Skip to content

Deployment

Talon is a Node.js daemon. The recommended production setup is a systemd service on a Linux host. A wake-only timer mode is available for low-traffic deployments.

  • Node.js 24+
  • npm
  • A Linux host with systemd
Terminal window
# build
npm install
npm run build
# apply migrations
npx talonctl migrate
# verify the setup
npx talonctl doctor

The deploy/install-service.sh script installs Talon as a systemd service:

Terminal window
sudo bash deploy/install-service.sh

This creates /etc/systemd/system/talond.service and enables it. The unit includes security hardening:

[Service]
NoNewPrivileges=true
PrivateTmp=true
SystemCallFilter=@system-service
ProtectSystem=strict
ReadWritePaths=/path/to/talon/data

To manage the service:

Terminal window
sudo systemctl start talond
sudo systemctl stop talond
sudo systemctl status talond
# view logs
journalctl -u talond -f

The service unit configures Restart=on-failure and RestartSec=5s. If the daemon crashes it restarts automatically. The daemon integrates with systemd’s watchdog heartbeat — if the process hangs without sending a heartbeat, systemd kills and restarts it.

The daemon listens for SIGTERM and SIGINT. On receipt it stops accepting new messages, waits for in-flight agent runs to complete (up to a configurable drain timeout), then exits cleanly.

For low-traffic deployments where you don’t want the daemon running 24/7, use a systemd timer:

# talond-timer.timer
[Unit]
Description=Run Talon daemon periodically
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Unit=talond-oneshot.service
[Install]
WantedBy=timers.target
# talond-oneshot.service
[Unit]
Description=Talon daemon (one-shot)
[Service]
Type=oneshot
ExecStart=/usr/bin/node /path/to/talon/dist/index.js --wake-mode
User=talon

In wake mode the daemon starts, processes the queue until it’s empty, then exits. The timer fires it every 5 minutes (configurable). Total idle resource usage is near zero between runs.

Docker v2 is now production-ready. See the Docker deployment guide for the complete setup.

FilePurpose
deploy/DockerfileMulti-stage daemon image with baked CLIs, tini init, and health checks
deploy/docker-compose.yamlProduction compose setup with security hardening and resource limits
Terminal window
# Quick start with docker compose
cp config/talond.example.yaml config/talond.yaml
# Edit with your API keys and channels
cp deploy/.env.example .env
# Fill in your secrets
docker compose -f deploy/docker-compose.yaml up -d

The image runs as non-root (1000:1000), drops all Linux capabilities, and comes with Codex CLI and Gemini CLI pre-installed — no host CLI setup needed.

All runtime config lives in talond.yaml. Point the daemon at it:

Terminal window
node dist/index.js --config /path/to/talond.yaml

Or set TALON_CONFIG in the environment. The daemon resolves all ${ENV_VAR} references at startup from the environment and from a .env file in the working directory.

Use talonctl doctor to verify your deployment before starting:

Terminal window
npx talonctl doctor

This checks Node version, required directories, config validity, database connectivity, and external references.