Modern, lightweight, self-hosted infrastructure automation
667
Modern, lightweight, self-hosted infrastructure automation by OneSystems GmbH.
OneRun runs Ansible playbooks from Git with a clean UI, live logs, encrypted credentials, schedules, and notifications — a practical alternative to heavier orchestration stacks. One image covers everything from a single container (Lite) to Postgres and remote runners (Standard / Scale).
| Vendor | OneSystems GmbH |
| Product | onesystems.ch/produkte/onetools/onerun |
| License / shop | my.onesystems.ch/store/onetools/onerun |
| Support | Submit a ticket |
| Image | onesystems/onerun on Docker Hub |
OneRun ships as one Docker image. Without a license key the instance runs as Community. Activate a Pro key under Administration → License to unlock additional features.
| Community | Pro | |
|---|---|---|
| Projects, tasks, inventories, schedules | ✓ | ✓ |
| Git repositories & encrypted key store | ✓ | ✓ |
| Local runner (in-process, max 2 parallel) | ✓ | ✓ |
| Live / raw logs, secret masking, simulation | ✓ | ✓ |
| Notifications (SMTP, ntfy, Nextcloud Talk, …) | ✓ | ✓ |
| Users, MFA, RBAC | ✓ | ✓ |
| Lite (SQLite) / Standard (Postgres) | ✓ | ✓ |
| Remote / Docker runners (Scale) | ✓ | |
| API tokens & task webhooks | ✓ | |
| OpenAPI / Swagger UI | ✓ | |
| OpenID Connect (SSO) | ✓ | |
| Git webhooks (auto sync / trigger) | ✓ | |
| Execution profiles | ✓ | |
| Config backup UI (scheduled YAML + age secrets) | ✓ | |
| Support bundle | ✓ |
CLI backup / restore remains available in both editions. Order or renew Pro at the shop.
docker pull onesystems/onerun:1.2.0
Tags: <version> and 1.0 (releases do not use latest).
The image includes the API, admin UI, ansible-core, and ansible-galaxy. Collections and roles are installed at run time from requirements.yml (or instance defaults), not baked into the image.
Same product and image — only persistence and where jobs execute change.
| Mode | Typical use | Database | Runner |
|---|---|---|---|
| Lite | Homelab, few jobs | SQLite on a volume | Built-in (same process) |
| Standard | Regular use, several projects | PostgreSQL | Local (and remote with Pro) |
| Scale | Teams, more parallelism | PostgreSQL | Runner pool + optional Redis (Pro) |
Switch by configuration (ONERUN_POSTGRES_ENABLED / Postgres env, runner token, Redis URL).
Migration: Lite → Standard without reinstall (same master key, backup, then onerun migrate-sqlite-to-postgres). Standard → Scale by registering remote runners (Pro).
services:
onerun:
image: onesystems/onerun:1.2.0
user: "1000:1000"
command: ["serve"]
environment:
TZ: Europe/Zurich
ONERUN_ENV: production
ONERUN_PUBLIC_URL: https://onerun.example.com
ONERUN_MASTER_KEY: "change-me-to-a-long-random-secret!!"
ONERUN_ADMIN_EMAIL: [email protected]
ONERUN_ADMIN_PASSWORD: "change-me-strong-password"
ONERUN_ADMIN_NAME: Administrator
ONERUN_TRUSTED_PROXIES: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
volumes:
- onerun_data:/data
ports:
- "8091:8080"
volumes:
onerun_data:
docker compose up -d
| URL | Description |
|---|---|
/ | Web UI |
/setup | First-run wizard (if no admin yet) |
/api/health | Health check |
/api/swagger | OpenAPI / Swagger UI (Pro, signed-in users only) |
/metrics | Prometheus scrape (only with ONERUN_METRICS_TOKEN, see below) |
The bootstrap admin from ONERUN_ADMIN_* is created only when no users exist. Changing those variables later does not update an existing account. Passwords must have at least 12 characters and must not be a known default.
services:
postgres:
image: postgres:17-alpine
environment:
POSTGRES_USER: onerun
POSTGRES_PASSWORD: "change-me"
POSTGRES_DB: onerun
volumes:
- postgres_data:/var/lib/postgresql/data
onerun:
image: onesystems/onerun:1.2.0
user: "1000:1000"
command: ["serve"]
depends_on:
- postgres
environment:
TZ: Europe/Zurich
ONERUN_ENV: production
ONERUN_PUBLIC_URL: https://onerun.example.com
ONERUN_MASTER_KEY: "change-me-to-a-long-random-secret!!"
ONERUN_ADMIN_EMAIL: [email protected]
ONERUN_ADMIN_PASSWORD: "change-me-strong-password"
ONERUN_POSTGRES_ENABLED: "true"
POSTGRES_HOST: postgres
POSTGRES_PORT: "5432"
POSTGRES_USER: onerun
POSTGRES_PASSWORD: "change-me"
POSTGRES_DB: onerun
POSTGRES_SSLMODE: disable # production default is `require`; set `disable` only for a non-TLS database on an isolated network
volumes:
- onerun_data:/data
ports:
- "8091:8080"
volumes:
onerun_data:
postgres_data:
command: ["runner"]: onerun-runner:
image: onesystems/onerun:1.2.0
user: "1000:1000"
command: ["runner"]
# Required on images that still probe :8080 (runner has no HTTP server).
healthcheck:
disable: true
environment:
ONERUN_URL: http://onerun:8080
# Plain http is only OK on an isolated Docker network:
ONERUN_RUNNER_ALLOW_INSECURE: "true"
ONERUN_RUNNER_TOKEN: "paste-token-here"
ONERUN_RUNNER_LABELS: docker,remote
ONERUN_DATA_DIR: /data
volumes:
- onerun_runner_data:/data
Without disabling (or updating) the healthcheck, Swarm marks the task unhealthy and restarts it in a loop.
Scheduling: Tasks with empty runner labels can be claimed by any online runner (the local one usually wins). To send jobs to this agent, set the task’s runner labels to match ONERUN_RUNNER_LABELS (e.g. docker, remote). The local runner only has the local label.
Optional Redis (wake queue): set a strong REDIS_PASSWORD, point ONERUN_REDIS_URL at redis://:<password>@redis:6379/0, and set ONERUN_REDIS_HMAC_SECRET in production.
| Command | Purpose |
|---|---|
serve (default) | HTTP API + web UI + local runner |
runner | Remote / Docker agent (Pro; ONERUN_URL, ONERUN_RUNNER_TOKEN) |
backup <path> | Create backup archive (excludes master.key, workspaces/, cache/, tmp/) |
restore <path> | Restore from backup (archive contents are validated; no symlinks, no path traversal) |
migrate-sqlite-to-postgres | Lite → Standard data migration |
keys | Key / crypto helpers |
help | Usage |
docker compose exec onerun onerun backup /tmp/onerun-backup.tar.gz
docker compose run --rm onerun migrate-sqlite-to-postgres --dry-run
Admin → System → Configuration backup:
ONERUN_BACKUP_DIR (Compose volume /backup)config/*.yaml — readable configuration without secret valuessecrets.age — credentials / tokens encrypted with a dedicated backup passphrase (age)age -d -o secrets.json /backup/onerun-config-…/secrets.age
ONERUN_MASTER_KEY)Every secret variable (ONERUN_MASTER_KEY, ONERUN_ADMIN_PASSWORD, POSTGRES_PASSWORD, ONERUN_SMTP_PASSWORD, ONERUN_REDIS_URL, ONERUN_REDIS_HMAC_SECRET, ONERUN_METRICS_TOKEN) can alternatively be read from a file via <NAME>_FILE (e.g. ONERUN_MASTER_KEY_FILE=/run/secrets/onerun_master_key for Docker/Swarm secrets). The plain variable wins when both are set.
| Variable | Description | Default |
|---|---|---|
TZ / ONERUN_TIMEZONE | Timezone | Europe/Zurich |
ONERUN_ENV | development / production. In production, known default secrets are refused and one-time codes are never echoed in API responses. | production |
ONERUN_DEV_OTP_ECHO | Echo verification / reset codes in API responses (development only; never in production) | false |
ONERUN_LOG_FORMAT | text (default, Portainer/docker-friendly) or json | text |
ONERUN_HOST | Listen address | 0.0.0.0 |
ONERUN_PORT | Listen port inside the container | 8080 |
ONERUN_PUBLIC_URL | Public base URL (links, OIDC redirect base) | http://localhost:8091 |
ONERUN_DATA_DIR | Persistent data (DB, caches, known_hosts, …) | /data |
ONERUN_BACKUP_DIR | Scheduled config backups | $ONERUN_DATA_DIR/backups |
ONERUN_MASTER_KEY | Encryption key for secrets (required, non-default in production) | — |
ONERUN_VERSION | Version label (set at image build) | image build |
ONERUN_UPDATEHUB_ENABLED | Show UpdateHub update hint in the UI (false to disable) | true |
ONERUN_TRUSTED_PROXIES | Comma-separated CIDRs trusted for X-Forwarded-* | empty |
ONERUN_COOKIE_SECURE | Secure session cookie | true when ONERUN_ENV=production and ONERUN_PUBLIC_URL starts with https:// (a warning is logged otherwise) |
ONERUN_METRICS_TOKEN | Bearer token for GET /metrics; without it the endpoint returns 404 (admins with a session can always scrape) | empty (disabled) |
ONERUN_SESSION_TTL | Session lifetime | 12h |
ONERUN_SESSION_COOKIE | Cookie name | onerun_session |
ONERUN_MAX_PARALLEL_RUNS | Instance-wide parallel runs (local runner hard-capped at 2) | 2 |
ONERUN_RETENTION_DAYS | Run/log retention | 30 |
ONERUN_KEEP_WORKSPACE_ON_FAILURE_HOURS | Keep failed workspaces (hours; 0 = delete immediately) | 24 |
ONERUN_MAX_RUN_TIMEOUT_SEC | Global timeout cap (0 = no cap) | 86400 |
ONERUN_DEFAULT_COLLECTIONS | Pre-warm Galaxy collections (none / empty = off) | ansible.posix,community.general |
ONERUN_MAX_BODY_BYTES | Max request body size | 2097152 |
ONERUN_ANSIBLE_HOST_KEY_CHECKING | ANSIBLE_HOST_KEY_CHECKING | true |
ONERUN_OIDC_ONLY | Disable local password login (SSO only; Pro) | false |
| Variable | Description |
|---|---|
ONERUN_ADMIN_EMAIL | Admin email |
ONERUN_ADMIN_PASSWORD | Admin password (must not be a known default in production) |
ONERUN_ADMIN_NAME | Display name |
| Variable | Description | Default |
|---|---|---|
ONERUN_DATABASE_DRIVER | sqlite or postgres | sqlite |
ONERUN_POSTGRES_ENABLED | Force Postgres driver when true | false |
ONERUN_SQLITE_PATH | SQLite file path | $ONERUN_DATA_DIR/onerun.db |
POSTGRES_HOST | Database host | postgres |
POSTGRES_PORT | Port | 5432 |
POSTGRES_USER | Username | onerun |
POSTGRES_PASSWORD | Password | — |
POSTGRES_DB | Database name | onerun |
POSTGRES_SSLMODE | SSL mode | require in production, else disable |
| Variable | Description |
|---|---|
ONERUN_REDIS_URL / REDIS_URL | e.g. redis://:password@redis:6379/0 |
ONERUN_REDIS_HMAC_SECRET | Required in production when Redis is enabled |
REDIS_PASSWORD | Used by Compose Redis --requirepass |
| Variable | Description |
|---|---|
ONERUN_URL | Base URL of the OneRun server (from the agent’s network) |
ONERUN_RUNNER_TOKEN | Token from Admin → Runners |
ONERUN_RUNNER_LABELS | Labels for scheduling (e.g. docker,remote) |
ONERUN_RUNNER_ALLOW_INSECURE | true to allow plain http:// to FQDNs/IPs (isolated network). Short Docker service names like http://onerun:8080 are allowed without this flag. |
Used exclusively for authentication e-mails (verify, password reset, MFA recovery). Run notifications use notification profiles in the UI — not these system SMTP settings.
| Variable | Description |
|---|---|
ONERUN_SMTP_ENABLED | true to enable |
ONERUN_SMTP_HOST | SMTP host |
ONERUN_SMTP_PORT | Port (default 587; 465 = implicit TLS / SMTPS) |
ONERUN_SMTP_USERNAME | Username |
ONERUN_SMTP_PASSWORD | Password (or ONERUN_SMTP_PASSWORD_FILE) |
ONERUN_SMTP_FROM | Sender, e.g. OneRun <[email protected]> |
ONERUN_SMTP_TLS | true requires STARTTLS (or implicit TLS on 465); delivery is refused if the server does not offer TLS. Set false only for a local relay on a trusted network. |
OneRun does not inject a global ansible.cfg. Ansible loads ansible.cfg from the playbook workspace (repository checkout) when present. To force a path, set ANSIBLE_CONFIG via an Execution Profile’s extra_env.
Task options:
ansible-playbook --forks N (0 = Ansible default)first_fatal forces --forks 1; any_errors_fatal sets ANSIBLE_ANY_ERRORS_FATAL=TrueGET /metrics exposes a small Prometheus text scrape (runs by status, runners, schedules, maintenance mode). The endpoint is disabled (404) unless ONERUN_METRICS_TOKEN is set; Prometheus authenticates with Authorization: Bearer <token>. A signed-in global administrator can also open it in the browser.
scrape_configs:
- job_name: onerun
scheme: https
authorization:
credentials: "<ONERUN_METRICS_TOKEN>"
static_configs:
- targets: ["onerun.example.com"]
Configure issuer, client ID/secret (and options) in Admin → System. Redirect URI:
{ONERUN_PUBLIC_URL}/api/v1/auth/oidc/callback
Local admin password login remains available as break-glass unless ONERUN_OIDC_ONLY=true.
/setup if prompted.ONERUN_ENV=production (the default) and set a unique ONERUN_MASTER_KEY (long random string) — prefer ONERUN_MASTER_KEY_FILE with a Docker secret. Losing the key means encrypted credentials cannot be recovered./data on a volume; back up the volume and the master key together (backup does not include master.key).ONERUN_PUBLIC_URL to the https:// URL (enables the Secure cookie flag), and set ONERUN_TRUSTED_PROXIES to your edge CIDRs.POSTGRES_SSLMODE=require (production default); only set disable for a database on an isolated network.ONERUN_SMTP_TLS=true; use port 465 or a STARTTLS-capable server.ONERUN_METRICS_TOKEN only if Prometheus needs /metrics; otherwise leave it unset (endpoint disabled).https://; use ONERUN_RUNNER_ALLOW_INSECURE=true only on an isolated Docker network.ONERUN_REDIS_URL.ONERUN_ANSIBLE_HOST_KEY_CHECKING=true unless you have a controlled exception.curl -fsS https://onerun.example.com/api/health
A healthy response includes "status":"ok" and database connectivity.
Michael Kleger
OneSystems GmbH
[email protected]
© OneSystems GmbH. Distributed as container images via Docker Hub.
Community edition is free to run; Pro unlocks additional features via a license key from the OneSystems shop.
For OEM or special licensing, contact OneSystems GmbH.
Content type
Image
Digest
sha256:44ddfaa0b…
Size
103.8 MB
Last updated
10 days ago
docker pull onesystems/onerun:1.2