1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai>
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 <https://www.gnu.org/licenses/>.
CENTRAL CONFIGURATION
Each installation has one root .env for deployment settings and secrets.
The published .env.example documents every supported setting with public
defaults, private placeholders, and comments. Hostnames are public information;
this arrangement centralizes configuration, not secrecy or access control.
Public values remain visible in generated pages, DNS, certificates, and URLs.
Existing installations keep their configured secrets and settings. Missing
public defaults are appended to the same .env by cargo stack config, service
initialization, or chat initialization. No second environment file is created.
The example is also the shared Rust configuration library's default source,
so missing public settings remain compatible with older exports.
PUBLIC SETTINGS
BASE_DOMAIN
Root web/WKD domain. www aliases are derived from each configured host.
SITE_HOST, GIT_HOST, SEARCH_HOST, WKD_HOST, CHAT_HOST
Fully qualified DNS names without schemes, paths, or ports. These
configure production HTTPS routes and their canonical www redirects.
CHAT_HOST also selects the exact trusted external chat origin.
CHAT_LOCAL_HOST
Dedicated development gateway hostname ending in .localhost. Default:
chat.localhost. Browser identity files bind to this origin and local port.
WEB_BIND
Production host publish address. Default :: serves IPv4 and IPv6. Use
127.0.0.1 for isolated staging; development mode always uses loopback.
HTTP_PORT, HTTPS_PORT
Production Caddy listener and Podman published ports. HTTPS also publishes
UDP for HTTP/3. Defaults are 80 and 443. Generated HTTPS links include a
nonstandard HTTPS port when configured. Ordinary public certificate
validation still needs the CA's standard external validation ports or an
appropriate alternative certificate/routing arrangement. Setting ports
alone does not configure DNS, firewall rules, or external port forwarding.
LOCAL_HTTP_PORT
Local Caddy HTTP port on 127.0.0.1. HTTPS host port is this value plus one.
Local Caddy still listens on container ports 80/443. --port overrides the
local port for that invocation. Existing installation/project names and
image state remain in var/state.json; an explicit .env local port takes
precedence over the previously saved port.
CGIT_UPSTREAM, SEARXNG_UPSTREAM, CHAT_UPSTREAM
Proxy connection targets such as cgit:8080, searxng:8080, and chat:8080. These are
addresses, not upstream bind settings. The bundled images' internal 8080
listeners and health checks remain image contracts. Changing a target
to another host/port requires an actual service at that address.
CHAT_BIND, CHAT_ORIGIN
Direct development socket and exact browser origin. Defaults:
127.0.0.1:9080 and http://127.0.0.1:9080. Direct development requires
loopback and an exact HTTP origin match. --bind overrides CHAT_BIND.
The container binds privately to 0.0.0.0:8080; its trusted origin comes
from CHAT_HOST/HTTPS_PORT or CHAT_LOCAL_HOST/LOCAL_HTTP_PORT instead.
Identity files pin their origin; editing these values does not migrate
encrypted identities or grant access on another origin.
BACKUP_RECIPIENT, BACKUP_PUBLIC_KEY
Public OpenPGP fingerprint and project-relative public key path used for
encrypted exports. --recipient and --key override them. The secret GnuPG
key and revocation certificate remain outside the project.
PRIVATE SETTINGS
SEARXNG_SECRET
Generated on first stack initialization. Existing values are preserved.
CHAT_SETUP_TOKEN
Generated by chat initialization or first stack startup. Used only to authorize first owner
registration, including a fresh registration after an explicit backend
reset. It cannot recover a lost owner private key.
RENDER AND APPLY
Edit .env locally. Never commit or publish it. Inspect the commented example
for exact keys. Hostnames, ports, socket addresses, fingerprints, and paths
are validated before use. Diagnostic formatting never dumps the config map.
Invalid environment-file syntax is reported without echoing its raw contents.
Render public deployment files without starting services:
cargo stack config
cargo stack config --production
Outputs are var/local/ or var/production/:
Caddyfile
cgitrc
web/
infra/Caddyfile, infra/Caddyfile.local, infra/containers/cgit/cgitrc, and the
first-party website HTML are templates using {{PUBLIC_KEY}} placeholders.
Do not run Caddy directly on an unrendered template. Podman mounts the generated
files. Public host/origin changes reach Caddy routes, www redirects, website
links, the cgit clone prefix, and the chat page's navigation. Local rendering
uses /git and /search paths and http://CHAT_LOCAL_HOST:LOCAL_HTTP_PORT for chat.
To apply changes to the existing services:
cargo stack up --local
Production uses its prebuilt management command and images:
./bin/stack up --production
Rendered website files can be read by an already running file server, while
listeners, container environment, and loaded Caddy configuration require the
service update above. Restart the local chat server with cargo stack chat to
load its new bind, origin, or public navigation settings. Reopen your identity
file afterward, as with any chat restart.
PUBLICATION AND LIMITS
The shared stack-config crate uses an explicit public allowlist for template
substitution. A {{CHAT_SETUP_TOKEN}} or other private/unknown placeholder
causes an error rather than publishing its value. Generated public pages and
proxy configuration never receive a full environment dump. Chat receives the public configuration allowlist plus CHAT_SETUP_TOKEN;
other containers receive only their declared service secrets. Caddy uses
rendered public configuration and does not need the .env or private tokens.
The root .env, runtime files, local render outputs, exports, and tool caches
remain ignored by Git. Source templates, the commented example, validated
defaults, and this configuration implementation are public. Full encrypted
backups include the single .env; source-only releases do not include it.
Personal content and attribution remain source content: copyright headers,
author names, canonical contact information, public key material/WKD hashes,
project repository metadata, and GNU license links. Changing a deployment
hostname does not create a new email identity or regenerate WKD keys.
Image digests, source hashes, and fixed crypto/protocol/resource bounds remain
reviewed reproducible code/configuration rather than private deployment knobs.
|