Deployment guide

WUD Container Update Monitor 9.6.0

Overview

WUD watches the containers running on a Docker host and tells you when a newer image tag, or a new digest of the same tag, is published in their registries (Docker Hub, GitHub Container Registry, Amazon ECR, GitLab, Quay and many more, plus any registry you add). It shows every container, its current and newest version, and the history of what it found. It can also notify you through triggers: HTTP webhooks, email, Slack, Teams, Telegram, MQTT, ntfy, Gotify and others.

This guide covers launching and verifying WUD Container Update Monitor 9.6.0 on Ubuntu 24.04 from SecureAnyCloud on Amazon EC2. The image is one version of the SecureAnyCloud Hardened Uptime Kuma, Gatus & Uptime and Status Pages AMIs listing on AWS Marketplace. You pick it as the software version when you subscribe and launch. The listing's guide hub describes the other products in the listing.

On this image, WUD watches the Docker Engine on the same instance. To show WUD at work from your first sign-in, the image ships a small demonstration. It has a read-only local registry holding a SecureAnyCloud demonstration image in versions 1.0.0, 1.1.0 and 1.2.0, and a container started on first boot from the deliberately old 1.0.0. WUD finds 1.2.0, marks the update and sends a notification to a local webhook receiver, all without touching the internet. You can remove the demonstration whenever you like (Step 6).

The image runs WUD 9.6.0, built by SecureAnyCloud from the official 9.6.0 source. Six of its dependencies are updated to releases that fix every known advisory (npm audit reports none). It runs on Node.js 24.22.1, with Docker Engine 29.9.2 from Docker's own repository. The base is a fully patched Ubuntu 24.04 LTS, and unattended security upgrades stay on for your instance, including for Docker Engine.

What you get:

  • WUD 9.6.0 (wud.service) running as the unprivileged wud user on 127.0.0.1:3000 only
  • Docker Engine 29.9.2 and containerd 2.4.2 (docker.service), reachable only through its unix socket
  • nginx publishing WUD over HTTPS on port 443 with a certificate created on your instance's first boot, and port 80 redirecting to HTTPS
  • A WUD administrator, wudadmin, with a password unique to your instance, created on first boot
  • The demonstration: sac-wud-registry.service (read-only registry on 127.0.0.1:5000), sac-wud-sink.service (webhook receiver on 127.0.0.1:3001) and the sac-demo-app container
  • wud-set-hostname, a helper to serve WUD under your own DNS name
  • The build record (BUILD-INFO.txt), the dependency lockfile, the npm audit and govulncheck results and the licences in /usr/share/doc/wud/
  • Default user: ubuntu
  • Architecture: x86_64
  • Root volume: 8 GiB gp3

Security posture

WUD reads the Docker Engine of the instance, so anyone who can use it can see every container, image and label on the host. The image is built around that:

  • Every page and every API call needs a sign-in. nginx asks WUD to check the caller's identity before it forwards anything. The web interface, the REST API, the live event streams, the API documentation, the Prometheus /metrics endpoint and the registry webhook receiver all answer 401 without valid credentials. The only exception is a static /healthz probe for load balancers, which returns ok and never reaches WUD.
  • Per-instance secrets. The administrator password, the key that WUD signs its session cookies with, and the TLS key are generated on your instance's first boot. WUD stores the password only as a bcrypt hash. First boot hands it over once and removes the hand-over file. Your credentials are in /root/wud-credentials.txt (mode 0600, root only). No database, password, key or session ships in the image.
  • Fail closed. WUD does not start until first boot has created the administrator and the session key, and nginx does not start until first boot has finished. There is no anonymous mode and no first-visitor setup page.
  • Loopback only. WUD listens on 127.0.0.1. nginx on port 443 is the only way in.
  • HTTPS on first boot. nginx serves WUD with a TLS key and self-signed certificate created on your instance (TLS 1.2 and 1.3 only). Port 80 only redirects to HTTPS. Session cookies are marked Secure and SameSite.
  • Fixed host name. WUD is served under a name taken from the instance metadata at first boot (or one you set), never from the request. nginx drops requests for any other host name, and it refuses cross-site form posts, WebSocket connections and event streams.
  • Real client addresses. nginx passes the connecting address to WUD and ignores any X-Forwarded-For header that a client sends.
  • The Docker API stays private. Docker Engine listens only on its unix socket (/var/run/docker.sock, mode 0660, group docker), and nothing listens on the Docker TCP ports 2375 or 2376. The only member of the docker group is wud.
  • No container-changing triggers. WUD can be configured to update containers or run commands when it finds a new version. None of those triggers is configured on this image. The only trigger is the demonstration's notification webhook.
  • No metadata access. WUD contacts the registries you configure and the webhooks you add, so wud.service and nginx.service are blocked from reaching the instance metadata service (169.254.169.254 and fd00:ec2::254). The two demonstration services can reach nothing but loopback. Amazon Time Sync keeps working.
  • Least privilege. WUD runs with no Linux capabilities, a read-only system (ProtectSystem=strict) except its own data directory, and a private /tmp.
  • No scheduled firmware-metadata refresh. The fwupd firmware updater stays installed, but its LVFS metadata refresh (fwupd-refresh.timer and .service) is masked, so an LVFS outage never marks your instance unhealthy at boot. Run sudo fwupdmgr refresh yourself if you use it.
  • IMDSv2 required. The AMI is registered with ImdsSupport v2.0, so instances launched from it refuse token-less (IMDSv1) metadata requests.
  • Per-instance identity. SSH host keys, the machine ID and Docker Engine's engine ID are generated fresh on every instance.

Known advisories and how the build handles them

  • WUD dependencies. npm audit on the upstream 9.6.0 lockfile lists six advisories in WUD's production dependencies: body-parser (a denial of service on compressed request bodies), multer, undici, fast-uri, ip-address and nodemailer. This build updates each one within its own major release line to a release that fixes it (body-parser 1.20.9, nodemailer 10.2.1, multer 2.5.0, undici 8.12.3, fast-uri 3.1.9, ip-address 10.7.5). No other package version changes. npm audit on the result, and on the web interface's dependencies, reports no vulnerabilities. The results ship in /usr/share/doc/wud/. No vite (a development tool) is installed.
  • Test keys. Two dependencies publish their test files in their npm packages, including SSH and TLS test keys. Those test directories are removed from the image, and a scan of the shipped files for private-key material finds none.
  • The web interface's icons. WUD's web interface loads some of its icons from the public Iconify icon service (api.iconify.design) in your browser. This is a request from the browser, not from the instance. If your browser cannot reach the service, a few icons are blank.

Prerequisites

  • An AWS account and permission to launch EC2 instances
  • An EC2 key pair in the Region you launch in
  • A subnet that gives the instance a public IPv4 address (or private connectivity from where you will use the web interface), and outbound HTTPS from the instance to the registries your images come from

Recommended instance type: m5.large. WUD is a single Node.js process with SQLite storage. The containers you run next to it decide how much more capacity you need.

Connecting to your instance

Connect over SSH to the instance running WUD Container Update Monitor 9.6.0 on Ubuntu 24.04 (Ubuntu 24.04 LTS). The SSH user is ubuntu.

1

Launch the instance

Option A: AWS Marketplace console

  • Open the SecureAnyCloud Hardened Uptime Kuma, Gatus & Uptime and Status Pages AMIs listing on AWS Marketplace. Choose View purchase options, then Subscribe. One subscription covers every version in the listing.
  • When the subscription is active, choose Launch your software.
  • Choose One-click launch from AWS Marketplace (or Launch from EC2 Console for the full launch wizard). In Version, choose WUD Container Update Monitor 9.6.0 on Ubuntu 24.04, then choose your Region.
  • Pick an instance type (m5.large recommended; the software charge is $0.04 per vCPU per hour) and your key pair.
  • In the security group, allow SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address and ports 80 and 443 to the people who use WUD, because whoever signs in sees this host's containers.
  • Choose your VPC and a subnet that gives the instance a public IP. Leave the metadata defaults (the image already requires IMDSv2), then choose Launch.

Option B: AWS CLI

Run these commands on your own workstation. They create a security group that allows SSH and HTTPS from your management address only, then launch the instance. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and replace the VPC, subnet, key pair and CIDR with your own:

SG=$(aws ec2 create-security-group --group-name wud \
  --description "WUD Container Update Monitor" --vpc-id vpc-0123456789abcdef0 \
  --query GroupId --output text) for p in 22 80 443; do aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port "$p" --cidr <your-mgmt-cidr> done aws ec2 run-instances \
  --image-id ami-0123456789abcdef0 \
  --instance-type m5.large \
  --key-name my-key-pair \
  --security-group-ids "$SG" \
  --subnet-id subnet-0123456789abcdef0 \
  --associate-public-ip-address \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=wud}]'

You do not need --metadata-options, because the AMI already makes IMDSv2 required.

2

Connect and read your credentials

Connect as ubuntu with the key pair that you chose:

ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>

First boot finishes within a minute or two of launch. It creates the certificate, the session key and the administrator, starts Docker Engine and the demonstration, and then lets nginx start. Read your credentials from a root-only file:

sudo cat /root/wud-credentials.txt
# WUD Container Update Monitor - generated on first boot by wud-firstboot.service
# These credentials are unique to this instance. Store them somewhere safe.
#
# "Docker" is a trademark of Docker, Inc. sac is not affiliated with, endorsed by, or sponsored by Docker, Inc. WUD_URL=https://ec2-34-239-126-168.compute-1.amazonaws.com/ wud.admin.user=wudadmin wud.admin.pass=<WUD_ADMIN_PASSWORD>
# Open WUD_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to # https) and sign in with the user and password above. Every page and API call needs them. # ANYONE WHO CAN SIGN IN SEES THIS HOST'S CONTAINER INVENTORY, and WUD reads the container engine as a member of
# the docker group: treat this login as privileged and restrict inbound 443 in your security group.
# Serve it under your own DNS name:
sudo wud-set-hostname <your-dns-name>
# Full deployment guide: https://secureanycloud.com/stacks/wud-container-update-monitor-9-6-0/

wud.admin.pass holds your instance's own password.

3

Confirm the services are running

Check that the first-boot unit, Docker Engine, the two demonstration services, WUD and nginx are active, that WUD runs as the unprivileged wud user, and that WUD reports healthy on its loopback port:

systemctl is-active wud-firstboot.service docker.service sac-wud-registry.service sac-wud-sink.service wud.service nginx.service ps -o user=,args= -p "$(systemctl show -p MainPID --value wud.service)"
H=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/health); echo "WUD health (loopback): $H" [ "$H" = 200 ] && [ "$(systemctl is-active wud.service nginx.service docker.service | sort -u)" = active ]
active active active active active active wud /opt/node/bin/node /opt/wud/dist/index.js WUD health (loopback): 200

List the TCP ports that the instance listens on:

sudo ss -Hltn | awk '{print $4}' | sort -u
0.0.0.0:22 0.0.0.0:443 0.0.0.0:80 127.0.0.1:3000 127.0.0.1:3001 127.0.0.1:5000 127.0.0.1:8081 127.0.0.53%lo:53 127.0.0.54:53 [::]:22 [::]:443 [::]:80

WUD (3000), the demonstration webhook receiver (3001), the demonstration registry (5000) and the demonstration container (8081) listen on loopback only. nginx publishes WUD on port 443. The loopback port 53 entries are Ubuntu's local stub resolver (systemd-resolved). Docker Engine has no TCP port at all.

Show the versions, the six updated dependencies and the build record:

jq -r '"WUD " + .version' /opt/wud/package.json /opt/node/bin/node --version sudo docker version --format 'Docker Engine {{.Server.Version}}' for p in body-parser nodemailer multer undici fast-uri ip-address; do jq -r '" \(.name) \(.version)"' "/opt/wud/node_modules/$p/package.json"; done grep -E '^(source|runtime) ' /usr/share/doc/wud/BUILD-INFO.txt | cut -c1-110 jq -c '.metadata.vulnerabilities' /usr/share/doc/wud/npm-audit-app-prod.json
WUD 9.6.0 v24.22.1 Docker Engine 29.9.2 body-parser 1.20.9 nodemailer 10.2.1 multer 2.5.0 undici 8.12.3 fast-uri 3.1.9 ip-address 10.7.5 source https://github.com/getwud/wud.git tag 9.6.0 = commit ae3c0827c020e62ba15b8df6edd5b04aa05e9e62 runtime Node.js v24.22.1 (https://nodejs.org/dist/v24.22.1/node-v24.22.1-linux-x64.tar.xz, sha256 6c17 {"info":0,"low":0,"moderate":0,"high":0,"critical":0,"total":0}
4

Sign in to WUD

Browse to the WUD_URL from Step 2, for example https://ec2-34-239-126-168.compute-1.amazonaws.com/. The certificate is self-signed, so your browser warns once. Accept the warning, or install your own certificate (Step 7). Your browser then asks for a user name and password: enter wudadmin and the wud.admin.pass value.

The Containers page lists what WUD watches. On a new instance, that is the demonstration container, already flagged with an update from 1.0.0 to 1.2.0:

You can confirm the sign-in rules from the command line. Port 80 only redirects to HTTPS. A request without credentials, or with a wrong password, is refused with 401. Your credentials are accepted, and the only WUD user is your administrator. The block reads your password from the credentials file into a temporary file that curl reads, so the password never appears on a command line. It stops with an error if any answer is not the expected one:

H=$(sudo sed -n 's/^set $wud_host "\(.*\)";$/\1/p' /etc/nginx/wud-host.conf) R=(--cacert /etc/ssl/wud/wud.crt --resolve "$H:443:127.0.0.1" --resolve "$H:80:127.0.0.1")
K=$(mktemp);
sudo awk -F= '/^wud.admin.user=/{u=$2} /^wud.admin.pass=/{p=$2} END{printf "user = \"%s:%s\"\n", u, p}' /root/wud-credentials.txt > "$K"
P80=$(curl -s "${R[@]}" -o /dev/null -w '%{http_code} %{redirect_url}' "http://$H/")
ANON=$(curl -s "${R[@]}" -o /dev/null -w '%{http_code}' "https://$H/api/containers")
WRONG=$(curl -s "${R[@]}" -u "wudadmin:not-the-password" -o /dev/null -w '%{http_code}' "https://$H/api/containers")
OK=$(curl -s "${R[@]}" -K "$K" -o /dev/null -w '%{http_code}' "https://$H/api/containers")
USERS=$(curl -s "${R[@]}" -K "$K" "https://$H/api/users" | jq -r '.[] | "\(.username) (\(.role))"'); rm -f "$K" echo "port 80 : $P80"; echo "no credentials : $ANON"; echo "wrong password : $WRONG" echo "your credentials : $OK"; echo "WUD users : $USERS" [ "$P80" = "301 https://$H/" ] && [ "$ANON" = 401 ] && [ "$WRONG" = 401 ] && [ "$OK" = 200 ] && [ "$USERS" = "wudadmin (admin)" ]
port 80 : 301 https://ec2-34-239-126-168.compute-1.amazonaws.com/ no credentials : 401 wrong password : 401 your credentials : 200 WUD users : wudadmin (admin)

Scripts and monitoring tools can use the same credentials with HTTP Basic authentication, or a WUD API token that you create under your profile in the web interface.

5

See an update being detected

Inspect the demonstration container. It runs version 1.0.0 of the SecureAnyCloud demonstration image from the local registry, which also holds 1.1.0 and 1.2.0:

sudo docker ps --format '{{.Names}} {{.Image}} {{.Status}}' curl -s http://127.0.0.1:5000/v2/sac/demo-app/tags/list; echo
sac-demo-app 127.0.0.1:5000/sac/demo-app:1.0.0 Up 2 minutes {"name":"sac/demo-app","tags":["1.0.0","1.1.0","1.2.0"]}

WUD checks the registry for every container, reports the newest version and sends a notification through its trigger. On this image, the trigger posts to the local webhook receiver, which writes each delivery to /var/log/sac/sac-wud/trigger.log:

H=$(sudo sed -n 's/^set $wud_host "\(.*\)";$/\1/p' /etc/nginx/wud-host.conf) R=(--cacert /etc/ssl/wud/wud.crt --resolve "$H:443:127.0.0.1")
K=$(mktemp);
sudo awk -F= '/^wud.admin.user=/{u=$2} /^wud.admin.pass=/{p=$2} END{printf "user = \"%s:%s\"\n", u, p}' /root/wud-credentials.txt > "$K"
C=$(curl -s "${R[@]}" -K "$K" "https://$H/api/containers" | jq -r '.[] | "\(.name): running \(.image.tag.value), newest \(.result.tag), updateAvailable=\(.updateAvailable)"'); rm -f "$K" echo "$C"
N=$(sudo grep -c '"updateAvailable":true' /var/log/sac/sac-wud/trigger.log); echo "notifications delivered to the demo webhook sink: $N" [ "$C" = "sac-demo-app: running 1.0.0, newest 1.2.0, updateAvailable=true" ] && [ "$N" -ge 1 ]
sac-demo-app: running 1.0.0, newest 1.2.0, updateAvailable=true notifications delivered to the demo webhook sink: 1

WUD checks every hour (WUD_WATCHER_LOCAL_CRON in /etc/wud/wud.env). To check immediately, choose Watch now on the Containers page.

6

Watch your own containers

WUD watches every container on this instance's Docker Engine by default (WUD_WATCHER_LOCAL_WATCHBYDEFAULT=true). Run your containers as usual, and they appear in WUD at the next check. Labels on a container tune what WUD compares. For example, these labels make WUD consider only semantic version tags and show a friendly name:

sudo docker run -d --name web \
  --label 'wud.tag.include=^\d+\.\d+\.\d+$' \
  --label 'wud.display.name=Company website' \
  nginx:1.27.0

Public images on Docker Hub, GitHub Container Registry, Amazon ECR Public, Quay and the other providers listed on the Registries page are checked anonymously out of the box:

For private registries, or to raise Docker Hub's anonymous rate limit, add credentials to /etc/wud/wud.env, then restart WUD. Every local user can read that file, so keep secrets in a root-only file instead (see Maintenance). This example configures a private GitHub Container Registry:

WUD_REGISTRY_GHCR_PRIVATE_USERNAME=my-github-user WUD_REGISTRY_GHCR_PRIVATE_TOKEN=<your-token>

Notifications are triggers. The image has one trigger, the demonstration webhook:

Add your own triggers in the same way, for example email or Slack:

WUD_TRIGGER_SMTP_MAIL_HOST=smtp.example.com WUD_TRIGGER_SMTP_MAIL_PORT=465 WUD_TRIGGER_SMTP_MAIL_FROM=wud@example.com WUD_TRIGGER_SMTP_MAIL_TO=ops@example.com WUD_TRIGGER_SLACK_OPS_TOKEN=<your-token> WUD_TRIGGER_SLACK_OPS_CHANNEL=#containers

WUD can also update containers for you (the docker and dockercompose triggers) or run a command. These triggers are powerful and are deliberately not configured, so read WUD's documentation before you enable one. The Watchers page shows the one watcher, local, reading this instance's Docker Engine:

To watch Docker Engines on other hosts, add a watcher for each in /etc/wud/wud.env. WUD connects to a remote engine over TLS-protected TCP, and you must never expose a Docker API without TLS.

Removing the demonstration. When you watch your own containers, remove the demonstration container, its image, the two demonstration services and their settings:

sudo docker rm -f sac-demo-app
sudo docker rmi 127.0.0.1:5000/sac/demo-app:1.0.0
sudo systemctl disable --now sac-wud-registry.service sac-wud-sink.service
sudo sed -i '/^WUD_REGISTRY_CUSTOM_SACDEMO_/d; /^WUD_TRIGGER_HTTP_SACSINK_/d' /etc/wud/wud.env
sudo sed -i 's/^Wants=network-online.target sac-wud-registry.service sac-wud-sink.service$/Wants=network-online.target/' /etc/systemd/system/wud.service
sudo systemctl daemon-reload && sudo systemctl restart wud.service
7

HTTPS certificate and host name

The certificate was created on your instance's first boot for the instance's public DNS name, public IP, private IP and localhost. Only their owners can read the key, the credentials file, the session key and WUD's data directory, and only root and the docker group can read the Docker socket:

sudo openssl x509 -in /etc/ssl/wud/wud.crt -noout -subject -ext subjectAltName
sudo stat -c '%a %U:%G %n' /etc/ssl/wud/wud.key /root/wud-credentials.txt /etc/wud/wud-secret.env /var/lib/wud /var/run/docker.sock
subject=CN = ec2-34-239-126-168.compute-1.amazonaws.com, O = sac X509v3 Subject Alternative Name: DNS:ec2-34-239-126-168.compute-1.amazonaws.com, IP Address:34.239.126.168, IP Address:172.31.95.137, IP Address:127.0.0.1, DNS:localhost 600 root:root /etc/ssl/wud/wud.key 600 root:root /root/wud-credentials.txt 600 root:root /etc/wud/wud-secret.env 700 wud:wud /var/lib/wud 660 root:docker /var/run/docker.sock

To serve WUD under your own DNS name (for example wud.example.com, pointed at this instance), run the helper. It records the name, creates a new self-signed certificate for it, updates nginx and WUD's public URL, restarts WUD and rewrites the URL in the credentials file:

sudo wud-set-hostname wud.example.com

Without a recorded name, WUD follows the instance's public address after a stop and start. To use a certificate from your own certificate authority, replace /etc/ssl/wud/wud.key (keep it 0600 root) and /etc/ssl/wud/wud.crt, then run sudo systemctl reload nginx.

8

Docker API, triggers and metadata

WUD and nginx cannot reach the instance metadata service, and the two demonstration services can reach nothing but loopback. The Docker API has no TCP listener, wud is the only member of the docker group, and the configured watcher, registry and trigger are the local ones described above. The firmware-metadata refresh is masked. Confirm each of these points:

for u in wud nginx sac-wud-registry sac-wud-sink; do printf '%-22s %s\n' "$u" "$(systemctl show -p IPAddressDeny --value $u.service)"; done
TCP=$(sudo ss -Hltn | grep -cE ':(2375|2376)( |$)' || true); echo "Docker API TCP listeners: $TCP" getent group docker grep -E '^WUD_(TRIGGER|REGISTRY|WATCHER)_' /etc/wud/wud.env
FW=$(systemctl is-enabled fwupd-refresh.timer fwupd-refresh.service || true); echo "$FW" [ "$TCP" = 0 ] && [ "$(getent group docker | cut -d: -f4)" = wud ] && [ "$(sort -u <<<"$FW")" = masked ] && ! grep -qE '^WUD_TRIGGER_(DOCKER|DOCKERCOMPOSE|COMMAND)_' /etc/wud/wud.env && [ "$(systemctl show -p IPAddressDeny --value wud.service | grep -c 169.254.169.254)" = 1 ]
wud 169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 nginx 169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 sac-wud-registry ::/0 0.0.0.0/0 sac-wud-sink ::/0 0.0.0.0/0 Docker API TCP listeners: 0 docker:x:987:wud WUD_WATCHER_LOCAL_SOCKET=/var/run/docker.sock WUD_WATCHER_LOCAL_CRON=0 * * * * WUD_WATCHER_LOCAL_WATCHBYDEFAULT=true WUD_REGISTRY_CUSTOM_SACDEMO_URL=http://127.0.0.1:5000 WUD_TRIGGER_HTTP_SACSINK_URL=http://127.0.0.1:3001/sac-wud-trigger WUD_TRIGGER_HTTP_SACSINK_METHOD=POST masked masked

The two demonstration services allow loopback explicitly and deny everything else, which is why their deny list is "all addresses".

Maintenance

  • Settings and secrets: WUD reads its configuration from /etc/wud/wud.env (world-readable) and from /etc/wud/wud-secret.env (root only, read by systemd before WUD starts). Put registry tokens, mail passwords and webhook secrets in a root-only file and add it to the service with a drop-in, then restart WUD:
sudo install -m 0600 /dev/null /etc/wud/my-secrets.env sudoedit /etc/wud/my-secrets.env
sudo systemctl edit wud.service
# add: [Service] EnvironmentFile=/etc/wud/my-secrets.env
sudo systemctl restart wud.service
  • Password and users: change your password and create API tokens under your profile in the web interface (the avatar at the bottom left). Administrators can add users with read-only or administrator roles under Users. Update or delete /root/wud-credentials.txt after you change the password.
  • Backups: WUD's users, settings and history are in /var/lib/wud (SQLite). Back up the directory with WUD stopped. It holds the password hashes and API tokens, so keep the backup as safe as the credentials.
  • Upgrades: to move to a newer WUD release, launch the newer version from the listing when it is published, and restore your backup. Docker Engine updates arrive through unattended-upgrades from Docker's repository.
  • Logs: run sudo journalctl -u wud -n 100 --no-pager, or open the web interface's Logs page.
  • Security patches: unattended-upgrades remains enabled for Ubuntu's security updates and for Docker Engine.

Security recommendations

  • Keep the security group tight. Open port 22 only to your management address, and ports 80 and 443 only to the people who use WUD. Anyone who can sign in sees this host's containers, images and labels.
  • Use your own certificate before other people sign in, so their browsers trust it without exceptions.
  • Keep WUD on loopback and reach it through nginx. nginx enforces the sign-in, keeps forwarded headers honest and refuses cross-site requests.
  • Think before you enable container-updating triggers. A docker or dockercompose trigger lets WUD replace running containers automatically. Enable one only for containers where that is what you want.
  • Never publish the Docker API. If you watch other hosts, connect to their engines over TLS.

Support and licensing

WUD is developed by its contributors (the project was formerly known as What's Up Docker?) and distributed under the MIT License. Node.js is distributed under the MIT License, and Docker Engine and containerd under the Apache License 2.0. This image ships WUD 9.6.0 built from the official source with two small changes (WUD listens on loopback, and its session key is generated per instance), six updated dependencies and two upstream test directories removed. The build record, the list of changes and the licences are in /usr/share/doc/wud/. SecureAnyCloud wrote the demonstration registry, image and webhook receiver. SecureAnyCloud provides the packaging, the hardening, first-boot HTTPS and per-instance credentials, and 24/7 support.

SecureAnyCloud is not affiliated with or endorsed by the WUD project or its authors. "Docker" is a trademark of Docker, Inc., used here only to describe the container engine WUD monitors; SecureAnyCloud is not affiliated with, endorsed by, or sponsored by Docker, Inc. Product names are marks of their owners and are used here only to identify the software.

For help with deployment or configuration, email sales@secureanycloud.com or visit SecureAnyCloud support.

Deploy on AWS

Launch WUD Container Update Monitor 9.6.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS