Architecture & services
Helpin Community runs as a single Docker Compose project. This page explains what each service does, which ports are exposed, and where your data lives, so you can plan capacity, networking, and backups.
How the pieces fit together
flowchart LR
subgraph Public["Your HTTPS reverse proxy"]
D["app.example.com"]
H["help.example.com"]
F["files.example.com"]
end
D --> FE["helpin-frontend :8085"]
H --> HC["helpin-helpcenter :8086"]
F --> G["garage :9005"]
FE --> API["helpin-api"]
HC --> API
API --> PG[("postgres")]
API --> R[("redis")]
API --> N["nats"]
API --> T["temporal"]
API --> G
W["helpin-worker"] --> PG
W --> T
API <--> AR["agent-runtime"]
AR --> ARW["agent-runtime-worker"]
ARW --> N
Only three ports are published, and all of them bind to 127.0.0.1 by default. Everything else talks over the private Compose network.
Services
Service | Role | Published port |
|---|---|---|
| Staff dashboard, plus the |
|
| Server-rendered public help center |
|
| S3-compatible object storage for attachments, images, and uploads |
|
| Application API, WebSockets, and agent event projection | Internal |
| Background jobs: indexing, sync, scheduled work | Internal |
| Agent Runtime API that plans and executes agent runs | Internal |
| Executes agent turns and tool calls | Internal |
| PostgreSQL 17 with pgvector. Holds four databases: Helpin, Runtime, Temporal, and Temporal visibility | Internal |
| Rate-limit counters and short-lived caches | Internal |
| NATS JetStream for real-time events between services | Internal |
| Durable workflow engine for long-running jobs | Internal |
| One-shot job that applies database migrations before the API starts | — |
| One-shot jobs that prepare Temporal | — |
Note: One-shot jobs exit with code
0when they succeed. That's expected, not a crash.
Built-in HTTPS proxy
On a public server with built-in HTTPS (the default), one more service runs, from compose.proxy.yaml:
Service | Role | Published port |
|---|---|---|
| Terminates HTTPS, gets and renews certificates, and routes the three public hostnames |
|
Caddy connects to helpin-frontend, helpin-helpcenter, and garage over a small private edge network, from a fixed address (EDGE_PROXY_IP). Helpin trusts forwarded client details from that address only. Its certificates live in the caddy_data and caddy_config volumes, which helpin backup includes. Installations that use their own proxy don't run this service or create the edge network.
Pinned infrastructure versions
Every image in a published bundle is pinned by digest, so an installation never changes underneath you.
Component | Version |
|---|---|
PostgreSQL + pgvector | 17 + 0.8.6 |
Redis | 7.2.16 |
NATS | 2.14.7 |
Temporal | 1.32.0 |
Garage | 2.3.0 |
Changing a version variable in .env does not upgrade Helpin. Use helpin upgrade, which verifies a tested upgrade path first.
Where your data lives
Volume | Contents |
|---|---|
| All four PostgreSQL databases |
| Object storage metadata and files |
| Redis persistence |
| JetStream streams |
| Agent execution scratch space, checkouts, and published artifacts |
Your .env file holds generated secrets and encryption keys. Stored credentials, such as AI keys, Git tokens, and SMTP passwords, can only be decrypted with those keys. Always back up .env together with the volumes. helpin backup does this for you.
What never leaves your server
There is no telemetry. Error reporting is off unless you set
SENTRY_DSNyourself.The chat widget snippet uses your own URLs and sends no analytics to Helpin.
AI requests go only to the providers you configure, using your own keys.
Network boundaries
Expose only your reverse proxy. Never publish PostgreSQL, Redis, NATS, Temporal, Agent Runtime, or the storage console to the internet, and never route /api/internal/ publicly. The public widget hostname only needs /widget/* and /sdk/*.
The single-node bundle has no storage redundancy. For fault tolerance, use off-host backups or an external, replicated S3-compatible store.
Was this article helpful?