uTask Automation Engine on AWS User Guide
Overview
This image runs uTask 1.34.0, OVH's open source automation engine, on Ubuntu 24.04 LTS. uTask turns an operational runbook into an auditable, resumable task: you describe a process once as a YAML task template with typed inputs, dependent steps, conditions, loops and JSON schema checks, and uTask executes it as a task with a full history, retrying what can be retried and pausing for human approval where you ask it to. It exposes those templates through a REST API and an Angular web dashboard.
The stack on this single instance is:
PostgreSQL 16 (loopback) <-- uTask 127.0.0.1:8081 <-- nginx :80 (sole network surface)
uTask deliberately ships no built-in authentication. Upstream's design is that uTask sits behind a trusted reverse proxy that authenticates the caller and passes the verified username in the x-remote-user header. This image implements exactly that: nginx on port 80 performs HTTP Basic authentication against a per-instance credential and injects the authenticated username as x-remote-user, overwriting anything a client tries to supply. uTask itself is bound away from the network by an nftables rule that drops inbound traffic to port 8081 on every non-loopback interface, so the proxy cannot be bypassed.
Nothing secret is baked into the image. On the first boot of every deployed instance a one-shot service generates three per-instance secrets - the PostgreSQL role password, the storage encryption key that protects every task input and result at rest, and the dashboard/API password - creates the database and schema from scratch, and writes the credentials to /root/utask-credentials.txt (mode 0600, root only). The image ships with no database at all, so no build-time data and no shared key can follow you into production.
The PostgreSQL data tier - the task templates, task history and every encrypted payload - lives under /var/lib/postgresql on a dedicated, independently resizable EBS data volume kept separate from the operating system disk.
The default security group for this listing opens port 22 (SSH) and port 80 (HTTP) only.
Prerequisites
- An AWS account subscribed to this product in AWS Marketplace.
- An EC2 key pair in your target region for SSH access.
- A security group allowing inbound TCP 22 (SSH) from your IP and TCP 80 (HTTP) from your users.
- Recommended instance type:
m5.largeor larger.
Connecting to your instance
SSH in as the default login user for your operating system variant, using the key pair you launched with.
| OS variant | Login user | Example |
|---|---|---|
| Ubuntu 24.04 | ubuntu |
ssh -i your-key.pem ubuntu@<instance-public-ip> |
Step 1 - Launch from the AWS Marketplace console
- Open the product page in AWS Marketplace and choose Continue to Subscribe, then Continue to Configuration.
- Select the software version and your AWS Region, then choose Continue to Launch.
- Choose an instance type (
m5.largeor larger), your VPC subnet, the security group described above, and your EC2 key pair. - Launch the instance and wait for it to reach the running state with status checks passed.
Step 2 - Launch from the AWS CLI (alternative)
Replace the AMI id, key name, security group and subnet with your own values:
aws ec2 run-instances \
--image-id ami-xxxxxxxxxxxxxxxxx \
--instance-type m5.large \
--key-name your-key \
--security-group-ids sg-xxxxxxxx \
--subnet-id subnet-xxxxxxxx \
--metadata-options "HttpTokens=required" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=utask}]'
Step 3 - Retrieve the per-instance credentials
SSH in, then read the credentials file that first boot generated. The dashboard username is admin; the password is unique to your instance.
sudo cat /root/utask-credentials.txt
The file also records the PostgreSQL role name and its per-instance password. The storage encryption key lives in /etc/utask/utask.env (mode 0640, root:utask) - back it up before rotating it, or previously stored task data becomes unreadable.
Confirm the engine is healthy. /healthz is served by nginx, and /unsecured/mon/ping is uTask's own unauthenticated liveness route proxied through nginx:
curl -s http://127.0.0.1/healthz
curl -s http://127.0.0.1/unsecured/mon/ping
Step 4 - Sign in to the dashboard
Browse to http://<instance-public-ip>/ui/dashboard and, when the browser prompts for HTTP Basic credentials, sign in as admin with the password from Step 3. The Tasks view opens, listing every task and its state. Two example templates are preloaded so the dashboard is useful the moment you sign in.

For production, front the dashboard with your own TLS certificate and domain (Step 8) and, if you wish, wire nginx to your identity provider so the reverse proxy passes real usernames.
Step 5 - Run a task and watch the engine resolve it
Open the Templates view to see the reusable YAML workflows exposed to your team.

Choose hello-world, then New task, supply a name and run it. uTask executes the step and moves the task to DONE, recording the full history and the produced result. You can drive the same thing from the REST API - this creates a task from the hello-world template and prints the created task:
ADMIN_PASS=$(sudo grep '^UTASK_ADMIN_PASSWORD=' /root/utask-credentials.txt | cut -d= -f2-)
curl -s -u admin:"$ADMIN_PASS" -H 'Content-Type: application/json' \
-d '{"template_name":"hello-world","input":{"name":"there"}}' \
http://127.0.0.1/task
List the templates the engine has loaded, authenticated through nginx:
ADMIN_PASS=$(sudo grep '^UTASK_ADMIN_PASSWORD=' /root/utask-credentials.txt | cut -d= -f2-)
curl -s -u admin:"$ADMIN_PASS" http://127.0.0.1/template | python3 -m json.tool | head -30
Open a finished task to inspect every step, who requested it, and the result the engine produced.

Step 6 - Write your own template
Templates are plain YAML files in /opt/utask/templates. Copy one of the shipped examples as a starting point, edit it, and uTask loads it on restart:
sudo cp /opt/utask/templates/hello-world.yaml /opt/utask/templates/my-first.yaml
sudo nano /opt/utask/templates/my-first.yaml
sudo systemctl restart utask
uTask ships builtin actions for HTTP calls, SSH commands, scripts, email, notifications and subtasks, and you can require human validation on the steps that need a second pair of eyes. See the upstream documentation at https://github.com/ovh/utask for the full template reference.
Step 7 - How the authentication model protects you
- nginx is the only network surface. It authenticates every request against the per-instance credential and sets
x-remote-userfrom the authenticated username. A client cannot assert its own identity - the header it sends is overwritten. - uTask is unreachable except through nginx. uTask has no bind-address option and would otherwise listen on
0.0.0.0:8081and trustx-remote-userunconditionally. An nftables rule drops inbound traffic to 8081 on every non-loopback interface. You can confirm it is blocked from off-box; locally you can see the table:
sudo nft list table inet cloudimg_utask
- Every secret is per-instance. The database password, dashboard password and storage encryption key are generated on first boot and never shared between instances.
Step 8 - Enable HTTPS (recommended for production)
For production, terminate TLS in front of uTask. Either put the instance behind an AWS Application Load Balancer or CloudFront with an ACM certificate, or obtain a Let's Encrypt certificate on the instance itself once a DNS name points at it:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com
certbot updates the nginx site in place and sets up automatic renewal.
Step 9 - Backups, storage and maintenance
- Database volume. All uTask state is in PostgreSQL under
/var/lib/postgresqlon a dedicated EBS volume. Take EBS snapshots on a schedule, and grow the volume (then the filesystem) as your task history grows. - Encryption key.
/etc/utask/utask.envholds the storage encryption key. Include it in your backup plan and store it securely; rotating it makes previously stored task inputs/results unreadable unless you retain the old key. - Service management. The product runs as four systemd services. Check their state:
systemctl is-active postgresql nftables utask nginx
Restart uTask after changing templates or configuration:
sudo systemctl restart utask
- Updates. The base OS has unattended security upgrades enabled. cloudimg can advise on uTask version upgrades and PostgreSQL maintenance.
Support
cloudimg provides 24/7 technical support for this product by email (support@cloudimg.co.uk) and live chat, with a one-hour average response for critical issues. We help with modelling your runbooks as task templates, template authoring and debugging, fronting the dashboard with your own TLS certificate and domain, integrating uTask with your identity provider and monitoring, storage encryption key rotation, PostgreSQL sizing and backup, and uTask version upgrades.