Skip to main content

Agent Architecture

The agent runs on servers and reconciles expected state from the control plane.

Node Types

The agent supports two modes:
TypeFlagTraefikDescription
WorkerDefaultNoRuns containers only
Proxy--proxyYesHandles TLS and public traffic

State Machine

The agent uses a two-state reconciliation model:
┌─────────┐                         ┌────────────┐
│  IDLE   │───drift detected───────▶│ PROCESSING │
│ (poll)  │◀────────────────────────│  (no poll) │
└─────────┘    done/failed/timeout  └────────────┘

IDLE State

  • Polls the control plane every 10 seconds for expected state.
  • Compares expected state against actual state.
  • Transitions to PROCESSING when drift is detected.

PROCESSING State

  • Uses a snapshot of expected state without re-polling.
  • Applies one change at a time:
    1. Stop orphan containers with no deployment ID.
    2. Start containers in created or exited state.
    3. Deploy missing containers.
    4. Redeploy containers with the wrong image.
    5. Update DNS records.
    6. Update Traefik routes on proxy nodes.
    7. Update WireGuard peers.
  • Times out after 5 minutes.
  • Always reports status before returning to IDLE.

Drift Detection

Drift detection is deterministic and uses hashes:
  • Containers: missing, orphaned, wrong state, or image mismatch.
  • DNS: hash of sorted records.
  • Traefik: hash of sorted routes on proxy nodes.
  • WireGuard: hash of sorted peers.

Container Labels

The agent tracks managed containers with Podman labels:
LabelDescription
techulus.deployment.idLinks the container to a deployment
techulus.service.idLinks the container to a service
techulus.service.nameHuman-readable service name
Containers without techulus.deployment.id are treated as orphans and cleaned up.

Command Line Flags

FlagDefaultDescription
--urlRequiredControl plane URL
--tokenEmptyRegistration token, required on first run
--logs-endpointEmptyVictoriaLogs endpoint for log shipping
--proxyfalseRun as a proxy node

Build System

Agents can build container images directly from GitHub sources:
  1. Poll for pending builds.
  2. Claim the build to prevent duplicate work.
  3. Clone the repository using a GitHub App installation token.
  4. Run Railpack to generate a build plan, or use the existing Dockerfile.
  5. Build the image with BuildKit.
  6. Push the image to the registry.
  7. Update build status.
Build logs stream to VictoriaLogs in real time.

Work Queue

Agents also process queue items for operations that cannot be modeled purely as expected state:
TypeDescription
restartRestart a specific container
stopStop a specific container
force_cleanupForce remove containers for a service
cleanup_volumesRemove volume directories for a service
deployHandled through expected-state reconciliation

Proxy vs Worker Behavior

Proxy Node

  • Runs Traefik for TLS termination.
  • Receives Traefik routes from the control plane.
  • Handles public traffic and routes requests to containers over WireGuard.
  • Collects and ships Traefik access logs.

Worker Node

  • Does not run Traefik.
  • Receives empty Traefik route sets from the control plane.
  • Skips Traefik-related drift detection and reconciliation.
  • Keeps a lighter runtime footprint focused on container workloads.