# Server Config PORT=3000 HOST=0.0.0.0 # Display name for this server (shown in multi-server sidebar) SERVER_NAME=Haven # Secret key for JWT tokens. CHANGE THIS to a long random string! # (Auto-generated on first boot if left as default) JWT_SECRET=change-me-to-something-random-and-long # Your admin username (register with this name first to get admin powers) ADMIN_USERNAME=admin # Optional: HTTPS (required for voice chat over the internet) # Paths are relative to the data directory: # Windows: %APPDATA%\Haven\ # Linux/macOS: ~/.haven/ # # Using Let's Encrypt or certbot? Point this at fullchain.pem, NOT at their # cert.pem. Their cert.pem holds only your own certificate, without the # intermediate one above it, and a server that hands out just the leaf gets # rejected by curl, by most automated link checkers, and by some mobile and # API clients. Browsers usually hide the problem by fetching the missing # piece themselves, so the site looks fine in Chrome while other things fail # against it. Haven's own setup-ssl script already copies fullchain.pem into # certs/cert.pem, so the default path below is fine. # SSL_CERT_PATH=/etc/letsencrypt/live/YOUR.DOMAIN/fullchain.pem # # SSL_CERT_PATH=./certs/cert.pem # SSL_KEY_PATH=./certs/key.pem # Force HTTP mode (useful behind a reverse proxy like Caddy, nginx, etc.) # Set to true to skip SSL even if certificates exist. # FORCE_HTTP=false # Public-facing URL for OAuth/OpenID callbacks. # Set this when the server cannot determine its own external address, # for example Docker port mapping (8080→3000), reverse proxies that strip # the port, or Cloudflare Tunnels. Must include the scheme (https://). # Example: PUBLIC_URL=https://haven.example.com:8443 # PUBLIC_URL= # Steam Web API Key: required for Steam rich presence (game activity display). # Get yours at https://steamcommunity.com/dev/apikey (any domain name works). # Once set, users can link their Steam account in Settings → Connections. # STEAM_API_KEY= # Optional: Override the data directory location # HAVEN_DATA_DIR= # Optional: let bot callback URLs point at private or local addresses. # By default Haven refuses to call back to 10.x, 172.16-31.x, 192.168.x, # localhost, .local and .internal, so a webhook can't be used to probe the # network the server sits on. Set this to true if your bot genuinely runs # on the same LAN or in a sibling Docker container. The same goes for push # notification endpoints, such as a self-hosted ntfy for UnifiedPush that # resolves to a private address from inside Haven's container. Cloud metadata # addresses (169.254.x.x) stay blocked either way. # HAVEN_ALLOW_PRIVATE_CALLBACKS=true # Optional: send outgoing requests through a proxy (link previews, the media # proxy, bot callbacks, push notifications, update and DDNS checks). Only # http:// proxy addresses are supported. Hosts in no_proxy connect directly. # Haven checks each name itself and sends the proxy to the checked address. # A name Haven cannot resolve itself is refused, unless # OUTBOUND_PROXY_RESOLVES_NAMES=true passes it to the proxy unchecked. With # that set, the proxy's own rules decide where those requests can go, so # restrict it to the destinations Haven needs. See "Outgoing Proxy" in GUIDE.md. # https_proxy=http://proxy.example:3128 # http_proxy=http://proxy.example:3128 # no_proxy=localhost,127.0.0.1 # OUTBOUND_PROXY_RESOLVES_NAMES=true # Optional: Override STUN servers for voice/WebRTC. # Default: stun.stunprotocol.org + stun.nextcloud.com # Comma-separated list of STUN URIs. Set this to point at your own coturn # or any STUN server for fully self-hosted voice with no external dependencies. # STUN_URLS=stun:your-server.com:3478,stun:backup-server.com:3478 # Optional: TURN server for voice/screen sharing across the internet. # Without TURN, voice only works on the same network (LAN). # Recommended: run coturn on the same box or a cheap VPS. # # Option A: Shared secret (coturn --use-auth-secret, recommended): # TURN_URL=turn:your-server.com:3478 # TURN_SECRET=your-coturn-static-auth-secret # # Option B: Static credentials: # TURN_URL=turn:your-server.com:3478 # TURN_USERNAME=haven # TURN_PASSWORD=your-password # GIF search: GIPHY (https://developers.giphy.com/). A supported provider. # GIPHY_API_KEY= # GIF search: KLIPY (https://klipy.com/developers). A supported provider. # KLIPY_API_KEY= # Legacy only: Tenor is no longer supported for new setup. Still read if no other key is set. # TENOR_API_KEY= # Which provider to use when more than one key is set: klipy, giphy, or tenor. # If unset or invalid, falls back to GIPHY, then KLIPY, then Tenor. # PREFERRED_GIF_SEARCH= # ── Dynamic DNS auto-updater ───────────────────────────── # Keeps a DNS record pointed at this server's current public IP so your # domain (e.g. anchaven.duckdns.org) never goes stale when your ISP # rotates your IP. Disabled unless DDNS_PROVIDER is set. # # DuckDNS: # DDNS_PROVIDER=duckdns # DDNS_DOMAINS=your-subdomain (no .duckdns.org, comma-separated for multiple) # DDNS_TOKEN=your-duckdns-token (from https://www.duckdns.org/) # # Cloudflare: # DDNS_PROVIDER=cloudflare # DDNS_CF_API_TOKEN=... (token with Zone:DNS:Edit on the zone) # DDNS_CF_ZONE_ID=... # DDNS_CF_RECORD_ID=... # DDNS_CF_RECORD_NAME=haven.example.com # # Generic (anything that takes the IP in a URL): # DDNS_PROVIDER=generic # DDNS_URL=https://example.com/update?host=h&ip={ip} # # Common: # DDNS_INTERVAL_MINUTES=5 (how often to re-check; default 5) # Checks unicode.org every month for a new emoji standard and automatically regenerates the built-in emojis in Haven based on that standard # If you choose to leave this feature disabled, Haven will default to Unicode standard 16.0 which is bundled with the server # Uncomment to enable this feature # UNICODE_EMOJI_AUTO_UPDATE=true # Your client secret as defined by your OIDC provider. The client secret must be set as an env var if using OIDC. # OIDC_CLIENT_SECRET=changeme-client-secret # Disk headroom kept free on the data volume, in MB (default 512). # Uploads are refused once accepting the largest allowed file would cut into # this, so a full disk can never leave admins unable to delete the files that # filled it (deleting a row is itself a database write, and that needs space). # HAVEN_DISK_RESERVE_MB=512 # Full text search tokenizer. Controls how message text is matched. # Takes effect on restart; changing it triggers a one time reindex. # trigram Matches text anywhere inside words, so apple finds apple, # applesauce and pineapple. Most flexible for partial matches. # Largest index (about 3 to 4x the message text) and needs # queries of at least 3 characters. # unicode61 Whole word and prefix matching, so apple finds apple and # apple* but not applesauce. Smallest, fastest index with the # best relevance ranking. # porter Like unicode61 plus English stemming, so run also finds # running and ran. Small index, English focused, still no # substring matches. # Default is unicode61, the closest match to how Discord search behaves. # HAVEN_SEARCH_TOKENIZER=unicode61 # ── Reverse proxy ───────────────────────────────────────── # Whose X-Forwarded-For header to believe for the visitor's real address. # Unset: a proxy on this same machine only (in Docker or Podman, also the # container network). If your reverse proxy runs on another machine, put its # address here, or 1 for one hop (Cloudflare's proxy). Haven logs a [proxy] # line naming the address to use when it sees an untrusted proxy. # TRUST_PROXY=192.168.1.20