toni
Deployment

Production Build

Building and running Toni applications in production.

Release build

cargo build --release

The compiled binary is in target/release/<project-name>. It has no runtime dependencies — ship just the binary.

Environment configuration

Set required environment variables before starting:

export DATABASE_URL="postgresql://user:pass@db-host:5432/myapp"
export JWT_SECRET="a-very-long-secret-key-at-least-32-chars"
export PORT=8080
export HOST=0.0.0.0

./target/release/my_api

Or use a .env file (if your application loads it with the dotenv crate):

# .env.production
DATABASE_URL=postgresql://...
JWT_SECRET=...
PORT=8080

Graceful shutdown

Toni handles SIGTERM and SIGINT signals and runs the shutdown hook sequence (on_module_destroy, before_application_shutdown, on_application_shutdown) before exiting. No extra configuration needed.

Listening on all interfaces

For production, listen on 0.0.0.0 (all interfaces) rather than 127.0.0.1 (loopback only):

app.listen(8080, "0.0.0.0").await;

Or read the host from configuration:

let host = std::env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
let port: u16 = std::env::var("PORT")
    .unwrap_or_else(|_| "8080".to_string())
    .parse()
    .expect("PORT must be a number");

app.listen(port, &host).await;

Systemd service

A basic systemd unit file:

[Unit]
Description=My Toni API
After=network.target

[Service]
Type=simple
User=api
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/my_api
EnvironmentFile=/opt/myapp/.env
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
sudo systemctl enable myapp
sudo systemctl start myapp
sudo journalctl -u myapp -f

Performance tuning (Axum / Tokio)

fn main() {
    tokio::runtime::Builder::new_multi_thread()
        .worker_threads(num_cpus::get())
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            let mut app = ToniFactory::create(AppModule, AxumAdapter::new()).await;
            app.listen(8080, "0.0.0.0").await;
        });
}
[dependencies]
num_cpus = "1"

Reverse proxy (nginx)

Run the Toni server on a local port and proxy from nginx:

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # WebSocket support
    location /ws {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Enable HTTPS via Certbot:

sudo certbot --nginx -d api.example.com

On this page