Skip to content

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 compose plugin 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 the NET_RAW capability 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 on 127.0.0.1:5432 only, 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.yaml

This 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 verify profile: none runs until you start it. The comments in the file say which is which.

1. Get the source

git clone https://gitlab.com/adminguide_pub/ahegao-kit.git
cd ahegao-kit

The address is the one the product shows on its Overview screen as "the source of this version".

2. Create .env

cp .env.example .env          # set AG_SECRET_KEY, AG_MODULE_SECRET,
                              # AG_ADMIN_PASSWORD

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

docker compose pull
docker compose up -d

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:

docker compose logs core

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:

AG_MODULES=net=http://host.docker.internal:8101,postgresql=http://kit-postgresql:8102,…
  • A kit is enabled by having its service in the compose file and its id=address in AG_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.internal because 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-14postgres-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:

docker compose --profile verify up -d postgres-verify-17

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:

docker compose stop postgres-verify-17

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 restart does not upgrade anything. It restarts the containers you already have; a new version arrives only with docker compose pull followed by docker compose up -d.
  • AG_SECRET_KEY is 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 polite on purpose: a development network must not be knocked over. AG_NET_ALLOW_PUBLIC=0 refuses to scan anything outside RFC 1918 — a typo in a prefix is the difference between sweeping your lab and sending traffic towards the internet.