Releases: psviderski/uncloud
Release list
Nightly Build
Built from main at db55df6 on 2026-09-14 09:45 UTC.
The commands below show how to install the nightly version of uncloud.
Warning
These are nightly development builds and may be unstable.
Install uncloud CLI:
curl -fsS https://get.uncloud.run/install.sh | VERSION=nightly sh
Initialize a cluster or add a machine:
uc machine init --version nightly user@host
uc machine add --version nightly user@host
Upgrade machine daemon:
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/nightly/uncloudd_linux_${ARCH}.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloud
v0.20.0
This release adds secrets for passing sensitive data to services, a new uc proxy command for port-forwarding, a Prometheus metrics endpoint, uc machine ls that surfaces each machine's OS, Docker, and daemon versions. Plus daemon self-upgrade on uc machine init/add, WireGuard MTU auto-detection, shell completion, and more.
uc CLI and the uncloudd daemon on every machine must be upgraded to 0.20. See Breaking changes below before you upgrade.
⚠️ Breaking changes
0.20 changes the internal gRPC API proxy format and migrates the cluster store to a new Corrosion version, so a mixed 0.19/0.20 cluster will not work. The built-in version check rejects requests between incompatible CLI and daemon versions, so upgrade everything together. See Upgrade to 0.20.0 for instructions.
- Server-side gRPC proxy resolution (#247). API proxy targets (machines) are now resolved on the daemon instead of the CLI. This changes the request format on the wire, so old and new components can't talk to each other. Thanks to @jabr for the contribution ❤️
- Corrosion now runs as a managed container (71da325). The Corrosion cluster store moved from a systemd unit to a Docker container and was upgraded to Corrosion v1 (
2026.6.15). Existing data is migrated to the new format automatically on first daemon start. Auth is now enabled for local Corrosion API requests too (#110). - CLI artifact renamed
uncloud_*→uc_*(a5d73fe). Homebrew and the install script handle this for you. Only update your own scripts if you download the CLI archive directly. The daemon archive name (uncloudd_*) is unchanged. - Unregistry image proxy moved from port
5000to51500(d36ff67).uchandles this automatically when pushing images. Only update your setup if you reach this proxy port directly in your own tooling.
Secrets support
You can now keep sensitive data like passwords, API tokens, and private keys out of your Compose file. Define a secret with the new x-command extension and reference it from a service's environment with secret://<name>. The command runs locally at deploy time and pulls the value from your password manager, cloud secrets store, or any CLI you already use.
services:
api:
image: myapp:latest
environment:
DB_PASSWORD: secret://db_password
secrets:
db_password:
x-command: op read "op://prod/myapp/db_password"The value never lands in your Compose file or git. See the new Secrets doc for supported sources, caveats, and examples.
Proxy a service port locally
PR: #384. Thanks to @miekg for the contribution ❤️
The new uc proxy command forwards a service port to a local port over the cluster network, similar to kubectl port-forward. This is handy for reaching an internal database or admin UI from your laptop without exposing them publicly.
Richer uc machine ls
Changes: 8aa0a96, ad43569, 1d5c717, 23d6b44
uc machine ls now shows the OS, KERNEL, ARCH, DOCKER, and VERSION (daemon) of each machine. You can spot version drift and outdated daemons at a glance.
$ uc machine ls
NAME STATE ADDRESS PUBLIC IP WIREGUARD ENDPOINTS OS KERNEL ARCH DOCKER VERSION
machine-1 Up 10.210.0.1/24 203.0.113.10 203.0.113.10:51820 Debian 12.12 6.1.0-41-amd64 amd64 29.4.0 0.20.0
machine-2 Up 10.210.1.1/24 198.51.100.7 198.51.100.7:51820 Debian 12.5 6.1.0-18-amd64 amd64 26.0.0 0.20.0
machine-3 Up 10.210.2.1/24 - 192.0.2.44:51820 Ubuntu 22.04.5 LTS 6.8.0-1050-oracle arm64 29.5.3 0.20.0Pass -o json for machine-readable output to use in scripts.
Prometheus metrics
PR: #304. Thanks to @miekg for the contribution ❤️
Each daemon now serves the initial set of Prometheus metrics on http://<machine-ip>:51090/metrics, listening on the machine's internal IP. Point your scraper at it to monitor the cluster.
Daemon self-upgrade on machine init/add
Change: a26af3b
uc machine init and uc machine add now upgrade the installed daemon binary to the latest (or a specified --version) if the daemon was already installed on the machine.
Improvements
- WireGuard now auto-detects the optimal interface MTU, with a new
--wg-mtuflag to override it (0c3b8b1). - New
--wg-portflag foruc machine init/addto customise the WireGuard listen port (#366). Thanks to @dasunsrule32 for the contribution ❤️ x-portscan bind to multiple host IP addresses given as a CIDR prefix (#358). Thanks to @miekg for the contribution ❤️- New
uc versionanduncloudd versioncommands that print full build information, replacing the--versionflag (2f15915). uc machine init/addinstallscurlon the remote machine if it's missing (#402).- New
uc caddy logsalias foruc logs caddy(#381). - Shell/argument completion for the
ucanducindCLIs (machines, services, volumes) (#309, #344, #352). Thanks to @miekg for the contributions ❤️ - Support rootless Docker locally when pushing images to the cluster (#347). Thanks to @tonyo for the contribution ❤️
- The CLI strips ANSI colors from table output and skips interactive TUI elements when stdout is not a TTY (e3823c2, #386).
Bug fixes
- Reject relative volume source paths in Compose with a clear error (#353). Thanks to @miekg for the contribution ❤️
- Return a non-zero exit code when a
uccommand is cancelled by declining a confirmation prompt (#354). - Don't include outdated containers from a removed machine in the DNS and Caddy configs (07acb31).
- Improve context cancellation and Corrosion resubscription handling during watch and sync operations (328d175, 83256b5, 99e1ae0, 5f07bc5).
- Use a forked Bubble Tea that drains pending TTY input on shutdown (#286).
Upgrade to 0.20.0
Upgrade all machines and your local CLI to 0.20. Corrosion data migrates automatically on the first daemon restart.
Important
On the first restart, each daemon pulls the Corrosion container image ghcr.io/unlabs-dev/corrosion:2026.6.15. Make sure your machines can reach ghcr.io, or pre-pull the image, otherwise the cluster store won't start.
Uncloud CLI locally
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
Run the following commands on each machine:
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.20.0/uncloudd_linux_${ARCH}.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudAfter upgrading
On the first restart, the daemon migrates the Corrosion store and stops the legacy systemd service. A couple of leftovers need manual cleanup on each machine:
-
The old store is preserved at
/var/lib/uncloud/corrosion.backup-<timestamp>. Once you've verified the cluster is healthy (uc machine ls), you can remove it:sudo rm -rf /var/lib/uncloud/corrosion.backup-* -
The legacy Corrosion systemd unit and binary are left in place because the daemon's sandbox doesn't have permission to delete them. Remove them manually:
sudo rm /etc/systemd/system/uncloud-corrosion.service /usr/local/bin/uncloud-corrosion sudo systemctl daemon-reload
Changelog
v0.19.0
This release brings easier debugging of failed deploys, new troubleshooting commands (uc machine logs and uc machine rtt), and a nightly release channel.
Read on for the full list of changes and upgrade instructions.
Show logs from a failed deploy
Changes: 8afe523, 303c8e4, 56a54ab
When uc deploy fails because a pre-deploy hook failed or a new container couldn't become healthy, it now prints the last 10 (configurable) log lines from the failed container.
This is a quality-of-life improvement that saves you from running a follow-up uc logs to figure out what went wrong.
See Failed container logs for more details.
Filter service logs by container
Change: 2045819
uc logs now accepts a SERVICE/CONTAINER form where CONTAINER is a container name, full ID, or unique ID prefix. This is handy when one replica of a service is misbehaving and you want to look at it without the noise from the others:
uc logs web/2f60
# Mix and match
uc logs api/61d57fd3428f web/2f60 dbStream machine logs
uc and the daemon to be upgraded to v0.19.0
PRs: #282, #283. Thanks to @miekg for the contribution ❤️
You can now stream logs from the systemd services that run Uncloud itself on remote machines using the new uc machine logs command. It covers three main services:
uncloud- the Uncloud daemonuncloud-corrosion- the Corrosion service providing the distributed cluster storedocker- the Docker daemon
For example, stream the Uncloud daemon logs from all machines with:
uc machine logs -f uncloudThis is useful for troubleshooting Uncloud operations without having to SSH into every machine and run journalctl yourself.
See uc machine logs for more details and examples.
Round-trip time between machines
uc and the daemon to be upgraded to v0.19.0
PR: #226. Thanks to @jabr for the contribution ❤️
The new uc machine rtt command shows the round-trip time between every pair of machines in the cluster. This gives you a real-time view of how the mesh network is performing without needing to run manual ping tests.
The data is collected from Corrosion's gossip protocol, which samples latency between peers as part of its normal operation.
$ uc machine rtt
MACHINE PEER MEDIAN STDDEV
machine-1 machine-2 140ms ±19.4ms
machine-1 machine-3 39ms ±1.1ms
machine-2 machine-1 168ms ±18.5ms
machine-2 machine-3 203ms ±42.3ms
machine-3 machine-1 40ms ±2.0ms
machine-3 machine-2 158ms ±15.2msA new RTT column has also been added to uc wg show to show the median round-trip time to each WireGuard peer.
Local machine upstreams first in Caddyfile
Change: 45cf87a
The generated Caddyfile now lists upstreams from the local machine first for each service.
On its own this doesn't change routing behaviour (Caddy's default random load balancing policy ignores order). But if you pair it with the first policy in a custom Caddy config, you can always prefer the same-host replica and only fall back to remote machines when the local one is unhealthy.
services:
app:
...
x-caddy: |
example.com {
reverse_proxy {{upstreams 8000}} {
import common_proxy
lb_policy first
}
log
}This saves a cross-machine WireGuard hop for every request that hits Caddy on the machine which already has a replica of the target service. This is especially useful if you have a multi-region setup.
Nightly builds
PR: #308. Thanks to @tonyo for the contribution ❤️
Every push to main now produces a set of nightly binaries tagged as the nightly release on GitHub.
They're great for testing upcoming unreleased changes and reporting regressions early. They might be unstable, so please don't run them in production.
Install the nightly uc CLI locally:
curl -fsS https://get.uncloud.run/install.sh | VERSION=nightly shInitialise a cluster or add a machine with a nightly daemon:
uc machine init --version nightly user@host
uc machine add --version nightly user@hostImprovements
uc machine init/addnow embed the install script into theucbinary and send it to the remote machine over the existing SSH connection instead ofcurl | bash(fe829ef).- New
uc ctx showcommand prints the name of the currently active cluster context, great for shell prompts and scripts (#317). - SSH connections now use
-o StrictHostKeyChecking=accept-new, which silently accepts host keys on first connection but still protects against key changes later (#303). - The
STOREcolumn inuc imagesis hidden when all machines use the containerd image store, which is the default for new clusters (c38d916) - Image push errors now include the underlying error from the unregistry proxy, which makes it much easier to tell apart a broken image push from a broken SSH tunnel (d340659)
ucindnow accepts aUNCLOUD_CONFIGenvironment variable to override the config file path for development clusters (#315).- New
ucind cluster lscommand lists the local development clusters managed byucindwith their machines (#316).
Bug fixes
- Fixed containerd socket auto-detection for unregistry after a machine reboot (47199c3).
- Fixed Caddy config being regenerated on every service change because container records were serialised non-deterministically (#111).
- Fixed SSH control socket path on WSL2 when the runtime directory doesn't exist (#319).
- Fixed a stale SSH
ControlMasterconnection sometimes causinguc machine init/addto hang (fdbffbf).
Upgrade to 0.19.0
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.19.0/uncloudd_linux_${ARCH}.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- 4d5ca42 chore: add more info about cluster connections in error for 'machine rm'
- f60a9ff chore: check SSH TCP forwarding for dial operations and return a friendlier error
- 3310b47 chore: do not log too noisy 'Sent log stream heartbeat.' log line for machine logs
- d340659 chore: enrich image push errors with errors from proxy to unregistry
- c38d916 chore: hide STORE column in 'uc images' output if all machines use containerd image store
- f415901 chore: make experiments a separate Go module, remove unnecessary dependencies from root module
- 3918170 chore: set x-context for website deploy
- 7b554cd chore: style the machine reset prompt in red and fix the padding for [y/N]
- 208a561 chore: trigger container sync on ActionHealthStatusRunning Docker event as well
- dd3d809 chore: use a non-registry image format for website
- 60ff088 ci: Add go build/module caching
- 02a318c ci: Build and publish latest (nightly) binaries (#308)
- b1be80a ci: Run nightly builds on macos runners
- 9cfcf49 ci: Update cache key for nightly builds
- 45cf87a feat(caddy): order local machine upstreams first in generated Caddyfile
- 8afe523 feat(deploy): print last logs from failed pre-deploy hook
- 303c8e4 feat(deploy): print last logs from new container when fails to become healthy
- f44ada0 feat(logs): 'uc machine logs' to view logs from systemd services on mac...
v0.18.0
The main highlights of this release are pre-deploy hooks for running database migrations and a redesigned deployment plan output that makes uc deploy much nicer to read and understand.
On top of that, 0.18.0 also:
- makes the system
sshCLI the default connection method (with fallback to the Go implementation) - adds Compose support for
pid,shm_size, and the newx-contextextension to pin a Compose file to a cluster - brings new docs, a bunch of quality-of-life improvements and bug fixes, read on for the full details!
Pre-deploy hooks
uc and the daemon to be upgraded to v0.18.0
Changes: f4581ea, 1c8b770, 772b31b, 0e820f9
You can now run a one-off command before deploying a service using the new x-pre_deploy Compose extension. This is ideal for database schema migrations, uploading static assets to a CDN, cache invalidation, and any other setup task that needs to run once before new code goes live.
services:
web:
build: ..
environment:
DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/postgres
x-pre_deploy:
# Apply Django migrations from the built image before deploying new app containers.
command: python manage.py migrate
depends_on:
- dbHere is how it's displayed in the deploy plan when you run uc deploy:
The hook command runs in a new container that inherits the service's image, environment variables, volumes, placement, and compute resources.
If the command exits successfully, the deployment continues with a normal rolling update. If it fails or times out, the deployment stops immediately and uc deploy displays the latest hook logs to help you diagnose the issue.
Container tables in uc ps and uc inspect now also list pre-deploy hook containers.
See the docs:
- Pre-deploy hooks guide for more details and examples
x-pre_deployreference for all available attributes
Restyled deployment plans
Changes: 0f4c211, f5a77b8, b4b1232
The deployment plan output that you see when running uc deploy, uc scale, and uc caddy deploy has been redesigned with consistent styling, clearer operation verbs, and a header and the prompt showing the target context.
We hope this makes it easier for you to understand what changes will be made and to which cluster before you confirm the deployment.
System ssh is now the default connection method
Change: 06c2bc5
The ssh+cli:// connection method that uses your system's ssh CLI is now the default for new connections, so the prefix can be omitted:
# Old
uc machine init ssh+cli://user@host
# New
uc machine init user@hostssh_cli: can also be replaced with just ssh: in the config file (~/.config/uncloud/config.yaml):
contexts:
prod:
connections:
- ssh: user@hostThis will by default use your existing SSH config, agent, keys, ProxyJump, and ProxyCommand setup automatically. You can fall back to the Go native SSH implementation using ssh+go:// prefix.
Combined with the SSH control socket reuse introduced in v0.17.0, this makes most uc commands noticeably faster and removes a whole class of authentication friction.
The new Connecting to a cluster doc walks through all the supported connection schemes (ssh://, ssh+go://, tcp://, unix://), how uc picks a machine to talk to from your config, and how to connect without a config file for CI pipelines and scripts.
Cluster context selection in Compose
Change: 1525d18
You can now pin a Compose file to a specific context using the new x-context extension. This prevents accidentally deploying to the wrong cluster when you switch contexts.
x-context: prod
services:
web:
image: myappWhen x-context is set, uc deploy will use that context regardless of your currently selected one in the Uncloud config. The deployment plan output also displays the target context so you always know where your changes are going.
See x-context reference for more details.
Compose pid namespace support
PR: #276. Thanks to @miekg for the contribution ❤️
You can now configure the PID namespace mode for service containers. The most common use case is pid: host, which lets a container see and interact with processes on the host. This is useful for monitoring agents, debuggers, and similar tooling.
services:
monitoring:
image: agent
pid: hostCompose shm_size support
Change: 8ae38cf
You can now set shm_size, the size of the /dev/shm shared memory tmpfs. This is useful for databases like Postgres, headless Chromium, and other workloads that need a larger shared memory segment.
services:
postgres:
image: postgres:18
shm_size: 256mbDocumentation
- Connecting to a cluster: a complete guide to cluster contexts, connection resolution and all supported types, and how to connect without a config file
- CLI configuration file: a full reference for the
~/.config/uncloud/config.yamlfile, covering contexts, connections, and all supported fields - Pre-deploy hooks: a guide for the new feature, with examples for database migrations and other one-off setup tasks
- Compose extensions: a dedicated reference page for all Uncloud-specific Compose extensions
Improvements
- The
ucCLI and the daemon now exchange versions on every gRPC call and error if they are incompatible. This is a groundwork to make better user experience when releasing breaking changes in the future (#260). Thanks to @jabr for the contribution ❤️ - New
uc execaccepts an optional--separator before the command, matching Docker and other CLIs (#301). Thanks to @nick-potts for the contribution ❤️ - New
uc docs --manualflag generates manual pages foruc, making it easier for distribution maintainers to package manpages alongside the binary (#302). Thanks to @miekg for the contribution ❤️ - The daemon now exposes a gRPC method to fetch journald logs from a machine, laying the groundwork for an upcoming
uc machine logscommand (#282). Thanks to @miekg for the contribution ❤️ - Warnings are now printed for detected unsupported Compose features (#288). Thanks to @miekg for the contribution ❤️
- New
--auto-confirmflag foruc scalewhich now always asks for confirmation before changing replica counts - New
--ulimitflag foruc runto set resource limits - bumped Go to 1.26.1 and modernized the codebase using Go 1.26 (#278)
- Migrated TUI components to
lipgloss/v2,bubbletea/v2, andhuh/v2
Bug fixes
- Fixed
uc deploycrash in an initialised but empty git repository (#275). Thanks to @tonyo for the contribution ❤️ - Fixed
ucinddownloading the wrong Corrosion architecture on arm64 (#285). Thanks to @miekg for the contribution ❤️ - Fixed output contamination in the SSH CLI executor by separating stdout and stderr (#270)
- Fixed trying other machine connections when the first one fails for the new default
sshtype. Fixed the TUI progress spinner.
Upgrade to 0.18.0
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz...v0.17.1
This is small patch release that adds WireGuard endpoint management for machines, Compose stop_grace_period support, and several networking fixes.
WireGuard endpoint management
You can now manually specify what WireGuard endpoint to use when adding or initialising a machine instead of relying on auto-detection. This is useful when a machine is behind a NAT or has multiple network interfaces.
uc machine init user@host --wg-endpoint 203.0.113.1
uc machine add user@host --wg-endpoint 203.0.113.2 --wg-endpoint 192.168.1.5You can also update the WireGuard endpoint for an existing machine:
uc machine update my-machine --wg-endpoint 203.0.113.1Compose stop_grace_period support
Control how long to wait before sending SIGKILL to a container during replacements and stops.
services:
app:
image: myapp
stop_grace_period: 30sImprovements
- Tailscale addresses are excluded from auto-detected WireGuard endpoints: see Discord thread
uc logsnow prints a warning and continues instead of failing when some Compose services are not found in the cluster- Improved reliability of the initial cluster store sync by waiting for known missing changes
- Removed the obsolete
uc machine tokencommand
Bug fixes
- Fixed Uncloud DNS resolution for IPv6 machines by creating AAAA records: #257
- Fixed connection formatting when changing connection with
uc ctx conn
Upgrade to 0.17.1
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.17.1/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.17.1/uncloudd_linux_arm64.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- d5687cd chore: combine some e2e tests to reduce the number of ucind clusters hence used system resources
- 4de17cb chore: delete the obsolete 'machine token' command
- e548717 chore: increase wait for test cluster timeout 30s -> 60s for e2e tests on GHA
- 38c7dda chore: rename --endpoint to --wg-endpoint for 'uc machine update' command
- 897f03a chore: skip not found services when streaming logs for Compose services (print warning)
- 2405b15 chore: validate endpoints is not empty in update machine requests
- a67f936 chore: wait for known missing changes during the initial cluster store sync
- 51c7b5b feat: add --wg-endpoint flag to 'uc machine add/init' to specify wireguard endpoint for the machine instead of auto-detecting
- bad0f97 feat: add support for updating WireGuard endpoints for a machine (uc machine update)
- d9934b9 feat: support compose stop_grace_period to change timeout before sending SIGKILL
- 7b306f2 fix: another attempt to fix flaky test container_crashes_on_startup_without_healthcheck
- 2222434 fix: connection formatting when changing connection with 'ctx conn'
- a507b20 fix: create AAAA DNS record for IPv6 machines" (#257)
- 3c43543 fix: flaky test TestDeployment/container_crashes_on_startup_without_healthcheck
- 1f328e9 fix: remove the incorrect e2e test for updating machine endpoints with empty list
- e6f013d fix: skip Tailscale addresses for using as auto-detected WireGuard endpoints
- 51b8c29 fix: typo
v0.17.0
This release brings container health monitoring with automatic rollback during rolling deployments, Compose spec support for healthcheck, devices, and ulimits, and various reliability improvements.
✨ Highlights
Container health monitoring and rollback
Changes: 7a9eac5, 7b88040, ce3cb8a
Rolling deployments now monitor crashes and health checks after starting new containers. If a container keeps restarting or becomes unhealthy, the deployment automatically rolls it back and fails to prevent downtime.
Screen.Recording.2026-03-02.at.8.48.29.am.mov
Compose healthcheck support
Compose files now support the healthcheck attribute, allowing you to define health checks for your services:
services:
app:
image: myapp
healthcheck:
test: curl -f http://localhost:8000/health
interval: 5s
retries: 3
start_period: 10s
start_interval: 1sUse uc deploy --skip-health flag to bypass health monitoring for faster emergency deployments.
See Rolling deployments for more details on how rolling deployments work and how to configure health checks for your services.
Control container replacement order during rolling deployments
PR: #248. Thanks to @nick-potts for the contribution ❤️
You can now control the order of container replacement during rolling deployments with deploy.update_config.order in your Compose file:
start-first(default): starts a new container before stopping the old onestop-first: stops the old container before starting a new one (brief downtime)
services:
app:
image: myapp
deploy:
update_config:
order: stop-firstThe default order automatically switches to stop-first if a service mounts a volume to prevent data corruption.
See Rolling deployments for more details.
Compose devices support
PR: #250. Thanks to @jabr for the contribution ❤️
You can now map host devices into containers, for example, Intel integrated GPU for video transcoding using the devices attribute in your Compose file:
services:
app:
image: myapp
devices:
- /dev/dri:/dev/dri
- /dev/ttyUSB0:/dev/ttyUSB0:rwCompose ulimits support
PR: #244. Thanks to @ipaddicting for the contribution ❤️
You can now set ulimits for service containers in your Compose file. For example, to increase the maximum number of open files:
services:
app:
image: myapp
ulimits:
nofile:
soft: 65536
hard: 65536Auto-provision volumes for global services
PR: #243. Thanks to @zasdaym for the contribution ❤️
When deploying a global service with a volume, the volume is now automatically created on all machines in the cluster.
Improvements
- SSH connections with
ssh+cli://prefix (usesshCLI instead of Go native SSH implementation) reuse a single SSH connection via control socket - significantly speeds upuccommands - Improved
uc image pushsupport on macOS by always running proxy to virtualised Docker (except OrbStack that doesn't require it) - Global service deployment stops all running conflicting containers, e.g. left from interrupted deploys, not just the first one
- Temporary socat proxy containers created by
uc image pushare labeled withuncloud.managed
Bug fixes
- Fixed IPv6 address formatting for HTTP URLs (#254)
- Fixed
uc image pushwhen using Rancher Desktop locally (#251) - Fixed
uc machine initto reset an already initialised machine when usingssh+cli://connection
Upgrade to 0.17.0
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.17.0/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.17.0/uncloudd_linux_arm64.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- b48ebe2 chore: UNCLOUD_HEALTH_MONITOR_PERIOD accepts duration (10s, 500ms, 0)
- f8d1945 chore: add TODO for ReplaceContainerOperation
- fe56d6d chore: always run proxy to virtualised Docker on macOS for 'image push' except OrbStack
- f48dc25 chore: fix landing navbar github/discord buttons wrap on mobile
- 44013da chore: format AGENTS, instruct to not use em dashes
- 6e59657 chore: global reconciliation: stop all running conflicting containers, not only replace the first one
- a5a9ef5 chore: init container healthcheck const
- 87e49df chore: label temporary socat proxy containers created by 'uc image push' with uncloud.managed
- 215f214 chore: lint and fix e2e deploy tests with ReplaceContainerOperation
- c91a964 chore: make ssh+cli connections reuse one SSH connection via control socket. Fix image push
- 185cf19 chore: minor full-spec test change
- 1d4dbd9 chore: minor sshcli refactgor
- 5c54e9d chore: refactor device mapping to be compliant with Compose (CDI requests)
- 93d7f29 chore: remove TODO about encapsulating Client in deploy operations
- 808bda6 chore: remove unused constants
- 2588279 chore: rename AI.md to AGENTS.md
- e670559 chore: rename env var UNCLOUD_DEFAULT_HEALTH_MONITOR_PERIOD_MS -> UNCLOUD_HEALTH_MONITOR_PERIOD_MS
- 7c4f739 chore: specify machines to deploy website to
- 18ebd29 chore: split deploy operations into separate files in operation package
- e0a63a3 chore: typo
- 4443fa9 chore: update full-spec test to include latest implemented Compose attributes
- 0b2e1bb chore: update newsletter form to substack
- 53bf446 deploy.update_config.order support to start-first or stop-first when replacing containers (#248)
- ab6f856 feat: Add support for compose
devicesmappings (#250) - ce3cb8a feat: add --skip-health flag to bypass health monitoring during container deployment
- 17c1bb5 feat: add WaitContainerHealthy client method and health check utilities
- 3056e2a feat: add support for healthcheck in Compose
- 3bd9400 feat: add support for ulimits in compose and container creation (#221) (#244)
- 15d9ceb feat: auto-provision volumes on all machines for global services (#243)
- 7a9eac5 feat: implement container health monitoring and rollback during rolling deployment (closes #24)
- 14056cc fix: format IPv6 addr correclty for HTTP URL (#254)
- 7bfaf31 fix: image tag template formatting in docs
- 2940965 fix: recreate container on ulimit changes, add test
- 476a2d5 fix: reset already initialised machine on 'uc machine init' when using ssh+cli connection
- 7b88040 fix: rolling container replacement: if new container fails, rollback and run old container only if it was running
- ce46a67 fix: ssh args for machine init/add when using ssh+cli
- a4a8e70 fix: sshcli tests
- d3ee739 fix: support image push when using Rancher Desktop locally (#251)
v0.16.0
This is a smaller release focused on reliability improvements, with a new WireGuard network inspection command and expanded Compose spec support for container capabilities and sysctls.
✨ Highlights
WireGuard network inspection
PR: #161. Thanks to @jabr for the contribution ❤️
The new uc wg show command displays the WireGuard network configuration for a machine, including the interface details and all configured peers. This is useful for debugging network connectivity issues and understanding the mesh topology.
Use the -m/--machine flag to inspect the configuration of a specific machine in the cluster or the global --connect user@host flag to inspect the machine that has issues connecting to the cluster.
uc wg show
uc wg show -m machine-1
uc wg show --connect user@hostKernel capabilities and sysctls support
PRs: #238, #239. Thanks to @4ndv for the contribution ❤️
You can now use cap_add, cap_drop, and sysctls attribute in your Compose files to add or remove Linux capabilities and configure kernel parameters for service containers. This allows fine-grained control over container privileges and behaviour.
services:
app:
image: myapp
cap_drop:
- ALL
cap_add:
- NET_ADMIN
sysctls:
net.core.somaxconn: 65535
net.ipv4.tcp_syncookies: 1Improved cluster initialisation reliability
Machine initialisation and joining with uc machine init/add have been made more reliable that fixed WireGuard peer misconfiguration for machines joining the cluster:
- The daemon now waits for the initial Corrosion state sync and cluster components before serving gRPC requests
uc machine initanduc machine addcommands wait for cluster readiness- gRPC auto-retries with exponential backoff for transient connection failures (up to ~8 seconds)
Note
You have to upgrade both the local uc CLI and the Uncloud daemon on all your current machines to v0.16.0 to benefit from this improvement.
Other improvements
- Added
--yesflag touc machine init/addto auto-confirm machine reset - Added
ctx connalias foruc ctx connectioncommand - Reduced gRPC connection timeout to proxied machines from 20s to 10s
- Machine state file is now saved atomically to prevent corruption
- Config mounts are now creating non-existent parent directories (#233)
Upgrade to 0.16.0
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.16.0/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.16.0/uncloudd_linux_arm64.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- 878f96a Revert "build: Generate CLI docs in GHA"
- 9efaab2 build: Generate CLI docs in GHA
- 5e0d4d0 build: Generate CLI docs in GHA (#236)
- 33a3683 chore: Regenerate CLI docs
- 85a2615 chore: add 'ctx conn' alias for 'ctx connection' command
- 5acf557 chore: add --yes flag to 'uc machine init/add' to auto-confirm machine reset
- 777615b chore: add TODO to remove extra checks after upgrading clusters to perform store sync
- 4d97c30 chore: enable gRPC auto retries for transient Unavailable failures up to ~8s
- 76affeb chore: minor formatting for 'wg show' command, enrich Unimplemented error with >=0.16 requirement
- fc84709 chore: new InspectMachine gRPC method that to return store DB version (lamport time)
- 4366714 chore: pass current store DB version when adding new machine to cluster
- f86e63c chore: reduce the default gRPC connection timeout to proxied machines 20->10s
- bac34eb chore: save machine state file atomically
- 5308c87 chore: update 'uc machine init/add' to wait for cluster readiness, confirm caddy deployment on added machine
- 9bd5ffc chore: update ucind cluster to wait for initial store sync and cluster readiness
- f6cf731 chore: wait for FailedPrecondition in addition to Unavailable for backward compatibility
- 8d8acd5 chore: wait for the initial store sync and cluster components before serving cluster gRPC requests
- a945291 feat: Add
uc wg showcommand to inspect a machine's uncloud wireguard network (#161) - 6c2f85d feat: add support for
cap_addandcap_dropcompose keys (#238) - 06c3fba feat: add support for
sysctlscompose key (#239) - 2c34ba7 fix(configs): Create non-existent parent directories automatically (#233)
- 9a1d2e0 fix: Equals and Clone for configs (#235)
- b2322e1 fix: WireGuard peers misconfiguration on joined machine by waiting for the initial store sync
- aa71ab0 fix: e2e caddy test after changing the config header
- 4be1ea3 fix: machine name for failed machines in 'uc ps'
- d2a7af7 fix: uncloud daemon crash when listing partially replicated container records
- 65e9cdd refactor: use WaitGroup.Go to replace wg.Add(1)/go/wg.Done() boilerplate (#222)
v0.15.1
This is a bug fix release that upgrades Unregistry to v0.4.1. It fixes occasional failures with pushing images that consist of big layers (hundreds of MBs).
Upgrade to 0.15.1
Machine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.15.1/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.15.1/uncloudd_linux_arm64.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- db09dec chore: add more tests for MatchesDockerVolume and update error message when volume spec doesn't match
- 0b32cd2 chore: upgrade unregistry 0.3.1 -> 0.4.1 with a fix for pushing big images
- 20cdcdf fix: Set volume driver name to "local" if not specified (#219)
- 425b974 fix: panic when initialising new cluster with --connect
v0.15.0
This release features 4 weeks of work from 6 contributors. It brings service logs streaming, new service management commands, SSH CLI connection mode, interactive cluster connection selection, HTTP/3 support, and various improvements and bug fixes.
✨ Highlights
Service logs streaming
PR: #196
The new uc logs command streams logs from service containers across all machines in the cluster. Logs are merged from all replicas with colored output, strict timestamp ordering, and service/container identification.
You can filter logs by machine using -m/--machine, follow mode with -f, and time ranges with --since/--until.
Running uc logs without arguments streams logs from all services defined in the local Compose file.
New service commands
PRs: #165, #195. Thank you @jabr for the contribution! ❤️
-
The
uc pscommand displays all running containers in the cluster with service name, machine, state, health status, IP address, and creation time. You can sort containers by service, machine, or health status using the--sortflag.
-
New
uc startanduc stopcommands allows starting and stopping all containers of the specified services across cluster machines. The stop command supports--signaland--timeoutoptions for graceful shutdown control.
SSH CLI connection mode
PRs: #152, #173. Thank you @luislavena for the contribution! ❤️
A new ssh+cli:// connection scheme allows using the system's ssh (OpenSSH) CLI client instead of the native Go implementation of the SSH protocol for connecting to cluster machines. This makes it possible to init machines in private networks via ProxyJump, use hardened SSH agents like 1Password or Yubikey, and use existing custom host configuration from your ~/.ssh/config.
If ssh <target> works from your terminal, then uc machine init/add ssh+cli://<target> should also work.
We will make this connection mode the default after addressing the edge case of removing machines when using the ssh+cli scheme.
Interactive connection selection
PR: #170. Thank you @jabr for the contribution! ❤️
The new uc ctx connection command provides an interactive selector for choosing the preferred cluster connection among multiple configured ones.
HTTP/3 support
PR: #204. Thank you @z0rrn for the contribution! ❤️
Caddy (reverse proxy) now exposes UDP port 443 for HTTP/3 (QUIC) protocol support, enabling faster HTTPS connections for supported clients.
New managed DNS domain
Free managed DNS subdomains now use the new shorter xxxxxx.uncld.dev domain instead of xxxxxx.cluster.uncloud.run to separate the main project domain (uncloud.run) from the user cluster's domains. See tweet for more details. Existing subdomains will continue to work.
You can run uc dns release && uc dns reserve to release your old subdomain and reserve a new one under uncld.dev.
Improvements
--contextflag is now a global option available on all commands (#174)- Unix domain socket connector for local daemon connections (#186)
- Machine ID stored on connection entries in
~/.config/uncloud/config.yamlfor automatic cleanup when removing machines (#182) - Services sorted by name in
uc lsoutput IP ADDRESScolumn added touc psanduc inspectoutputCREATEDcolumn added touc pswith fallback sorting by creation time- Machine install.sh script supports
INSTALL_ONLYmode to skip daemon setup (#194) uc --helpoutput shows links to documentation and Discord- Minor documentation updates and improvements
Bug fixes
- Fixed volume driver options not being used when driver is not explicitly specified (#211)
- Fixed new Compose deployment with volumes and
--recreateflag (#176)
Upgrade to 0.15.0
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.15.0/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.15.0/uncloudd_linux_arm64.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- 3c33973 chore(exec): Update TODO regarding signal forwarding
- 596bc56 chore: 'uc stop' - make --timeout default explicit, update flag and long descriptions
- bc65c73 chore: add CREATED column to 'uc ps', fallback sorting by CREATED
- 05c8117 chore: add redirect from uncloud.run/discord to discord invite
- e30ea89 chore: enable CGO to be able to build fsevent required by updated compose on macOS
- 2e655d8 chore: extract version from latest redirect in install_cli.sh (#180)
- e87207e chore: fix landing logo shadow
- f215fae chore: group deploy and service management commands in uc --help
- 4433095 chore: show links to docs and Discord for the root 'uc --help' command
- 95afc7f chore: sort 'uc inspect' containers by CREATED
- 3fbba6d chore: sort services in 'uc ls' output by name
- 3019377 chore: update logo for docs
- 53def3a chore: update white color in logo-title-dark.svg
- bf65fba feat --utc flag for 'uc logs' command to print timestamps in UTC
- 234985b feat(install): Add install-only mode to the install script (#194)
- eea8172 feat(ssh+cli): Support SSH CLI on machine init and add commands (#173)
- 4b4b721 feat(uc/caddy): expose 443/udp port for HTTP3 (#204)
- 27cfe1c feat: 'uc logs' without argements streams logs for services in the local Compose file
- a9a720f feat: Add
uc service start/stopcommands (#195) - 1d41373 feat: Interactive 'uc ctx connection` command to select preferred cluster connection (#170)
- 91a09d5 feat: add CLI connector for unix domain socket (#186)
- cb0df21 feat: add IP ADDRESS column to 'uc ps' and 'uc inspect'
- d89bfb8 feat: add
uc pscommand to list all containers in the cluster (#165) - 79dc05c feat: service logs command to stream service logs (#196)
- 76b4369 feat: store machine id on connection entries in Uncloud config so it can be removed with machine (#182)
- 1e6aaf4 feat: support filtering service logs by machine (-m/--machine)
- 796363f fix: TestCollectContainers unit tests
- 57205e1 fix: new Compose deployment with volumes and --recreate flag (fixes #176)
- 6373d40 fix: volume driver options are not used if driver if not specified [bug #210] (#211)
- f6d75d5 lint
- ebd4622 lint
- 939645e refactor: Make
--contextcli flag a global option (#174) - 75085b3 refactor: Simplify dns e2e test using new ExecContainer functionality (#178)
- 6a1cd7b refactor: replace loadProjectFromContent with compose.LoadProjectFromContent
v0.14.0
This release features 3 weeks of work from 4 contributors. It's focused on deploying apps from source code, executing commands in running containers, and expanding Compose support.
✨Highlights
Deploy an app from source code
Build and deploy your apps in one command. No registry required.
Just configure a build section in your Compose file and run:
uc deploy- Builds your images locally
- Tags images with a Git version making every deployment traceable to its source commit
- Pushes images straight to your cluster machines using unregistry
- Deploys your services as usual
See the new Deploy an app guide for full details.
Watch uc deploy building and deploying a demo app (18 seconds):
uc-deploy-demo.mp4
Execute commands in running containers
You can now run interactive shells or execute one-off commands in running service containers using uc exec command.
# Start an interactive shell ("bash" or "sh" will be tried by default)
uc exec web-service
# Restore a database from an SQL dump
cat backup.sql | uc exec -T db psql -U postgres mydbGPU support
Services can now request GPU resources and device reservations through standard Compose attributes:
gpusfor GPU allocationdeploy.resources.reservations.devicesfor device access
This enables deployment of workloads requiring GPU like machine learning applications and video processing services.
Nearest replica DNS
Internal DNS now supports nearest.<service>.internal resolution, which prioritises machine-local replicas by returning their IPs first in the response.
New documentation
- Deploy an app: A comprehensive how-to guide for deploying applications from source code or pre-built images
- Deploy to specific machines: Deploy services to specific machines in your cluster
- Deploy a global service: Deploy exactly one replica of a service on each machine in your cluster
- Compose file reference: Image tag template: Template syntax for tagging built images
Bug fixes
- Fixed
uc deployto push images to all machines whenx-machinesis not specified - Fixed WireGuard peer reconfiguration when machines join cluster (#155)
- Fixed image push progress percent overflow (#153)
Additional updates
- Container images displayed in removal plan operations
- Shorter container IDs shown in deploy plan operations
- Corrosion version pinned to v0.2.2
- Docker and Compose dependencies updated to latest versions
- Installation script now respects
GITHUB_TOKENenvironment variable
Upgrade to 0.14.0
Uncloud CLI locally
To upgrade the Uncloud CLI (uc) locally:
# Homebrew (macOS, Linux)
brew upgrade uncloud
# Install script (macOS, Linux)
curl -fsS https://get.uncloud.run/install.sh | shMachine daemon
To upgrade the Uncloud daemon on your machines, run the following commands on each machine:
# AMD64
curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.14.0/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.14.0/uncloudd_linux_arm64.tar.gz
tar -xf uncloudd.tar.gz
sudo install uncloudd /usr/local/bin/uncloudd
rm uncloudd uncloudd.tar.gz
sudo systemctl restart uncloudChangelog
- 48d2239 Connect to remote SSH nodes using SSH CLI (#152)
- 1c3f210 bug: Use GITHUB_TOKEN if present in scripts/install_cli.sh (#169)
- 2f5f515 build: Bump go tests timeout to 15 min
- 90d244f chore: 'uc image push' fix long description
- 6da8e98 chore: add TODO to refactor docker client method
- 7e366ff chore: add gitutils package to inspect local git repo
- 89db50e chore: consistent casing
- 4cdbaa20b909ef6ae47a386b9d7b5be84996fd8c chore: enable CGO to be able to build fsevent required by updated compose on macOS
- 497b948 chore: fix the examples for 'uc image push' command after changing default
- 722615c chore: go mod tidy
- 328ace1 chore: implement image template processing using git repo state (not enabled)
- dde23b5 chore: increase timeout 5->30s for waiting for machines to be ready in ucind cluster
- bd8a843 chore: inspecrt git state without an error if git utility not available
- 4de068c chore: pin corrosion version to the latest working version v0.2.2
- 9a0b1a4 chore: print (custom Caddy config) for service ENDPOINTS if x-caddy is used
- 2d292ed chore: remove x-machines from website compose
- 6e4439b chore: show container image for the remove container plan operation
- 2b93a1c chore: update --container flag help that accepts ID prefix
- 3ac5992 chore: use short container ID for stop operation in deploy plan
- 06d9885 doc: Generate docs
- c3ecd37 feat(build): --push and --push-registry flags to push build images to cluster or registries
- 65c3e0a feat(build): print if no services to build, build dependencies --dep, check build configuration --check
- 882f2f5 feat(build,deploy): build service images using compose (bake/buildkit), push to cluster, and deploy
- abea3e2 feat: "exec" command to start processes inside remote containers (#139)
- 15d4ef5 feat: Allow container matching by ID prefix (#175)
- 6af7a98 feat: Allow to match containers against truncated ID (#160)
- ba6290d feat: add "nearest..internal" mode to internal DNS (#159)
- 5c4f49b feat: new cbuild (compose build) command using Compose implementation
- 26c3699 feat: process image templates in compose services, set default git-based tags if not specified
- 3b4bcb7 feat: support service.gpus and reservations.devices (#156)
- 30bb33f fix(exec): Handle context cancellation server-side
- 9770151 fix: 'uc deploy' push image to all machines if x-machines is not specified
- 0153e9f fix: progress percent overflow in image push (#153)
- b6dfc21 fix: reconfigure WireGuard peers when listed >=1 machines in cluster store (fixes #155)
- 4d591f9 lint
- 809d1ec lint
- d0c23fa lint: fix ineffassign
- 7bff706 ref: Rewrite config tests with Exec
- 4bc47af refactor: strip project name from volume names without mangling project name