Skip to content

Releases: psviderski/uncloud

v0.14.0

12 Nov 14:47

Choose a tag to compare

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 mydb

GPU support

Services can now request GPU resources and device reservations through standard Compose attributes:

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

Bug fixes

  • Fixed uc deploy to push images to all machines when x-machines is 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_TOKEN environment 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 | sh

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

Changelog

  • 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

v0.13.2

20 Oct 11:23

Choose a tag to compare

This is a bug fix release for the uc CLI, no daemon update on the machines is required. See update your CLI.

Changelog

  • e251dd9 fix: Improve wording for containerd warning
  • 40862df fix: compose variables are now interpolated from .env file (fixes #144)

v0.13.1

13 Oct 10:43

Choose a tag to compare

Bug fixes

  • Now uc image push doesn't fail when uploading a large image that takes more than 10s. You need to update only the uc CLI. #141

Changelog

  • 6ba98e4 fix: uc image push closed network connection error if takes >10s (fixes #141)

v0.13.0

10 Oct 09:03

Choose a tag to compare

This release features 3 weeks of work from 3 contributors. It's focused on unregistry integration and expanding Compose support.

Highlights

Unregistry integration (push images to cluster)

We've integrated unregistry to make image distribution way easier. You can build your Docker images locally or on CI and push them directly to your Uncloud cluster without needing an external registry. Only the missing layers are transferred, making it efficient and fast.

# Push local Docker image to a specific or multiple machines.
uc image push IMAGE [-m/--machine NAME[,NAME]]

# Push local Docker image to all machines.
uc image push IMAGE -m all

See uc image push documentation for more details and examples.

Screen.Recording.2025-09-30.at.8.01.39.pm.mov

Under the hood, uncloudd daemon on each machine runs an embedded unregistry server that handles the image receiving and storage in containerd. uc image push requires containerd image store to be enabled for Docker on the target machines.

This brings us one step closer to an end-to-end uc deploy experience which will handle building, pushing, and deploying images in one go.

Inspect images

You can now inspect what images you have on your machines in the cluster.

# List all images on all machines.
uc images

# List images on specific machines.
uc images -m machine1,machine2

# List images filtered by name pattern.
uc images "myapp:1.*"

See uc images documentation for more details and examples.

Screenshot 2025-10-10 at 6 53 47 pm
Untitled.mp4

Compose configs

PR: #116 Thank you @tonyo for the contribution! ❤️

Uncloud now supports Compose configs for managing configuration files in your services. Configs allow you to store non-sensitive configuration data separately from your container images and mount them into containers at runtime.

Example compose.yaml using configs:

services:
  app:
    image: myapp:latest
    configs:
      - source: app_config
        target: /app/config.yaml

configs:
  app_config:
    # Local path is relative to compose.yaml location
    file: ./config.yaml

See Configs documentation for more details.

Internal DNS improvements

PR: #123 Thank you @jabr for the contribution! ❤️

New machine-scoped DNS entries <machine-id>.m.<service-name>.internal allow targeting services on specific machines.
This is useful for debugging, health checks, or machine-specific routing needs.

See Internal DNS documentation for more details.

Containerd image store integration

Uncloud now automatically configures Docker to use the containerd image store by default on new machines, enabling:

  • uc image push feature to push images directly to the cluster machines via unregistry
  • ability to push and store multi-platform images

The system gracefully handles machines without containerd support and provides clear error messages when required features aren't available.

Improvements

  • uc ls now displays the IMAGE column showing which container image(s) each service is running
  • Service containers now receive UNCLOUD_MACHINE_ID environment variable with the machine ID they are running on
  • Updated Docker and Compose Go dependencies to latest versions for better compatibility

Bug fixes

  • Fixed panic in Docker when pushing images without authentication
  • Fixed error handling when removing non-existent services

Changelog

  • 2d361d3 Adding machine.service.internal dns entries (#123)
  • a2c6cbe chore(images): filter images by name with wildcard pattern using Docker filter
  • 509c9eb chore(images): format platforms as pills, sort images by name
  • 59074a2 chore(images): initialise Docker service with containerd client
  • cce81ec chore(images): simplifies ListImages service, server, and client to only list Docker images and not directly access containerd
  • e8b4dd0 chore(push): fail 'image push' when containerd image store not used on target machine
  • 521ccf2 chore(push): run unregistry only if containerd image store enabled for docker
  • 337c15d chore: Add node to Mise
  • c6d18f5 chore: NAME -> IMAGE column name
  • 782f4cb chore: Update AI.md with instructions around tests and docs
  • 977fdf3 chore: add Proxy for proxing local connections to a remote TCP address using the dialer
  • fa004d6 chore: add firewall rule to allow cluster machines to push to other machines unregistry
  • e0d11a8 chore: configure Docker to use containerd image store by default (closes #129)
  • 458d282 chore: correct comment and add TODO to move machine resolution to grpc-proxy router
  • bc6f2fd chore: fix docker client CreateContainerWithImagePull, add WaitPortPublished
  • 3bac1e6 chore: go mod tidy
  • fc3297c chore: go mod tidy
  • bcc504b chore: internal Docker client PushImage
  • 27bbbe7 chore: internal docker package with handy PullImage and CreateContainerWithImagePull methods
  • ae458d2 chore: refactor duplication
  • e0045c7 chore: refactor gRPC docker client
  • 82fd974 chore: remove unused imports
  • 2969b40 chore: return a proxy dialer for SSH connections
  • a217643 chore: shorten socat proxy container progress message
  • a30ed60 chore: update docker and compose Go dependencies to the latest versions
  • 6d2e100 feat(images): 'uc image ls' and 'uc images' (alias) commands to list images on machines
  • 0fc5032 feat(images): add IN USE column to highlight which images are used by any container
  • 92975ee feat(images): add gRPC proto ListImages
  • cdff036 feat(images): gRPC client and server for ListImages
  • fba03b3 feat(images): list image platforms and do not group images by machine
  • 1f9c2c8 feat(images): list images filtered by name
  • 684f0d3 feat(push): '--platform all' to push image to all machines in cluster
  • ffed906 feat(push): 'image push' to single or multiple machines via unregistry proxy
  • 332e7bc feat(push): --platform flag to push a specific platform of a multi-platform image
  • 9f6880b feat(push): stub for 'image push' command and Dialer interface for cluster connectors
  • 63c4de5 feat: Initial support for Compose configs (#116)
  • b6b8286 feat: run embedded unregistry on machine IP in uncloudd daemon
  • 3e804d9 feat: set UNCLOUD_MACHINE_ID in service container ENV (#135)
  • 60926f6 feat: show IMAGE column when listing services (uc ls) #13
  • 5aa85ab fix(push): always provide encoded empty auth config to work around panic in Docker
  • 08f233c fix: auto-detect containerd.sock path and conditionally start unregistry
  • cd25b97 fix: docker client PullImage
  • 1a1afec fix: e2e test rebind the registry port to unoccupied 5001
  • 893ab1f fix: negotiate docker client API version in e2e test
  • 20cf98d fix: return an error if 'uc rm' tries to remove a service that doesn't exist
  • 784d86d fix: test build for docker server
  • 265042e lint

v0.12.2

22 Sep 01:42

Choose a tag to compare

What's new

Multiple connection support

When connecting to a cluster, the CLI will now try each connection in the Uncloud config (~/.config/uncloud/config.yaml) until one succeeds. A progress spinner indicates what connection it is trying.

current_context: default
contexts:
  default:
    connections:
      - ssh: ubuntu@152.67.101.198
      - ssh: root@1.2.3.4
      - ssh: ubuntu@137.123.45.67
Screen.Recording.2025-09-13.at.9.15.40.pm.mov

Auto-confirmation for deployment

You can auto-confirm the deployment plan either locally or on CI with -y|--yes flag or UNCLOUD_AUTO_CONFIRM=true environment variable:

uc deploy --yes
# or
UNCLOUD_AUTO_CONFIRM=true uc deploy

Skip machine provisioning

New --no-install flag for machine init and machine add commands allows you to skip the automatic installation of Docker, Uncloud daemon, and dependencies on the machine. Useful when you want to use your own method for installing Uncloud daemon on the machine. See #122.

uc machine init user@server --no-install

Env vars

Instead of the --uncloud-config and --connect flags, you can now use the following environment variables:

  • UNCLOUD_CONFIG - Override the default config file path (~/.config/uncloud/config.yaml)
  • UNCLOUD_CONNECT - Connect to a remote machine without using a config file

Changelog

  • 6d0b1dc chore bump mise version on CI to 2025.9.6
  • e1734a1 chore: bump Go to 1.25.1
  • 51840e0 chore: bump golangci-lint to 2.4.0
  • 375bb38 chore: bump golangci-lint to 2.4.0 on CI
  • 84376bb chore: mise.lock include checksums for linux-x64
  • 8a273db chore: rename cluster -> context option in commands for consistency
  • 1f62e30 chore: update mise checksums for linux-x64
  • 88f05ff chore: update mise checksums for macos-arm64
  • f8fe3c7 feat: --no-install flag for 'machine init/add' to skip installing Uncloud daemon and dependencies #122
  • bc07847 feat: add -y|--yes flag for 'us deploy' to auto-confirm deployment plan
  • 3db07ca feat: allow setting config and connection with UNCLOUD_CONFIG and UNCLOUD_CONNECT env vars
  • 831c581 feat: try each cluster connection in order until one succeeds, add progress spinner
  • 8f906cf fix: do not auto-confirm deploy plan on CI (no TTY), require explicit --yes or UNCLOUD_AUTO_CONFIRM=true
  • b6e9766 lint: gRPC status.Error for static error messages

v0.12.1

10 Sep 07:05

Choose a tag to compare

Caddy config loading

After upgrading both CLI and machine daemons to v0.12.1, you can redeploy Caddy without using the --watch flag.

The Caddy config is now loaded automatically by the machine daemon via the Caddy Admin API. This allows to log errors and not overwrite the Caddyfile on disk if the config is invalid. uc caddy config should now return the latest config that was successfully loaded into Caddy.

Unique context name for new clusters

When creating a new cluster, if the default context name default is already taken, a unique name like default-1, default-2, etc. will be generated automatically.

Changelog

  • 8358343 chore: Add GH bug report template
  • 9963f9d chore: Update bug template
  • 5baa808 chore: load Caddy config via admin API instead of watching Caddyfile change on fs
  • d25864e feat: automatically generate a unique 'default-N' context name for new cluster (fixes #113)
  • ec2787c fix: Handle implicit relative path for config
  • 51ba3c7 fix: landing navbar on mobile
  • 97bdb8e fix: skip validation for user-defined Caddy configs if caddy not running locally
  • 7b88b8b fix: write generated Caddyfile to disk only if succesfully loaded into local Caddy (means valid)

v0.12.0

28 Aug 10:20

Choose a tag to compare

What's new

✨ Custom Caddy configuration (per-service and global)

For advanced routing and behavior, use x-caddy instead of x-ports in Compose files. It allows you to provide custom Caddy configuration for a service in Caddyfile format. See Ingress & HTTPS docs for details.

compose.yaml example
  • Use templates like {{upstreams 8000}} to automatically insert healthy container IPs for reverse_proxy.
  • Deploy global Caddy config with uc caddy deploy --caddyfile or x-caddy in a Compose file for caddy service.
  • Invalid Caddy configs are skipped instead of breaking everything.
  • View the complete generated Caddyfile served by Caddy with uc caddy config:
SCR-20250828-saca

New documentation

Improvements

  • Caddy now uses Caddyfile format instead of JSON which is more human-friendly.
  • Caddy keeps its data between restarts (certificates are preserved) using a persistent volume.

Upgrade to 0.12.0

⚠️ After upgrading both machines and CLI, you need to redeploy the caddy service to be able to use the new custom Caddy configs. This update will also lose all the previously issued TLS certificates because a persistent data wasn't used before.
Please follow Deploying or updating Caddy.

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 | sh

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.12.0/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.12.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 uncloud

Changelog

  • e99e769 chore: add Caddy gRPC service to retrieve Caddyfile config from machines
  • c01365b chore: add header to generated Caddyfile that it's autogenerated
  • 3cda5cc chore: caddy client to get caddy config
  • 813c397 chore: change reverse_proxy upstreams from 'to' to the directive arguments
  • 48dc1dd chore: delete unused image digest resolver
  • 81f4e3a chore: fix mockery for linux in .mise.lock
  • 455174c chore: generate sites in Caddyfile from x-ports alongside caddy.json
  • 11949ee chore: include validation errors for user-defined Caddy configs as a comment in Caddyfile
  • 8bf9fc0 chore: introduce mockery for generating mocks, generate for CaddyfileValidator
  • db60a81 chore: lint
  • 066d411 chore: parse Created time on container with CreatedTime
  • 93fef88 chore: refactor Caddyfile generator to accept a validator
  • 75fdbaf chore: relax ports+Caddy spec validation to allow host mode ports
  • b437659 chore: update comments in generated Caddyfile
  • 290e6db docs(ingress): Publishing service and Managing Caddy
  • 9f5ca9a feat: add 'uc caddy config' command to show the current Caddyfile
  • 3a6eef4 feat: add --caddyfile flag to 'uc caddy deploy' and 'uc run' commands
  • 0397086 feat: concatenate custom Caddy configs for services into final Caddyfile (no upstream interpolation)
  • b046b78 feat: migrate Caddy to generated Caddyfile, mount persistent data volume
  • 5cc005a feat: validate and append custom per-service Caddy configs to generated Caddyfile
  • 0107363 fix: allow host mode x-ports with x-caddy in compose
  • 5a1e61c fix: broken links to completions docs in CLI reference
  • 6476908 fix: format for --publish flag
  • ff213e7 fix: unmarshaling of ServiceSpec in ServiceContainer struct

v0.11.1

15 Aug 04:17

Choose a tag to compare

Private registry support

Fixed authentication when pulling images from private container registries. uc deploy or uc run will try to retrieve the registry credentials from your local Docker config (~/.docker/config.json), including the configured credentials store. If the credentials are not found locally, the uncloudd daemon on the remote machine will try to retrieve the credentials from its own Docker config (/root/.docker/config.json).

In order to configure the credentials for your private registries, you can:

  1. (Recommended) Run docker login locally (where you run uc) if you have Docker CLI installed.
  2. Run docker login on your remote machines under root user or using sudo docker login so that the credentials are stored in the root-owned Docker config.

Upgrade to 0.11.1

⚠️ IMPORTANT: You need to run the following commands on your existing remote machines to allow the daemon to read credentials from the Docker config:

sudo sed -i 's/ProtectHome=true/ProtectHome=read-only/' /etc/systemd/system/uncloud.service
sudo systemctl daemon-reload
sudo systemctl restart uncloud

Newly provisioned machines will have the correct configuration automatically.

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 | sh

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.11.1/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.11.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 uncloud

Changelog

  • 12c0781 chore: add Caddy config to ServiceSpec, load x-caddy to it
  • 4be8339 chore: generate a minimal Caddyfile with verify handler alongside caddy.json
  • 9186d31 chore: go mod tidy
  • ec73f9e chore: handle x-caddy: path/to/Caddyfile to read Caddy config in compose from file
  • 8dd69b4 chore: refactor docker gRPC server to use docker service for inspecting and listing containers
  • 4cc1e55 chore: store ServiceContainer (includes service spec) instead of Container in Corrosion store
  • dd7bc6c chore: trim spaces for x-caddy, diff Caddy configs when comparing service specs
  • 5d3f1fe chore: x-caddy extension type in compose
  • c67127f feat: Add basic LLM instruction files
  • 1ce3e62 fix: use local and remote Docker credentials to pull image from private registry

v0.11.0

07 Aug 08:12

Choose a tag to compare

What's new

Force service redeployment

Added --recreate flag to the deploy command to force container recreation even if their configuration and image haven't changed. This is particularly useful when you've pushed updated images directly to machines using tools like unregistry, and need to redeploy services to use the updated images without changing their tags. Or just want to test the redeployment process without changing the service configuration.

Screenshot 2025-08-07 at 6 23 01 pm

Reset machine on initialisation

machine init and machine add commands now ask you whether to reset the machine if they detect that the machine is already a cluster member. This helps when:

  • Repurposing a machine that was previously part of a different Uncloud cluster
  • Recovering from a failed or incomplete previous installation
  • Starting fresh after testing or experimentation with Uncloud
Screenshot 2025-08-07 at 6 25 49 pm

Default restart policy

Changed the default restart policy for service containers from always to unless-stopped. This allows you to stop containers manually and have them remain stopped even after a system reboot or Docker restart.

Upgrade to 0.11.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 | sh

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.11.0/uncloudd_linux_amd64.tar.gz
# ARM64
# curl -fsSL -o uncloudd.tar.gz https://github.com/psviderski/uncloud/releases/download/v0.11.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 uncloud

Changelog

  • ae9f943 chore: change default restart policy for service containers always -> unless-stopped
  • 8805178 doc: Add Sentry to sponsors
  • 2e585d0 feat: add --recreate flag for deploy command to force container recreation
  • ec3de3a feat: ask whether to reset already initialised machine on 'machine init/add'

v0.10.1

06 Aug 07:05

Choose a tag to compare

Changelog

  • fc0bf4a chore: lint
  • 6cc0611 chore: meaningful error message when passwordless sudo required on machine provisioning
  • 2c02139 fix: add ssh_key_path for connections in uncloud config only when using SSH key explicitly (not SSH agent)
  • 6c244bb fix: do not try to reset machine when removing unreachable machine