# RustBox 0.2.16 host = "127.0.0.1" port = 3001 environment = "production" # Secure attribute of session cookies: auto | always | never. # auto (default) sets Secure only when the browser reached RustBox over HTTPS: # X-Forwarded-Proto / Forwarded: proto= / X-Forwarded-Ssl from a trusted proxy, # otherwise the scheme of the browser's Origin/Referer. Plain-HTTP installations # therefore keep working. Use "always" behind HTTPS if your proxy strips headers. cookie_secure = "auto" # Global light/dark theme: system | dark | light default_theme = "system" # Global interface style used by the login screen and by accounts set to # "Global default". Each user can additionally choose a style depth (colors only, # standard or immersive) in Appearance. Available styles: # rustbox, roundcube-classic, roundcube-larry, roundcube-elastic, clean, gmail, # proton, zoho, outlook, minimal, graphite, high-contrast, fastmail, apple-mail, # yahoo, hey, nord, github, gitlab, discord, slack, reddit, notion, dracula, # catppuccin, solarized, gruvbox, tokyo-night, rose-pine, everforest, synthwave, # paper, terminal, aqua, linear, material, retro, winxp, osx, ios6, win7, # frutiger-aero, beos default_interface_skin = "gmail" data_dir = "/var/lib/rustbox" log_dir = "/var/log/rustbox" # trace | debug | info | warn | error | off. RUST_LOG still overrides this value. log_level = "info" session_timeout_hours = 24 # Application database. The selected engine stores all RustBox account data. # With session_backend="database", it stores sessions as well. database_backend = "sqlite" # sqlite | mysql | pgsql # SQLite defaults to data_dir/rustbox.sqlite. MySQL/PostgreSQL require database_url. # database_url = "postgres://rustbox:secret@db.example.com/rustbox" session_backend = "database" # database | redis cluster_mode = false # For shared database sessions, Redis sessions, or cluster mode provide the same 32-byte key (base64) on all nodes. # session_encryption_key = "..." # Direct Redis session backend: # redis_url = "redis://redis.example.com:6379/" # Or Redis Sentinel: # redis_sentinel_nodes = ["sentinel-a:26379", "sentinel-b:26379", "sentinel-c:26379"] # redis_sentinel_master = "mymaster" # redis_sentinel_password = "sentinel-secret" # redis_password = "secret" remember_me_enabled = true remember_me_days = 30 # Mail profile. When hosts/ports are omitted RustBox defaults to: # IMAP localhost:993 and SMTP localhost:587 with TLS enabled. # SMTP host falls back to the IMAP host. # imap_host = "localhost" # imap_port = 993 # smtp_host = "localhost" # smtp_port = 587 tls_enabled = true # Certificate/hostname verification. If omitted, RustBox skips verification only # for localhost/127.0.0.1/::1 and verifies certificates for remote hosts. # tls_verify = true # Maximum size of one raw uploaded attachment (MiB). max_attachment_size_mb = 10 # Maximum size of the complete RFC822/MIME message submitted to the MTA (MiB). max_message_size_mb = 50 # Memory guard for messages with attachments. Sending a message or saving an IMAP # draft snapshot loads every attachment into RAM and the MIME builder keeps several # copies (about 3-4x the message size). Attachment sets that cannot fit # max_message_size_mb are rejected with 413 before any file is read, and at most # max_concurrent_message_builds requests may hold attachments in memory at once; # the others wait up to message_build_wait_secs and then get 503. # Rough peak RAM = max_concurrent_message_builds x 4 x max_message_size_mb. max_concurrent_message_builds = 4 message_build_wait_secs = 30 # "Undo Send" window in seconds. A submitted message is held in memory (not # persisted) for this long before it is actually dispatched to SMTP, so the # sender can cancel it. 0 disables the feature and sends immediately. Must be # <= 120; keep this short, since a server restart during the window loses the # staged send. undo_send_window_secs = 8 # Optional reverse-proxy subpath, e.g. "/mail". # base_path = "/mail" # Optional product features. Disabled features are not registered in the API/UI. sieve_enabled = true diagnostics_enabled = true about_enabled = true # Allow more than one signed-in account in the same browser session. multi_account_enabled = true # Adds content-type-aware browser security headers: document policies on HTML, private no-store/framing/CORP policy on /api, Referrer-Policy on HTML/CSS, and nosniff broadly. security_headers_enabled = false # ManageSieve. If sieve_host is omitted, imap_host from the authenticated # session is used. Plaintext authentication stays blocked unless explicitly # enabled. # sieve_host = "mail.example.com" sieve_port = 4190 sieve_tls_mode = "starttls" # starttls | implicit | none sieve_allow_insecure_auth = false sieve_timeout_secs = 10 trusted_proxies = "127.0.0.1,::1" # Optional server-wide defaults for special IMAP folders. These are used when # a mailbox has no per-account override and the named folder exists. # default_sent_folder = "Sent" # default_drafts_folder = "Drafts" # default_trash_folder = "Trash" # default_junk_folder = "Junk" # default_archive_folder = "Archive" # Optional headers added to every outgoing message. Use `Header-Name: value`. # RustBox rejects structural/MIME header overrides and CR/LF injection. outgoing_headers = [] # OpenPGP. Private keys are stored per user below data_dir with 0700/0600 # permissions. Passphrases are never persisted. WKD is enabled by default; # HKP lookup is opt-in and HTTPS-only. Cluster mode requires pgp_enabled=false. pgp_enabled = true pgp_wkd_enabled = true pgp_hkp_enabled = false pgp_hkp_url = "https://keys.openpgp.org" pgp_network_timeout_secs = 10 pgp_max_key_bytes = 1048576 # Private-key export is deliberately disabled unless the administrator opts in. pgp_allow_private_export = false # Login brute-force protection (POST /api/auth/login). Enabled by default. # Environment overrides use a double underscore, e.g. # LOGIN_RATE_LIMIT__ACCOUNT_MAX_FAILURES=10 or LOGIN_RATE_LIMIT__ENABLED=false. # Client IPs are taken from X-Forwarded-For only when the peer is in trusted_proxies. # State is kept in memory on each node: behind a load balancer every node counts # separately, so use sticky routing or lower thresholds in cluster mode. [login_rate_limit] enabled = true # Per-IP token bucket: up to ip_burst attempts at once, then one new attempt # every ip_replenish_secs seconds. Requests over the limit get HTTP 429. ip_burst = 5 ip_replenish_secs = 12 # Failed logins counted inside failure_window_secs before a lockout. # account_max_failures: per mailbox (case-insensitive), from any IP. # ip_max_failures: per client IP, across all mailboxes (password spraying). # 0 disables that lockout type. account_max_failures = 5 ip_max_failures = 20 failure_window_secs = 900 # First lockout length; every consecutive lockout of the same key doubles it # up to max_lockout_secs. Locked attempts are refused before contacting IMAP. # Trade-off: an attacker can keep a known mailbox locked for webmail logins # (IMAP/SMTP clients are unaffected), so keep max_lockout_secs moderate. lockout_secs = 300 max_lockout_secs = 3600 # IPs/CIDRs exempt from the per-IP lockout (account lockouts still apply). exempt_networks = [] # Memory cap per tracking table (accounts, IPs). max_tracked_keys = 100000 [storage] backend = "filesystem" # filesystem | s3 # path = "/var/lib/rustbox/blobs" # defaults to data_dir for filesystem shared = false # true only when every RustBox node sees the same filesystem prefix = "" # S3-compatible settings: # bucket = "rustbox" # region = "us-east-1" # endpoint = "https://s3.example.com" # MinIO/Ceph RGW/etc. optional for AWS S3 # path_style = false # allow_http = false request_timeout_secs = 30 connect_timeout_secs = 5 max_retries = 3 retry_timeout_secs = 60 # access_key_id = "..." # AWS_* environment variables are also supported # secret_access_key = "..." # server_side_encryption = "AES256" # or "aws:kms" # kms_key_id = "..." # Periodic IMAP reconciliation. Active folders still use IMAP IDLE; this is the # background/fallback cadence for folder counters, flags, new headers in other # folders, and the automatic deep-index pass. Lower values improve convergence but # increase IMAP traffic and mail-server load. [sync] interval_secs = 30 # Maximum full message bodies downloaded from IMAP per periodic pass when deep index # is effective. Larger batches catch up faster at the cost of network traffic, # application-database/search-storage usage and indexing CPU/I/O. deep_index_batch_size = 10 # Search is independent from blob storage. Local Tantivy is single-node only. [search] backend = "local_tantivy" # disabled | local_tantivy | opensearch # path = "/var/lib/rustbox/search" # defaults to data_dir for local_tantivy # urls = ["https://opensearch.example.com:9200"] index_prefix = "rustbox" required = false allow_insecure_http = false request_timeout_secs = 10 # Server-wide automatic full-body cache/index switch. When true, RustBox proactively # downloads message bodies from IMAP and indexes them for every account, up to # sync.deep_index_batch_size per sync pass. This increases IMAP traffic, # application-database/search-storage usage and indexing load. Production default # is false. When false, # the existing per-account deep_index preference may still opt an account in. deep_index = false # Search outbox worker cadence/batch; these do NOT control IMAP body downloads. worker_interval_secs = 2 worker_batch_size = 100 worker_max_attempts = 8 # username = "rustbox" # password = "..." # RustBox 0.2 blob/search backends # Blob storage is independent from the SQL database. PostgreSQL/MySQL can still use # local filesystem storage in single-node mode. In cluster mode use S3-compatible # storage or a genuinely shared POSIX filesystem (NFS/CephFS/GlusterFS). # Built-in CalDAV / CardDAV server. Disabled by default. # Every account gets one calendar and one address book, backed by the same tables # as the webmail calendar and contacts: # https://mail.example.com/dav/calendars//default/ # https://mail.example.com/dav/addressbooks//default/ # Clients may also start from https://mail.example.com/dav/ or rely on # /.well-known/caldav and /.well-known/carddav. Authentication is HTTP Basic with # the IMAP login and password (checked against imap_host, brute-force protected by # [login_rate_limit]). Serve RustBox over HTTPS when this is enabled. # Environment overrides: DAV__ENABLED=true, DAV__AUTH_CACHE_SECS=300, ... [dav] enabled = false # Seconds a successful Basic login is remembered before IMAP is asked again # (DAV clients authenticate on every request). 0 disables the cache. auth_cache_secs = 300 # Largest accepted calendar object / vCard (bytes). max_resource_size = 8388608 # Display names of the collections. calendar_name = "Calendar" addressbook_name = "Contacts" # Administrator-only system diagnostics endpoint. Disabled by default. # When enabled it exposes a redacted runtime/configuration report plus live probes # for SQL, session persistence (database/Redis), blob storage (filesystem/S3), # search (Tantivy/OpenSearch), IMAP IDLE counters and security telemetry. # Access requires BOTH an allowed source network and the configured auth method. # Secrets (passwords, tokens, S3 keys, session keys and URL credentials) are never returned. [diagnostics_endpoint] enabled = false path = "/api/system/diagnostics" # Default/fail-safe allowlist: only this host. Add trusted LAN/pod/monitoring CIDRs explicitly. allowed_networks = ["127.0.0.1/32", "::1/128"] # token | basic. Credentials should normally come from .env / secret manager, not TOML. auth = "token" # token = "replace-with-at-least-24-random-characters" # basic_username = "rustbox-monitor" # basic_password = "replace-with-a-long-random-password" # E-mail addresses and stable user hashes are omitted by default; aggregate counts remain available. include_user_identifiers = false # Timeout applied independently to database/session/storage/search probes. probe_timeout_secs = 5 # Rolling in-memory window used for login failures, 403, 429 and 5xx attack/problem signals. security_window_secs = 900