On this page

Configuration

Rivetr reads server configuration from a TOML file, rivetr.toml by default. Pass --config <path> to use another file. Every table and field is optional: a missing file means all defaults apply. Restart the service after editing the file.

Instance settings changed in the dashboard are stored in SQLite and apply without a restart. Server settings such as ports, the data directory, proxy and ACME, runtime limits, rate limits and retention come from this file. Per-app settings (build type, health check, resources, domains, environment) live in the database and are managed from the dashboard or API. They are not stored in a repository file.

Minimal production example

[server]
host = "0.0.0.0"
api_port = 8080
proxy_port = 80
proxy_https_port = 443
data_dir = "/var/lib/rivetr"
external_url = "https://rivetr.example.com"

[auth]
admin_token = "replace-with-openssl-rand-hex-32"
encryption_key = "replace-with-openssl-rand-hex-32"

[proxy]
acme_enabled = true
acme_email = "admin@example.com"
instance_domain = "rivetr.example.com"

[rate_limit]
trusted_proxies = ["127.0.0.1"]

[email]
enabled = true
smtp_host = "smtp.example.com"
from_address = "rivetr@example.com"

[server]

FieldDefaultDescription
host"0.0.0.0"Address the API and proxy bind to
api_port8080REST API and dashboard port
proxy_port80Embedded HTTP proxy port
proxy_https_port443Embedded HTTPS proxy port
data_dir"./data"SQLite database, ACME cache, backups and key files
external_urlnoneExternally reachable base URL for callbacks and webhook URLs

[auth]

FieldDefaultDescription
admin_tokenrandom 256-bit hex per startStable bearer token for programmatic API access. Set it explicitly in production.
encryption_keynoneKey for encrypting secrets at rest. Use at least 32 random characters, for example from openssl rand -hex 32.

The key is resolved in this order: [auth] encryption_key, then <data_dir>/.encryption_key, then on a fresh install a generated key written to that file with mode 0600. An existing install with no key keeps values in plaintext and logs a warning.

Back up .encryption_key and .encryption_salt with the database. To encrypt values that already exist, stop Rivetr and run rivetr --config rivetr.toml db encrypt-secrets (dry run) followed by the same command with --execute. There is no key rotation command in 1.0.0.

[runtime]

FieldDefaultDescription
runtime_type"auto"auto, docker or podman
docker_socketplatform defaultDocker daemon socket path or URL
build_cpu_limit"2"CPU limit for builds
build_memory_limit"2g"Memory limit for builds
max_concurrent_deployments2Builds allowed at once; extra deploys queue
health_check_timeout_secs20Seconds a new container has to pass its health check
default_memory_limit"512m"Fallback memory cap for running containers; empty disables
default_pids_limit512Fallback PID limit; 0 disables
default_oom_score_adj500OOM score adjustment, -1000 to 1000
default_log_max_size"10m"Log rotation size per container; empty disables
default_log_max_file3Rotated log files retained; Docker only

Per-resource limits override the defaults. The running-container defaults protect the host from a runaway app; the build limits protect it from a runaway build.

[proxy]

FieldDefaultDescription
acme_enabledfalseEnable Let's Encrypt certificates
acme_emailnoneACME account email; required when ACME is enabled
acme_stagingfalseUse the Let's Encrypt staging environment
health_check_interval30Seconds between backend checks
health_check_timeout5Timeout per backend check
health_check_threshold3Consecutive failures before a backend is unhealthy
drain_timeout_secs30Wait for in-flight requests before stopping an old container; 0 disables
base_domainnoneBase for auto-generated app subdomains
auto_subdomain_enabledfalseGenerate subdomains for new apps; needs base_domain
server_ipnonePublic IP for sslip.io domains; auto-detected when unset
sslip_enabledfalseEnable sslip.io automatic domains
preview_domainnoneBase domain for PR preview deployments
instance_domainnoneDomain that routes the dashboard and API through the proxy

Per-domain certificate mode is set on the app's Domains page: automatic HTTP-01, wildcard DNS-01 through a configured DNS provider, or a custom uploaded certificate. Custom certificates win over ACME. Renewal starts 30 days before expiry.

[logging]

level sets the log filter: trace, debug, info, warn or error. Default "info".

[webhooks]

FieldDefaultDescription
github_secretnoneVerifies X-Hub-Signature-256 (HMAC-SHA256)
gitlab_tokennoneMatched against X-Gitlab-Token
gitea_secretnoneVerifies the Gitea HMAC-SHA256 signature
bitbucket_secretnoneVerifies the Bitbucket HMAC-SHA256 signature
dockerhub_secretnoneShared token required as ?token= on DockerHub webhooks

Inbound webhooks fail closed. GitHub rejects requests when neither github_secret nor a connected GitHub App secret is configured. The other providers reject requests when their secret or token is unset. DockerHub sends no signature header, so its secret travels in the webhook URL; treat that URL as a credential.

[oauth]

Optional provider subtables: [oauth.github], [oauth.gitlab] and [oauth.bitbucket]. Each accepts client_id (required), client_secret (required) and redirect_uri (optional). Other OAuth providers are configured from the authentication settings page and stored in the database.

[rate_limit]

FieldDefaultDescription
enabledtrueMaster switch
api_requests_per_window100General API requests per window
webhook_requests_per_window500Webhook requests per window
auth_requests_per_window20Authentication requests per window
window_seconds60Window length
cleanup_interval300Seconds between expired-entry cleanups
trusted_proxies[]IPs or CIDRs whose forwarded headers are trusted

Forwarded headers are read right to left, skipping trusted hops. Loopback peers are always trusted. List only proxies that untrusted clients cannot connect from. Account lockout is separate from IP rate limiting and is described in /docs/security.

Background loops and retention

TableFields and defaults
[cleanup]enabled = true, max_deployments_per_app = 3 (the example file shows 10 as a sample), cleanup_interval_seconds = 3600, prune_images = true
[disk_monitor]enabled = true, check_interval_seconds = 300, warning_threshold = 80, critical_threshold = 90
[container_monitor]enabled = true, check_interval_secs = 30, max_restart_attempts = 5, initial_backoff_secs = 5, max_backoff_secs = 300, stable_duration_secs = 120
[database_backup]enabled = true, check_interval_seconds = 60, backup_dir = "backups", timeout_seconds = 3600
[stats_retention]enabled = true, raw_retention_days = 7, hourly_retention_days = 30, daily_retention_days = 365, cleanup_interval_seconds = 3600
[data_retention]proxy_logs_days = 14, webhook_events_days = 30, audit_logs_days = 90, scheduled_job_runs_keep = 100, deployment_snapshots_keep = 3

In [data_retention], a value of 0 disables pruning for that item; expired sessions are always removed after a one-day grace period. The cleanup loop prunes old deployments and, when prune_images is on, dangling images.

[email]

FieldDefaultDescription
enabledfalseEnable outgoing email
smtp_hostnoneSMTP server hostname
smtp_port587SMTP port
smtp_usernamenoneSMTP username
smtp_passwordnoneSMTP password
smtp_tlstrueUse TLS
from_addressnoneSender address
from_name"Rivetr"Sender display name

Email is considered configured only when enabled is true and both smtp_host and from_address are set. Invitations, password resets and notification channels use it.

[auto_update]

FieldDefaultDescription
enabledtrueCheck for new releases
auto_applyfalseDownload and install automatically
check_interval_hours6Hours between checks
github_repo"KwaminaWhyte/rivetr"Repository to check
include_prereleasesfalseInclude prerelease versions

The check calls the GitHub Releases API only. Rivetr has no telemetry. Disable it for an air-gapped install and update manually.

[ai]

FieldDefaultDescription
provider"claude" when unsetclaude, openai, gemini or moonshot
api_keynoneProvider API key; stored in the config file, so protect its permissions
modelprovider defaultModel override
max_tokens2048Maximum output tokens

Full reference

The exhaustive field list, including every type and default, is maintained in the repository at docs/reference/configuration.md. rivetr.example.toml is a copyable starter with comments. Run rivetr --config rivetr.toml config check to validate a file and print a summary with warnings.