One-command deploy
Deploy NetTact's server (server-lite) and agent with Docker Compose. The server ships with the web console built in; the agent is a pure outbound client (it listens on no ports) that dials out to the server.
Supported: Docker Engine 24+ with bundled Compose v2 (the
docker composesubcommand). The old standalonedocker-compose(v1) is untested.
For the full configuration reference, see: Server configuration · Agent configuration.
1. One-command install script (Linux)
On a Linux host with nothing but Docker installed, a single command runs the whole deployment — it downloads the compose assets, generates .env and the secret, brings up the server, waits for it to become healthy, logs in automatically and issues an enrollment token, brings up the agent and confirms it enrolled, then prints the console URL and the first-run password:
curl -fsSL https://d.nettact.org/install.sh | bashIf you would rather read it before running it:
curl -fsSL https://d.nettact.org/install.sh -o install.sh
less install.sh
bash install.shCommon options (bash install.sh --help lists them all):
| Option | What it does |
|---|---|
--port <n> | Console port (written to .env as NETTACT_HTTP_PORT, default 12450) |
--lite-version / --agent-version <tag> | Pin the image versions (default latest) |
--server-only | Deploy the server only |
--host-network | Have the agent monitor the host network (Linux; trade-offs in section 9) |
--auto-update | Check daily for a new Agent image and restart the Agent automatically. |
-y / --yes | Non-interactive (on a non-first run where the password cannot be retrieved automatically, it prints the manual fallback command instead) |
The script is idempotent: re-running it leaves an existing .env, secret and data volumes untouched, so it is safe to re-run after a partial failure. Every step that fails prints the reason plus the manual fallback command for it.
The source is owned by the server-lite repository at deploy/install.sh. From the NetTact superproject root, run run ./deploy/install.sh. The script uses local docker-compose.yml and .env.example files when they exist in the current directory, otherwise it downloads them from https://d.nettact.org. Set NETTACT_DIST_BASE_URL to use an internal mirror.
The sections below are the manual version of that same flow, and also the reference for understanding each step and for troubleshooting.
2. Quick start (Docker Compose)
Run this in the directory that contains docker-compose.yml and .env.example (the repository root):
# 1) Prepare the configuration
cp .env.example .env
# Review .env as needed (port, image versions, ...); you do not need to set an
# admin password — one is generated automatically on first run
# 2) Start the server first
mkdir -p secrets
touch secrets/agent_enroll_token # placeholder: this file must exist before the first `up`
docker compose up -d server
# 3) Read the auto-generated admin password from the logs (printed only once)
docker compose logs server # look for username / password in the "NetTact first run" block
# 4) Open the console and log in
# http://localhost:12450 (the port comes from NETTACT_HTTP_PORT in .env)
# Log in with the credentials from the previous step, then change the password under Settings
# (or run `docker compose exec server nettact-lite passwd -db /data/nettact.db`)
# 5) On the console's "Agent" page, issue a one-time enrollment token and write it to the secret file
printf '%s' '<paste the token generated in the console>' > secrets/agent_enroll_token
# 6) Start the agent (it enrolls itself and starts reporting)
docker compose up -d agentWhen this finishes, the agent appears in the console's agent list and starts reporting metrics, and the server can hand monitoring targets down to it.
Enrollment tokens are valid for 60 minutes by default and can be used only once. After a successful enrollment the agent stores its credentials in its own data volume, so restarts no longer need a token. Details in Agent configuration — enrollment flow.
About HTTPS and session cookies
By default (-secure-cookie auto) the session cookie carries the Secure flag only when the server itself is running TLS, so a plain-HTTP deployment lets you log in out of the box. For production we recommend either:
- configuring TLS on the server (see Enabling HTTPS below), or
- putting a TLS-terminating reverse proxy in front (Caddy/Nginx/Traefik) and setting
NETTACT_SECURE_COOKIE=truein.env(the browser side is https, so the cookie should carrySecure).
3. Checking status
docker compose ps # containers and health (server should be healthy)
docker compose logs -f server # server logs
docker compose logs -f agent # agent logs (enrollment, reporting)
curl -f http://localhost:12450/api/v1/healthz # health check, returns {"status":"ok"}The health check distinguishes "the process is up" from "the service is usable": it actually requests /api/v1/healthz, so it will not turn healthy while DB migrations or the listener are not ready, and depends_on makes the agent wait until the server is healthy.
4. Upgrading
The server and the agent are released independently, so upgrading means changing the matching version variable. Back up before upgrading (section 5).
# Back up nettact-data first (see the next section)
# Edit .env: set NETTACT_LITE_VERSION / NETTACT_AGENT_VERSION to the target versions
docker compose pull # pull the new images
docker compose up -d # recreate the containers on the new images; volumes are kept
docker compose ps # confirm it is healthy againData lives in named volumes, so configuration and history survive container recreation and host reboots, and no second identity is created. If something breaks after an upgrade, set the version variables in .env back to the old version and run pull && up -d again; if the data schema has already changed, restore from a backup (below).
5. Backup and restore
The persistent data you need to back up:
- volume
nettact-data→ the server'snettact.db(including the-wal/-shmsidecar files) - volume
agent-data→ the agent's identity (agent.key), credentials (agent.json) and send buffer (wal.db*)
To get a consistent snapshot, stop the service before backing it up (this avoids copying a half-written SQLite file):
# Back up the server data
docker compose stop server
docker compose cp server:/data ./backup-$(date +%F) # or use the volume approach below
docker compose start serverYou can also archive the named volume directly (the volume name is <project name>_nettact-data; docker volume ls will show it):
docker compose stop server
docker run --rm \
-v "$(basename "$PWD" | tr '[:upper:]' '[:lower:]')_nettact-data":/data \
-v "$PWD":/backup alpine \
tar czf /backup/nettact-data-$(date +%F).tar.gz -C /data .
docker compose start serverTo restore: stop the service → extract the tar back into the volume → start the service. The agent works the same way (volume agent-data; restoring it avoids having to enroll again).
6. Uninstalling
# Stop and remove the containers but keep the data volumes (data is still there on the next `up`)
docker compose down
# Remove everything, including the data volumes (irreversible!)
docker compose down -v7. Enabling HTTPS (optional)
The server can serve HTTPS/WSS natively. Once you have a certificate:
- Create
certs/in the project directory and puttls.crtandtls.keyin it. - In the
serverservice indocker-compose.yml, uncomment the./certs:/certs:romount and the-tls-cert /certs/tls.crt -tls-key /certs/tls.keylines. - Also switch the healthcheck to its https variant (the commented-out line is already in the compose file): with TLS enabled the listener is TLS-only, so a plaintext http health check can never pass, the server stays unhealthy forever, and the agent (
depends_on: service_healthy) never starts. docker compose up -d server. The console is now onhttps://, and the agent connects tohttps://server:12450(the certificate must match the internal compose hostname, or setNETTACT_AGENT_TLS_INSECURE=trueas a stopgap).
-tls-cert and -tls-key must be supplied together, otherwise the server refuses to start (so it can never silently fall back to plaintext).
8. Deploying a remote agent on another machine (optional)
The agent in the compose file only monitors the machine the server runs on. To monitor other machines (another server, the NAS at home, a Windows PC at the office), run a separate agent on that machine pointing at the server's externally reachable address. Prerequisites:
- that machine can reach the server (
http(s)://<server host>:<NETTACT_HTTP_PORT>); - you have issued a fresh one-time enrollment token for it on the console's "Agent" page (one token per agent).
Merged one-command Agent installer (Linux / macOS / Docker):
Native Linux or macOS:
curl -fsSL https://d.nettact.org/agent/install.sh | sudo bash -s -- \
--server-url http://<server host>:12450 --token '<one-time token>'Docker:
curl -fsSL https://d.nettact.org/agent/install.sh | bash -s -- --docker \
--server-url http://<server host>:12450 --token '<one-time token>'Append --auto-update to either command to enable daily Agent updates.
Choose permissions while you are at it (optional): add --permissions to fix what this Agent may collect up front, instead of editing a config file and restarting after the fact. The console's "Agent" page generates the whole command for the preset you pick.
curl -fsSL https://d.nettact.org/agent/install.sh | sudo bash -s -- \
--server-url http://<server host>:12450 --token '<one-time token>' \
--permissions 'probe.icmp,probe.dns,probe.http,probe.tcp,host.cpu.read,host.memory.read'Without the argument the Agent uses its built-in default set. Note that a list replaces that set rather than adding to it — see the permission reference for the full list and per-platform availability.
The one-command Docker install monitors the host by default: on a Linux Docker host, --docker starts the container with --network host --pid host --cap-add NET_RAW --user 0:0 and bind-mounts the host's /proc and /sys read-only, so what you see is the machine rather than the container. To monitor the container itself, add --container-view.
Three caveats:
- This applies to the one-command installer only. The manual
docker runbelow and the agent service in the compose file still default to the container's own view; add the same settings yourself (the compose file carries the full block, commented out). - "Host" means the machine running the Docker daemon. Under Docker Desktop that is its Linux VM, not your Windows or macOS system — a Linux container has no way to observe the outer OS.
- Disk metrics are the exception and still describe the container's filesystem even in host view; see the permission reference.
Docker (Linux, manual):
docker run -d --name nettact-agent --restart unless-stopped \
-e NETTACT_AGENT_SERVER_URL=http://<server host>:12450 \
-e NETTACT_AGENT_ENROLL_TOKEN='<one-time token>' \
-e NETTACT_AGENT_DATA_DIR=/agent-data \
-v nettact-agent-data:/agent-data \
ghcr.io/nettact/nettact-agent:latestBare binary (Windows / Linux): download nettact-agent for your platform from the agent repository's releases and write a YAML config file (see agent/agent.example.yaml):
# nettact-agent.yaml (next to the binary, or at the platform's conventional path; chmod 600 recommended)
server_url: http://<server host>:12450
enroll_token: "<one-time token>"Then just start nettact-agent (it auto-discovers nettact-agent.yaml in the working directory). The token is spent as soon as enrollment succeeds and can be removed from the config file. For every configuration option (data directory, permission policy, probe target access control, ...) see Agent configuration.
9. Letting the agent monitor the Docker host (optional, Linux)
By default the agent in the compose file sees the container's own interfaces and metrics. To monitor the real network of the Docker host, enable network_mode: host on the agent service in docker-compose.yml (adding pid: host if needed).
Note: with network_mode: host the agent leaves the compose network, so the service name server no longer resolves — you must also change NETTACT_AGENT_SERVER_URL to an address reachable on the host, for example http://127.0.0.1:12450 (the port must match NETTACT_HTTP_PORT in .env).
This is a deliberate trade-off, not a requirement for the probes: the Linux agent in this build only runs DNS/HTTP/TCP/NAT probes and host metrics, needs no NET_RAW and no privileges, and the container runs as non-root.
10. Troubleshooting
- The agent restarts in a loop / never enrolls: usually
secrets/agent_enroll_tokenis empty or the token has expired (60 minutes by default). Issue a new one in the console, write it to that file, and rundocker compose up -d agent. - You get logged out immediately after logging in: see About HTTPS and session cookies in section 2 — switch to HTTPS or put a reverse proxy in front (and set
NETTACT_SECURE_COOKIE=true). - The server stays unhealthy: check
docker compose logs serverfor DB migrations or a port conflict, and make sure nothing else is usingNETTACT_HTTP_PORT. - Changes to .env have no effect:
.envis only read onup/pull, so rundocker compose up -dto recreate the containers. - The console will not open even though the API works (placeholder page / 503): the server downloads its frontend from a GitHub release at runtime, so the first start needs internet access. If the download fails it serves a placeholder page and retries in the background; on an isolated network, point
NETTACT_WEBUI_BASE_URLat a mirror (see Server configuration).