Sign inSign up

onesystems/onerun

By onesystems

•Updated 10 days ago

Modern, lightweight, self-hosted infrastructure automation

Image
Networking
API management
Developer tools
1

667

onesystems/onerun repository overview

⁠OneRun

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).


⁠Editions: Community & Pro

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.

CommunityPro
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⁠.


⁠Image

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.


⁠Operating modes

Same product and image — only persistence and where jobs execute change.

ModeTypical useDatabaseRunner
LiteHomelab, few jobsSQLite on a volumeBuilt-in (same process)
StandardRegular use, several projectsPostgreSQLLocal (and remote with Pro)
ScaleTeams, more parallelismPostgreSQLRunner 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).


⁠Quick start

⁠Lite (Community-friendly)
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
URLDescription
/Web UI
/setupFirst-run wizard (if no admin yet)
/api/healthHealth check
/api/swaggerOpenAPI / Swagger UI (Pro, signed-in users only)
/metricsPrometheus 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.

⁠Standard (App + Postgres)
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:
⁠Scale (remote runner, Pro)
  1. Activate a Pro license.
  2. In the UI: Admin → Runners — create a runner and copy the token once.
  3. Start another container from the same image with 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.


⁠Container commands

CommandPurpose
serve (default)HTTP API + web UI + local runner
runnerRemote / 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-postgresLite → Standard data migration
keysKey / crypto helpers
helpUsage
docker compose exec onerun onerun backup /tmp/onerun-backup.tar.gz
docker compose run --rm onerun migrate-sqlite-to-postgres --dry-run
⁠Configuration backup (Pro UI)

Admin → System → Configuration backup:

  • Writes to ONERUN_BACKUP_DIR (Compose volume /backup)
  • config/*.yaml — readable configuration without secret values
  • secrets.age — credentials / tokens encrypted with a dedicated backup passphrase (age⁠)
  • Schedule: daily / weekly / monthly, retention by max versions
age -d -o secrets.json /backup/onerun-config-…/secrets.age

⁠Core features

  • Projects & Git — SSH/HTTPS repositories, branches/tags, host-key handling, connection tests; playbooks from Git as source of truth
  • Encrypted key store — SSH keys, passwords, vault / become secrets, tokens (encrypted at rest with ONERUN_MASTER_KEY)
  • Inventories & tasks — Git or local inventory, extra vars, tags/skip-tags, check/diff, timeouts, simulation (check mode)
  • Runs — Live and raw logs with secret masking, cancel/rerun, summaries, retention
  • Schedules — Cron with timezone, pause, no overlapping runs for the same task
  • Auth — Local users, MFA (TOTP + recovery), optional SMTP for email OTP recovery; SSO and API tokens with Pro. Invitations use one-time links (24 h); without SMTP the link is shown once to the administrator.
  • RBAC — Project roles and admin separation. Project creation is admin-only unless Allow users to create projects is enabled in Admin → System.
  • Secret reveal — Stored credentials can only be revealed from an interactive session with TOTP enabled plus a fresh step-up; API tokens cannot reveal secrets.
  • Notifications — SMTP, ntfy, Nextcloud Talk (and related channels as configured)
  • Ops — Health check, backup/restore CLI, SQLite → Postgres migration, audit trail

⁠Environment variables

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.

⁠General
VariableDescriptionDefault
TZ / ONERUN_TIMEZONETimezoneEurope/Zurich
ONERUN_ENVdevelopment / production. In production, known default secrets are refused and one-time codes are never echoed in API responses.production
ONERUN_DEV_OTP_ECHOEcho verification / reset codes in API responses (development only; never in production)false
ONERUN_LOG_FORMATtext (default, Portainer/docker-friendly) or jsontext
ONERUN_HOSTListen address0.0.0.0
ONERUN_PORTListen port inside the container8080
ONERUN_PUBLIC_URLPublic base URL (links, OIDC redirect base)http://localhost:8091
ONERUN_DATA_DIRPersistent data (DB, caches, known_hosts, …)/data
ONERUN_BACKUP_DIRScheduled config backups$ONERUN_DATA_DIR/backups
ONERUN_MASTER_KEYEncryption key for secrets (required, non-default in production)—
ONERUN_VERSIONVersion label (set at image build)image build
ONERUN_UPDATEHUB_ENABLEDShow UpdateHub update hint in the UI (false to disable)true
ONERUN_TRUSTED_PROXIESComma-separated CIDRs trusted for X-Forwarded-*empty
ONERUN_COOKIE_SECURESecure session cookietrue when ONERUN_ENV=production and ONERUN_PUBLIC_URL starts with https:// (a warning is logged otherwise)
ONERUN_METRICS_TOKENBearer token for GET /metrics; without it the endpoint returns 404 (admins with a session can always scrape)empty (disabled)
ONERUN_SESSION_TTLSession lifetime12h
ONERUN_SESSION_COOKIECookie nameonerun_session
ONERUN_MAX_PARALLEL_RUNSInstance-wide parallel runs (local runner hard-capped at 2)2
ONERUN_RETENTION_DAYSRun/log retention30
ONERUN_KEEP_WORKSPACE_ON_FAILURE_HOURSKeep failed workspaces (hours; 0 = delete immediately)24
ONERUN_MAX_RUN_TIMEOUT_SECGlobal timeout cap (0 = no cap)86400
ONERUN_DEFAULT_COLLECTIONSPre-warm Galaxy collections (none / empty = off)ansible.posix,community.general
ONERUN_MAX_BODY_BYTESMax request body size2097152
ONERUN_ANSIBLE_HOST_KEY_CHECKINGANSIBLE_HOST_KEY_CHECKINGtrue
ONERUN_OIDC_ONLYDisable local password login (SSO only; Pro)false
⁠Bootstrap admin (empty database only)
VariableDescription
ONERUN_ADMIN_EMAILAdmin email
ONERUN_ADMIN_PASSWORDAdmin password (must not be a known default in production)
ONERUN_ADMIN_NAMEDisplay name
⁠Database
VariableDescriptionDefault
ONERUN_DATABASE_DRIVERsqlite or postgressqlite
ONERUN_POSTGRES_ENABLEDForce Postgres driver when truefalse
ONERUN_SQLITE_PATHSQLite file path$ONERUN_DATA_DIR/onerun.db
POSTGRES_HOSTDatabase hostpostgres
POSTGRES_PORTPort5432
POSTGRES_USERUsernameonerun
POSTGRES_PASSWORDPassword—
POSTGRES_DBDatabase nameonerun
POSTGRES_SSLMODESSL moderequire in production, else disable
⁠Redis (optional, Scale / Pro)
VariableDescription
ONERUN_REDIS_URL / REDIS_URLe.g. redis://:password@redis:6379/0
ONERUN_REDIS_HMAC_SECRETRequired in production when Redis is enabled
REDIS_PASSWORDUsed by Compose Redis --requirepass
⁠Remote runner agent (Pro)
VariableDescription
ONERUN_URLBase URL of the OneRun server (from the agent’s network)
ONERUN_RUNNER_TOKENToken from Admin → Runners
ONERUN_RUNNER_LABELSLabels for scheduling (e.g. docker,remote)
ONERUN_RUNNER_ALLOW_INSECUREtrue to allow plain http:// to FQDNs/IPs (isolated network). Short Docker service names like http://onerun:8080 are allowed without this flag.
⁠SMTP (optional; auth mail only)

Used exclusively for authentication e-mails (verify, password reset, MFA recovery). Run notifications use notification profiles in the UI — not these system SMTP settings.

VariableDescription
ONERUN_SMTP_ENABLEDtrue to enable
ONERUN_SMTP_HOSTSMTP host
ONERUN_SMTP_PORTPort (default 587; 465 = implicit TLS / SMTPS)
ONERUN_SMTP_USERNAMEUsername
ONERUN_SMTP_PASSWORDPassword (or ONERUN_SMTP_PASSWORD_FILE)
ONERUN_SMTP_FROMSender, e.g. OneRun <[email protected]>
ONERUN_SMTP_TLStrue 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.
⁠Ansible config

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:

  • Forks → ansible-playbook --forks N (0 = Ansible default)
  • Fail-fast → first_fatal forces --forks 1; any_errors_fatal sets ANSIBLE_ANY_ERRORS_FATAL=True
⁠Metrics

GET /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"]
⁠OpenID Connect (SSO, Pro)

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.


⁠First steps after install

  1. Open the UI — complete /setup if prompted.
  2. Sign in and finish MFA (TOTP). Store recovery codes; configure SMTP if you want email OTP recovery. TOTP is also required to reveal stored secrets later.
  3. Create a repository, credential, inventory, and task.
  4. Run a simulation, then a real run; confirm live logs and secret masking.
  5. Optionally add schedules and notification profiles.
  6. For Pro features: Administration → License and activate your key.

⁠Production security checklist

  • Keep 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.
  • Do not use Compose/dev defaults for admin password, master key, Postgres, or Redis; production refuses known defaults at startup.
  • Persist /data on a volume; back up the volume and the master key together (backup does not include master.key).
  • Terminate TLS at a reverse proxy, set ONERUN_PUBLIC_URL to the https:// URL (enables the Secure cookie flag), and set ONERUN_TRUSTED_PROXIES to your edge CIDRs.
  • Keep POSTGRES_SSLMODE=require (production default); only set disable for a database on an isolated network.
  • Keep ONERUN_SMTP_TLS=true; use port 465 or a STARTTLS-capable server.
  • Set ONERUN_METRICS_TOKEN only if Prometheus needs /metrics; otherwise leave it unset (endpoint disabled).
  • Remote runners must reach the server via https://; use ONERUN_RUNNER_ALLOW_INSECURE=true only on an isolated Docker network.
  • Do not publish Redis to the public internet; always use a password in ONERUN_REDIS_URL.
  • Keep ONERUN_ANSIBLE_HOST_KEY_CHECKING=true unless you have a controlled exception.
  • Restrict who can manage repositories, webhooks, and system settings.
  • Rotate runner tokens and API tokens if leaked; treat runner hosts as trusted execution environments.

⁠Health check

curl -fsS https://onerun.example.com/api/health

A healthy response includes "status":"ok" and database connectivity.


⁠Author

Michael Kleger
OneSystems GmbH⁠
[email protected]⁠


⁠License

© 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⁠.

Tag summary

Content type

Image

Digest

sha256:44ddfaa0b…

Size

103.8 MB

Last updated

10 days ago

docker pull onesystems/onerun:1.2