Every Binions daemon stands on a handful of shared supporting services, and they all run on the same single host. The daemons do the visible work — sending email, calling APIs, running queries, moving files, talking to AI models — but underneath them sits a small set of infrastructure pieces that carry events between daemons, store relational data, expose HTTPS to the outside world, hold uploaded objects, and record traces. This page explains what each one is, which daemon relies on it, and why it all lives on one machine.
Good to know. There is nothing to install or wire up separately here. These services come with the platform, are provisioned automatically, and talk to the daemons over
localhost— no cluster, no external broker, no cloud account. You only ever need to know they exist when you are reading logs or tuning the host.
Binions is event-driven. Daemons never call each other directly — they publish and consume small messages (we call them events) on a fast internal bus, and they keep their own private state. A few supporting services make that possible and add the things a real platform needs — a database, a web edge, object storage, and tracing. Each supporting service runs as its own background service under systemd, exactly like the daemons themselves, and each is locked down to a dedicated user and a tight filesystem sandbox.
The five pieces below, plus one small licensing helper, are the entire foundation:
| Redis | Internal event bus + each daemon’s private state store (one dedicated instance per daemon) | Every daemon | 127.0.0.1 + a private Unix socket, one port per daemon |
| Database | Relational or document database for structured business data (PostgreSQL by default; SQLite, MySQL/MariaDB, MongoDB, and MSSQL also supported) | database-service | Depends on the backend; default PostgreSQL on 127.0.0.1:5432 |
| Traefik | HTTP edge / reverse proxy — terminates TLS, routes inbound traffic | traefiklinker-service | Public HTTPS edge; admin API on 127.0.0.1:8080 |
| MinIO | S3-compatible object storage for files and large payloads | datatransporter-service | 127.0.0.1:9000 (S3 API) |
| Jaeger | Distributed tracing collector and viewer | Every daemon (optional) | 127.0.0.1:4317 (receiver), UI on :16686 |
| Licence refresh | Hourly job that refreshes the certificate-revocation list | The licensing system | Outbound fetch only |
Redis is the single most important supporting service: it is both how the daemons talk to each other and where each daemon keeps its private state. Binions uses Redis Streams as an append-only event log — a daemon publishes an event, and any daemon that cares about it reads it back through a consumer group at its own pace. Events are not lost when they are delivered, so the platform can recover and replay rather than drop work under load.
Crucially, Binions does not use one big shared Redis. Each daemon gets its own dedicated Redis instance, running as a separate background service named redis-binions-<name>.service (for example redis-binions-logger). That instance holds three things for its daemon:
Giving every daemon its own instance keeps them isolated: one busy daemon can never starve another of memory, and each can be tuned, backed up, or restarted on its own. Each instance listens only on the loopback address and a private Unix socket, is password-protected, and writes an append-only file to disk so its state survives a restart.
# A daemon's [redis] block in application.toml — loopback only, password from a file.
[redis]
host = "127.0.0.1"
port = 6390
password_file = "/opt/binions/logger-service/secrets/redis.password"
[stream]
name = "events:logs"
consumer_group = "logger-service"
block_ms = 200
One bus, many mailboxes. Think of the streams as a shared noticeboard the daemons read and write, and each daemon’s private Redis as its own locked drawer. Coordination happens on the noticeboard; nothing reaches into another daemon’s drawer.
When a playbook needs to store or query structured data — customers, invoices, line items, anything that fits in tables or documents — that data lives in a database managed by database-service, the one daemon that owns the database connection, runs your queries safely, and turns the results into events the rest of the platform can use. Playbooks never connect to a database directly.
PostgreSQL is the default bundled backend. On a standard install the database is called binions and listens only on the loopback address, so it is never exposed to the network:
# database-service [postgres] block — local only, dedicated user.
[postgres]
host = "127.0.0.1"
port = 5432
database = "binions"
username = "binions_sql"
password_file = "/opt/binions/database-service/secrets/postgres.password"
PostgreSQL is not the only option. database-service can be configured to connect to any of five backends:
All five backends expose the same playbook verbs, so a playbook written against PostgreSQL works unchanged if you later switch to a different backend. For the full configuration matrix and backend-specific connection options, see database-service and Storage & data transfer.
Traefik is the platform’s front door. It is a reverse proxy that listens for inbound web traffic, terminates TLS (so connections are encrypted with HTTPS), and forwards each request to the right daemon inside the host. This is what lets an external system — a web form, a payment provider, a partner’s API — reach an automation running on your machine.
You do not edit Traefik’s routing by hand. Routes are published programmatically by traefiklinker-service: when a playbook needs to receive web traffic, that daemon writes the matching route into Traefik’s watched configuration directory and Traefik picks it up automatically. Traefik runs under its own restricted user and exposes its management API only on the loopback address, so the routing engine itself is never reachable from outside.
# Traefik entry points. The network-facing ones listen on your configured
# bind address; the management API stays on loopback. Ports are fixed defaults.
entryPoints:
traefik: # management API — loopback only
address: "127.0.0.1:8080"
web: # HTTP — redirects to HTTPS
address: "<bind-address>:8081"
web-acme: # ACME http-01 challenge (Let's Encrypt), when used
address: ":80"
websecure: # main HTTPS edge — TLS terminated here
address: "<bind-address>:8443"
traefik-admin: # Traefik dashboard
address: "<bind-address>:8444"
minio-admin: # MinIO console
address: "<bind-address>:8445"
showman-edge: # Showman operator hub
address: "<bind-address>:8446"
providers:
file:
directory: "/opt/binions/traefiklinker-service/config/dynamic"
watch: true # traefiklinker writes routes here; Traefik reloads live
Beyond the main HTTPS edge, the same Traefik process publishes the platform’s bundled operator tools on their own dedicated entry points: the Traefik dashboard on :8444, the MinIO console on :8445, and the Showman hub on :8446. All of them are TLS-encrypted and authenticated. For the complete map of edge and loopback ports, see Network requirements.
Certificates, handled for you. Traefik can obtain and renew real TLS certificates from Let’s Encrypt once your host has a public DNS name and the firewall allows inbound traffic. Until then it serves a built-in self-signed certificate, so HTTPS works out of the box on your local network.
MinIO is a private, S3-compatible object store. It gives your automations somewhere to keep files and large payloads — attachments pulled from a mailbox, reports a playbook generates, anything too big to sit comfortably inside an event — using the same API conventions as Amazon S3, but entirely on your own host. Nothing is sent to a cloud provider.
MinIO is the default backend for datatransporter-service, the daemon that uploads and downloads objects on a playbook’s behalf. Out of the box the daemon talks to MinIO on the loopback address and stores into a default bucket; you can point it at any other S3-compatible endpoint if you prefer.
# datatransporter-service [minio] block — the default object-storage backend.
[minio]
endpoint_url = "http://127.0.0.1:9000"
region = "us-east-1"
credentials_file = "/opt/binions/datatransporter-service/secrets/minio.password"
default_bucket = "binions-data-transport"
force_path_style = true
MinIO writes its objects to a single data directory on the host and ships with a small web console for browsing buckets. For the playbook verbs that move data in and out, see datatransporter-service.
Because a single automation can hop through several daemons, it helps to see the whole journey in one place. Jaeger is a distributed-tracing tool that does exactly that. Every event carries a correlation id, and any daemon can export timing information (called spans) tagged with that id. Jaeger stitches the spans together so a complete playbook run — trigger, every step, every daemon involved — shows up as one traceable timeline.
Tracing is entirely optional and off by default at the level of each daemon. A daemon only sends traces if its configuration contains an [otel] block pointing at the collector; remove that block and the daemon simply logs as usual with no tracing overhead.
# Optional [otel] block — present means "export traces to Jaeger".
# Remove it and the daemon stops tracing entirely.
[otel]
endpoint = "http://127.0.0.1:4317"
sample_rate = 1.0
Jaeger receives traces on the loopback address and offers a web UI for searching and visualising them. For how to turn tracing on and read a trace, see Monitoring & tracing and Observability.
Binions licences can be revoked — for example if a licence is withdrawn — and the platform checks against a certificate-revocation list (CRL) when it validates a licence. A small scheduled job, binions-crl-refresh, keeps that list current: roughly once an hour it fetches the latest signed revocation list and saves it locally. If the fetch fails (say the host is briefly offline), it quietly keeps the copy it already has, so a hiccup never breaks anything. You never run this yourself; it is part of how the licensing system stays trustworthy. For how licences themselves work, see Security & hardening.
All of the above — every daemon, every per-daemon Redis instance, the database service, Traefik, MinIO, and Jaeger — runs on a single Linux machine. This is a deliberate design rule:
localhost. Services reach each other on the loopback address or a Unix socket, so there is no network hop between a daemon and its Redis, and far less to misconfigure or expose.If you outgrow the hardware, you scale up — more CPU, RAM, or disk on the same host — rather than spreading across machines. That keeps operations simple and predictable, which is the whole point. For the bigger picture of how the daemons and these services fit together, see the Architecture overview.
The numbers in code blocks are defaults. The ports and paths shown above are the out-of-the-box loopback bindings; they are there so you recognise them in logs and config, not because you need to change them. The whole platform is provisioned and wired together for you at install time.