Quickstart (self-hosted)¶
From nothing to the first login. The commands below are the ones the project itself deploys and verifies with; nothing here is a paraphrase.
What you need¶
- Docker with Docker Compose (the
docker composeplugin syntax is used throughout). The deployment target is Docker Compose on a VM or in an LXC container; the project itself is verified in an LXC container. - A host inside the network you want to inventory. The Network Map Kit
runs on the host network (
network_mode: host) with theNET_RAWcapability and nothing more — no privileged mode. A scanner that cannot see the L2 segment gets no ICMP replies and cannot read the kernel ARP cache, so the host itself has to sit on the segment it scans. - Ports.
8090— the platform (core).8101— the Network Map Kit; it is on the host network, so this is a port of the host. PostgreSQL is published on127.0.0.1:5432only, and only because the host-networked kit needs it. - Memory and disk. The compose file sets no CPU or memory limits, and the repository contains no sizing figures. Backups are written as a stream (dump → compression → encryption → storage) precisely so that no intermediate file needs space on the executor; the storage volume is where the space goes.
About
compose.yamlThis is the file the project itself runs and verifies, and it is the one the README's quick start uses. Besides the core, PostgreSQL and the kits it also brings up the database servers into which copies are restored for verification, under the
verifyprofile: none runs until you start it. The comments in the file say which is which.
1. Get the source¶
The address is the one the product shows on its Overview screen as "the source of this version".
2. Create .env¶
Three variables are required, and the compose file refuses to start without
the first two (${AG_SECRET_KEY:?AG_SECRET_KEY must be set}):
| Variable | Why | How to generate |
|---|---|---|
AG_SECRET_KEY |
Encrypts stored secrets (database passwords, SSH keys). Without it the core does not start — there is no "runs without encryption". Losing it means losing every stored secret. | openssl rand -base64 32 |
AG_MODULE_SECRET |
Every kit's token is derived from it, so both sides compute it and it is stored nowhere. Without it a kit would trust whoever called it first — and the network kit's port is on the LAN it scans. | openssl rand -hex 32 |
AG_ADMIN_PASSWORD |
Password of the first administrator (AG_ADMIN_USER, default admin). If left empty, the password is written once to the core's log at first start. |
— |
Back up AG_SECRET_KEY somewhere that is not the installation. The
Configuration page has every other variable.
AG_IMAGE_REPO and AG_TAG are commented out on purpose: the compose file
of the release you checked out already names the Docker Hub namespace and
the tag, so an installation runs what its tree says and an upgrade is git
pull away. Uncomment AG_TAG only to pin a version while the tree moves
on, and AG_IMAGE_REPO only after building the images yourself.
2a. Behind a reverse proxy (optional)¶
The platform speaks plain HTTP and expects TLS to be the proxy's. It must
own the root of a hostname — https://ahegao.example.internal/, not
https://host/ahegao/ — because the interface uses absolute paths. A worked
example with Traefik is compose.traefik.yaml in the repository; the
three .env lines the platform needs are AG_TRUST_PROXY=1,
AG_SECURE_COOKIES=1 and AG_PUBLIC_URL, plus AG_HOSTNAME for the
proxy's routing rule. Add COMPOSE_FILE=compose.yaml:compose.traefik.yaml
to .env as well: then every docker compose command below includes the
overlay without you naming two files each time. Behind the proxy the core
stays published on 127.0.0.1:<AG_PORT> only — from outside the host the
proxy is the single door, and the loopback binding is what the
host-networked Network Map Kit reaches the core through. Behind the proxy
its X-Forwarded-For reaches the sign-in limiter, a forged one is discarded
by the proxy, and the session cookie carries Secure.
3. Start¶
Each schema is created and migrated when the core and each kit start. The core refuses to start if the schema is newer than what the build knows — a downgrade would lose data.
4. First login¶
Open http://<host>:8090. The first administrator is created at first start
with AG_ADMIN_USER and AG_ADMIN_PASSWORD. If you did not set the
password, it is in the core's log, written once:
Set AG_SECURE_COOKIES=1 only when the platform is behind HTTPS: otherwise
the browser will not return the session cookie.
5. Kits and AG_MODULES¶
The core knows which kits exist only from AG_MODULES — a comma-separated
list of id=address pairs. The compose file's default names every kit in
the release, and .env.example shows the same list commented out — set it
only to leave a kit out or point one at another address, because a line set
in .env replaces the default entirely and stops following releases:
- A kit is enabled by having its service in the compose file and its
id=addressinAG_MODULES. The two go together: the core proxies the browser to the kit at that address and reads the kit's manifest from it at start. - The Network Map Kit is reached through
host.docker.internalbecause it is on the host network; every other kit is on the private compose network. - The core reads a kit's manifest when it starts. A manifest can be re-read
without a restart:
POST /api/modules/{id}/probe.
Which kits a user actually sees is then a matter of rights: a user with no grant on a kit does not see it in the menu at all.
6. Where copies go¶
Copies (backups) are written by a kit into a storage and measured by the
core. On first start the installation already has one: default · local,
on /srv/artifacts — the artifacts volume the compose file mounts into the
core and into every kit that writes copies. A target that names no storage
writes there, and every kit keeps to its own directory inside it
(postgresql/<target>/<database>/<timestamp>…), so one storage serves them
all. Nothing has to be configured before the first backup.
To keep the copies on the host rather than in a Docker volume, replace the volume with a bind mount in both services — the core measures, the kit writes, and each must see the same directory:
services:
core:
volumes:
- /var/lib/ahegao/artifacts:/srv/artifacts
kit-postgresql:
volumes:
- /var/lib/ahegao/artifacts:/srv/artifacts
The path inside the containers stays /srv/artifacts; AG_ARTIFACTS_DIR
changes it if you must. A path is always the path as the containers see
it: a storage on a directory that only the executor can reach is shown by
the core as "not visible from here", which is a state, not an error.
Additional storages of kind nfs and smb are whatever the administrator
mounted — the platform mounts nothing itself. s3 buckets need no mount at
all, and are on the free level.
6a. Check servers for verification¶
A backup is not made until it has been restored, and restoring needs a
PostgreSQL to restore onto — never the one the copy came from. The compose
file ships one per supported major, postgres-verify-14 … postgres-verify-18,
under the verify profile: none of them runs until you say so, because
five idle database engines is the cost that makes people switch verification
off.
Open the PostgreSQL Kit's Verification screen: one card per major, all grey. Pick the version your databases run and start that server on the host:
Within a minute the card turns green and the server is in the pool; nothing to register, no password to enter — the compose file gave the kit and the server the same account. A copy restores forward, never backward, so one server of the newest major you run is enough to check everything older. To stop paying for it:
The card turns red ("Offline") and stays so until you press Forget on it. Your own check servers, anywhere the kit can reach, go into Custom verification servers on the same screen.
7. Check the installation (optional)¶
A smoke test ships with the source. It is read-only: it signs in with the credentials you give it, asks the platform and every configured kit how they are, and changes nothing — no rows, no files, no containers. Run it from the directory with the source, against the address you use yourself:
AG_BASE=http://127.0.0.1:8090 AG_ADMIN_PASSWORD='…' sh tests/smoke.sh
# behind a proxy with your own certificate:
AG_BASE=https://backup.example.org AG_INSECURE=1 AG_ADMIN_PASSWORD='…' sh tests/smoke.sh
It reports what it found — the platform answers, the login works, each kit is
online and healthy, the storages are visible and are themselves, the check
servers are listed — and exits non-zero if anything is wrong. Needs curl
and python3 on the machine you run it from.
Things that bite¶
docker compose restartdoes not upgrade anything. It restarts the containers you already have; a new version arrives only withdocker compose pullfollowed bydocker compose up -d.AG_SECRET_KEYis required, and that is not a formality. Replacing it without re-encrypting does not break the core, but marks such secrets as "does not open with this key" — see them before a backup fails, not after.- The scan profile defaults to
politeon purpose: a development network must not be knocked over.AG_NET_ALLOW_PUBLIC=0refuses to scan anything outside RFC 1918 — a typo in a prefix is the difference between sweeping your lab and sending traffic towards the internet.