Use Rocket.toml to configure Hagrid.

- Fixes #69.
This commit is contained in:
Justus Winter
2019-03-12 10:31:56 +01:00
parent f3aa4e45a4
commit 008d4d756d
5 changed files with 47 additions and 119 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
/node_modules
/Rocket.toml
/target
**/*.rs.bk
/dist/public/by-*

View File

@@ -16,13 +16,14 @@ keys, user IDs and tokens. To run it, supply the absolute path to where you
want the database to live and the absolute path to the template directory.
```bash
cargo run --bin hagrid -- dist
cp Rocket.toml.dist Rocket.toml
cargo run --bin hagrid
```
This will spawn a web server listening on port 8080.
Hagrid uses `sendmail` for mailing, so you also need a working local mailer
setup. The FROM field of the mails can be configured with the `-F` switch.
setup.
Usage
-----
@@ -125,20 +126,20 @@ After compilation a binary is placed in `target/release/` called
cp target/release/hagrid /usr/local/bin
```
To deploy the key server copy all
directories under `public/` to a writable location. Then start the server with
the _absolute_ path to the directory as argument:
To deploy the key server copy all directories under `dist/` to a
writable location, and create a suitable configuration file.
```bash
mkdir /var/lib/hagrid
cp -R dist/* /var/lib/hagrid
hagrid /var/lib/hagrid
cp Rocket.toml.dist /var/lib/hagrid/Rocket.toml
$EDITOR /var/lib/hagrid/Rocket.toml
/usr/bin/env --chdir=/var/lib/hagrid ROCKET_ENV=production hagrid
```
This will spawn the server in foreground, listening on `0.0.0.0:8080`. The
`--listen` argument can be used to change port and listen address. The server
will put all keys and runtime data under the base folder (`/var/lib/hagrid`
in the above example).
This will spawn the server in foreground. The server will put all
keys and runtime data under the base folder (`/var/lib/hagrid` in the
above example).
Reverse Proxy
-------------

20
Rocket.toml.dist Normal file
View File

@@ -0,0 +1,20 @@
[global]
address = "0.0.0.0"
port = 8080
template_dir = "dist/templates"
state_dir = "dist"
[development]
domain = "localhost"
from = "noreply@localhost"
x-accel-redirect = false
[staging]
domain = "keys.openpgp.org"
from = "noreply@keys.openpgp.org"
x-accel-redirect = true
[production]
domain = "keys.openpgp.org"
from = "noreply@keys.openpgp.org"
x-accel-redirect = true

View File

@@ -22,7 +22,6 @@ extern crate sequoia_openpgp;
extern crate handlebars;
extern crate lettre;
extern crate lettre_email;
extern crate structopt;
extern crate tempfile;
#[cfg(test)]
@@ -34,43 +33,8 @@ extern crate hagrid_database as database;
mod mail;
mod web;
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(
name = "hagrid",
about = "Hagrid - The verifying OpenPGP key server."
)]
pub struct Opt {
/// More verbose output. Disabled when running as daemon.
#[structopt(short = "v", long = "verbose")]
verbose: bool,
/// Daemonize after startup.
#[structopt(short = "d", long = "daemon")]
daemon: bool,
/// Base directory
#[structopt(parse(from_os_str))]
base: PathBuf,
/// Port and address to listen on.
#[structopt(short = "l", long = "listen", default_value = "0.0.0.0:8080")]
listen: String,
/// FQDN of the server. Used in templates.
#[structopt(short = "D", long = "domain", default_value = "localhost")]
domain: String,
#[structopt(
short = "F",
long = "from",
default_value = "noreply@localhost"
)]
from: String,
/// Use NGINX'es X-Accel-Redirect feature.
#[structopt(long = "use-x-accel-redirect")]
x_accel_redirect: bool,
}
fn main() {
if let Err(e) = real_main() {
if let Err(e) = web::serve() {
let mut cause = e.as_fail();
eprint!("{}", cause);
while let Some(c) = cause.cause() {
@@ -81,12 +45,3 @@ fn main() {
::std::process::exit(2);
}
}
fn real_main() -> Result<()> {
use database::{Filesystem, Polymorphic};
let mut opt = Opt::from_args();
opt.base = opt.base.canonicalize()?;
let db = Filesystem::new(&opt.base)?;
web::serve(&opt, Polymorphic::Filesystem(db))
}

View File

@@ -17,7 +17,6 @@ use mail;
use database::{Database, Polymorphic, Query};
use database::types::{Email, Fingerprint, KeyID};
use Result;
use Opt;
use std::result;
use std::str::FromStr;
@@ -627,51 +626,11 @@ fn apidoc() -> Template {
Template::render("apidoc", templates::General::default())
}
pub fn serve(opt: &Opt, db: Polymorphic) -> Result<()> {
use rocket::config::{Config, Environment};
use std::str::FromStr;
let (addr, port) = match opt.listen.find(':') {
Some(p) => {
let addr = opt.listen[0..p].to_string();
let port = if p < opt.listen.len() - 1 {
u16::from_str(&opt.listen[p + 1..]).ok().unwrap_or(8080)
} else {
8080
};
(addr, port)
}
None => (opt.listen.to_string(), 8080),
};
let config = Config::build(Environment::Staging)
.address(addr)
.port(port)
.workers(2)
.root(opt.base.clone())
.extra(
"template_dir",
opt.base
.join("templates")
.to_str()
.ok_or(failure::err_msg("Template path invalid"))?,
)
.extra(
"state_dir",
opt.base.to_str()
.ok_or(failure::err_msg("Static path invalid"))?,
)
.extra("domain", opt.domain.clone())
.extra("from", opt.from.clone())
.extra("x-accel-redirect", opt.x_accel_redirect)
.finalize()?;
rocket_factory(rocket::custom(config), db).launch();
Ok(())
pub fn serve() -> Result<()> {
Err(rocket_factory(rocket::ignite())?.launch().into())
}
fn rocket_factory(rocket: rocket::Rocket, db: Polymorphic) -> rocket::Rocket {
fn rocket_factory(rocket: rocket::Rocket) -> Result<rocket::Rocket> {
let routes = routes![
// infra
root,
@@ -695,7 +654,11 @@ fn rocket_factory(rocket: rocket::Rocket, db: Polymorphic) -> rocket::Rocket {
apidoc,
];
rocket
use database::{Filesystem, Polymorphic};
let db = Polymorphic::Filesystem(
Filesystem::new(&PathBuf::from(rocket.config().get_str("state_dir")?))?
);
Ok(rocket
.attach(Template::fairing())
.attach(AdHoc::on_attach("state", |rocket| {
let state_dir: PathBuf = rocket.config().get_str("state_dir")
@@ -748,7 +711,7 @@ fn rocket_factory(rocket: rocket::Rocket, db: Polymorphic) -> rocket::Rocket {
}))
}))
.mount("/", routes)
.manage(db)
.manage(db))
}
#[cfg(test)]
@@ -819,10 +782,7 @@ mod tests {
#[test]
fn basics() {
let (_tmpdir, config) = configuration().unwrap();
let db = Polymorphic::Filesystem(
Filesystem::new(config.root().unwrap().to_path_buf()).unwrap());
let rocket = rocket_factory(rocket::custom(config), db);
let rocket = rocket_factory(rocket::custom(config)).unwrap();
let client = Client::new(rocket).expect("valid rocket instance");
// Check that we see the landing page.
@@ -854,9 +814,7 @@ mod tests {
// eprintln!("LEAKING: {:?}", tmpdir);
// ::std::mem::forget(_tmpdir);
let db = Polymorphic::Filesystem(
Filesystem::new(config.root().unwrap().to_path_buf()).unwrap());
let rocket = rocket_factory(rocket::custom(config), db);
let rocket = rocket_factory(rocket::custom(config)).unwrap();
let client = Client::new(rocket).expect("valid rocket instance");
// Generate a key and upload it.
@@ -911,9 +869,7 @@ mod tests {
let (tmpdir, config) = configuration().unwrap();
let filemail_into = tmpdir.path().join("filemail");
let db = Polymorphic::Filesystem(
Filesystem::new(config.root().unwrap().to_path_buf()).unwrap());
let rocket = rocket_factory(rocket::custom(config), db);
let rocket = rocket_factory(rocket::custom(config)).unwrap();
let client = Client::new(rocket).expect("valid rocket instance");
// Generate two keys and upload them.
@@ -1086,9 +1042,7 @@ mod tests {
// eprintln!("LEAKING: {:?}", tmpdir);
// ::std::mem::forget(tmpdir);
let db = Polymorphic::Filesystem(
Filesystem::new(config.root().unwrap().to_path_buf()).unwrap());
let rocket = rocket_factory(rocket::custom(config), db);
let rocket = rocket_factory(rocket::custom(config)).unwrap();
let client = Client::new(rocket).expect("valid rocket instance");
// Generate a key and upload it.
@@ -1140,9 +1094,7 @@ mod tests {
let (tmpdir, config) = configuration().unwrap();
let filemail_into = tmpdir.path().join("filemail");
let db = Polymorphic::Filesystem(
Filesystem::new(config.root().unwrap().to_path_buf()).unwrap());
let rocket = rocket_factory(rocket::custom(config), db);
let rocket = rocket_factory(rocket::custom(config)).unwrap();
let client = Client::new(rocket).expect("valid rocket instance");
// Generate two keys and upload them.