Areas we serve

Self-Hosted µTask: YAML Business Processes With a Human Pause

A payments API gets a charge that needs an antifraud check. Low risk: green light. Ugly score: reject. The mushy middle: a person has to look and type a number into a form. That is not cron. That is not "SSH in and run a script." That is a business process with retries, a human pause, and a record of every in-between state. OVH built µTask (ovh/utask) for exactly that shape of work.

Go, BSD-3-Clause, ~1.4k GitHub stars, 105 forks, 85 open issues. Last push mid-2026. The pitch is small: declare a process in YAML, run it asynchronously, encrypt the trail, and let a person step in when a template asks for it. Docs live in the repo README; the dashboard sits on port 8081.

YAML graph, not a pile of scripts

A template names inputs (the requester fills those) and optional resolver inputs (the person who actually runs the task). Steps form a graph with dependencies. Each step is an action: HTTP, SSH, email, script, ping, notify, spawn a subtask, call OVH's API, stash a tag, fire a callback. Conditions can skip a step or remap a 404 into a custom NOT_FOUND so the next step can create the missing user instead of treating it as a crash. Loops (foreach), pre-hooks, and Go/Sprig templating plug values from earlier steps into later ones.

Two roles matter. The requester opens the task. The resolver is allowed to execute it: global admins, names on the template, a group, or a per-task list. auto_runnable can start the work immediately when the requester is already allowed. State names are boring on purpose (TODO, RUNNING, DONE, TO_RETRY, plus your own). Transient errors get retried with a seconds/minutes/hours pattern. After too many consecutive runs (default 100) the task blocks for a human.

The engine keeps an encrypted, auditable snapshot of every intermediate state until the graph finishes. Storage keys rotate with symmecrypt and a maintenance-mode /key-rotate call. Notifications can hit Slack, Opsgenie, or a generic webhook on task and step changes.

Not StackStorm, not Kestra, not OliveTin

StackStorm is IFTTT for ops: sensors, packs, ChatOps, Mongo and Rabbit. µTask is a YAML business workflow with a form for the human in the loop. Kestra and Airflow are pipeline orchestrators. µTask is "provision this cert," "bootstrap this hire," "wait for antifraud." OliveTin is a button that runs a command you already trust. µTask is the graph around several of those commands, plus a pause until someone types an answer.

OVH's own examples are the tell: Kubernetes ingress TLS (key, challenge, write the cert back), new-hire bootstrap (wait for their SSH pubkey in a generated form, then accounts and a welcome mail), payments antifraud with a human score step. Other APIs can treat µTask as a backend and look up tasks by tags.

Why self-host?

Those templates hold SSH keys, payment-risk scores, and onboarding identity. Encrypted-at-rest is nice. Encrypted-on-someone-else's-SaaS is still someone else's disk. BSD-3-Clause is easy internally. The only hard dependency is Postgres 9.5 or newer. Scheduler and workers share one Go runtime; several instances coordinate on that database and take a lock per task so two boxes do not stomp the same run. Work is not farmed out to mystery agents.

Auth is the part people skip. Vanilla µTask trusts x-remote-user from a reverse proxy. basic-auth in configstore is for development. Production wants TLS and a real IdP in front, or an init plugin that wires your own auth. Default docker-compose login is admin / 1234. Change that before the box sees a network.

Quick start

Official path is a folder that becomes your git of templates and plugins:

mkdir utask && cd utask
wget https://github.com/ovh/utask/releases/latest/download/install-utask.sh
sh install-utask.sh
docker-compose up

Dashboard: http://localhost:8081/ui/dashboard. OpenAPI: /unsecured/spec.json. Swagger UI is on /ui/swagger/ in the Docker image. Production is "build your image FROM the official one, bake templates and .so plugins in." HTTP port default 8081. You can also make all against your own Postgres.

Plugins are Go shared objects. Init plugins can swap auth and configstore providers. Builtin actions already cover HTTP, SSH, email, and scripts under a scripts/ folder, so many shops never write a plugin.

Who it is for

Good fit: a team that already describes work as a checklist with a human gate; APIs that need an async sidecar they can poll by task ID; people who want YAML in git instead of a vendor BPM suite.

Skip it: if crontab or OliveTin covers you; if you wanted StackStorm packs and ChatOps; if nobody will own Postgres, encryption keys, and a reverse proxy. 1.4k stars and 85 open issues is a real OVH tool, not a weekend binary. The UI is an Angular dashboard from the same repo. Keep templates in git or you will lose the point.

Hosting in Canada

Put µTask and Postgres on a CloudBox you snapshot. The encrypted task history is still an onboarding and payments log; Canadian residency is the reason to self-host instead of a US workflow SaaS. Slack/Opsgenie notifications still leave the building if you turn them on. The YAML, the keys, and the resolver forms stay on your side.

Bottom line

µTask is YAML business automation with retries, encryption, and a human form when the graph says so. Self-host it when the process is more than a script and the state cannot live in a SaaS. Start with one HTTP step and one resolver input. Grow templates only after that loop is boring.

Talk with Swift Host if you want a Canadian VPS for µTask plus Postgres (TLS, snapshots, not a leftover 1 GB box). We are in St. Albert and actually answer the phone.

Tags:
  • µTask
  • YAML
  • Workflow
  • Self-Hosted
  • Go

Need Help With Your Hosting?

Tell us about your application — we respond within 1 hour with honest recommendations.