Agents
The agent is the part of Reporting that runs on your infrastructure. It holds database credentials, executes queries, renders documents, and delivers them. The control plane never touches your data.
Deployment​
Docker​
docker run -d --name rynko-agent \
--restart unless-stopped \
-e RYNKO_API_KEY=your_agent_key \
-v $(pwd)/config:/app/config \
-v $(pwd)/data:/app/data \
ghcr.io/delivstat/rynko-reporting-agent:latest
Or with docker compose, which is the better option once you have secrets and volumes to manage:
services:
agent:
image: ghcr.io/delivstat/rynko-reporting-agent:latest
restart: unless-stopped
environment:
RYNKO_API_KEY: ${RYNKO_API_KEY}
PG_PASSWORD: ${PG_PASSWORD}
volumes:
- ./config:/app/config
- ./data:/app/data
ports:
- "8080:8080" # local health check only
Archive (no Docker)​
For Windows servers and locked-down Linux hosts:
- Download and extract the release archive
- Edit
config/agent.yaml - Run
./start.sh(Linux) orstart.bat(Windows)
The archive bundles its own Node runtime. There is no JVM and no system-wide install.
rynko-reporting-agent/
├── bin/agent # agent binary (includes the rynko-run CLI)
├── config/agent.yaml # your configuration
└── data/ # SQLite metadata, template cache, generated documents
Configuration​
Everything lives in config/agent.yaml. Values may reference environment variables with ${VAR_NAME}, which is how credentials should be supplied.
server:
apiKey: ${RYNKO_API_KEY} # from agent registration
apiUrl: https://api.rynko.dev
port: 8080 # local health check port
datasources:
production-erp:
type: oracle
host: 10.0.1.50
port: 1521
serviceName: ERPDB.example.com
user: report_reader
password: ${ORACLE_PASS}
pool:
min: 2
max: 10
queryTimeout: 60000
distribution:
smtp:
host: smtp.company.com
port: 587
secure: true
user: [email protected]
password: ${SMTP_PASS}
from: [email protected]
fromName: "Rynko Reports"
database:
path: ./data/agent.db # agent-local SQLite metadata
storage:
type: filesystem
path: ./data/documents
retentionDays: 30 # local document retention
archive: false # also upload documents to Rynko for long-term storage
offline:
templateCachePath: ./data/templates
maxQueueSizeMb: 500
scheduling:
timezone: UTC
maxConcurrentRuns: 3
updates:
autoUpdate: false
Document retention and archiving​
Generated documents are written to the agent's local filesystem and swept after storage.retentionDays (a cleanup pass runs at startup and every six hours). The webapp's download button fetches them from the agent on demand, so recent reports are viewable without any object storage at all.
Set storage.archive: true to also upload each generated document to Rynko for long-term retention. An individual report can force this on regardless of the agent default.
Connectivity​
The agent opens one outbound HTTPS connection and holds it open as a server-sent events stream. Configuration changes, template updates, and run commands are pushed down it. Results and status are posted back over ordinary HTTPS.
This means:
- No inbound firewall rules. Nothing needs to reach the agent from outside.
- No VPN or IP allowlist.
- Egress to one host. If you filter outbound traffic, allow
api.rynko.devover 443.
If the connection drops, the agent reconnects with backoff. Scheduled runs continue against the local cache while it is down, and their results sync when it returns.
Security model​
Credentials never leave your network. Database passwords, SMTP passwords, and webhook URLs exist only in agent.yaml on your host. The control plane stores the connection shape — driver, host, port, database name — so the UI can show you what a datasource is, but never the secret.
Result sets never leave your network unless you distribute them. Query output goes straight into the local renderer. What the control plane records is metadata: run status, duration, row count, and any error.
Credentials pushed from the webapp are end-to-end encrypted. Distribution channel credentials entered in the UI are encrypted to the target agent's public key before transmission. Rynko cannot read them in transit or at rest.
Agent keys are pinned. Each agent's key has a fingerprint. If a key is used from an unexpected agent identity, the control plane raises an alert rather than silently accepting it.
Operating the agent​
Health​
The agent exposes a local health endpoint on server.port:
curl http://localhost:8080/health
Agent status, last heartbeat, and per-datasource connection pool health are also visible in Reporting → Agents in the webapp.
The CLI​
rynko-run executes a report and exits. It shares agent.yaml and the agent's connection pools, which makes it the right tool for system cron, Windows Task Scheduler, and CI pipelines.
rynko-run --list
rynko-run --report monthly-sales \
--params '{"region":"APAC","date_from":"2026-09-01"}'
rynko-run --report monthly-sales --dry-run # run the query, skip the document
rynko-run --report monthly-sales --no-distribute # generate, don't deliver
rynko-run --report monthly-sales --output ./out.xlsx
Reports are addressable by slug, short ID (rpt_a1b2c3d4), or UUID.
Upgrades​
Set updates.autoUpdate: true to let the agent update itself, or leave it off and pull a new image or archive on your own change schedule. Pin the image tag in production rather than tracking latest.
How many agents do I need?​
One agent can serve many datasources, so most sites need one. Add more when you have networks that cannot reach each other, want to isolate environments, or need to spread report load across hosts.
Your subscription tier caps the number of agents — see Limits & Quotas.