Configure security

Tune Resuma's HTTP hardening from Rust or environment variables.

ServeOptions + SecurityConfig

use resuma::prelude::*;

pub fn serve_options() -> ServeOptions {
    ServeOptions {
        addr: "127.0.0.1:3000".parse().unwrap(),
        security: SecurityConfig {
            csrf: true,
            origin_check: true,
            trust_proxy: true,          // Fly.io / nginx
            body_limit_bytes: 256 * 1024,
            actions_per_minute: 90,
            submits_per_minute: 45,
            hide_benchmark: true,
            production: true,
        },
    }
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
    ResumaApp::new()
        .page("/", || page())
        .serve(serve_options())
        .await
}

Environment variables

When you omit explicit config, SecurityConfig::from_env() reads:

RESUMA_ENV=production        # generic client errors
RESUMA_TRUST_PROXY=1       # X-Forwarded-For / Proto
RESUMA_CSRF=1              # default on (set 0 to disable)
RESUMA_ORIGIN_CHECK=1      # default on
RESUMA_BODY_LIMIT=1048576
RESUMA_RATE_ACTIONS=120    # per IP / minute — in-memory
RESUMA_RATE_SUBMITS=60     # per IP / minute — in-memory

CSP and with_head()

Each HTML response gets a unique CSP nonce. Inline &lt;style&gt; and &lt;script&gt; tags inside with_head() receive the nonce automatically. External scripts (e.g. ClientComponent bundles at /static/client/*.js) are allowed via script-src 'self'.

FlowApp::new()
    .with_head("<style>.hero { color: var(--accent); }</style>") // nonce at SSR
    .client_asset("chart", include_bytes!("../static/client/chart.js"))

Flow apps

FlowApp::new()
    .pages_from_dir("src/pages")
    .serve(FlowServeOptions {
        addr: ([0, 0, 0, 0], 3000).into(),
        security: SecurityConfig::from_env(),
    })
    .await

Fly.io

Production deploy guide (Dockerfile, fly.toml, health checks): Docker deploy cookbook. This repo ships a working config at the workspace root — live at resuma-docs.fly.dev.

# fly.toml [env] — minimum for production
RESUMA_ENV = "production"
RESUMA_TRUST_PROXY = "1"
SITE_URL = "https://your-app.fly.dev"
HOST = "0.0.0.0"
PORT = "3000"

[http_service]
  force_https = true

Security checklist before deploy

  • RESUMA_ENV=production — sanitized errors
  • RESUMA_TRUST_PROXY=1 — real client IP + HTTPS detection
  • force_https = true on Fly / reverse proxy
  • Run container as non-root (see Dockerfile)
  • Auth + validation on sensitive #[server] actions — todo example