Self-hosting
Run Runnel Server on your own infrastructure with Docker and Postgres, point your workers at it and keep it upgraded.
Runnel Server is the same queue, scheduler, API and dashboard that runs Runnel Cloud, packaged as one Docker image. It is open source under the Apache 2.0 licence. Teams self-host when their data must stay in their own network or region; for everything else, the cloud is less work. The SDKs, CLI and API are identical in both, so you can move between them without changing your jobs.
What you need
- Docker, or any platform that runs OCI images. The image is
runnel/server:2.8, about 60 MB. - PostgreSQL 15 or newer. We recommend 17, which Runnel Server has used in its own tests since 2.7.
- About 1 vCPU and 1 GB of memory per 2,000 runs a minute. The database does most of the work; give it fast disks.
- A domain with TLS in front of the server, for example
runnel.internal.example.
Starting with Docker Compose
This is a complete setup for a trial or a small team. For production, use a managed Postgres with backups instead of the container.
services:
runnel:
image: runnel/server:2.8
ports: ["8288:8288"]
environment:
DATABASE_URL: postgres://runnel:${POSTGRES_PASSWORD}@db:5432/runnel
RUNNEL_SECRET_KEY: ${RUNNEL_SECRET_KEY}
RUNNEL_PUBLIC_URL: https://runnel.internal.example
depends_on: [db]
db:
image: postgres:17
environment:
POSTGRES_USER: runnel
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes: ["pgdata:/var/lib/postgresql/data"]
volumes:
pgdata:export RUNNEL_SECRET_KEY=$(openssl rand -hex 32) POSTGRES_PASSWORD=$(openssl rand -hex 16)
docker compose up -d
docker compose exec runnel runnel-server admin create --email ops@yourcompany.exampleThe server runs its database migrations on start. The last command prints a one-time sign-in link for the first admin.
Configuration
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | yes | A Postgres connection string. The user needs to create tables in its database. |
RUNNEL_SECRET_KEY | yes | 32 random bytes as hex. Encrypts webhook secrets and signs sessions. Keep it safe and never change it casually. |
RUNNEL_PUBLIC_URL | yes | The address workers, the CLI and browsers use. Used in links and webhook payloads. |
RUNNEL_LOG_RETENTION | no | How long run logs are kept. Default '30d'. |
RUNNEL_SMTP_URL | no | For invitations and failure emails. Without it, invitations are shown as links. |
Warning Losing
RUNNEL_SECRET_KEYmeans every webhook endpoint secret has to be rotated and every user signs in again. Store it with the database credentials.
Pointing workers and the CLI at your server
Set RUNNEL_URL wherever you set RUNNEL_API_KEY. Everything else stays the same.
export RUNNEL_URL=https://runnel.internal.example
runnel login
runnel deploy --env productionWorkers connect out to the server, so they can run in another network as long as they can reach RUNNEL_PUBLIC_URL over HTTPS. The server never connects to the workers, except for push endpoints if you use serverless functions.
Upgrading and backups
Minor versions (2.7 to 2.8) can be upgraded in place: change the image tag and restart. Migrations are backwards compatible within a major version, so you can roll back the image if something looks wrong. Read the changelog before each upgrade; anything that needs a step from you is listed under “Upgrading”.
Back up Postgres the way you back up any other production database. The database is the only state; the server containers can be replaced at any time, and you can run two or more behind a load balancer for availability.
Support
The community helps on Discord and GitHub Discussions, and we answer there too. The Enterprise plan adds support for self-hosted installations: a private channel with our engineers, a four-hour response time for production incidents, upgrade reviews and help with sizing. See pricing or write to sales@runnel.example.