Skip to content

Deployment

gladsonsam edited this page Apr 13, 2026 · 6 revisions

Deployment

Requirements

  • Server: Docker and Docker Compose v2, or Rust + PostgreSQL (see Development).
  • Agent: Windows 10/11 (64-bit). Build on Windows, or cross-compile from Linux with cargo-xwin.

Docker (repository default)

The repo has one docker-compose.yml and one .env.example with the minimum variables. Copy it to .env, edit secrets, then run Compose (Compose reads .env automatically for variable substitution; server uses env_file: .env).

  • server uses network_mode: host (Linux) so mDNS (_sentinel._tcp) can reach your LAN. Docker’s default bridge does not forward that multicast.
  • db publishes PostgreSQL on 127.0.0.1:5432 only. The host-network server connects with DATABASE_URL pointing at 127.0.0.1.
cp .env.example .env
# edit .env
docker compose up -d

Pull the published image from GHCR (default image: in compose). To build the server image from the same repo:

docker compose up -d --build

The compose file sets both image: ghcr.io/gladsonsam/sentinel/server:latest and build:; --build rebuilds and tags that image locally.

Minimal .env keys (from .env.example)

Variable Purpose
POSTGRES_PASSWORD Postgres password (required).
ADMIN_PASSWORD First-run dashboard admin password.
AGENT_SECRET Shared secret Windows agents must use.
ENFORCE_HTTPS false for plain HTTP on port 9000; set true behind a TLS-terminating reverse proxy.

For LAN mDNS discovery and correct “add agent” hints, also set a non-localhost URL (see mDNS below).

URLs and ports

  • Dashboard and API: http://<docker-host>:9000 by default (LISTEN_ADDR, overridable in .env).
  • Agents (WebSocket): ws://<host>:9000/ws/agent with plain HTTP, or wss://…/ws/agent when TLS terminates in front of the server.

Health check

curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9000/healthz

Expect 200. The server image includes a Docker HEALTHCHECK on /healthz.

Docker image

Built from server/Dockerfile (multi-stage: frontend build, Rust release binary, Debian slim runtime). The dashboard static files are baked into /app/static.


mDNS (LAN discovery)

mDNS is on by default unless you set SENTINEL_MDNS=0 or SENTINEL_MDNS_DISABLE=1.

It needs a resolvable WebSocket URL for agents. Set one of:

  • PUBLIC_BASE_URL=https://your-host or http://192.168.1.10:9000 (HTTPS or HTTP; server derives wss:// / ws:// for the TXT record), or
  • SENTINEL_MDNS_WSS_URL=wss://host:port/ws/agent explicitly.

If neither is set, registration is skipped (warning in logs).

Variable When to set
SENTINEL_MDNS_PORT TLS on 443 in front of the app (e.g. Traefik). Default advertised TCP port is the server listen port (9000).
SENTINEL_MDNS_ADDRESSES Comma-separated LAN IPs if the host advertises the wrong interface.

Docker Desktop (Windows/macOS): host networking does not behave like Linux; LAN mDNS may still fail. Prefer a manual agent WebSocket URL and a correct PUBLIC_BASE_URL for your network.

Firewall: allow UDP 5353 (mDNS) on the server host where relevant.


Traefik (TLS) and mDNS on Linux

Plain bridge + Traefik labels without host networking: TLS and routing work, but mDNS from inside the container usually does not reach the LAN.

To use both Traefik (HTTPS on 443) and LAN mDNS, run the same stack shape as the default compose: network_mode: host on server, Postgres on 127.0.0.1, and attach Traefik labels to the server service so Traefik (on another Docker network) forwards to the host’s Sentinel port (default 9000).

  1. Create the external network Traefik uses (name may differ; match your Traefik stack):

    docker network create traefik
  2. Extend the labels on server (example; adjust host, entrypoint, cert resolver to your Traefik static config):

    labels:
      - traefik.enable=true
      - traefik.http.routers.sentinel.rule=Host(`your.domain.example`)
      - traefik.http.routers.sentinel.service=sentinel
      - traefik.http.routers.sentinel.entrypoints=websecure
      - traefik.http.routers.sentinel.tls=true
      - traefik.http.routers.sentinel.tls.certresolver=cloudflare
      - traefik.http.services.sentinel.loadbalancer.server.url=http://172.17.0.1:9000
    • Replace 172.17.0.1 with your Linux docker0 gateway if different (ip -br addr show docker0). Traefik must reach HTTP on Sentinel (plain HTTP on 9000 behind the proxy).
    • Do not set loadbalancer.server.scheme or loadbalancer.server.port in addition to server.url — Traefik rejects “scheme or port” when url is set.
    • With network_mode: host, omit traefik.docker.network on this service (the container is not attached to the traefik bridge).
  3. In .env, set for example:

    ENFORCE_HTTPS=true
    PUBLIC_BASE_URL=https://your.domain.example
    SENTINEL_MDNS_PORT=443
  4. If Traefik returns 404, the Host() rule must match the hostname in the browser (including www vs apex). If you get 502, the server.url IP/port is wrong for your host.

Agents should use wss://your.domain.example/ws/agent when the public URL is HTTPS.


Non-Docker

Run sentinel-server with DATABASE_URL and the same environment variables as in Configuration. Build the binary from the repo (cargo build -p sentinel-server --release) and serve static files from STATIC_DIR (defaults to ./static; the Docker image uses /app/static).

Home

Install and configure

Day to day

Integrations

Developers and security

Clone this wiki locally