Configuration¶
Everything is configured through the environment — .env next to the compose
file — and read by core/app/config.py and by each kit's config.py. Nothing
is configured in code.
AG_SECRET_KEY: losing it means every stored secret is unreadableDatabase passwords, SSH keys and every other secret are encrypted at rest with this key. There is no recovery path without it. Replacing the key without re-encrypting does not break the core: it shows such secrets as "does not open with this key", and every job that needs one of them fails. There is no re-encryption procedure in the platform yet — the repository names this explicitly as not done.
Keep a copy of
AG_SECRET_KEYoutside the installation, and keep your licence key separately from the installation as well: a rebuilt host with neither is an installation nobody can open and a licence nobody can prove.What reaches the containers, and what does not
compose.yamlpasses variables to each service explicitly, in itsenvironment:block; it has noenv_file:. A variable that.env.examplelists but the compose file does not pass (for exampleAG_TICKorAG_PG_COMPRESS) is read by the code, but setting it in.envhas no effect until you add it to the service'senvironment:. The tables below say for each variable whether the compose file passes it.
Set in the interface, not here¶
Some things are decided once per installation and live on the Configuration screen rather than in this file, because they are read from the database and changed while the platform runs.
The timezone. What a schedule means by "03:00", and when a rota hands
over. An IANA name — Europe/Moscow — with today's offset shown beside it;
an offset alone is not a timezone, because it does not know when the clocks
change. Changing it takes with it every schedule and every team that was
still on the previous one: those took it because it was the installation's
answer, not because anybody chose it. Anything told something else stays
where it is, and the screen says how many will move before you press Save.
A schedule may still name its own, and an offset in that box is refused:
UTC+3 is not a zone, and a schedule that carries one runs at a different
hour from the one the screen shows.
The environments. What a resource may be marked as. A new installation
starts with prod, stage, test and dev, and the list is editable:
an estate with preprod or qa says so. Renaming one renames it on every
resource that carries it — otherwise one environment would quietly become
two, and the old one would appear in the table and in no filter. One that
resources still carry cannot be deleted, and the refusal says how many.
The platform's own copy. A pg_dump of this platform's database — the
targets, the rules, the schedules, the secrets and the record of every copy
ever made — written to a volume of its own on a cadence you set, keeping as
many as you say. Free on every level: an installation that had to buy the
ability to keep its own configuration is not one anybody should trust with
anybody else's.
A copy on this machine survives a mistake, not a fire. Download the newest
one and take it somewhere else, and keep AG_SECRET_KEY with it — the
secrets inside are encrypted with that key, and a copy without it is a copy
of ciphertext. The list says which key each copy opens with, by name.
How deep the history goes. Every measurement the platform and its kits take is kept in three resolutions, each for as long as you say: full detail (days), one row an hour (months), one row a day (years). Older detail is folded into the next resolution rather than deleted, and a summary carries the smallest and largest value it was made from — a mean on its own would hide exactly the spike that made somebody open the graph.
The defaults are two days, ninety days and two years, and the screen shows what the history occupies now and what it will settle at before you change anything. It is worth a look: full detail is what the table is mostly made of, and eight days of it on a modest estate is well over a gigabyte, while two years of daily summaries is a fraction of that.
Required¶
| Variable | What it does | If not set |
|---|---|---|
AG_SECRET_KEY |
Key for encrypting secrets at rest (С1.1 in the specification). Generate with openssl rand -base64 32. Passed to core. |
The core does not start. The compose file refuses with AG_SECRET_KEY must be set. |
AG_MODULE_SECRET |
The one installation secret from which each kit's token is derived, so both sides compute it and it is stored nowhere. Generate with openssl rand -hex 32. Passed to core and to every kit. |
Nothing starts. The compose file refuses with AG_MODULE_SECRET must be set, and the core and each kit refuse on their own as well, saying how to make one — without it a kit would trust whoever called it first, and the network kit's port is on the LAN. |
Signing in¶
Optional, and the defaults are the ones described on the
Security page. The first four are passed by the compose file and read by the core.
AG_INSECURE_TRUST_FIRST_CALLER is read by the core and by every kit, and
the compose file does not pass it: if you must set it, add it to each
service's environment:.
| Variable | What it does | Default |
|---|---|---|
AG_LOGIN_MAX_FAILS |
Failed sign-ins allowed for one login inside the window, after which the answer is 429 with a Retry-After. |
10 |
AG_LOGIN_MAX_FAILS_ADDRESS |
The same for one source address. Much larger on purpose: an office behind one NAT is a single address for everybody in it. | 100 |
AG_LOGIN_WINDOW |
The window, in seconds. It slides — the wait is until the oldest failure in it ages out — and a correct password clears the count. | 900 |
AG_TRUST_PROXY |
Whether X-Forwarded-For is believed. Set it to 1 behind a reverse proxy, where otherwise every request arrives from the proxy and the whole installation shares one address's budget. Leave it off when there is no proxy: a header anybody can set would let anybody be any address. |
0 |
AG_INSECURE_TRUST_FIRST_CALLER |
Set to yes to start without AG_MODULE_SECRET, restoring the old behaviour where a kit trusts the first token it is shown. Defensible on one machine where nothing but the core can reach the kits, and nowhere else. |
unset |
First administrator¶
| Variable | Default | What it does | Passed by compose |
|---|---|---|---|
AG_ADMIN_USER |
admin |
Login of the first administrator, created once on an empty installation. | yes (core) |
AG_ADMIN_PASSWORD |
(empty) | Password of the first administrator. If empty, it is written once to the core's log at first start. | yes (core) |
Database and ports¶
| Variable | Default | What it does | Passed by compose |
|---|---|---|---|
AG_DB_NAME |
adminguide |
Name of the shared PostgreSQL database. | used to build AG_DATABASE_URL and to configure postgres |
AG_DB_USER |
ag |
Database user. | same |
AG_DB_PASSWORD |
ag |
Database password. The default is ag; set your own. |
same |
AG_DB_PORT |
5432 |
Host port PostgreSQL is published on, loopback only. Change it when the host already runs a PostgreSQL of its own; the Network Map Kit reaches the database through this port because it is on the host network. | port mapping of postgres, kit-net |
AG_DATABASE_URL |
built from the three above | The connection string the core and every kit actually read. Set by the compose file per service. | yes |
AG_PORT |
8090 |
Port of the platform's web interface on the host. | port mapping of core |
AG_IMAGE_REPO |
adminguide1, set in .env.example |
The Docker Hub namespace the images are pulled from: adminguide1/ahegao-kit is the core, adminguide1/ahegao-kit-<kit> a kit. Set it to your own namespace after building from source with tools/images.sh. |
image: of every service |
AG_TAG |
the release version, set in .env.example |
The image tag every service runs. Pin it to a version; latest moves. The compose file has no fallback for this variable or for AG_IMAGE_REPO: unset, docker compose refuses and names it. |
image: of every service |
AG_ARTIFACTS_DIR |
/srv/artifacts |
Where the default storage default · local is created on first start, as seen from inside the core. Only if the directory is visible from the core; the compose file mounts the artifacts volume there. |
no |
AG_NET_PORT |
8101 |
Port of the Network Map Kit. The kit is on the host network, so this is a host port. | yes (kit-net) |
AG_<KIT>_KIT_PORT — one per kit in the compose file, e.g. AG_PG_KIT_PORT, AG_NEXUS_KIT_PORT |
8102 and up |
Ports of the other kits on the private compose network. Each is handed to its kit as AG_<KIT>_PORT. Must match the address in AG_MODULES. |
yes |
AG_MODULES |
every kit this release ships (see Quickstart) | Which kits are deployed: id=address,id=address. The core contains no kit name of its own — this list is the list of kits. |
yes (core) |
AG_CORE_URL |
http://core:8090 (kit-net: http://127.0.0.1:8090) |
Where a kit finds the core. Set by the compose file per kit. | yes |
Licence¶
| Variable | Default | What it does | Passed by compose |
|---|---|---|---|
AG_LICENSE_KEY |
(empty) | The licence key. Usually installed through the interface; can be given here. Absent means the free level — nothing phones home. | yes (core) |
AG_LICENSE_PUBKEY |
(empty) | Public half of the signing pair. In a release build it is baked into config.RELEASE_PUBKEY; the override is for development and is not a security boundary — what forbids swapping it is the licence, not the code. |
yes (core) |
Secrets in HashiCorp Vault (optional)¶
Without these, secrets live in the platform's own store and are opened with the installation key — the default, and it works with nothing else deployed. With them, a secret can be a pointer into Vault: the row holds a path, the value is read at the moment of use and not cached, so a rotation in Vault takes effect from the next job.
| Variable | Default (compose) | What it does |
|---|---|---|
AG_VAULT_ADDR |
(empty) — secrets stay in the platform's own store | Vault address. |
AG_VAULT_TOKEN |
(empty) | A plain token. A development arrangement; not a production one. |
AG_VAULT_ROLE_ID, AG_VAULT_SECRET_ID |
(empty) | AppRole credentials — what production should use: an eternal token is exactly what Vault exists to avoid. |
AG_VAULT_CA |
(empty) | Your own certificate authority, if it is your own. 0 disables verification and says so at every start. |
AG_VAULT_NAMESPACE |
(empty) | Vault Enterprise only. |
Any of the Vault credentials can be given through a file instead:
AG_VAULT_TOKEN_FILE, and the same _FILE spelling for the others. A secret
in an environment variable is a secret in docker inspect.
A Vault that is down does not stop the platform from starting: secrets kept locally still open, and pointers say why they cannot.
Network Map Kit¶
| Variable | Default | What it does | Passed by compose |
|---|---|---|---|
AG_NET_PROFILE |
polite |
Traffic budget: polite, normal, fast. polite by default on purpose. |
yes |
AG_NET_ALLOW_PUBLIC |
0 |
Refuse to scan anything outside RFC 1918 unless 1. |
yes |
AG_NET_MAX_TARGETS |
8192 |
Hard ceiling on targets per scan, which no profile can exceed. | no — read by the kit, not passed by the compose file |
AG_NET_MAX_SOCKETS |
768 |
Hard ceiling on concurrent sockets. | no |
AG_NET_PROBE_PORTS |
33 ports (shells, web, databases, caches, brokers, cluster services) | The TCP ports knocked on during discovery for addresses that answered neither ICMP nor ARP. Also settable per run in the interface. | no |
PostgreSQL Kit¶
| Variable | Default | What it does | Passed by compose |
|---|---|---|---|
AG_PG_RATE_MIB |
0 (no limit) |
Ceiling on dump read rate, MiB/s. For a database somebody is using, set a number: a backup that takes production down gets switched off together with the backups. | yes |
AG_PG_COMPRESS |
6 |
Whether the stream is compressed: 0 — no, anything above — yes. |
no |
AG_PG_DUMP_TIMEOUT |
21600 (6 h) |
How long to wait for one dump, in seconds. A hung backup is worse than a failed one: the failed one reports itself. | no |
The kit reads more knobs than .env.example lists — AG_PG_CONNECT_TIMEOUT,
AG_PG_BINDIR, AG_PG_SSLMODE (default require) — in
kits/postgresql/app/config.py. The same is true of every other kit; the
authoritative list for a kit is its app/config.py.
Other¶
| Variable | Default | What it does | Passed by compose |
|---|---|---|---|
AG_TICK |
15 |
How often, in seconds, the platform looks at its schedules and cleans up after dead executors. | no |
AG_POLL |
3 |
How often, in seconds, a kit asks the core for work. | no |
AG_METRICS_EVERY |
60 |
How often the core measures what it depends on: the database, storages, kits, agents, its own queue. Separate from AG_TICK because none of that changes every fifteen seconds. |
no |
AG_LOG_LEVEL |
info |
Log level of the core and kits. | yes |
AG_SECURE_COOKIES |
0 |
Set to 1 only behind HTTPS: otherwise the browser will not return the session cookie. |
yes (core) |
AG_PUBLIC_URL |
http://localhost:<AG_PORT> |
The address the platform is visible at from outside. Used for links inside messages: an "acknowledge" link pointing at http://core:8090 is useless to somebody reading it on a phone. |
yes (core) |
AG_SESSION_TTL |
2592000 (30 days) |
Session lifetime in seconds. Read by the core; not in .env.example. |
no |
Storage paths inside containers¶
Not environment variables, but part of the deployment contract:
| Path | Where | What |
|---|---|---|
/srv/artifacts |
core and every kit that writes copies |
The artifacts volume: where copies are written by kits and measured by the core. One volume, two mounts. |