Guide

The ins and outs of Rocket, in detail.

Configuration#

Rocket's configuration system is flexible. Based on Figment, it allows you to configure your application the way you want while also providing with a sensible set of defaults.

Overview#

Rocket's configuration system is based on Figment's Providers, types which provide configuration data. Rocket's Config and Config::figment(), as well as Figment's Toml and Json, are some examples of providers. Providers can be combined into a single Figment provider from which any configuration structure that implements Deserialize can be extracted.

Rocket expects to be able to extract a Config structure from the provider it is configured with. This means that no matter which configuration provider Rocket is asked to use, it must be able to read the following configuration values:

keykinddescriptiondebug/release default
addressIpAddrIP address to serve on127.0.0.1
portu16Port to serve on.8000
workersusizeNumber of threads to use for executing futures.cpu core count
identstring, falseIf and how to identify via the Server header."Rocket"
keep_aliveu32Keep-alive timeout seconds; disabled when 0.5
log_levelLogLevelMax level to log. (off/normal/debug/critical)normal/critical
cli_colorsboolWhether to use colors and emoji when logging.true
secret_keySecretKeySecret key for signing and encrypting values.None
tlsTlsConfigTLS configuration, if any.None
tls.key&[u8]/&PathPath/bytes to DER-encoded ASN.1 PKCS#1/#8 key.
tls.certs&[u8]/&PathPath/bytes to DER-encoded X.509 TLS cert chain.
limitsLimitsStreaming read size limits.Limits::default()
limits.$name&str/uintRead limit for $name.forms = "32KiB"
ctrlcboolWhether ctrl-c initiates a server shutdown.true
shutdownShutdownGraceful shutdown configuration.Shutdown::default()

Profiles#

Configurations can be arbitrarily namespaced by Profiles. Rocket's Config and Config::figment() providers automatically set the configuration profile to "debug" when compiled in "debug" mode and "release" when compiled in release mode. With the exception of log_level, which changes from normal in debug to critical in release, all of the default configuration values are the same in all profiles. What's more, all configuration values have defaults, so no configuration needs to be supplied to get an application going.

In addition to any profiles you declare, there are two meta-profiles, default and global, which can be used to provide values that apply to all profiles. Values provided in a default profile are used as fall-back values when the selected profile doesn't contain a requested values, while values in the global profile supplant any values with the same name in any profile.

Default Provider#

Rocket's default configuration provider is Config::figment(); this is the provider that's used when calling rocket::build().

The default figment merges, at a per-key level, and reads from the following sources, in ascending priority order:

  1. Config::default() - which provides default values for all parameters.
  2. Rocket.toml or TOML file path in ROCKET_CONFIG environment variable.
  3. ROCKET_ prefixed environment variables.

The selected profile is the value of the ROCKET_PROFILE environment variable, or if it is not set, "debug" when compiled in debug mode and "release" when compiled in release mode.

As a result, without any effort, Rocket's server can be configured via a Rocket.toml file and/or via environment variables, the latter of which take precedence over the former. Note that neither the file nor any environment variables need to be present as Config::default() is a complete configuration source.

Rocket.toml#

Rocket searches for Rocket.toml or the filename in a ROCKET_CONFIG environment variable starting at the current working directory. If it is not found, the parent directory, its parent, and so on, are searched until the file is found or the root is reached. If the path set in ROCKET_CONFIG is absolute, no such search occurs and the set path is used directly.

The file is assumed to be nested, so each top-level key declares a profile and its values the value for the profile. The following is an example of what such a file might look like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
## defaults for _all_ profiles
[default]
address = "0.0.0.0"
limits = { forms = "64 kB", json = "1 MiB" }

## set only when compiled in debug mode, i.e, `cargo build`
[debug]
port = 8000
## only the `json` key from `default` will be overridden; `forms` will remain
limits = { json = "10MiB" }

## set only when the `nyc` profile is selected
[nyc]
port = 9001

## set only when compiled in release mode, i.e, `cargo build --release`
## don't use this secret_key! generate your own and keep it private!
[release]
port = 9999
secret_key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk="

The following is a Rocket.toml file with all configuration options set for demonstratation purposes. You do not and should not set a value for configuration options needlessly, preferring to use the default value when sensible.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[default]
address = "127.0.0.1"
port = 8000
workers = 16
keep_alive = 5
ident = "Rocket"
log_level = "normal"
temp_dir = "/tmp"
cli_colors = true
## NOTE: Don't (!) use this key! Generate your own!
secret_key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk="

[default.limits]
forms = "64 kB"
json = "1 MiB"
msgpack = "2 MiB"
"file/jpg" = "5 MiB"

[default.tls]
certs = "path/to/cert-chain.pem"
key = "path/to/key.pem"

[default.shutdown]
ctrlc = true
signals = ["term", "hup"]
grace = 5
mercy = 5

Environment Variables#

Rocket reads all environment variable names prefixed with ROCKET_ using the string after the _ as the name of a configuration value as the value of the parameter as the value itself. Environment variables take precedence over values in Rocket.toml. Values are parsed as loose form of TOML syntax. Consider the following examples:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
ROCKET_FLOAT=3.14
ROCKET_ARRAY=[1,"b",3.14]
ROCKET_STRING=Hello
ROCKET_STRING="Hello There"

ROCKET_KEEP_ALIVE=1
ROCKET_IDENT=Rocket
ROCKET_IDENT="Hello Rocket"
ROCKET_IDENT=false
ROCKET_TLS={certs="abc",key="foo/bar"}
ROCKET_LIMITS={forms="64 KiB"}

Secret Key#

The secret_key parameter configures a cryptographic key to use when encrypting application values. In particular, the key is used to encrypt private cookies, which are available only when the secrets crate feature is enabled.

Generating a string suitable for use as a secret_key configuration value is usually done through tools like openssl. Using openssl, a 256-bit base64 key can be generated with the command openssl rand -base64 32.

When compiled in debug mode, a fresh key is generated automatically. In release mode, Rocket requires you to set a secret key if the secrets feature is enabled. Failure to do so results in a hard error at launch time. The value of the parameter may either be a 256-bit base64 or hex string or a slice of 32 bytes.

Limits#

The limits parameter configures the maximum amount of data Rocket will accept for a given data type. The value is expected to be a dictionary table where each key corresponds to a data type and each value corresponds to the maximum size in bytes Rocket should accept for that type. Rocket can parse both integers (32768) or SI unit based strings ("32KiB") as limits.

By default, Rocket specifies a 32 KiB limit for incoming forms. Since Rocket requires specifying a read limit whenever data is read, external data guards may also choose to have a configure limit via the limits parameter. The Json type, for instance, uses the limits.json parameter.

TLS#

Rocket includes built-in, native support for TLS >= 1.2 (Transport Layer Security). In order for TLS support to be enabled, Rocket must be compiled with the "tls" feature:

1
2
[dependencies]
rocket = { version = "0.5.0-dev", features = ["tls"] }

TLS is configured through the tls configuration parameter. The value of tls is a dictionary with two keys: certs and key, described in the table above. Each key's value may be either a path to a file or raw bytes corresponding to the expected value. When a path is configured in a file source, such as Rocket.toml, relative paths are interpreted as being relative to the source file's directory.

Warning: Rocket's built-in TLS implements only TLS 1.2 and 1.3. It may not be suitable for production use.

Workers#

The workers parameter sets the number of threads used for parallel task execution; there is no limit to the number of concurrent tasks. Due to a limitation in upstream async executers, unlike other values, the workers configuration value cannot be reconfigured or be configured from sources other than those provided by Config::figment(), detailed below. In other words, only the values set by the ROCKET_WORKERS environment variable or in the workers property of Rocket.toml will be considered - all other workers values are ignored.

Extracting Values#

Your application can extract any configuration that implements Deserialize from the configured provider, which is exposed via Rocket::figment():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
use rocket::serde::Deserialize;

#[launch]
fn rocket() -> _ {
    let rocket = rocket::build();
    let figment = rocket.figment();

    #[derive(Deserialize)]
    struct Config {
        port: u16,
        custom: Vec<String>,
    }

    // extract the entire config any `Deserialize` value
    let config: Config = figment.extract().expect("config");

    // or a piece of it into any `Deserialize` value
    let custom: Vec<String> = figment.extract_inner("custom").expect("custom");

    rocket
}

Both values recognized by Rocket and values not recognized by Rocket can be extracted. This means you can configure values recognized by your application in Rocket's configuration sources directly. The next section describes how you can customize configuration sources by supplying your own Provider.

Because it is common to store configuration in managed state, Rocket provides an AdHoc fairing that 1) extracts a configuration from the configured provider, 2) pretty prints any errors, and 3) stores the value in managed state:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
use rocket::{State, fairing::AdHoc};

#[get("/custom")]
fn custom(config: &State<Config>) -> String {
    config.custom.get(0).cloned().unwrap_or("default".into())
}

#[launch]
fn rocket() -> _ {
    rocket::build()
        .mount("/", routes![custom])
        .attach(AdHoc::config::<Config>())
}

Custom Providers#

A custom provider can be set via rocket::custom(), which replaces calls to rocket::build(). The configured provider can be built on top of Config::figment(), Config::default(), both, or neither. The Figment documentation has full details on instantiating existing providers like Toml and Json as well as creating custom providers for more complex cases.

Note: You may need to depend on figment and serde directly.

Rocket reexports figment and serde from its crate root, so you can refer to figment types via rocket::figment and serde types via rocket::serde. However, Rocket does not enable all features from either crate. As such, you may need to import crates directly:

figment = { version = "0.9", features = ["env", "toml", "json"] }

As a first example, we override configuration values at runtime by merging figment's tuple providers with Rocket's default provider:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use rocket::data::{Limits, ToByteUnit};

#[launch]
fn rocket() -> _ {
    let figment = rocket::Config::figment()
        .merge(("port", 1111))
        .merge(("limits", Limits::new().limit("json", 2.mebibytes())));

    rocket::custom(figment).mount("/", routes![/* .. */])
}

More involved, consider an application that wants to use Rocket's defaults for Config, but not its configuration sources, while allowing the application to be configured via an App.toml file that uses top-level keys as profiles (.nested()), APP_ environment variables as global overrides (.global()), and APP_PROFILE to configure the selected profile:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
use rocket::serde::{Serialize, Deserialize};
use rocket::fairing::AdHoc;

use figment::{Figment, Profile, providers::{Format, Toml, Serialized, Env}};

#[derive(Debug, Deserialize, Serialize)]
struct Config {
    app_value: usize,
    /* and so on.. */
}

impl Default for Config {
    fn default() -> Config {
        Config { app_value: 3, }
    }
}

#[launch]
fn rocket() -> _ {
    let figment = Figment::from(rocket::Config::default())
        .merge(Serialized::defaults(Config::default()))
        .merge(Toml::file("App.toml").nested())
        .merge(Env::prefixed("APP_").global())
        .select(Profile::from_env_or("APP_PROFILE", "default"));

    rocket::custom(figment)
        .mount("/", routes![/* .. */])
        .attach(AdHoc::config::<Config>())
}

Rocket will extract it's configuration from the configured provider. This means that if values like port and address are configured in Config, App.toml or APP_ environment variables, Rocket will make use of them. The application can also extract its configuration, done here via the Adhoc::config() fairing.