Every part of Binions runs as an ordinary systemd service, so you administer it with the same systemctl and journalctl commands you already use for the rest of your Linux host. There is nothing exotic to learn: the platform is a set of focused background services (we call them daemons), each one a normal systemd unit, all living on a single machine. This page is the operator’s reference for starting, stopping, inspecting, and reloading those units — and for understanding the safety net systemd gives you for free.
Good to know. Binions is single-host by design. There is no cluster controller, no orchestration layer, and no special CLI you must use to manage services — just stock systemd on the one machine where Binions is installed. If you know
systemctl, you already know how to operate Binions.
Binions ships as twelve long-running daemon services. Each one does a single job and runs under its own systemd unit named binions-<name>.service:
| Unit | What the daemon does |
|---|---|
binions-logger | Collects structured log events from every daemon and writes them to disk |
binions-database | Runs database reads and writes on behalf of the platform |
binions-playbook | Matches incoming events to your playbooks and drives each step |
binions-mailbox | Sends and receives email |
binions-aiinjector | Talks to AI models for extraction and generation |
binions-webhookcaller | Calls outbound web APIs and webhooks |
binions-datatransporter | Moves files and data between storage backends |
binions-traefiklinker | Keeps the HTTP edge in step with your routes |
binions-scheduler | Fires time-based and cron-style triggers |
binions-dataanaliser | Aggregates and analyses event data |
binions-showman | Coordinates interactive and routing flows |
binions-modbus | Reads and writes industrial hardware over MODBUS |
Every one of these units is built to the same template, so once you understand one, you understand them all:
Type=notify service. The daemon tells systemd the moment it is genuinely ready — not just launched — so systemctl start only returns once the service can actually do work.<name>svc (for example, the mailbox daemon runs as mailboxsvc). No daemon runs as root, and none can read another’s files.NoNewPrivileges=yes, ProtectSystem=strict, ProtectHome=yes, PrivateTmp=yes, a system-call filter, and memory ceilings. A daemon can touch only the handful of paths it needs.redis-binions-<name>.service, that holds just that daemon’s state — its transactional outbox and idempotency keys. Daemons never share a Redis instance, so one busy service cannot crowd out another.All twelve daemons are grouped under a single target unit, binions.target, so you can act on the whole platform at once (each daemon is bound to it with PartOf=). A thirteenth tool, binions-cliconsole, is an on-demand command-line program, not a service — you run it when you want it, and it does not appear in the list of long-running units.
Alongside the daemons sit a few supporting units that the platform manages for you:
binions-traefik.service — the HTTP/HTTPS edge that fronts your public routes.binions-minio.service — the built-in S3-compatible object store used for backups and file data.binions-jaeger.service — the bundled trace collector and UI (LAN-only).binions-crl-refresh.service and its .timer — keep the licence revocation list current.binions-pending-release-drain.service and its .timer — housekeeping for licence tokens.You drive a single daemon with the five commands you already know. Use the unit name from the table above — here, the mailbox daemon as the example:
# Is it running, and is it healthy?
systemctl status binions-mailbox.service
# Start / stop / restart one daemon
sudo systemctl start binions-mailbox.service
sudo systemctl stop binions-mailbox.service
sudo systemctl restart binions-mailbox.service
# Make it start automatically at boot
sudo systemctl enable binions-mailbox.service
Because each daemon depends on its own Redis companion, systemd starts and stops that companion for you — you operate the binions-<name> unit and the matching redis-binions-<name> follows automatically.
To act on the whole platform at once, target the group unit instead of naming twelve services:
# Stop, start, or restart every daemon together
sudo systemctl stop binions.target
sudo systemctl start binions.target
sudo systemctl restart binions.target
# Enable the whole platform to start on boot (the installer already does this)
sudo systemctl enable binions.target
# See which daemons the target currently pulls in
systemctl list-dependencies binions.target
Restart one, not all. Day to day, you rarely need to bounce the whole platform. Restarting a single daemon affects only its own work; the others keep running and simply queue any events destined for the daemon that is briefly down, then catch up when it returns.
Start with systemctl status for the one-screen summary, then drop into journalctl for detail. The status command shows whether a unit is active, how long it has been up, its main process, and the last few log lines:
systemctl status binions-playbook.service
For the full log of a unit, follow it live, scope it to a time window, or filter by severity:
# Everything this daemon has logged, newest at the bottom
journalctl -u binions-playbook.service
# Follow new log lines as they happen
journalctl -u binions-playbook.service -f
# Only the last 15 minutes
journalctl -u binions-playbook.service --since "15 min ago"
# Only errors and worse
journalctl -u binions-playbook.service -p err
The journal is excellent for “is this unit healthy right now?” questions. When you need to follow a single piece of work as it hops between daemons, Binions also writes richer, structured logs to disk — see Logs for reading those by correlation id.
Most configuration changes take effect with a restart, which is the safe default. A restart is fast and clean: the daemon finishes anything in flight, the framework persists its outbox to its private Redis, and the freshly started process picks up the new settings.
| What you changed | What to do |
|---|---|
A daemon’s own settings (its application.toml — bind ports, batch sizes, memory caps, tracing) | Restart that one daemon |
| A secret or credential file | Replace the file, then restart the affected daemon |
The systemd unit itself (sandbox directives, Restart=, limits) | systemctl daemon-reload, then restart the daemon |
| Log rotation behaviour | Handled automatically — the logger is signalled to reopen its files |
If you edit a unit file (or a drop-in under its .d directory), systemd needs to re-read its own configuration before your change is visible:
# After editing a unit file or drop-in
sudo systemctl daemon-reload
sudo systemctl restart binions-traefiklinker.service
When in doubt, restart. Binions daemons are designed to restart cleanly and quickly. If you have changed a daemon’s configuration, a plain
systemctl restartof that daemon is always the correct, predictable way to apply it — there is no risk of a half-applied config.
The per-daemon user and sandbox are what keep a problem in one service from becoming a problem for the whole host. They are not optional extras you configure — they are baked into every unit. Here is what each directive means in practice when you are operating the platform:
| Directive | What it means for you operationally |
|---|---|
User=<name>svc | The daemon runs as an unprivileged, purpose-built account. Files it creates are owned by that account, and it cannot read other daemons’ secrets. |
NoNewPrivileges=yes | The process can never gain extra privileges, even via a setuid binary. A compromised daemon stays unprivileged. |
ProtectSystem=strict | The whole filesystem is read-only to the daemon except for the few writable paths it genuinely needs. |
ProtectHome=yes / PrivateTmp=yes | Home directories are hidden, and the daemon gets its own private /tmp that no other process can see. |
SystemCallFilter=… | The kernel refuses any system call outside the small set the daemon is allowed to make. |
MemoryHigh / MemoryMax | The daemon has a soft and a hard memory ceiling, so a runaway service is throttled and capped rather than starving the host. |
The practical upshot for an operator: if a daemon ever misbehaves, the blast radius is its own user, its own files, and its own memory budget. The rest of your host — and the other eleven daemons — carry on. The deeper rationale lives in Service hardening.
Binions does not rely on you to notice when a service falls over — systemd brings it back automatically. Two complementary mechanisms work together.
First, every daemon sets a Restart= policy so systemd relaunches it after a crash. The exact policy varies by daemon, depending on how critical continuous availability is:
Restart=always — used for the most central daemons (such as the database, AI-injector, playbook, and MODBUS services). These come back whenever they exit, for any reason.Restart=on-failure with a short RestartSec — used elsewhere (for example the logger and the Traefik edge). These restart on a fault but respect a clean, intentional stop.Second, the units run with an active watchdog (WatchdogSec=30). A healthy daemon sends systemd a heartbeat roughly every ten seconds — about a third of the watchdog interval — but only while it is genuinely making progress and not deadlocked. If a daemon hangs and stops sending heartbeats, systemd notices the missing pulse and recycles it, even though the process is technically still alive. The watchdog is the catch for “stuck but not crashed”; Restart= is the catch for “exited.”
# See how many times a unit has been restarted, and why it last stopped
systemctl show binions-aiinjector.service \
-p NRestarts -p Restart -p WatchdogUSec -p ExecMainStatus
A climbing restart count is a signal. Occasional restarts are normal and self-healing. But if
NRestartskeeps rising for one daemon, that daemon is unhealthy — read its journal withjournalctl -u <unit> -p errand check the relevant troubleshooting page below.
The units know how to start themselves in the right order, so a fresh boot brings the whole platform up cleanly without intervention. This works because the installer enables binions.target (the single boot entry); its Wants= lists every daemon, so one enabled target pulls the whole stack up at boot — you never enable the daemons one by one. The dependency chain then follows the data each daemon needs:
binions-<name> unit declares Requires and After on its redis-binions-<name> companion, so a daemon never starts before the store that holds its state.binions-database declares an After= and Wants= dependency on the unit for whatever backend is configured — for example, postgresql.service on a PostgreSQL install. The exact dependency unit therefore varies with the backend in use (postgres, sqlite, mysql, mongo, or mssql), but the guarantee is the same in all cases: the database engine is ready before the daemon that fronts it.binions-playbook is ordered After binions-database, because playbooks routinely read and write through it.Because Type=notify means “ready” rather than merely “launched,” each dependency is genuinely available before the next service begins — not just spawned. You can see the resulting ordering at any time:
# Visualise the start-up tree for the whole platform
systemctl list-dependencies binions.target
# Confirm the ordering systemd computed for one daemon
systemctl list-dependencies --after binions-playbook.service
If the platform ever comes up in an unexpected state after a reboot, this dependency chain is the first thing to inspect: a daemon stuck in activating is almost always waiting on a dependency that has not yet reported ready. Daemon start-up problems walks through diagnosing exactly that.