Copyright (C) 2026 Doan Luu Duc Tai This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . CENTRAL CONFIGURATION One root .env holds each installation's deployment settings and secrets. Public .env.example documents every supported key, public default, private placeholder, and comment. Hostnames remain public in generated pages, DNS, certificates, and URLs. Centralization is not secrecy or access control. cargo stack config, service initialization, and chat initialization preserve existing settings/secrets and append missing public defaults to the same .env. No second environment file. The shared Rust configuration library also reads defaults from .env.example, keeping older exports compatible. PUBLIC SETTINGS BASE_DOMAIN Root web/WKD domain. Derive www aliases from each configured host. SITE_HOST, GIT_HOST, SEARCH_HOST, WKD_HOST, CHAT_HOST Fully qualified DNS names; no scheme, path, or port. Set production HTTPS routes and canonical www redirects. CHAT_HOST also selects the exact trusted external chat origin. CHAT_LOCAL_HOST Development gateway hostname ending in .localhost. Default: chat.localhost. Browser identity files bind to this origin and local port. WEB_BIND Production publish address. Default :: serves IPv4/IPv6. Use 127.0.0.1 for isolated staging. Development always binds loopback. HTTP_PORT, HTTPS_PORT Caddy listeners and Podman published ports; defaults 80/443. HTTPS also publishes UDP for HTTP/3. Generated links include nonstandard HTTPS ports. Public certificate validation still needs standard external CA validation ports or alternative certificate/routing arrangements. Port settings do not configure DNS, firewall rules, or external forwarding. LOCAL_HTTP_PORT Local HTTP on 127.0.0.1; host HTTPS port is this value plus one. Caddy still listens on container ports 80/443. --port overrides one invocation. var/state.json retains installation/project names and image state. An explicit .env local port overrides the saved port. CGIT_UPSTREAM, SEARXNG_UPSTREAM, CHAT_UPSTREAM Proxy targets, e.g. cgit:8080, searxng:8080, chat:8080. Not bind settings. Bundled internal 8080 listeners and health checks remain image contracts. A changed target needs an actual service at that host/port. CHAT_BIND, CHAT_ORIGIN Direct development socket and exact browser origin. Defaults: 127.0.0.1:9080 and http://127.0.0.1:9080. Require loopback and an exact HTTP origin match. --bind overrides CHAT_BIND. Containers bind privately to 0.0.0.0:8080; trusted origin comes from CHAT_HOST/HTTPS_PORT or CHAT_LOCAL_HOST/LOCAL_HTTP_PORT. Identity files pin their origin. Editing these settings neither migrates encrypted identities nor grants access on another origin. BACKUP_RECIPIENT, BACKUP_PUBLIC_KEY Public OpenPGP fingerprint and project-relative public key path for encrypted exports. --recipient/--key override them. Keep the secret GnuPG key and revocation certificate outside the project. PRIVATE SETTINGS SEARXNG_SECRET Generated at first stack initialization; existing values preserved. CHAT_SETUP_TOKEN Generated by chat initialization or first startup. Authorizes only first owner registration, including after an explicit backend reset. Cannot recover a lost owner private key. RENDER AND APPLY Edit .env locally; never commit or publish it. See .env.example for exact keys. Validate hostnames, ports, sockets, fingerprints, and paths before use. Diagnostics never dump the config map or echo invalid .env contents. Render public deployment files without starting services: cargo stack config cargo stack config --production Output under var/local/ or var/production/: Caddyfile cgitrc web/ Templates use {{PUBLIC_KEY}} placeholders: infra/Caddyfile, infra/Caddyfile.local, infra/containers/cgit/cgitrc, first-party website HTML. Never run Caddy on unrendered templates. Podman mounts generated files. Public host/origin changes reach routes, www redirects, website links, cgit clone prefixes, and chat navigation. Local rendering uses /git, /search, and http://CHAT_LOCAL_HOST:LOCAL_HTTP_PORT for chat. Apply to existing local services: cargo stack up --local Production uses prebuilt management command/images: ./bin/stack up --production Running file servers can read rendered website updates. Listener, container environment, and loaded Caddy changes need the service update above. Restart direct local chat with cargo stack chat for new bind/origin/navigation settings. Reopen your identity file afterward, as after any chat restart. PUBLICATION AND LIMITS stack-config substitutes only explicitly allowlisted public values. {{CHAT_SETUP_TOKEN}} and other private/unknown placeholders fail instead of exposing values. Public pages/proxy config never receive a full environment dump. Chat receives the public allowlist plus CHAT_SETUP_TOKEN; other containers receive only declared secrets. Caddy needs rendered public config, not .env or private tokens. Git ignores .env, runtime files, local renders, exports, and tool caches. Source templates, commented example, validated defaults, and configuration implementation remain public. Full encrypted backups include the single .env; source-only releases exclude it. Personal content stays in source: copyright, author names, canonical contact, public keys/WKD hashes, repository metadata, GNU license links. Changing a hostname creates no new email identity and regenerates no WKD keys. Image digests, source hashes, fixed crypto/protocol/resource bounds remain reviewed reproducible code/config, not private deployment knobs.