### 2 Getting Started/1 Install Cli
# Install CLI
Install the Uncloud command-line utility to manage your machines and deploy apps using `uc` commands. You will run `uc`
locally so choose the appropriate installation method for your operating system.
:::info NOTE
Windows is not natively supported yet, but you can install and run `uc` in a
[WSL](https://learn.microsoft.com/en-us/windows/wsl/) terminal by following the instructions for Linux.
:::
## Homebrew (macOS, Linux)
If you have [Homebrew](https://brew.sh/) package manager installed, this is the recommended installation method on macOS
and Linux:
```shell
brew install psviderski/tap/uncloud
```
To upgrade to the latest version:
```shell
brew upgrade uncloud
```
## Install script (macOS, Linux)
For a quick automated installation, use the install script:
```shell
curl -fsS https://get.uncloud.run/install.sh | sh
```
The script will:
- Detect your operating system and architecture
- Download the appropriate latest binary from [GitHub releases](https://github.com/psviderski/uncloud/releases)
- Install it to `/usr/local/bin/uc` using `sudo` (you may need to enter your user password)
Don't like `curl | sh`? You can download and review the [install script](https://get.uncloud.run/install.sh) first and
then run it:
```shell
curl -fsSO https://get.uncloud.run/install.sh
cat install.sh
sh install.sh
```
### Nightly builds
If you want to try the latest features and fixes before they are included in an official release, you can install the `nightly` version of Uncloud CLI (as well as the Uncloud daemon) which are built from the latest main branch code. Just set the `VERSION` environment variable to `nightly` when running the install script:
```shell
curl -fsS https://get.uncloud.run/install.sh | VERSION=nightly sh
```
More information about nightly builds of the CLI and daemon can be found [here](https://github.com/psviderski/uncloud/releases/tag/nightly).
## GitHub download (macOS, Linux)
You can manually download and use a pre-built binary from the
[latest release](https://github.com/psviderski/uncloud/releases/latest) on GitHub.
```shell
curl -L https://github.com/psviderski/uncloud/releases/latest/download/uc_macos_arm64.tar.gz | tar xz
```
```shell
curl -L https://github.com/psviderski/uncloud/releases/latest/download/uc_macos_amd64.tar.gz | tar xz
```
```shell
curl -L https://github.com/psviderski/uncloud/releases/latest/download/uc_linux_amd64.tar.gz | tar xz
```
```shell
curl -L https://github.com/psviderski/uncloud/releases/latest/download/uc_linux_arm64.tar.gz | tar xz
```
You can use the `./uc` binary directly from the current directory, or move it to a directory in your system's `PATH`
to run it as `uc` from any location.
For example, move it to `/usr/local/bin` which is a common location for user-installed binaries:
```shell
sudo mv ./uc /usr/local/bin
```
Follow the same steps to upgrade to the latest version in the future.
## Debian
On a Debian system, you can install Uncloud CLI from an unofficial
[repository](https://deb.griffo.io/) maintained by
[@dariogriffo](https://github.com/dariogriffo):
```shell
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg
echo "deb [signed-by=/etc/apt/keyrings/deb.griffo.io.gpg] https://deb.griffo.io/apt $(lsb_release -sc 2>/dev/null) main" | sudo tee /etc/apt/sources.list.d/deb.griffo.io.list
sudo apt update
sudo apt install -y uncloud
```
Alternatively, you can download `.deb` packages directly from the repository
[releases](https://github.com/dariogriffo/uncloud-debian/releases) page.
## Verify installation
After installation, verify that `uc` command is working:
```shell
uc version
```
## Next steps
Now that you have `uc` installed, you're ready to:
- [Deploy demo app](./2-deploy-demo-app.md)
---
### 2 Getting Started/2 Deploy Demo App
# Deploy demo app
In this guide, we'll deploy [Excalidraw](https://excalidraw.com), a popular sketching and diagramming tool, to your
Linux server. You'll learn the **basics of Uncloud** and see how simple it is to **run web apps** on your own
infrastructure with secure internet access.
:::info NOTE
To give you a chance to play with Uncloud without even leaving your browser or needing your own servers, we're providing
interactive tutorials and playgrounds on the [iximiuz Labs](https://labs.iximiuz.com/) platform.
You can follow [this tutorial](https://labs.iximiuz.com/tutorials/uncloud-create-cluster-ebebf72b) which walks you
through creating a new cluster with two machines and then deploying a simple web service to it.
You can also launch the [Uncloud playground](https://labs.iximiuz.com/playgrounds/uncloud-cluster-64523f7c) where you
can play with an already initialised Uncloud cluster.
:::
## Prerequisites
Before you begin, you'll need:
- **Uncloud CLI** [installed](1-install-cli.md) on your local machine
- A **Ubuntu or Debian server** with **public IP address** and **SSH access** using a **private key** (as `root` or a
user with **passwordless** `sudo` privileges).
:::tip Need a server?
A small Virtual Private Server (VPS) or dedicated server from providers like [Hetzner](https://www.hetzner.com) or
[DigitalOcean](https://www.digitalocean.com) is a great choice for learning Uncloud and running lightweight services. We
recommend using a freshly installed server as existing services on ports 80 and 443 can cause conflicts.
**Minimum requirements:** 1 vCPU, 512 MB RAM, Ubuntu 22.04 or Debian 11, AMD64 (recommended) or ARM64 architecture.
Other Linux distributions may work, but haven't been tested yet.
:::
## Set up your server
First, let's turn your server into an Uncloud **machine**. This simply means setting it up so you can deploy and manage
services on it using `uc`.
```shell
uc machine init root@
```
If the SSH key to access your server isn't added to your [SSH agent](https://www.ssh.com/academy/ssh/agent), specify it
with the `-i` flag:
```shell
uc machine init root@ -i ~/.ssh/id_xxx
```
This command will:
- Install the latest stable Docker version on your server if it's not already installed
- Install the Uncloud daemon on your server
- Create a Docker network for Uncloud-managed containers
- Deploy [Caddy](https://caddyserver.com/) as your reverse proxy listening on host ports 80 and 443
- Reserve a free `xxxxxx.uncld.dev` subdomain via the Uncloud managed DNS service and point it to your server's IP
All in about a minute!
๐ก Expand to see example output
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Deploy Excalidraw
Now that your machine is set up, let's deploy `excalidraw` service from the
[official Docker image](https://hub.docker.com/r/excalidraw/excalidraw). The service will publish the container port 80
as HTTPS endpoint on the previously reserved domain via Caddy.
```shell
uc run --name excalidraw --publish 80/https excalidraw/excalidraw
```
You'll see the progress of the deployment and the public URL where you can access the service:
```
[+] Running service excalidraw (replicated mode) 2/2
โ Container excalidraw-azpc on machine-dc3c Healthy 37.1s
โ Image excalidraw/excalidraw on machine-dc3c Pulled 4.7s
excalidraw endpoints:
โข https://excalidraw.sh8hsb.uncld.dev โ :80
```
## Verify your deployment
After the service is deployed, use the `uc inspect` command to check its status and details:
```shell
uc inspect excalidraw
```
```
Service ID: 4d2de1600b6ada221a03896cd388836c
Name: excalidraw
Mode: replicated
CONTAINER ID IMAGE CREATED STATUS IP ADDRESS MACHINE
fde7ac7f11ad excalidraw/excalidraw:latest About a minute ago Up About a minute (healthy) 10.210.0.3 machine-dc3c
```
In this example, the service has one container running on the machine `machine-dc3c` (our server). The container is up
and healthy.
You can also list all deployed services and their public endpoints using the `uc ls` command:
```shell
uc ls
```
```
NAME MODE REPLICAS IMAGE ENDPOINTS
caddy global 1 caddy:2.11.4
excalidraw replicated 1 excalidraw/excalidraw:latest https://excalidraw.sh8hsb.uncld.dev โ :80
```
You can see `caddy` service listed here. That's your reverse proxy, running as a regular Uncloud service.
## It's live! Start drawing! โจ
Open your browser and navigate to the URL shown in the endpoints. It may take a moment for Caddy to obtain a TLS
certificate from Let's Encrypt. If it doesn't load immediately, wait a few seconds and try again.
You now have:
- Your **own Excalidraw instance** running on your server
- A **public URL** with **automatic HTTPS** you can share with your team and friends
- **Full control over your data** โ no analytics or tracking
## View service logs
Want to see what's happening inside your service? Use the `uc logs` command to view logs from the service container:
```shell
uc logs excalidraw
```
```
Jul 14 10:53:05.910 machine-dc3c excalidraw/fde7a ::1 - - [14/Jul/2026:00:53:05 +0000] "GET / HTTP/1.1" 200 6843 "-" "Wget" "-"
Jul 14 10:53:31.456 machine-dc3c excalidraw/fde7a 10.210.0.2 - - [14/Jul/2026:00:53:31 +0000] "GET /sw.js HTTP/1.1" 200 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:150.0) Gecko/20100101 Firefox/150.0"
```
Add the `-f` flag to stream new logs in real-time. Press `Ctrl+C` to stop:
```shell
uc logs excalidraw -f
```
## Convert to Docker Compose format
Uncloud supports the [Compose file format](https://docs.docker.com/reference/compose-file/) for defining services. This
allows you to version control your deployments, share configurations with your team, and deploy complex multi-service
applications with a single command.
Let's create a `compose.yaml` file in your current directory for the `excalidraw` service we just deployed.
```yaml title="compose.yaml"
services:
excalidraw:
image: excalidraw/excalidraw
x-ports:
- 80/https
```
:::info note
The [`x-ports`](../8-compose-file-reference/2-extensions.md#x-ports) key is an Uncloud-specific extension to the Compose
file format. It allows you to specify ports that should be published as HTTP(S) endpoints. Uncloud automatically
configures the reverse proxy (Caddy) to route traffic to these ports.
:::
Now deploy it:
```shell
uc deploy
```
```
Services are up to date.
```
Since `excalidraw` service is already running with the same configuration, Uncloud recognises there's nothing to change.
We've successfully converted our deployment created with `uc run` to a Compose file.
## Use your own domain
Want to use your own domain, for example, `excalidraw.example.com` instead of `excalidraw.sh8hsb.uncld.dev`?
Add a CNAME record `excalidraw.example.com` in your DNS provider (Cloudflare, Namecheap, etc.) pointing to
`excalidraw.sh8hsb.uncld.dev`. Alternatively, you can add an A record pointing to your server's IP.
:::info note
These instructions set up your own domain **in addition to** the Uncloud managed DNS name
`excalidraw.sh8hsb.uncld.dev`.
If you want to avoid the managed service altogether, add `--no-dns` to your `uc machine init` command, and point an A
DNS record to your servers' IPs.
:::
Then update the published port `80/https` in `compose.yaml` to use your domain:
```yaml title="compose.yaml"
services:
excalidraw:
image: excalidraw/excalidraw
x-ports:
- excalidraw.example.com:80/https
```
Finally, deploy the changes:
```shell
uc deploy
```
```
Deployment plan
context: default
~ update service excalidraw
โ image: excalidraw/excalidraw:latest
โ
โฐโโ +/- replace container excalidraw/fde7ac7f11ad on machine-dc3c
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1 replace (start-first) ยท across 1 machine
Proceed with deployment to default? [y/N] y
[+] Deploying to default 2/2
โ Container excalidraw-0z12 on machine-dc3c Healthy 30.6s
โ Container excalidraw/fde7ac7f11ad on machine-dc3c Removed 0.4s
```
Uncloud prints a deployment plan and asks for confirmation before making any changes. The plan says it will replace the
running container with a new one using the
[`start-first` order](../4-guides/1-deployments/4-rolling-deployments.md#update-order). This means Uncloud starts the
new container with the updated configuration, waits for it to become healthy, and only then removes the old one. Your
service stays available throughout the update. That's a **zero-downtime deployment**.
Give it a moment for Caddy to obtain a TLS certificate, then visit https://excalidraw.example.com (use your own domain).
## Clean up
When you're done experimenting, you can remove the `excalidraw` service or uninstall Uncloud completely.
### Remove the service
Remove the `excalidraw` service while keeping your Uncloud machine running for future deployments:
```shell
uc rm excalidraw
```
### Uninstall Uncloud
If you want to completely uninstall Uncloud from your server and clean up everything it created, SSH into your server
and run:
```shell
sudo uncloud-uninstall
```
This command will:
- Remove all Uncloud-managed containers (including Caddy)
- Remove the Uncloud-managed Docker and WireGuard networks
- Uninstall the Uncloud daemon from the server
๐ก Expand to see example output
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Further reading
- **[Add more machines](../9-cli-reference/uc_machine_add.md)**: Scale horizontally by creating a cluster of machines
- **[Ingress & HTTP](../3-concepts/2-ingress/1-overview.md)**: Learn how Uncloud handles incoming traffic and how to
expose your services to the internet
- **[CLI reference](../9-cli-reference/uc.md)**: Explore all available commands and options
---
### 3 Concepts/1 Clusters/1 Connecting
# Connecting to a cluster
`uc` only needs to reach **one machine** to work with the entire cluster. That machine acts as an **entry point** and
forwards requests to other machines as needed.
`uc` stores **cluster contexts** and **connection details** in a [configuration file](../../7-cli-config-reference.md)
(default location is `~/.config/uncloud/config.yaml`).
When you initialise a new cluster with `uc machine init` or add a machine to an existing cluster with `uc machine add`,
they automatically save the SSH addresses of your machines to the config so you don't have to specify them every time.
## Cluster contexts
The [config file](../../7-cli-config-reference.md) organises connections into **contexts**. Each context represents a
cluster. It has a name and a list of connection details for the machines in that cluster.
A context is not the same thing as a cluster. It is your local view of a cluster: which machines you can connect through
and in what order to try them. Different people or environments may need to reach the same cluster in different ways.
You can also manually create multiple contexts for the same cluster. For example, one that connects through
a machine with a public IP when you're not in the office, and another that connects through a private machine on the
office network when you're on-site to reduce latency. You can switch between them depending on where you are.
### Managing contexts
Use these commands to manage the contexts in your config:
- [`uc ctx`](../../9-cli-reference/uc_ctx.md): Switch contexts using an interactive TUI
- [`uc ctx ls`](../../9-cli-reference/uc_ctx_ls.md): List all contexts and see which one is current
- [`uc ctx use`](../../9-cli-reference/uc_ctx_use.md): Switch the current context by name
- [`uc ctx conn`](../../9-cli-reference/uc_ctx_connection.md): Change the default connection for the current context
using an interactive TUI
You can also set `x-context` in your Compose file to pin a specific context for deployments. See
[Deploy to a specific cluster context](../../4-guides/1-deployments/1-deploy-app.md#deploy-to-a-specific-cluster-context)
for details.
## Connection resolution
When you run a `uc` command, it determines which cluster to connect to using this priority:
1. If `--connect` is set, `uc` connects directly to that machine and ignores the config file entirely.
2. If `--context` is set, `uc` uses that context from the config.
3. Otherwise, `uc` uses `current_context` from the config.
Once the context is resolved, `uc` tries each connection in the context's `connections` list in order until one
succeeds.
## User permissions on the machine
When `uc` connects to a machine over SSH, it communicates with the Uncloud daemon through the Unix socket
`/run/uncloud/uncloud.sock` on that machine. The daemon restricts access to the socket to the `root` user and members
of the `uncloud` Linux group. This means your SSH user must be either `root` or a member of the `uncloud` group.
In most cases you don't need to set this up manually. When you initialise or add a machine with a non-root user,
`uc machine init` and `uc machine add` automatically add that user to the `uncloud` group during installation.
If you want to connect with a different non-root user later, add them to the group on the machine:
```shell
sudo usermod -aG uncloud
```
The group change only applies to new SSH sessions. If `uc` still fails with a permission denied error after adding the
user, close any long-running SSH connections to the machine (for example, SSH ControlMaster sessions) and try again.
The same requirement applies when running `uc` locally on a cluster machine with a `unix://` connection. The local user
must be `root` or a member of the `uncloud` group.
## Global flags and environment variables
These flags are available on every `uc` command. They can also be set with an environment variable. The flag takes
priority if both are set.
| Flag | Environment variable | Description |
|--------------------|----------------------|-------------------------------------------------------------------|
| `--uncloud-config` | `UNCLOUD_CONFIG` | Path to the config file |
| `--context` | `UNCLOUD_CONTEXT` | Use a specific context instead of `current_context` in the config |
| `--connect` | `UNCLOUD_CONNECT` | Bypass the config file and connect directly |
### Connecting directly without a config
The `--connect` flag or `UNCLOUD_CONNECT` environment variable let you run one-off commands against a cluster without
using a config. This is useful for CI pipelines and scripts where you don't want to set up a config file.
It accepts these formats:
```shell
# System 'ssh' command with full SSH config support
uc --connect root@203.0.113.1 ls
# System 'ssh' command (explicit scheme, same as above)
uc --connect ssh://root@203.0.113.1 ls
# Go's built-in SSH library (no SSH config support, useful when the system ssh is not available)
uc --connect ssh+go://root@203.0.113.1 ls
# Direct connection to machine gRPC API over TCP (for advanced users with custom setups)
uc --connect tcp://[fdcc:4439:f545:3ca:5d17:66e5:7c96:40bd]:51000 ls
# Direct connection to machine gRPC API over a Unix socket (for running uc locally on a cluster machine)
uc --connect unix:///run/uncloud/uncloud.sock ls
```
:::info
Don't use `--connect` with `uc machine init`. `--connect` is for specifying or overriding the connection to an existing
cluster, but `uc machine init` creates a new one and writes the new cluster context to the config file. You can discard
the config when initialising a cluster with `--uncloud-config /dev/null` if you don't want to save it.
:::
---
### 3 Concepts/2 Ingress/1 Overview
---
sidebar_label: Overview
---
# Ingress & HTTPS
Uncloud uses [Caddy](https://caddyserver.com/) as its reverse proxy to handle incoming traffic, provide automatic HTTPS
with [Let's Encrypt](https://letsencrypt.org/), and route requests to your services.
## How it works
By default, Caddy runs as a global service `caddy` on every machine in your cluster, listening on the host ports 80
(HTTP), 443 (HTTPS), and 443/UDP (HTTP/3).
It's deployed during cluster initialisation (`uc machine init`) unless you use the `--no-caddy` flag.
See [Managing Caddy](3-managing-caddy.md) for deployment and customisation instructions.
When you [publish a service port](2-publishing-services.md), Uncloud automatically configures Caddy to:
1. Listen for requests on the specified hostname (domain name).
2. Automatically obtain and renew a TLS certificate from Let's Encrypt for HTTPS.
3. Route traffic to the **healthy** service container(s).
4. Load balance across healthy replicas if there are multiple.
For advanced use cases, Uncloud allows to customise the Caddy config using the `x-caddy` extension in Compose files.
See [Custom Caddy configuration](2-publishing-services.md#custom-caddy-configuration) for details.
---
### 3 Concepts/2 Ingress/2 Publishing Services
# Publishing services
Publishing service ports makes your services available outside the cluster. This means your services can be accessed
from the internet or local network, depending on your setup.
You can publish service ports in three ways:
- Using the `-p/--publish` flag with `uc run`.
- Using the `x-ports` extension in a Compose file with `uc deploy`.
- Using the `--caddyfile` flag with `uc run` or `x-caddy` extension in a Compose file for custom Caddy configuration.
For example, run a service with container port 8000 exposed as https://app.example.com via Caddy reverse proxy:
```shell
uc run -p app.example.com:8000/https app:latest
```
```
[+] Running service app-mwng (replicated mode) 1/1
โ Container app-mwng-6lub on machine-fnr9 Running
app-mwng endpoints:
โข https://app.example.com โ :8000
```
Create an `A` record in your DNS provider (Cloudflare, Namecheap, etc.) pointing `app.example.com` to the public IP
address or your machine(s). Once DNS is propagated and Caddy obtains a TLS certificate, you can access your service
securely over HTTPS.
## Ingress vs host mode
**HTTP/HTTPS** ports are exposed via Caddy using the following format for the `-p/--publish` flag and `x-ports`
extension:
```
[hostname:]container_port[/protocol]
```
- `hostname` (optional): The domain name to use for accessing the service. If omitted and a cluster domain is reserved,
`.` is used.
- `container_port`: The port number within the container that's listening for traffic.
- `protocol` (optional): `http` or `https` (default: `https`)
**TCP/UDP** ports can only be exposed in host mode, which binds the container port directly to the host machine's
network interface(s). This is useful for non-HTTP services that need direct port access (bypasses Caddy):
```
[host_ip|host_prefix:]host_port:container_port[/protocol]@host
```
- `host_ip` / `host_prefix` (optional): The IP address on the host to bind to. Or an IP prefix in
[CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) notation, which binds to every host IP address
that is contained in the prefix. If omitted, binds to all interfaces.
- `host_port`: The port number on the host to bind to.
- `container_port`: The port number within the container that's listening for traffic.
- `protocol` (optional): `tcp` or `udp` (default: `tcp`)
| Port value | Description |
|--------------------------------------|--------------------------------------------------------------------------------------|
| `8000/http` | Publish port 8000 as HTTP via Caddy using hostname `.` |
| `app.example.com:8080/https` | Publish port 8080 as HTTPS via Caddy using hostname `app.example.com` |
| `127.0.0.1:5432:5432@host` | Bind TCP port 5432 to host port 5432 on loopback interface only |
| `53:5353/udp@host` | Bind UDP port 5353 to host port 53 on all network interfaces |
| `192.168.76.0/24:5432:5432/tcp@host` | Bind TCP port 5432 to host port 5432 on every host IP contained in 192.168.76.0/24 |
:::warning
Do not publish internal-only services like databases unless absolutely necessary. You only need to publish ports for
services that should be accessible from outside the cluster. Services within the cluster can communicate with each other
by their DNS names `service-name` or `service-name.internal` without publishing ports.
:::
## Using Compose
Use the `x-ports` extension in a Compose file to publish service ports:
```yaml title="compose.yaml"
services:
app:
image: app:latest
x-ports:
- example.com:8000/https
- www.example.com:8000/https # The same port can be published with multiple hostnames
- api.domain.tld:9000/https # Another port can be published with a different hostname
```
## Custom Caddy configuration
For advanced routing and behavior, use `x-caddy` instead of `x-ports`. It allows you to provide custom Caddy
configuration for a service in [Caddyfile](https://caddyserver.com/docs/caddyfile) format.
```yaml title="compose.yaml"
services:
app:
image: app:latest
x-caddy: |
www.example.com {
redir https://example.com{uri} permanent
}
example.com {
basic_auth /admin/* {
admin $2a$14$... # bcrypt hash
}
header /static/* Cache-Control max-age=604800
reverse_proxy {{upstreams 8000}} {
import common_proxy
}
log
}
```
You can inline the Caddyfile or load it from a file: `x-caddy: ./Caddyfile`. When using a file, the path is relative to
the Compose file location. See the [Caddy documentation](https://caddyserver.com/docs/caddyfile) for syntax and
features.
:::info note
You cannot use `x-caddy` with `http` or `https` ports in `x-ports`. `tcp` and `udp` ports in host mode are allowed
though.
:::
Use it when you need:
- Custom routing rules (different paths, redirects, rewrites, multiple services on one domain).
- Custom headers, authentication, or caching.
- Custom load balancing strategies and options.
- Request and response manipulation.
- Advanced TLS settings.
- Other Caddy features and plugins.
See [Deploying or updating Caddy](3-managing-caddy.md#deploying-or-updating-caddy) for details on deploying Caddy with a
custom global configuration.
### Templates
`x-caddy` configs are processed as [Go templates](https://pkg.go.dev/text/template), allowing you to use dynamic values.
The following functions and variables are available:
| Template | Description |
| ------------------------------------- | --------------------------------------------------------------------------------------------- |
| `{{upstreams [service-name] [port]}}` | A space-separated list of healthy container IPs for the current or specified service and port |
| `{{.Name}}` | The name of the service the config belongs to |
| `{{.Upstreams}}` | A map of all service names to their healthy container IPs |
The templates are automatically re-rendered and Caddy is reloaded when service containers start/stop or health status
changes.
**Examples:**
1. Current service upstreams, default port:
```caddyfile
reverse_proxy {{upstreams}}
```
โ
```caddyfile
reverse_proxy 10.210.1.3 10.210.2.5
```
2. Current service upstreams, port 8000:
```caddyfile
reverse_proxy {{upstreams 8000}}
```
โ
```caddyfile
reverse_proxy 10.210.1.3:8000 10.210.2.5:8000
```
3. Current service upstreams with `https` scheme:
```caddyfile
reverse_proxy {{- range $ip := index .Upstreams .Name}} https://{{$ip}}{{end}}
```
โ
```caddyfile
reverse_proxy https://10.210.1.3 https://10.210.2.5
```
4. `api` service upstreams, port 9000:
```caddyfile
handle_path /api/* {
reverse_proxy {{upstreams "api" 9000}}
}
```
โ
```caddyfile
handle_path /api/* {
reverse_proxy 10.210.2.2:9000 10.210.1.7:9000 10.210.2.3:9000
}
```
### Verifying Caddy config
Use `uc caddy config` to view the complete generated Caddyfile served by the `caddy` service. This is useful for
debugging and verifying your `x-caddy` configs.
Example output:
```
/* Detailed source-code truncated for AI context efficiency. */
```
The generated config combines:
- Global Caddy configuration (`x-caddy` from the `caddy` service).
See [Deploying or updating Caddy](3-managing-caddy.md#deploying-or-updating-caddy) for details.
- Auto-generated configs from published service ports (`x-ports`).
- Custom Caddy configs from services (`x-caddy`).
- Skipped invalid configs with error messages as comments.
:::warning important
Custom Caddy configs from different services must not conflict (all services must use unique hostnames).
See [Multiple services on one domain](#multiple-services-on-one-domain) for an example of how to share one hostname
between multiple services.
Conflicting or invalid configs are detected using [caddy adapt](https://caddyserver.com/docs/command-line#caddy-adapt)
command and skipped. However, some errors could still break the entire config so Caddy will fail to load it. Check the
`caddy` service logs to troubleshoot.
:::
### Common use cases
#### Redirects
Publish a service on `example.com` and redirect requests from `www.example.com` to `example.com`:
```yaml
services:
app:
image: app:latest
x-caddy: ./Caddyfile
```
```caddyfile
www.example.com {
redir https://example.com{uri} permanent
}
example.com {
reverse_proxy {{upstreams 8000}} {
import common_proxy
}
log
}
```
#### Multiple services on one domain
You can publish multiple services on the same hostname by using different paths for each service. For example, route
`/` to the web service and `/api` to the API service:
```yaml
services:
api:
image: api:latest
web:
image: web:latest
# Make sure only one service defines a Caddy config for the hostname.
x-caddy: ./Caddyfile
```
```caddyfile
example.com {
handle_path /api/* {
reverse_proxy {{upstreams "api" 9000}} {
import common_proxy
}
}
reverse_proxy {{upstreams}} {
import common_proxy
}
log
}
```
---
### 3 Concepts/2 Ingress/3 Managing Caddy
# Managing Caddy
Caddy is automatically deployed as a global service `caddy` when you initialise a cluster with `uc machine init`. By
default, it runs on every machine to handle incoming HTTP/HTTPS traffic and route it to your services.
## Checking status
View the `caddy` service status and which machines it's running on:
```shell
uc inspect caddy
```
```
ID: b5b269d5dc5ed4fdae6542894f94de82
Name: caddy
Mode: global
CONTAINER ID IMAGE CREATED STATUS MACHINE
fb8f390e634d caddy:2.10.0 3 weeks ago Up 3 weeks prod-ap1
0182f5d7bd9f caddy:2.10.0 3 months ago Up 3 weeks prod-us1
```
## Deploying or updating Caddy
### Using CLI
Update to the latest stable version using the [caddy](https://hub.docker.com/_/caddy) image from Docker Hub:
```shell
uc caddy deploy
```
Deploy a specific version or custom image:
```shell
uc caddy deploy --image caddybuilds/caddy-cloudflare:2.10.2
```
Deploy only to a specific machine or a subset of machines (comma-separated list):
```shell
uc caddy deploy --machine machine1
uc caddy deploy --machine machine2,machine3,machine4
```
Deploy with custom global configuration:
```shell
uc caddy deploy --caddyfile global.Caddyfile
```
Example global configuration:
```caddyfile title=global.Caddyfile
# Global options.
{
debug
}
# A snippet that can be reused in custom Caddy configs for services (x-caddy).
(my_snippet) {
...
}
# Expose an internal service that is not managed by Uncloud.
internal.example.com {
reverse_proxy 192.168.1.100
}
```
### Using Compose
You can manage the Caddy deployment with a Compose file for more control. For example, to deploy a custom global Caddy
config that uses the DNS challenge with Cloudflare to obtain a wildcard TLS certificate for `*.example.com`:
```yaml
services:
caddy:
image: caddybuilds/caddy-cloudflare:2.10.2
command: caddy run -c /config/Caddyfile
environment:
CADDY_ADMIN: unix//run/caddy/admin.sock
env_file:
# Contains CLOUDFLARE_API_TOKEN=xxxxx
- .env.secrets
volumes:
- /var/lib/uncloud/caddy:/data
- /var/lib/uncloud/caddy:/config
- /run/uncloud/caddy:/run/caddy
x-ports:
- 80:80@host
- 443:443@host
- 443:443/udp@host
x-caddy: Caddyfile
deploy:
mode: global
# Optional: deploy only to specific machines.
# x-machines:
# - machine1
# - machine2
```
```caddyfile
# Global options.
{
debug
}
# A snippet that can be reused in custom Caddy configs for services (x-caddy).
(my_snippet) {
...
}
# Obtain a wildcard TLS certificate for all subdomains of example.name using DNS challenge with Cloudflare.
# It will be used for services that publish ports with hostnames under example.name.
*.example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
respond "No host matched" 404
}
# Expose an internal service that is not managed by Uncloud.
internal.example.com {
reverse_proxy 192.168.1.100
}
```
:::info note
The specified `command`, `environment`, `volumes`, and `x-ports` properties are essential for Caddy to function
correctly in the Uncloud cluster. Do not change the source paths of the volume mounts as the Uncloud daemon relies on
them to communicate with Caddy and update its configuration.
:::
Deploy or update the `caddy` service from the Compose file:
```shell
uc deploy
```
## Verifying config
View the complete generated Caddyfile served by the `caddy` service. This is useful for debugging and verifying custom
global and service-specific Caddy configs.
```shell
uc caddy config
```
Example output:
```
/* Detailed source-code truncated for AI context efficiency. */
```
The generated config combines:
- Global Caddy configuration (`x-caddy` from the `caddy` service).
- Auto-generated configs from published service ports (`x-ports`).
- Custom Caddy configs from services (`x-caddy`).
- Skipped invalid configs with error messages as comments.
---
### 3 Concepts/6 Services/1 Internal Dns
# Internal DNS
Services can be addressed on the internal WireGuard network by service name, service ID, or a machine-scoped service name:
## Service name
```
$ nslookup nats.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: nats.internal
Address: 10.210.0.2
Name: nats.internal
Address: 10.210.1.2
```
```
$ nslookup worker.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: worker.internal
Address: 10.210.0.3
Name: worker.internal
Address: 10.210.0.4
Name: worker.internal
Address: 10.210.1.3
Name: worker.internal
Address: 10.210.1.4
```
## Service ID
```
$ nslookup 3ecb3a8bbec5fd3f46efb056a934714a.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: 3ecb3a8bbec5fd3f46efb056a934714a.internal
Address: 10.210.0.4
```
## Machine ID scoped service name
```
$ nslookup 0903f0ee483aa97d559eeeaac5e22283.m.nats.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: nats.internal
Address: 10.210.1.2
```
```
$ nslookup 0903f0ee483aa97d559eeeaac5e22283.m.worker.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: worker.internal
Address: 10.210.1.3
Name: worker.internal
Address: 10.210.1.4
```
## IP Ordering Mode
Additionally, the IP ordering preference can be specified with a `rr` (round-robin) or `nearest` subdomain prefix.
### `rr` (round-robin) *current default*
Randomly shuffled order on each lookup.
```
$ nslookup rr.worker.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: rr.worker.internal
Address: 10.210.0.3
Name: rr.worker.internal
Address: 10.210.0.4
Name: rr.worker.internal
Address: 10.210.1.3
Name: rr.worker.internal
Address: 10.210.1.4
$ nslookup rr.worker.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: rr.worker.internal
Address: 10.210.0.4
Name: rr.worker.internal
Address: 10.210.1.3
Name: rr.worker.internal
Address: 10.210.1.4
Name: rr.worker.internal
Address: 10.210.0.3
```
## Nearest scope
Returns machine-local instances first.
`machine-a`:
```
$ nslookup nearest.worker.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: nearest.worker.internal
Address: 10.210.0.3
Name: nearest.worker.internal
Address: 10.210.0.4
Name: nearest.worker.internal
Address: 10.210.1.3
Name: nearest.worker.internal
Address: 10.210.1.4
```
`machine-b`:
```
$ nslookup nearest.worker.internal
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: nearest.worker.internal
Address: 10.210.1.3
Name: nearest.worker.internal
Address: 10.210.1.4
Name: nearest.worker.internal
Address: 10.210.0.3
Name: nearest.worker.internal
Address: 10.210.0.4
```
The prefixes can be used with service ID and machine-scoped service names, as well (e.g. `nearest.3ecb3a8bbec5fd3f46efb056a934714a.internal` or `rr.0903f0ee483aa97d559eeeaac5e22283.m.worker.internal`).
---
### 3 Concepts/6 Services/2 Container Env
# Container ENV Variables
- `UNCLOUD_MACHINE_ID`
- Machine ID the service container is running on.
- Example: `UNCLOUD_MACHINE_ID=0903f0ee483aa97d559eeeaac5e22283`
- `HOSTNAME`
- Service name with unique suffix.
- Example: `HOSTNAME=worker-c1zd`
---
### 3 Concepts/7 Configs
# Configs
Uncloud supports [Compose configs](https://github.com/compose-spec/compose-spec/blob/main/08-configs.md) 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.
See also [Docker Compose documentation](https://docs.docker.com/reference/compose-file/configs/) for the same feature.
## Overview
Configs provide a way to:
- Store configuration files outside of container images
- Share configuration between multiple services
- Update configuration without rebuilding images
- Version control your configuration separately
## Defining Configs
Configs are defined in two places in your `compose.yaml`:
1. **Top-level `configs` section**: Define the config content
2. **Service-level `configs` section**: Mount configs into containers
## Top-level Configs
Define configs using either file-based or inline content:
### File-based Configs
Read configuration from a file on the (local/control) host where `uc deploy` is run:
```yaml
configs:
nginx_config:
file: ./nginx.conf
app_config:
file: ./config/app.properties
```
The file path is relative to the compose file location.
### Inline Configs
Define configuration content directly in the compose file:
```yaml
configs:
app_config:
content: |
database_url=postgres://localhost:5432/myapp
redis_url=redis://localhost:6379
# Variable interpolation is supported
log_level=${LOG_LEVEL:-info}
```
When using inline configs, [environment variable interpolation](https://docs.docker.com/compose/how-tos/environment-variables/variable-interpolation/) is supported so that you can customize configuration based on your deployment environment. Variables are resolved from the environment where `uc deploy` is executed.
## Service-level Config Mounts
Mount configs into containers using the long syntax:
```yaml
services:
web:
image: nginx:alpine
configs:
- source: nginx_config
target: /etc/nginx/nginx.conf
mode: 0644
- source: app_config
target: /app/config.properties
uid: "1000"
gid: "1000"
mode: 0600
```
### Config Mount Options
| Option | Description | Default |
| -------- | ------------------------------------------------- | ---------- |
| `source` | Name of the config (from top-level configs) | Required |
| `target` | Path where the config is mounted in the container | Required |
| `mode` | File permissions (octal format) | `0644` |
| `uid` | User ID that owns the file | Root user |
| `gid` | Group ID that owns the file | Root group |
## Complete Examples
### Example 1: Web Server with Custom Configuration
```yaml
services:
web:
image: nginx:alpine
configs:
- source: nginx_conf
target: /etc/nginx/nginx.conf
x-ports:
- 80/https
configs:
nginx_conf:
file: ./nginx.conf
```
Create `nginx.conf` in the same directory as your compose file:
```nginx
events {
worker_connections 1024;
}
http {
server {
listen 80;
location / {
return 200 'Hello from Uncloud!\n';
add_header Content-Type text/plain;
}
}
}
```
### Example 2: Application with Multiple Config Files
```yaml
services:
app:
image: node:18-alpine
command: ["node", "server.js"]
configs:
- source: app_config
target: /app/config.json
mode: 0644
- source: database_config
target: /app/database.json
uid: "1000"
gid: "1000"
mode: 0600
environment:
NODE_ENV: production
configs:
app_config:
content: |
{
"port": 3000,
"logLevel": "info",
"features": {
"analytics": true,
"cache": true
}
}
database_config:
file: ./configs/database.json
```
## Implementation details
Here are the key characteristics of the configs feature implementation:
- **Client-side processing**: When you run `uc deploy`, the Uncloud CLI reads config files from your local machine and includes their content in the service specification.
- **Content transfer**: Config content (both file-based and inline) is sent to the Uncloud daemon via gRPC as part of the deployment request.
- **Container deployment**: During container creation, configs are copied inside the container.
- **File lifecycle**: Config files exist only for the lifetime of the container. When a container is removed, its config files are cleaned up automatically.
- **Per-container isolation**: Each container gets its own copy of config files.
- **Atomic updates**: Config changes require redeployment, ensuring consistency across all replicas.
## Best Practices
### Security Considerations
- **Sensitive Data**: Don't put secrets in configs. Use environment variables or external secret management
- **File Permissions**: Set appropriate `mode`, `uid`, and `gid` for sensitive config files
- **Version Control**: Be careful about committing sensitive configuration files to git
### Config Sharing
Configs can be shared across multiple services:
```yaml
services:
web:
image: nginx
configs:
- source: shared_config
target: /etc/app/config.yaml
api:
image: myapi
configs:
- source: shared_config
target: /app/config.yaml
configs:
shared_config:
content: |
environment: production
debug: false
```
## Limitations
- **External configs**: Not supported. All configs must be defined in the compose file
- **Short syntax**: Not yet supported. Use the long syntax with `source` and `target`
- **Config updates**: Changing config content requires redeployment to take effect
## Troubleshooting
### Config File Not Found
If you get an error about config file not found:
1. Check the file path is correct relative to the compose file
2. Ensure the file exists and is readable
3. Verify file permissions
### Permission Denied
If containers can't read config files:
1. Check the `mode` setting allows read access
2. Verify `uid` and `gid` match the container's user
3. Ensure the container user has permission to access the target directory
### Config Not Updating
If config changes don't take effect:
1. Run `uc deploy` to redeploy with new config content
2. Check that you're modifying the correct config file
3. Verify the config is properly mounted in the container with `docker exec cat ` on the remote machine
## See also
- [Secrets](8-secrets.md): Pass sensitive values such as passwords, tokens, and keys to your services
- [Compose support matrix](../8-compose-file-reference/1-support-matrix.md): Which Compose features Uncloud supports
---
### 3 Concepts/8 Secrets
# Secrets
Secrets allow you to keep **sensitive data** for your services out of your Compose file and version control. This
includes database passwords, API tokens, TLS or SSH private keys.
Uncloud provides an extended support for
[Compose secrets](https://github.com/compose-spec/compose-spec/blob/main/09-secrets.md), allowing you to fetch secret
values at deploy time from your password manager, a cloud secrets store, or local files.
## How it works
Two things go into your Compose file:
1. Define a secret in the top-level `secrets` section. This tells Uncloud how to get the secret value.
2. Reference that secret value in a service's `environment` using the `secret://` format. This tells Uncloud to
resolve the secret and set the environment variable to its value at deploy time.
```yaml title="compose.yaml"
services:
api:
image: myapp:latest
environment:
DB_PASSWORD: secret://db_password
TLS_KEY: secret://tls_key
secrets:
db_password:
# Read the secret value from 1Password by running this command locally.
x-command: op read "op://prod/myapp/db_password"
tls_key:
# Read the secret value from a local file. Do NOT commit this file to the repository.
file: ./secrets/tls_key.pem
```
When you run `uc deploy`, it sees each `secret://` reference, resolves the secret on your local machine, and sets
the environment variable to its value. For example, it runs the command for `db_password` and reads the file for
`tls_key`. The values never land in your Compose file or git. They go straight into the deployment.
Only secrets you reference in the services that you currently deploy get resolved. A secret referenced in multiple
places or by several services resolves only once, and the value is reused.
Secrets are resolved after building images (if any) and before preparing the deployment plan.
:::info note
Secrets can only be used to set environment variables in your services. \
Mounting a secret as a file inside the container is not supported yet. For mounting config files,
see [Configs](7-configs.md).
:::
## Secret sources
Uncloud supports multiple sources for fetching secret values. Choose the one for each secret that fits your workflow.
### Arbitrary command
The `x-command` extension runs a command and uses its output as the secret value. It's the most versatile option that
lets you pull a secret from a system Keychain, password managers, cloud services and secrets stores, or any CLI tool you
already use.
```yaml title="compose.yaml"
secrets:
# 1Password
db_password:
x-command: op read "op://prod/myapp/db_password"
# Bitwarden
api_token:
x-command: bw get password api-token
# Infisical
smtp_password:
x-command: infisical secrets get --env=prod SMTP_PASSWORD --plain --silent
# AWS Secrets Manager
stripe_key:
x-command: aws secretsmanager get-secret-value --secret-id stripe --query SecretString --output text
```
The command runs on the machine where you run `uc deploy`, in the same directory as your Compose file and with the same
environment. So it uses the CLIs and credentials you are already logged into.
If your password manager needs you to unlock it or touch a hardware key, the prompt shows up right in your terminal.
Uncloud never stores your provider credentials.
A few details worth knowing:
- The command runs directly without a shell. To use pipes or variables, call a shell yourself: `sh -c 'cmd1 | cmd2'`.
- A single trailing newline is trimmed from the output, because most CLI tools add one. Everything else is kept as is.
- The command has 1 minute to finish before `uc` times out and aborts the deployment.
`x-command` is a short form for `driver: exec`. Use the long form if you prefer to be explicit:
```yaml title="compose.yaml"
secrets:
db_password:
driver: exec
driver_opts:
command: op read "op://prod/myapp/db_password"
```
:::tip
To pull secrets from many providers through a single CLI, or to keep **encrypted secrets in your git repository**,
consider [fnox](https://fnox.jdx.dev/). It works with AWS, GCP, Azure, HashiCorp Vault, 1Password, Bitwarden, and more,
and prints a plain value you can read with `x-command`:
```yaml title="compose.yaml"
secrets:
db_password:
x-command: fnox get DB_PASSWORD
```
:::
### File
Read the content of a local file as the secret value. The file path is relative to the Compose file location.
```yaml title="compose.yaml"
secrets:
db_password:
file: ./secrets/db_password.txt
```
The file content is used verbatim without trimming any whitespaces.
:::warning
Do NOT commit these files to your repository and ensure they are protected with proper file permissions. For example,
make the file readable only by your user with `chmod 600 ./secrets/db_password.txt`.
:::
## Things to keep in mind
- Secrets resolve on the machine where you run `uc deploy`, not on the cluster. The cluster only receives the final
value.
- Secret values passed as environment variables are stored **unencrypted** as part of the service specification in the
distributed cluster store.
- Docker also stores the resolved environment variables **unencrypted** in each container's configuration at
`/var/lib/docker/containers//config.v2.json` on the machine running the container. Anyone with `root` access to
that machine or able to run `docker inspect` can read them.
## See also
- [Configs](7-configs.md): Mount non-sensitive configuration files into your containers
- [Compose support matrix](../8-compose-file-reference/1-support-matrix.md): Which Compose features Uncloud supports
---
### 4 Guides/1 Deployments/1 Deploy App
# Deploy an app
Deploy a containerised application to your Uncloud cluster using either source code or pre-built images.
This guide covers both scenarios:
- **[Deploy from source code](#deploy-from-source-code)**: Build Docker images from your application code and use them
to deploy service containers
- **[Deploy pre-built images](#deploy-pre-built-images)**: Deploy service containers using existing images from a
registry or your local machine
Uncloud uses [Compose Specification](https://compose-spec.io/) for defining the deployment configuration of your app's
services. It implements the most common Compose features with some Uncloud-specific extensions. See
[Compose support matrix](../../8-compose-file-reference/1-support-matrix.md) for details.
## Prerequisites
- `uc` CLI [installed](../../2-getting-started/1-install-cli.md) on your local machine
- An Uncloud cluster with at least one machine (see [Quick start](../../2-getting-started/2-deploy-demo-app.md))
- Basic knowledge of [Compose Specification](https://compose-spec.io/)
## Deploy from source code
Use this scenario when you want to build and deploy your application from
a [Dockerfile](https://docs.docker.com/reference/dockerfile/) and source code available on your local machine.
### 1. Create a Compose file
Create a `compose.yaml` file in your application directory with a
[`build`](https://github.com/compose-spec/compose-spec/blob/main/spec.md#build) section for each service you want to
build. Here is a minimal example of a Compose file that builds and deploys a web app that consists of a single service
called `web`:
```yaml title="compose.yaml"
services:
web:
# Build an image from the Dockerfile in the current directory
build: .
# Publish the container port 8000 as https://app.example.com
x-ports:
- app.example.com:8000/https
```
If you don't have a Dockerfile for building an image from your source code, create one in the same directory.
### 2. Build and deploy your app
To build and deploy services defined in your Compose file, navigate to the directory with `compose.yaml` and run:
```shell
uc deploy
```
This command looks for a Compose file in your current working directory and:
1. **Builds images** for services with a `build` section using your local Docker and tags them with the current Git
version
2. **Pushes built images** directly **to cluster machines** using
[unregistry](https://github.com/psviderski/unregistry), transferring only the missing layers
3. **Plans the deployment** and shows you what will change, asking for confirmation
4. **Creates any missing volumes** on target machines
5. **Deploys service containers** using the built images and latest configuration changes with zero-downtime rolling
updates
See the [`uc deploy` ](../../9-cli-reference/uc_deploy.md) reference for all available options.
Watch `uc deploy` building and deploying a demo app (12 seconds):
### Customise the build configuration
If you need more control over the build configuration, you can specify additional attributes in the `build` section of
your Compose file. For example, to specify a custom Dockerfile location, set build-time arguments, or build
multi-platform images.
```yaml
services:
web:
build:
# Relative path to the directory with your Dockerfile
context: ./backend
# Set build-time variables defined as ARG in your Dockerfile
args:
ALPINE_VERSION: 3.22
BUILD_ENV: prod
# Build a multi-platform image
platforms:
- linux/amd64
- linux/arm64
```
You can pass additional build arguments or override existing ones using the `--build-arg` flag with `uc deploy`:
```shell
uc deploy --build-arg BUILD_ENV=dev
```
You can also use advanced features like build caches or SSH access.
See [Compose Build Specification](https://github.com/compose-spec/compose-spec/blob/main/build.md) for all supported
attributes. Note that build [secrets](https://github.com/compose-spec/compose-spec/blob/main/build.md#secrets) are not
supported though.
:::info note
To build multi-platform images, you need to configure your local Docker to use the
[containerd image store](https://docs.docker.com/desktop/features/containerd/).
:::
### Customise image tags
If you don't specify the `image` attribute, `uc deploy` tags built images with a Git-based version like
```yaml
# /:.
myapp/web:2025-10-30-223604.84d33bb
```
It uses your local date/time if the working directory is not a Git repository.
You can customise the image name and tag format using the `image` attribute. It can be a static name or a dynamic
template using [environment variables](https://github.com/compose-spec/compose-spec/blob/main/spec.md#interpolation) and
the [Go template](https://pkg.go.dev/text/template) syntax.
```yaml
services:
web:
build: .
# Custom image name and tag format
image: myapp:{{gitdate "20060102"}}.{{gitsha 7}}.${GITHUB_RUN_ID:-local}{{if .Git.IsDirty}}.dirty{{end}}
```
This generates tags like:
- `myapp:20251030.84d33bb.local.dirty` when building locally with uncommitted changes
- `myapp:20251030.84d33bb.1234` when building in CI with `GITHUB_RUN_ID=1234` and a clean repo
`uc deploy` renders the image templates when it loads the Compose file and then uses the resulting names for the build
and deploy stages.
See the [Image tag template](../../8-compose-file-reference/3-image-tag-template.md) reference for all available
template variables and functions.
### Separate build and deploy steps
You might want to build and deploy services as separate commands. For example, to run them as separate steps in your
CI/CD pipeline or have more control over the build and deploy process. Here are the commands that are equivalent to
`uc deploy`:
```shell
# Build images and push to cluster machines
uc build --push
# Deploy services using the built images
uc deploy --no-build
```
### Deploy configuration changes only
You can use the `--no-build` flag with `uc deploy` to deploy only the configuration changes in your Compose file if your
source code and images haven't changed. However, the image tag may still change if you're using
[dynamic tags](#customise-image-tags) based on the Git state (default). In that case, the deploy will likely fail
because the new tag won't be found on cluster machines.
Use less sensitive dynamic tags or specify the built and pushed image tags you want to deploy explicitly to avoid this
issue.
The recommended approach though is to commit all your changes, including the configuration ones, to the repo. Then
rebuild and deploy your services from a clean repo state. This way, the image tags will always reflect the exact source
code and configuration used for the deployment.
## Deploy pre-built images
Use this scenario when you want to deploy your application using pre-built images from a container registry (for
example, Docker Hub or GitHub Container Registry) or your local Docker.
### 1. Create a Compose file
Create a `compose.yaml` file that references an image from a registry using the
[`image`](https://github.com/compose-spec/compose-spec/blob/main/spec.md#image) attribute. It's important that you don't
include a `build` section for services using pre-built images. Here is a minimal example of a Compose file that deploys
an app that consists of a single `nginx` service:
```yaml title="compose.yaml"
services:
nginx:
# Use the nginx image from Docker Hub
image: nginx:latest
# Publish the container port 80 as https://nginx.example.com
x-ports:
- nginx.example.com:80/https
```
### 2. Deploy your app
To deploy services defined in your Compose file, navigate to the directory with `compose.yaml` and run:
```shell
uc deploy
```
This command looks for a Compose file in your current working directory and:
1. **Plans the deployment** and shows you what will change, asking for confirmation
2. **Creates any missing volumes** on target machines
3. **Pulls images** from a registry on cluster machines where services are deployed according to the
[`pull_policy`](https://github.com/compose-spec/compose-spec/blob/main/spec.md#pull_policy)
4. **Deploys service containers** using the pulled images and latest configuration changes with zero-downtime rolling
updates
### Control image pulling
By default, `uc deploy` pulls an image from a registry only if it's missing on a target machine. You can change this
behavior using the [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/main/spec.md#pull_policy)
attribute. For example, to always pull the latest version of an image before deploying.
```yaml
services:
nginx:
image: nginx:alpine
# Always pull the latest :alpine tag before deploying
pull_policy: always
```
Available `pull_policy` values:
- `always`: Always pull the image from the registry before deploying
- `missing` (default): Pull only if the image isn't available on the target machine
- `never`: Never pull, the image must be present on the target machine or the deploy will fail
### Pull from a private registry
If your images are in a private registry, `uc deploy` needs an authentication token to pull them. You can provide it by
either:
- Logging in to the registry using your local Docker (recommended)
- Logging in to the registry using Docker on each cluster machine you want to deploy to
When you're logged in using your local Docker, `uc deploy` automatically passes your local Docker credentials for the
private registry to cluster machines when pulling images. This way, you don't need to log in on each machine manually.
See [`docker login`](https://docs.docker.com/reference/cli/docker/login/) for instructions on how to log in to a private
registry.
### Push local images to cluster machines
You can also deploy pre-built images that exist only in your local Docker and are not available for pulling on cluster
machines. For example, images you built locally outside of the Compose workflow or pulled from a private registry that
is unreachable from your cluster machines. This is useful for deploying to air-gapped or restricted environments.
You can push these local images directly to your cluster machines using the
[`uc image push`](../../9-cli-reference/uc_image_push.md) command:
```shell
# Push to *all* cluster machines
uc image push myapp:latest
# Push to specific machines only
uc image push myapp:latest -m machine1,machine2
```
This command uploads the image from your local Docker to the cluster machines using
[unregistry](https://github.com/psviderski/unregistry) running as part of the Uncloud daemon on each machine. It
efficiently transfers only the image layers that don't already exist on the target machines.
After pushing the image, update your Compose file to reference it:
```yaml
services:
web:
# Reference the image you just pushed
image: myapp:latest
# Never try to pull from a registry since the image is only available locally
pull_policy: never
```
Run [`uc images`](../../9-cli-reference/uc_images.md) to verify that the image is available on the target machines.
Then deploy as usual:
```shell
uc deploy
```
:::tip
Set `pull_policy: never` when using local images to prevent `uc deploy` from trying to pull them from a registry.
:::
## Mix source builds and pre-built images
Define multiple services in your Compose file, mixing source builds and pre-built images:
```yaml
services:
web:
# Build web service from source
build: .
x-ports:
- app.example.com:8000/https
db:
# Pull a pre-built PostgreSQL image from Docker Hub
image: postgres:18
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
```
`uc deploy` builds and pushes images for services with a `build` section and pulls images from a registry for services
with only an `image` attribute.
:::warning
**Service names must be globally unique** across all Compose files deployed to the same cluster.
Unlike Docker Compose or Docker Swarm, Uncloud doesn't automatically prefix service names with project or stack names.
Choose unique names to avoid conflicts with services deployed from other Compose files.
:::
## Deploy to a specific cluster context
If you manage multiple clusters, you can set `x-context` in your Compose file to make sure it always deploys to the
correct one. You won't need to remember to manually switch clusters with `uc ctx` or `--context`.
```yaml title="compose.yaml"
x-context: prod
services:
web:
image: myapp:latest
```
With this configuration, `uc deploy` and other commands using the Compose file will always target the `prod` context,
regardless of your currently active context. You can still override it with the `--context` flag if needed.
See [`x-context`](../../8-compose-file-reference/2-extensions.md#x-context) for more details.
## Use a different Compose file location
If your Compose file has a different name or location, use the `-f/--file` flag to specify its path:
```shell
uc deploy -f path/to/your-compose.yaml
```
You can also specify multiple Compose files to merge configurations:
```shell
uc deploy -f compose.yaml -f compose.prod.yaml
```
See [Use multiple Compose files](https://docs.docker.com/compose/how-tos/multiple-compose-files/) for details on how you
can customise your Compose application for different environments or workflows.
## Verify your deployment
After deploying your app, you can verify that your services are running as expected by listing all deployed services in
the cluster:
```shell
uc ls
```
and inspecting the status of containers for a specific service:
```shell
uc inspect web
```
# See also
- [Deploy to specific machines](2-deploy-specific-machines.md): Deploy services to specific machines in your cluster
- [Deploy a global service](3-deploy-global-services.md): Deploy one service replica on each cluster machine
- [Compose Specification](https://compose-spec.io/): Official specification for the Compose file format
- [Compose support matrix](../../8-compose-file-reference/1-support-matrix.md): Supported Compose features and Uncloud
extensions
---
### 4 Guides/1 Deployments/2 Deploy Specific Machines
# Deploy to specific machines
Deploy services to specific machines in your cluster using the
[`x-machines`](../../8-compose-file-reference/2-extensions.md#x-machines) extension in your Compose file.
## When to target specific machines
By default, Uncloud randomly chooses available machines to run your services on, evenly spreading multiple replicas of a
service across all machines for high availability. You can restrict which machines can run your service using the
[`x-machines`](../../8-compose-file-reference/2-extensions.md#x-machines) extension in your Compose file.
This is useful when you want to:
- Deploy services to machines in a **specific region** or **data center**
- Run services only on machines with **specific hardware** (for example, GPUs or ARM processors)
- Specify where to deploy **stateful services** and create their data volumes
- Keep certain services isolated to **dedicated machines**
- Deploy to a subset of machines for **testing** before rolling out cluster-wide
## Target machines in a Compose file
Set `x-machines` to a list of machine names or a single machine name to restrict which machines a service can run on.
```yaml title="compose.yaml"
services:
web:
build: .
x-ports:
- app.example.com:8000/https
# Spread 3 replicas across machine-1 and machine-2 only
x-machines:
- machine-1
- machine-2
scale: 3
db:
image: postgres:18
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql
# Create the db-data volume and run the DB container on machine-db
x-machines: machine-db
volumes:
db-data:
```
When you deploy this Compose file with [`uc deploy`](../../9-cli-reference/uc_deploy.md):
- The `web` service will create and spread its 3 replicas only across `machine-1` and `machine-2`
- The `db` service will create its `db-data` volume and run only on `machine-db`
:::tip
Use [`uc machine ls`](../../9-cli-reference/uc_machine_ls.md) to see available machines in your cluster.
:::
## Push images to specific machines only
When [building from source](1-deploy-app.md#deploy-from-source-code), `uc deploy` and `uc build --push` automatically
push built images to **all** cluster machines by default. This ensures images are available wherever services might be
deployed.
If you're using `x-machines` to restrict deployments to specific machines, `uc deploy` and `uc build --push` push images
**only to those** machines. This saves time and bandwidth by uploading images only where they're needed.
You can also manually push your local Docker images to specific machines using the [
`uc image push`](../../9-cli-reference/uc_image_push.md) command:
```shell
# Push the local Docker image 'myapp:latest' to machine-1 and machine-2
uc image push myapp:latest -m machine-1,machine-2
```
See [Push local images to cluster machines](1-deploy-app.md#push-local-images-to-cluster-machines) for more details.
## See also
- [Deploy an app](1-deploy-app.md): Build and deploy from source code or pre-built images
- [Deploy a global service](3-deploy-global-services.md): Deploy one service replica on each cluster machine
- [Compose support matrix](../../8-compose-file-reference/1-support-matrix.md): Supported Compose features and Uncloud
extensions
---
### 4 Guides/1 Deployments/3 Deploy Global Services
# Deploy a global service
Deploy exactly one replica of a service on each machine in your cluster.
This is useful for cluster-wide infrastructure services like monitoring or security agents, log collectors, or reverse
proxies.
## Deploy to all machines
To deploy exactly one replica on each machine in your cluster for a specific service, set
[`mode: global`](https://github.com/compose-spec/compose-spec/blob/main/deploy.md#mode) under the `deploy` section in
your Compose file:
```yaml title="compose.yaml"
services:
monitoring:
image: quay.io/prometheus/node-exporter:latest
deploy:
# Run one container on each machine in the cluster
mode: global
```
Then deploy:
```shell
uc deploy
```
Before creating replicas on cluster machines, it will show you a deployment plan and ask for confirmation.
If you add more machines to the cluster later, you need to run `uc deploy` again to create replicas on the new machines.
Uncloud doesn't automatically scale global services to new machines.
## Deploy to a subset of machines
You can combine the `global` mode with [`x-machines`](../../8-compose-file-reference/2-extensions.md#x-machines)
to deploy one container to each specified machine:
```yaml title="compose.yaml"
services:
caddy:
image: caddy:2
deploy:
# Run one container on each of the three specified machines
mode: global
x-machines:
- ingress-1
- ingress-2
- ingress-3
```
This is useful when you want a service on a specific group of machines (for example, ingress or GPU machines) but still
want the one-per-machine guarantee that global mode provides.
## Global vs replicated mode
The default mode is `replicated`, where you specify the number of replicas.
| Mode | Replicas | Placement |
|------------------------|-----------------------------------------------|---------------------------------------------------------------------|
| `replicated` (default) | You specify with `scale` or `deploy.replicas` | Uncloud evenly spreads replicas across all machines or `x-machines` |
| `global` | Always one per machine | One replica on each machine or each `x-machines` machine |
## See also
- [Deploy an app](1-deploy-app.md): Deploy from source code or pre-built images
- [Deploy to specific machines](2-deploy-specific-machines.md): Deploy services to specific machines in your cluster
- [Compose Specification: deploy.mode](https://github.com/compose-spec/compose-spec/blob/main/deploy.md#mode):
Compose specification for deployment modes
---
### 4 Guides/1 Deployments/4 Rolling Deployments
# Rolling deployments
How `uc deploy` updates your services without downtime and automatically rolls back on failure.
Uncloud uses a rolling deployment to update your service by replacing its containers **one at a time**. Before moving on
to the next container, Uncloud waits for the new one to pass [health monitoring](#health-monitoring). If it fails to
become healthy, Uncloud stops the deployment and rolls back that container to the old one. This keeps your service
available throughout the update.
For a service with three replicas and the default `start-first` [update order](#update-order), the deployment looks like
this:
1. Start new container #1, wait until healthy
2. Stop and remove old container #1
3. Start new container #2, wait until healthy
4. Stop and remove old container #2
5. Start new container #3, wait until healthy
6. Stop and remove old container #3
At every step, at least three containers are serving traffic.
## Update order
The **update order** controls whether Uncloud starts the new container before or after stopping the old one.
| Order | What happens | Best for |
|---------------|-----------------------------------------------------------------------------|-------------------------------------|
| `start-first` | Start new container, then stop old (running containers briefly overlap) | Stateless services (web apps, APIs) |
| `stop-first` | Stop old container, then start new | Stateful services (databases) |
The default is `start-first` so there's **no downtime**. But it automatically switches to `stop-first` in two cases:
- **Host port conflicts**: the old container must free the port before the new one can bind to it.
- **Single-replica service with a volume**: two containers simultaneously writing to the same volume can
**corrupt data**, so Uncloud stops the old container first to prevent this.
`stop-first` can cause a **brief downtime** while the old container stops and the new one starts in these cases. The
deployment plan printed by `uc deploy` indicates which containers will be replaced with `stop-first`.
A multiple-replica service with a volume doesn't automatically switch to `stop-first` as Uncloud assumes that the
concurrent access is desired and safe. Host path and tmpfs mounts don't trigger the switch either.
### Override update order
You can override the update order with `deploy.update_config.order`:
```yaml title="compose.yaml"
services:
app:
image: myapp
volumes:
- data:/data
deploy:
update_config:
order: start-first
volumes:
data:
```
This single-replica service uses a volume, so Uncloud would normally use `stop-first`. Setting `order: start-first`
overrides that.
This is useful if your app handles concurrent access to data safely and you want to avoid downtime. For example, the app
uses an SQLite database in WAL mode on the volume.
## Health monitoring
After starting each new container, Uncloud **monitors** it for failures for **5 seconds** to make sure it keeps running
and not crashing. If it keeps restarting after this period, the deployment fails and Uncloud
[rolls back](#rollback-on-failure) that container to the old one.
This is a safeguard to prevent you from deploying broken code or misconfiguration that would cause downtime. 5 seconds
is typically enough for a process in a container to initialise all its dependencies and start.
You can change the monitoring period for a service with `deploy.update_config.monitor`. For example, increase it if your
app takes longer to start or if you want to give it more time to recover from transient errors on startup.
```yaml title="compose.yaml"
services:
app:
image: myapp
deploy:
update_config:
# Specified as duration: 500ms, 20s, 1m30s, 0s (skip)
monitor: 10s
```
Set it to `0s` to skip monitoring entirely if you are confident the new containers will start correctly and want to
speed up the deployment. A safer alternative is to configure a [health check](#health-checks) instead.
You can also change the default monitoring period (`5s`) for all services globally with an environment variable
`UNCLOUD_HEALTH_MONITOR_PERIOD`:
```shell
export UNCLOUD_HEALTH_MONITOR_PERIOD=10s
# or skip monitoring for all services
export UNCLOUD_HEALTH_MONITOR_PERIOD=0s
```
`deploy.update_config.monitor` overrides the global default for that service.
### Health checks
If your service has a [`healthcheck`](https://github.com/compose-spec/compose-spec/blob/main/spec.md#healthcheck)
configured, Uncloud also checks its health status during and after the monitoring period.
If a container becomes `healthy` before the monitoring period ends, the deployment succeeds early and moves on to the
next container. If the container is `unhealthy` after the monitoring period, Uncloud
[rolls it back](#rollback-on-failure) and fails the deployment. Transient `unhealthy` states during the monitoring
period are tolerated to give the container time to recover from startup issues.
To make deployments **safer** and **faster**, it's recommended to configure a health check that can quickly notify
Uncloud when containers start successfully and become ready to serve traffic. You can configure it with
[`healthcheck`](https://github.com/compose-spec/compose-spec/blob/main/spec.md#healthcheck) in your Compose file or
[`HEALTHCHECK`](https://docs.docker.com/reference/dockerfile#healthcheck) in your image `Dockerfile`:
```yaml title="compose.yaml"
services:
app:
image: myapp
healthcheck:
test: curl -f http://localhost:8000/health
interval: 5s
retries: 3
start_period: 10s
start_interval: 1s
```
:::info important
If a health check fails after the deployment, Uncloud automatically removes the unhealthy container from the
[Caddy](../../3-concepts/2-ingress/1-overview.md) configuration to prevent routing traffic to that container. But it
doesn't automatically restart or roll it back.
Uncloud automatically adds it back to Caddy when it recovers and becomes healthy again. You can inspect the health
status of your containers with [`uc ps`](../../9-cli-reference/uc_ps.md) or
[`uc inspect`](../../9-cli-reference/uc_inspect.md) and check their logs with
[`uc logs`](../../9-cli-reference/uc_logs.md).
:::
### Skip health monitoring
To skip health monitoring for **faster emergency deployments**, use `uc deploy --skip-health`.
:::warning
`--skip-health` won't detect containers that crash on startup or become unhealthy so won't roll them back or stop the
deployment. Use this only for emergency deployments when you are confident the new containers will start correctly.
:::
## Rollback on failure
If a new container fails health monitoring during a deployment, Uncloud stops it but keeps it around for inspection. For
`stop-first` order, Uncloud also restarts the old container. The deployment then stops and the remaining containers are
left untouched.
For example, if the first container in a rolling update succeeds but the second one fails, the first replacement stays
in place.
### Failed container logs
To help you diagnose the failure, `uc deploy` prints the last 10 log lines from the failed container.
You can change how many lines are printed with the `UNCLOUD_FAILED_CONTAINER_LOGS_TAIL` environment variable. Set it to
a number or to `all` to print the full container log:
```shell
export UNCLOUD_FAILED_CONTAINER_LOGS_TAIL=50
```
You can fetch the full logs with [`uc logs`](../../9-cli-reference/uc_logs.md) or inspect the status of the stopped
container with [`uc inspect`](../../9-cli-reference/uc_inspect.md) or [`uc ps`](../../9-cli-reference/uc_ps.md).
## Retry after failure
You can retry the deployment by running `uc deploy` again. Uncloud will skip the successfully deployed containers if the
configuration hasn't changed and only redeploy the remaining ones.
## See also
- [Pre-deploy hooks](5-pre-deploy-hooks.md): Run a command before deploying service containers
- [Deploy an app](1-deploy-app.md): Build and deploy from source code or pre-built images
- [Compose support matrix](../../8-compose-file-reference/1-support-matrix.md): Supported Compose features and Uncloud
extensions
---
### 4 Guides/1 Deployments/5 Pre Deploy Hooks
# Pre-deploy hooks
Run a one-off command before deploying a service.
Pre-deploy hooks are useful for **one-off tasks** such as:
- Database schema and data migrations
- Uploading static assets to a CDN
- Cache invalidation
- Any setup task that needs to run **once** before new code goes live, not on every container startup
## How it works
When you run `uc deploy` for a service with a pre-deploy hook configured, the hook command runs after building and
pushing the new image (if [building from source](1-deploy-app.md#deploy-from-source-code)) but **before** rolling out
any new containers.
`uc deploy` runs your hook command inside a new container and waits for it to finish or time out (**5 minutes** by
default). This container **inherits** most of the **service's configuration**, including the image, environment
variables, volumes, placement, and compute resources.
If the command exits with code 0, the deployment continues with a normal [rolling update](4-rolling-deployments.md). If
the command fails or times out, the deployment stops immediately with an error. `uc deploy` will display the latest logs
from the hook container to help you diagnose the issue.
The hook runs on one of the machines where the service will be deployed. Similar to service containers, hook containers
can reach other services over the network, connect to databases, and read or write shared volumes. Note that file system
changes do not persist after the hook finishes, except for changes written to shared volumes.
## Usage
Add the [`x-pre_deploy`](../../8-compose-file-reference/2-extensions.md#x-pre_deploy) extension to a service in your
Compose file. The only required attribute is `command`, which can be a string or a list of strings, just like the
service's [`command`](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#command).
```yaml title="compose.yaml"
services:
web:
build: .
x-pre_deploy:
command: python manage.py migrate
```
:::info note
The `command` replaces the image's default command ([`CMD`](https://docs.docker.com/reference/dockerfile/#cmd)) but the
[`ENTRYPOINT`](https://docs.docker.com/reference/dockerfile/#entrypoint) still runs. If your image has an entrypoint,
the hook command is passed as arguments to it. You can override the entrypoint for the service using
[`entrypoint`](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#entrypoint) which applies to both
hook and regular service containers.
:::
Since your command runs in the same image as the service, any tools or dependencies it needs must be installed in that
image.
See [`x-pre_deploy`](../../8-compose-file-reference/2-extensions.md#x-pre_deploy) for all available attributes and their
defaults.
### Database migrations
The most common use case for pre-deploy hooks is running database migrations before deploying a new app version:
```yaml title="compose.yaml"
services:
web:
build: .
environment:
DATABASE_URL: postgres://postgres:${DB_PASSWORD}@db:5432/postgres
x-ports:
- app.example.com:8000/https
x-pre_deploy:
# Apply Django migrations from the built image before deploying new app containers
command: python manage.py migrate
depends_on:
- db
db:
image: postgres:18
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/postgresql
volumes:
db-data:
```
When you run `uc deploy`, the migration runs first inside a new container created with the same image and environment
variables as the `web` service. Only after it succeeds, the deployment starts replacing service containers with the new
image.
### Running multiple commands
If you need to run several tasks before deployment, you can wrap them in a single shell command:
```yaml title="compose.yaml"
services:
web:
build: .
x-pre_deploy:
# Apply Django migrations, collect static files, and upload them to S3 bucket
command: sh -c "python manage.py migrate && python manage.py collectstatic --no-input"
```
For more complex scenarios, create a dedicated script and use it as the hook command:
```yaml
services:
web:
build: .
x-pre_deploy:
command: ./scripts/pre_deploy.sh
```
```bash
#!/bin/bash
# Ensure the script exits immediately with a non-zero code if any command fails.
set -e
python manage.py migrate
python manage.py collectstatic --no-input
python manage.py clear_cache
```
Make sure the script is included in your service image and exits with a non-zero code on any command failure (`set -e`).
### Custom environment and user
The hook container inherits environment variables from the service. You can add hook-specific variables or override
existing ones with `environment`. Use `user` to run the command as a different user.
For example, if your service runs as a non-root user but the hook needs root to fix file permissions on a shared volume:
```yaml title="compose.yaml"
services:
web:
build: .
user: app
volumes:
- data:/data
x-pre_deploy:
command: chown -R app:app /data/uploads
user: root
volumes:
data:
```
:::tip
Uncloud automatically sets `UNCLOUD_HOOK_PRE_DEPLOY=true` in the hook container. You can check this variable in a shared
entrypoint script or your command to detect when it's running as a pre-deploy hook versus a regular service container.
:::
## Failure handling
### Non-zero exit code
When the hook command exits with a non-zero code, the deployment stops immediately. No service containers are created or
replaced. `uc deploy` prints the latest logs from the failed hook container to help you diagnose the issue and keeps it
around for inspection. See [Failed hook logs](#failed-hook-logs) below for details.
Fix the issue and run `uc deploy` again to retry.
### Timeout
If the hook doesn't finish within the timeout (default **5 minutes**), Uncloud kills the container and fails the
deployment. The killed container is kept for inspection. See [Failed hook logs](#failed-hook-logs) below for details.
You can increase the timeout for long-running tasks like large database migrations or data uploads:
```yaml title="compose.yaml"
services:
web:
x-pre_deploy:
command: python manage.py migrate
timeout: 30m
```
### Failed hook logs
When a hook fails with a non-zero exit code or a timeout, `uc deploy` prints the last 10 log lines from the failed hook
container to help you diagnose the issue.
You can change how many lines are printed with the `UNCLOUD_FAILED_CONTAINER_LOGS_TAIL` environment variable. Set it to
a number or to `all` to print the full container log. The same setting applies to regular containers that fail during a
[rolling deployment](4-rolling-deployments.md#failed-container-logs):
```shell
export UNCLOUD_FAILED_CONTAINER_LOGS_TAIL=50
```
You can fetch the full logs as part of the service logs with [`uc logs`](../../9-cli-reference/uc_logs.md) or inspect
the status of the failed container with [`uc inspect`](../../9-cli-reference/uc_inspect.md)
or [`uc ps`](../../9-cli-reference/uc_ps.md).
### Idempotency
Design your hook commands to be **idempotent** when possible. If a deployment fails after the hook succeeds (for
example, a new container crashes on startup) and you retry with `uc deploy`, the hook runs again.
Most database migration tools handle this naturally since they track which migrations have already been applied.
## See also
- [`x-pre_deploy` reference](../../8-compose-file-reference/2-extensions.md#x-pre_deploy): All available attributes and
their defaults
- [Rolling deployments](4-rolling-deployments.md): How Uncloud updates containers with zero downtime
- [Deploy an app](1-deploy-app.md): Build and deploy from source code or pre-built images
---
### 8 Compose File Reference/1 Support Matrix
# Compose support matrix
Uncloud supports a subset of the [Compose specification](https://compose-spec.io/) with some
[extensions](2-extensions.md) and limitations. The following table shows the support status for main Compose features.
:::info
If you rely on a specific Compose feature that is not supported by Uncloud, please submit a feature request in
[GitHub Discussions](https://github.com/psviderski/uncloud/discussions) or on [Discord](https://uncloud.run/discord).
:::
| Feature | Support Status | Notes |
|----------------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| **Services** | | |
| `build` | โ Supported | Build context and Dockerfile |
| `cap_add` | โ Supported | Additional kernel [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) |
| `cap_drop` | โ Supported | Which kernel [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) to drop |
| `command` | โ Supported | Override container command |
| `configs` | โ Supported | File-based and inline configs |
| `cpus` | โ Supported | CPU limit |
| `depends_on` | โ ๏ธ Limited | Deployed in dependency order. Use [pre-deploy hooks](../4-guides/1-deployments/5-pre-deploy-hooks.md) for `service_completed_successfully` |
| `devices` | โ Supported | Device mappings |
| `dns` | โ Not supported | Built-in service discovery |
| `dns_search` | โ Not supported | Built-in service discovery |
| `entrypoint` | โ Supported | Override container entrypoint |
| `env_file` | โ Supported | Environment file |
| `environment` | โ Supported | Environment variables |
| `gpus` | โ Supported | GPU device access |
| `healthcheck` | โ Supported | Health check configuration |
| `image` | โ Supported | Container image specification |
| `init` | โ Supported | Run init process in container |
| `labels` | โ Not supported | |
| `links` | โ Not supported | Use service names for communication |
| `logging` | โ Supported | Defaults to [local](https://docs.docker.com/engine/logging/drivers/local/) log driver |
| `mem_limit` | โ Supported | Memory limit |
| `mem_reservation` | โ Supported | Memory reservation |
| `mem_swappiness` | โ Not supported | |
| `memswap_limit` | โ Not supported | |
| `networks` | โ Not supported | All containers share cluster network |
| `pid` | โ Supported | Set the PID namespace mode, `pid: host` only |
| `ports` | โ ๏ธ Limited | `mode: host` only, use [`x-ports`](2-extensions.md#x-ports) for HTTP/HTTPS |
| `privileged` | โ Supported | Run containers in privileged mode |
| `pull_policy` | โ Supported | `always`, `missing`, `never` |
| `secrets` | โ ๏ธ Limited | Reference secrets in `environment`, see [Secrets](../3-concepts/8-secrets.md). File mounts not supported |
| `security_opt` | โ Not supported | |
| `shm_size` | โ Supported | Shared memory size |
| `stdin_open` | โ Supported | Allocate standard input and keep it open |
| `stop_grace_period` | โ Supported | Time to wait after SIGTERM before SIGKILL |
| `storage_opt` | โ Not supported | |
| `sysctls` | โ Supported | Namespaced kernel parameters |
| `tty` | โ Supported | Allocate a pseudo-TTY and connect the container's standard streams to it |
| `ulimits` | โ Supported | Resource limits |
| `user` | โ Supported | Set container user |
| `volumes` | โ Supported | Named volumes, bind mounts, tmpfs |
| **Deploy** | | |
| `labels` | โ Not supported | |
| `mode` | โ Supported | Either `global` or `replicated` |
| `placement` | โ Not supported | Use [`x-machines`](2-extensions.md#x-machines) extension |
| `replicas` | โ Supported | Number of container replicas |
| `resources` | โ ๏ธ Limited | CPU, memory limits and device reservations |
| `restart_policy` | โ Not supported | Defaults to `unless-stopped` |
| `rollback_config` | โ Not supported | See [#151](https://github.com/psviderski/uncloud/issues/151) |
| `update_config` | โ ๏ธ Limited | `order` and `monitor` supported. See [rolling deployments](../4-guides/1-deployments/4-rolling-deployments.md) |
| **Volumes** | | |
| Named volumes | โ Supported | Docker volumes |
| Bind mounts | โ Supported | Host path binding |
| Tmpfs mounts | โ Supported | In-memory filesystems |
| Volume labels | โ Supported | Custom labels |
| External volumes | โ Supported | Must exist before deployment |
| [Volume drivers][volume-drivers] | โ Supported | `local` (supports [NFS][volume-nfs], [CIFS/Samba][volume-cifs]) and manually installed third-party drivers |
| **Configs** | | |
| File-based configs | โ Supported | Read from file |
| Inline configs | โ Supported | Defined in compose file |
| External configs | โ Not supported | Not supported |
| Short syntax | โ Not supported | Use long syntax only |
| **Extensions** | | |
| `x-context` | โ Uncloud-specific | Cluster context override |
| `x-caddy` | โ Uncloud-specific | Custom Caddy configuration |
| `x-machines` | โ Uncloud-specific | Machine placement constraints |
| `x-ports` | โ Uncloud-specific | Service port publishing |
| `x-pre_deploy` | โ Uncloud-specific | Pre-deploy hook command |
[volume-drivers]: https://docs.docker.com/engine/storage/volumes/#use-a-volume-driver
[volume-nfs]: https://docs.docker.com/engine/storage/volumes/#create-a-service-which-creates-an-nfs-volume
[volume-cifs]: https://docs.docker.com/engine/storage/volumes/#create-cifssamba-volumes
### Legend
- โ **Supported**: Feature works as documented
- โ ๏ธ **Limited**: Partial support or with restrictions
- โ **Not supported**: Feature is not (yet) available
See [Compose extensions](2-extensions.md) for details on additional Compose features provided by Uncloud.
---
### 8 Compose File Reference/2 Extensions
---
title: Compose extensions
---
# Uncloud-specific Compose extensions
Uncloud provides several custom extensions to the standard [Compose specification](https://compose-spec.io/) that let
you configure Uncloud-specific features directly in your Compose file.
See the [support matrix](1-support-matrix.md) for the full list of supported standard Compose features.
## `x-context`
Set the cluster context for all commands that use the Compose file, such as `deploy`, `build`, and `logs`. This is
useful when you manage multiple clusters and want to make sure a Compose file is always deployed to the right one. No
need to remember to manually switch clusters with `uc ctx` or `--context`.
`x-context` is a top-level key, not a service-level attribute.
```yaml
x-context: prod
services:
web:
image: nginx
```
The `--context` and `--connect` flags take precedence over `x-context`. If you don't specify any of these, the current
context from your Uncloud config (`--uncloud-config`) is used.
:::warning
If you share the Compose file with other users, make sure to use the same context name for the target cluster in your
Uncloud configs.
:::
## `x-ports`
Expose HTTP/HTTPS service ports via the Caddy reverse proxy, or bind TCP/UDP ports directly to the host:
```yaml
services:
web:
image: nginx
x-ports:
- 80/https
- example.com:80/https
- 8080:80/tcp@host
```
See [Publishing services](../3-concepts/2-ingress/2-publishing-services.md) for more details.
## `x-caddy`
Custom Caddy reverse proxy configuration for a service:
```yaml
services:
web:
image: nginx
x-caddy: |
example.com {
reverse_proxy {{upstreams 80}}
}
```
See [Publishing services](../3-concepts/2-ingress/2-publishing-services.md) for more details.
## `x-machines`
Restrict which machines can run your service. If you deploy multiple replicas, Uncloud automatically spreads them across
the specified machines.
```yaml
services:
web:
image: nginx
x-machines:
- machine-1
- machine-2
# Short syntax for a single machine
# x-machines: machine-1
```
## `x-pre_deploy`
Configure a pre-deploy hook to run a one-off command in a separate container and wait for it to finish successfully
before rolling out service containers. It's useful for preparation tasks that need to run before every service
deployment, such as database migrations, static asset uploads, or cache invalidation.
The hook container uses the service's image and inherits its environment variables, volumes, placement, and compute
resources. If the command fails or times out (5 minutes by default), the deployment stops.
```yaml
services:
web:
build: .
x-pre_deploy:
command: python manage.py migrate
environment:
LOG_LEVEL: DEBUG
timeout: 10m
```
### Attributes
| Attribute | Type | Default | Description |
|---------------|-------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `command` | string / list | (required) | The command to run in the hook container (same format as the service's [`command`](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#command)) |
| `environment` | map / list of KEY=VALUE | - | Additional env vars that override or extend the service's [`environment`](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#environment) |
| `privileged` | bool | service's value | Override the service's [`privileged`](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#privileged) mode |
| `timeout` | duration | `5m` | Max time to wait for the command to finish before killing it (e.g., `1m30s`, `30m`, `1h`) |
| `user` | string | service's value | Override the service's [`user`](https://github.com/compose-spec/compose-spec/blob/main/05-services.md#user) to run as (`user`, `UID`, `user:group`, or `UID:GID`) |
The hook container also gets `UNCLOUD_HOOK_PRE_DEPLOY=true` environment variable set automatically.
See [Pre-deploy hooks](../4-guides/1-deployments/5-pre-deploy-hooks.md) for more details, usage examples, and failure
handling.
## `secrets.*.x-command`
Resolve a secret by running a command locally and using its output as the value. Define a secret under the top-level
`secrets` section, then reference it as `secret://` in a service's `environment`:
```yaml
services:
api:
image: myapp
environment:
DB_PASSWORD: secret://db_password
secrets:
db_password:
# Read the secret value from 1Password by running this command locally.
x-command: op read "op://prod/myapp/db_password"
```
See [Secrets](../3-concepts/8-secrets.md) for more details and supported secret sources.
---
### 8 Compose File Reference/3 Image Tag Template
# Image tag template
Template syntax for tagging built images.
## Overview
When building service images as part of [`uc build`](../9-cli-reference/uc_build.md) or
[`uc deploy`](../9-cli-reference/uc_deploy.md) commands, Uncloud automatically generates image tags based on the current
Git repository state. You can customise the image name and tag format for the built images using the
[Go template](https://pkg.go.dev/text/template) syntax and environment variables.
## Default template
If you **don't specify** an `image` attribute for a service with a `build` section, Uncloud uses the following Go
template for tagging the built image:
```
{{.Project}}/{{.Service}}:{{if .Git.IsRepo}}{{gitdate "2006-01-02-150405"}}.{{gitsha 7}}{{if .Git.IsDirty}}.dirty{{end}}{{else}}{{date "2006-01-02-150405"}}{{end}}
```
```yaml title="compose.yaml"
services:
web:
build: .
```
This generates image tags as follows:
- Git repository (clean): `myapp/web:2025-10-30-223604.84d33bb`
- Git repository (with uncommitted changes): `myapp/web:2025-10-30-223604.84d33bb.dirty`
- Non-Git directory: `myapp/web:2025-10-31-120651`
If you specify only an **image name without a tag** in the `image` attribute, Uncloud appends the tag portion of the
default template to your image name.
```yaml title="compose.yaml"
services:
web:
build: .
image: webapp # โ webapp:2025-10-30-223604.84d33bb
```
If you specify a full **image name with tag** in the `image` attribute, Uncloud uses it as-is without modification.
```yaml title="compose.yaml"
services:
web:
build: .
image: webapp:1.2.3 # โ webapp:1.2.3
```
## Template functions
### `gitsha [length]`
Returns the Git commit SHA, optionally truncated to the specified length.
```yaml
image: myapp:{{gitsha 7}} # โ myapp:84d33bb
image: myapp:{{gitsha}} # โ myapp:84d33bbf0dbb37f96e7df6a5010aed7bab00b089
```
Returns empty string if the working directory is not a Git repository.
### `gitdate "format" ["timezone"]`
Returns the current Git commit date/time formatted using [Go time layout format](#date-format-reference). The `timezone`
parameter is optional and defaults to UTC.
Use [IANA timezone names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) like `America/New_York` or
`Europe/London`.
```yaml
image: myapp:{{gitdate "2006-01-02"}} # โ myapp:2025-10-30
image: myapp:{{gitdate "20060102-150405"}} # โ myapp:20251030-223604
image: myapp:{{gitdate "2006-01-02-150405" "Australia/Brisbane"}} # โ myapp:2025-10-31-083604
```
Returns empty string if the working directory is not a Git repository.
### `date "format" ["timezone"]`
Returns the current local date/time formatted using [Go time layout format](#date-format-reference). The `timezone`
parameter is optional and defaults to UTC.
Use [IANA timezone names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) like `America/New_York` or
`Europe/London`.
```yaml
image: myapp:{{date "2006-01-02"}} # โ myapp:2025-10-31
image: myapp:{{date "20060102-150405"}} # โ myapp:20251031-120651
image: myapp:{{date "20060102-150405" "Local"}} # โ myapp:20251031-220651
```
### Date format reference
Go uses a reference time `Mon Jan 2 15:04:05 MST 2006` for formatting. Replace reference components with desired format:
| Component | Reference | Example |
|-----------|-----------|-------------|
| Year | `2006` | `2025` |
| Month | `01` | `10` |
| Day | `02` | `30` |
| Hour | `15` | `22` (24hr) |
| Minute | `04` | `36` |
| Second | `05` | `04` |
**Common patterns:**
| Format | Pattern | Example |
|------------------------|---------------------|---------------------|
| ISO 8601 date | `2006-01-02` | `2025-10-30` |
| Compact date | `20060102` | `20251030` |
| Date with compact time | `2006-01-02-150405` | `2025-10-30-223604`
See Go [time.Format documentation](https://pkg.go.dev/time#Time.Format) for all formatting options.
## Template fields
Access metadata about your project, service, and Git state:
| Field | Type | Description | Example |
|----------------|-----------|--------------------------------------------------------------------|-----------------------------|
| `.Project` | string | Project name from `name` in Compose file or working directory name | `myapp` |
| `.Service` | string | Service name | `web` |
| `.Tag` | string | Pre-rendered default tag (without image name) | `2025-10-30-223604.84d33bb` |
| `.Git.IsRepo` | bool | Whether working directory is a Git repository | `true` or `false` |
| `.Git.IsDirty` | bool | Whether there are uncommitted changes | `true` or `false` |
| `.Git.SHA` | string | Full SHA (40 characters) of the latest Git commit | `84d33bb1234567...` |
| `.Git.Date` | time.Time | Git commit date/time (use `gitdate` function to format) | - |
## Environment variable interpolation
Combine templates with environment variable
[interpolation](https://github.com/compose-spec/compose-spec/blob/main/spec.md#interpolation) using Bash-like syntax.
The environment variables are expanded before rendering the template.
```yaml
# CI build number from environment
image: myapp:{{gitdate "20060102"}}.{{gitsha 7}}.${GITHUB_RUN_ID} # โ myapp:20251030.84d33bb.1234
# With default value
image: myapp:{{gitsha 7}}.${GITHUB_RUN_ID:-local} # GITHUB_RUN_ID not set โ myapp:84d33bb.local
```
## See also
- [Deploy an app](../4-guides/1-deployments/1-deploy-app.md): Deploy from source code or pre-built images
- [Compose Build Specification](https://github.com/compose-spec/compose-spec/blob/main/build.md)
- [Compose Specification: image](https://github.com/compose-spec/compose-spec/blob/main/spec.md#image)
- [Go template documentation](https://pkg.go.dev/text/template)
- [Go Time.Format documentation](https://pkg.go.dev/time#Time.Format)
---
### 9 Cli Reference/Uc
# uc
A CLI tool for managing Uncloud resources such as machines, services, and volumes.
## Options
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
-h, --help help for uc
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc build](uc_build.md) - Build services from a Compose file.
* [uc caddy](uc_caddy.md) - Manage Caddy reverse proxy service.
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
* [uc deploy](uc_deploy.md) - Deploy services from a Compose file.
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
* [uc exec](uc_exec.md) - Execute a command in a running service container.
* [uc image](uc_image.md) - Manage images on machines in the cluster.
* [uc images](uc_images.md) - List images on machines in the cluster.
* [uc inspect](uc_inspect.md) - Display detailed information on a service.
* [uc logs](uc_logs.md) - View service logs.
* [uc ls](uc_ls.md) - List services.
* [uc machine](uc_machine.md) - Manage machines in the cluster.
* [uc proxy](uc_proxy.md) - Proxy a service port to a local port.
* [uc ps](uc_ps.md) - List all service containers.
* [uc rm](uc_rm.md) - Remove one or more services.
* [uc run](uc_run.md) - Run a service.
* [uc scale](uc_scale.md) - Scale a replicated service by changing the number of replicas.
* [uc service](uc_service.md) - Manage services in the cluster.
* [uc start](uc_start.md) - Start one or more services.
* [uc stop](uc_stop.md) - Stop one or more services.
* [uc version](uc_version.md) - Show version and build information.
* [uc volume](uc_volume.md) - Manage volumes in the cluster.
* [uc wg](uc_wg.md) - Inspect WireGuard network
---
### 9 Cli Reference/Uc Build
# uc build
Build services from a Compose file.
## Synopsis
Build images for services from a Compose file using local Docker.
By default, built images remain on the local Docker host. Use --push to upload them
to cluster machines or --push-registry to upload them to external registries.
```
uc build [FLAGS] [SERVICE...] [flags]
```
## Examples
```
# Build all services that have a build section in compose.yaml.
uc build
# Build specific services that have a build section.
uc build web api
# Build services and push images to all cluster machines or service x-machines if specified.
uc build --push
# Build services and push images to specific machines.
uc build --push -m machine1,machine2
# Build services and push images to external registries (e.g., Docker Hub).
uc build --push-registry
# Build services with build arguments, pull newer base images before building, and don't use cache.
uc build --build-arg NODE_VERSION=24 --build-arg ENV=production --no-cache --pull
```
## Options
```
--build-arg stringArray Set a build-time variable for services. Used in Dockerfiles that declare the variable with ARG.
Can be specified multiple times. Format: --build-arg VAR=VALUE
--check Check the build configuration for services without building them.
--deps Also build services declared as dependencies of the selected services.
-f, --file strings One or more Compose files to build. (default compose.yaml)
-h, --help help for build
-m, --machine strings Machine names or IDs to push the built images to (requires --push).
Can be specified multiple times or as a comma-separated list. (default is all machines or x-machines)
--no-cache Do not use cache when building images.
-p, --profile strings One or more Compose profiles to enable.
--pull Always attempt to pull newer versions of base images before building.
--push Upload the built images to cluster machines after building.
Use --machine to specify which machines. (default is all machines)
--push-registry Upload the built images to external registries (e.g., Docker Hub) after building.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Caddy
# uc caddy
Manage Caddy reverse proxy service.
## Options
```
-h, --help help for caddy
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
* [uc caddy config](uc_caddy_config.md) - Show the current Caddy configuration (Caddyfile).
* [uc caddy deploy](uc_caddy_deploy.md) - Deploy or upgrade Caddy reverse proxy across all machines in the cluster.
* [uc caddy logs](uc_caddy_logs.md) - View caddy logs.
---
### 9 Cli Reference/Uc Caddy Config
# uc caddy config
Show the current Caddy configuration (Caddyfile).
## Synopsis
Display the current Caddy configuration (Caddyfile) from the connected machine or a specified one.
```
uc caddy config [flags]
```
## Options
```
-h, --help help for config
-m, --machine string Name or ID of the machine to get the configuration from. (default is connected machine)
--no-color Disable syntax highlighting for the output.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc caddy](uc_caddy.md) - Manage Caddy reverse proxy service.
---
### 9 Cli Reference/Uc Caddy Deploy
# uc caddy deploy
Deploy or upgrade Caddy reverse proxy across all machines in the cluster.
## Synopsis
Deploy or upgrade Caddy reverse proxy across all machines in the cluster.
A rolling update is performed when updating existing containers to minimise disruption.
```
uc caddy deploy [flags]
```
## Options
```
--caddyfile string Path to a custom global Caddy config (Caddyfile) that will be prepended to the auto-generated Caddy config.
-h, --help help for deploy
--image string Caddy Docker image to deploy. (default caddy:LATEST_VERSION)
-m, --machine strings Machine names or IDs to deploy to. Can be specified multiple times or as a comma-separated list. (default is all machines)
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc caddy](uc_caddy.md) - Manage Caddy reverse proxy service.
---
### 9 Cli Reference/Uc Caddy Logs
# uc caddy logs
View caddy logs.
## Synopsis
View caddy logs.
This calls "uc logs caddy", see "uc logs" for the documention.
```
uc caddy logs [flags]
```
## Options
```
-f, --follow Continually stream new logs.
-h, --help help for logs
-m, --machine strings Filter logs by machine name or ID. Can be specified multiple times or as a comma-separated list.
--since string Show logs generated on or after the given timestamp. Accepts relative duration, RFC 3339 date, or Unix timestamp.
Examples:
--since 2m30s Relative duration (2 minutes 30 seconds ago)
--since 1h Relative duration (1 hour ago)
--since 2025-11-24 RFC 3339 date only (midnight using local timezone)
--since 2024-05-14T22:50:00 RFC 3339 date/time using local timezone
--since 2024-01-31T10:30:00Z RFC 3339 date/time in UTC
--since 1763953966 Unix timestamp (seconds since January 1, 1970)
-n, --tail string Show the most recent logs and limit the number of lines shown per replica. Use 'all' to show all logs. (default "100")
--until string Show logs generated before the given timestamp. Accepts relative duration, RFC 3339 date, or Unix timestamp.
See --since for examples.
--utc Print timestamps in UTC instead of local timezone.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc caddy](uc_caddy.md) - Manage Caddy reverse proxy service.
---
### 9 Cli Reference/Uc Ctx
# uc ctx
Switch between different cluster contexts. Contains subcommands to manage contexts.
```
uc ctx [flags]
```
## Options
```
-h, --help help for ctx
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
* [uc ctx connection](uc_ctx_connection.md) - Choose a new default connection for the current context.
* [uc ctx ls](uc_ctx_ls.md) - List available cluster contexts.
* [uc ctx show](uc_ctx_show.md) - Show current cluster context.
* [uc ctx use](uc_ctx_use.md) - Switch to a different cluster context.
---
### 9 Cli Reference/Uc Ctx Connection
# uc ctx connection
Choose a new default connection for the current context.
```
uc ctx connection [flags]
```
## Options
```
-h, --help help for connection
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
---
### 9 Cli Reference/Uc Ctx Ls
# uc ctx ls
List available cluster contexts.
```
uc ctx ls [flags]
```
## Options
```
-h, --help help for ls
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
---
### 9 Cli Reference/Uc Ctx Show
# uc ctx show
Show current cluster context.
```
uc ctx show [flags]
```
## Options
```
-h, --help help for show
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
---
### 9 Cli Reference/Uc Ctx Use
# uc ctx use
Switch to a different cluster context.
## Synopsis
Switch to a different cluster context. If no context is provided, a list of available contexts will be displayed for selection.
```
uc ctx use [CONTEXT] [flags]
```
## Options
```
-h, --help help for use
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc ctx](uc_ctx.md) - Switch between different cluster contexts. Contains subcommands to manage contexts.
---
### 9 Cli Reference/Uc Deploy
# uc deploy
Deploy services from a Compose file.
```
uc deploy [FLAGS] [SERVICE...] [flags]
```
## Options
```
--build-arg stringArray Set a build-time variable for services. Used in Dockerfiles that declare the variable with ARG.
Can be specified multiple times. Format: --build-arg VAR=VALUE
--build-pull Always attempt to pull newer versions of base images before building service images.
-f, --file strings One or more Compose files to deploy services from. (default compose.yaml)
-h, --help help for deploy
--no-build Do not build new images before deploying services.
--no-cache Do not use cache when building images.
-p, --profile strings One or more Compose profiles to enable.
--recreate Recreate containers even if their configuration and image haven't changed.
--skip-health Skip the monitoring period and health checks after starting new containers. Useful for faster emergency deployments.
Warning: This may cause downtime if new containers fail to start properly.
-y, --yes Auto-confirm deployment plan. Should be explicitly set when running non-interactively,
e.g., in CI/CD pipelines. [$UNCLOUD_AUTO_CONFIRM]
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Dns
# uc dns
Manage cluster domain in Uncloud DNS.
## Synopsis
Manage cluster domain in Uncloud DNS.
DNS commands allow you to reserve or release a unique 'xxxxxx.uncld.dev' domain for your cluster. When reserved, Caddy service deployments will automatically update DNS records to route traffic to the services in the cluster.
## Options
```
-h, --help help for dns
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
* [uc dns release](uc_dns_release.md) - Release the reserved cluster domain.
* [uc dns reserve](uc_dns_reserve.md) - Reserve a cluster domain in Uncloud DNS.
* [uc dns show](uc_dns_show.md) - Print the cluster domain name.
---
### 9 Cli Reference/Uc Dns Release
# uc dns release
Release the reserved cluster domain.
```
uc dns release [flags]
```
## Options
```
-h, --help help for release
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
---
### 9 Cli Reference/Uc Dns Reserve
# uc dns reserve
Reserve a cluster domain in Uncloud DNS.
```
uc dns reserve [flags]
```
## Options
```
--endpoint string API endpoint for the Uncloud DNS service. (default "https://dns.uncloud.run/v1")
-h, --help help for reserve
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
---
### 9 Cli Reference/Uc Dns Show
# uc dns show
Print the cluster domain name.
```
uc dns show [flags]
```
## Options
```
-h, --help help for show
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc dns](uc_dns.md) - Manage cluster domain in Uncloud DNS.
---
### 9 Cli Reference/Uc Exec
# uc exec
Execute a command in a running service container.
## Synopsis
Execute a command (interactive shell by default) in a running container within a service.
If the service has multiple replicas and no container ID is specified, the command will be executed in a random container.
```
uc exec [OPTIONS] SERVICE [COMMAND ARGS...] [flags]
```
## Examples
```
# Start an interactive shell ("bash" or "sh" will be tried by default)
uc exec web-service
# Start an interactive shell with explicit command
uc exec web-service /bin/zsh
# List files in the specific container of the service; --container accepts full ID or a (unique) prefix
uc exec --container d792e web-service ls -la
# Pipe input to a command inside the service container
cat backup.sql | uc exec -T db-service psql -U postgres mydb
# Run a task in the background (detached mode)
uc exec -d web-service /scripts/cleanup.sh
```
## Options
```
--container string ID of the container to exec into. Accepts full ID or a unique prefix (default is the random container of the service)
-d, --detach Detached mode: run command in the background
-h, --help help for exec
-T, --no-tty Disable pseudo-TTY allocation. By default 'uc exec' allocates a TTY when connected to a terminal.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Image
# uc image
Manage images on machines in the cluster.
## Options
```
-h, --help help for image
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
* [uc image ls](uc_image_ls.md) - List images on machines in the cluster.
* [uc image push](uc_image_push.md) - Upload a local Docker image to the cluster.
---
### 9 Cli Reference/Uc Image Ls
# uc image ls
List images on machines in the cluster.
## Synopsis
List images on machines in the cluster. By default, on all machines. Optionally filter by image name.
```
uc image ls [REPO:[TAG]] [flags]
```
## Examples
```
# List all images on all machines.
uc image ls
# List images on specific machine.
uc image ls -m machine1
# List images on multiple machines.
uc image ls -m machine1,machine2
# List images filtered by name (with any tag) on all machines.
uc image ls myapp
# List images filtered by name pattern on specific machine.
uc image ls "myapp:1.*" -m machine1
```
## Options
```
-h, --help help for ls
-m, --machine strings Filter images by machine name or ID. Can be specified multiple times or as a comma-separated list. (default is include all machines)
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc image](uc_image.md) - Manage images on machines in the cluster.
---
### 9 Cli Reference/Uc Image Push
# uc image push
Upload a local Docker image to the cluster.
## Synopsis
Upload a local Docker image to the cluster transferring only the missing layers.
The image is uploaded to all cluster machines (default) or the specified machine(s).
```
uc image push IMAGE [flags]
```
## Examples
```
# Push image to all machines in the cluster.
uc image push myapp:latest
# Push image to specific machine.
uc image push myapp:latest -m machine1
# Push image to multiple machines.
uc image push myapp:latest -m machine1,machine2,machine3
# Push a specific platform of a multi-platform image.
uc image push myapp:latest --platform linux/amd64
```
## Options
```
-h, --help help for push
-m, --machine strings Machine names or IDs to push the image to. Can be specified multiple times or as a comma-separated list. (default is all machines)
--platform string Push a specific platform of a multi-platform image (e.g., linux/amd64, linux/arm64).
Local Docker must be configured to use containerd image store to support multi-platform images.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc image](uc_image.md) - Manage images on machines in the cluster.
---
### 9 Cli Reference/Uc Images
# uc images
List images on machines in the cluster.
## Synopsis
List images on machines in the cluster. By default, on all machines. Optionally filter by image name.
```
uc images [IMAGE] [flags]
```
## Examples
```
# List all images on all machines.
uc images
# List images on specific machine.
uc images -m machine1
# List images on multiple machines.
uc images -m machine1,machine2
# List images filtered by name (with any tag) on all machines.
uc images myapp
# List images filtered by name pattern on specific machine.
uc images "myapp:1.*" -m machine1
```
## Options
```
-h, --help help for images
-m, --machine strings Filter images by machine name or ID. Can be specified multiple times or as a comma-separated list. (default is include all machines)
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Inspect
# uc inspect
Display detailed information on a service.
```
uc inspect SERVICE [flags]
```
## Options
```
-h, --help help for inspect
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Logs
# uc logs
View service logs.
## Synopsis
View logs from all replicas of the specified service(s) across all machines in the cluster.
To view logs from specific replicas (containers) within a service, use the SERVICE/CONTAINER form,
where CONTAINER is a container name, full ID, or unique ID prefix.
If no services are specified, streams logs from all services defined in the Compose file
(compose.yaml by default or the file(s) specified with --file).
```
uc logs [SERVICE[/CONTAINER]...] [flags]
```
## Examples
```
# View recent logs for a service.
uc logs web
# Stream logs in real-time (follow mode).
uc logs -f web
# View logs from multiple services.
uc logs web api db
# View logs from all services in compose.yaml.
uc logs
# Show last 20 lines per replica (default is 100).
uc logs -n 20 web
# Show all logs without line limit.
uc logs -n all web
# View logs from a specific time range.
uc logs --since 3h --until 1h30m web
# View logs only from specific replicas (containers).
uc logs web/61d57fd3428f api/2f60
# View logs only from replicas running on specific machines.
uc logs -m machine1,machine2 web api
```
## Options
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Ls
# uc ls
List services.
```
uc ls [flags]
```
## Options
```
-h, --help help for ls
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Machine
# uc machine
Manage machines in the cluster.
## Options
```
-h, --help help for machine
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
* [uc machine add](uc_machine_add.md) - Add a remote machine to a cluster.
* [uc machine init](uc_machine_init.md) - Initialise a new cluster with a remote machine as the first member.
* [uc machine logs](uc_machine_logs.md) - View system service logs.
* [uc machine ls](uc_machine_ls.md) - List machines in a cluster.
* [uc machine rename](uc_machine_rename.md) - Rename a machine in the cluster.
* [uc machine rm](uc_machine_rm.md) - Remove a machine from a cluster and reset it.
* [uc machine rtt](uc_machine_rtt.md) - Show round-trip times between machines.
* [uc machine update](uc_machine_update.md) - Update machine configuration in the cluster.
---
### 9 Cli Reference/Uc Machine Add
# uc machine add
Add a remote machine to a cluster.
## Synopsis
Add a new machine to an existing Uncloud cluster.
By default, it installs Docker and the Uncloud daemon on the machine over SSH unless --no-install
is specified, which assumes they are already installed and running.
Connection methods:
[ssh://]user@host - Use system 'ssh' command with full SSH config support (default, no prefix required)
ssh+go://user@host - Use Go's built-in SSH library
```
uc machine add [USER@]HOST[:PORT] [flags]
```
## Options
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Init
# uc machine init
Initialise a new cluster with a remote machine as the first member.
## Synopsis
Initialise a new cluster by setting up a remote machine as the first member.
This command creates a new context in your Uncloud config to manage the cluster.
By default, it installs Docker and the Uncloud daemon on the machine over SSH unless --no-install
is specified, which assumes they are already installed and running.
Connection methods:
[ssh://]user@host - Use system 'ssh' command with full SSH config support (default, no prefix required)
ssh+go://user@host - Use Go's built-in SSH library
```
uc machine init [schema://]USER@HOST[:PORT] [flags]
```
## Examples
```
# Initialise a new cluster with default settings.
uc machine init root@
# Initialise with a context name 'prod' in the Uncloud config (~/.config/uncloud/config.yaml) and machine name 'vps1'.
uc machine init root@ -c prod -n vps1
# Initialise with a non-root user and custom SSH port and key.
uc machine init ubuntu@:2222 -i ~/.ssh/mykey
# Initialise without Caddy (no reverse proxy) and without an automatically managed domain name (xxxxxx.uncld.dev).
# You can deploy Caddy with 'uc caddy deploy' and reserve a domain with 'uc dns reserve' later.
uc machine init root@ --no-caddy --no-dns
```
## Options
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Logs
# uc machine logs
View system service logs.
## Synopsis
View logs from the specified system service(s) across all machines in the cluster.
Use -m to restrict to specific machines.
Supported services:
corrosion the Corrosion distributed state store
docker the Docker daemon
uncloud the Uncloud daemon
If no services are specified, streams logs from the uncloud service.
```
uc machine logs [SERVICE...] [flags]
```
## Examples
```
# View recent logs for the uncloud service.
uc machine logs
uc machine logs uncloud
# Stream logs in real-time (follow mode).
uc machine logs -f uncloud
# View logs from multiple services.
uc machine logs uncloud docker corrosion
# Show last 20 lines per machine (default is 100).
uc machine logs -n 20 docker
# Show all logs without line limit.
uc machine logs -n all docker
# View logs from a specific time range.
uc machine logs --since 3h --until 1h30m docker
# View logs only from specific machines.
uc machine logs -m machine1,machine2 uncloud corrosion
```
## Options
```
-f, --follow Continually stream new logs.
-h, --help help for logs
-m, --machine strings Filter logs by machine name or ID. Can be specified multiple times or as a comma-separated list.
--since string Show logs generated on or after the given timestamp. Accepts relative duration, RFC 3339 date, or Unix timestamp.
Examples:
--since 2m30s Relative duration (2 minutes 30 seconds ago)
--since 1h Relative duration (1 hour ago)
--since 2025-11-24 RFC 3339 date only (midnight using local timezone)
--since 2024-05-14T22:50:00 RFC 3339 date/time using local timezone
--since 2024-01-31T10:30:00Z RFC 3339 date/time in UTC
--since 1763953966 Unix timestamp (seconds since January 1, 1970)
-n, --tail string Show the most recent logs and limit the number of lines shown per replica. Use 'all' to show all logs. (default "100")
--until string Show logs generated before the given timestamp. Accepts relative duration, RFC 3339 date, or Unix timestamp.
See --since for examples.
--utc Print timestamps in UTC instead of local timezone.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Ls
# uc machine ls
List machines in a cluster.
```
uc machine ls [flags]
```
## Options
```
-h, --help help for ls
-o, --output string Output format: 'json' or empty for a human-readable table.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Rename
# uc machine rename
Rename a machine in the cluster.
## Synopsis
Rename a machine in the cluster.
This command changes the name of an existing machine while preserving all other
configuration including network settings, public IP, and cluster membership.
```
uc machine rename OLD_NAME NEW_NAME [flags]
```
## Options
```
-h, --help help for rename
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Rm
# uc machine rm
Remove a machine from a cluster and reset it.
```
uc machine rm MACHINE [flags]
```
## Options
```
-h, --help help for rm
--no-reset Do not reset the machine after removing it from the cluster. This will leave all containers and data intact.
-y, --yes Do not prompt for confirmation before removing the machine.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Rtt
# uc machine rtt
Show round-trip times between machines.
## Synopsis
Show round-trip times between machines.
Round-trip time statistics are collected from the Corrosion gossip protocol
and represent the median of recent RTT samples between each pair of machines
in the cluster. The values shown include the median RTT and standard deviation
for each machine-to-machine connection.
```
uc machine rtt [flags]
```
## Options
```
-h, --help help for rtt
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Machine Update
# uc machine update
Update machine configuration in the cluster.
## Synopsis
Update machine configuration in the cluster.
Change the name, public IP address, or WireGuard endpoints of an existing machine.
At least one flag must be specified to perform an update.
```
uc machine update MACHINE [flags]
```
## Examples
```
# Rename a machine.
uc machine update machine1 --name web-server
# Set the public IP address of a machine.
uc machine update machine1 --public-ip 203.0.113.10
# Remove the public IP address from a machine.
uc machine update machine1 --public-ip none
# Update WireGuard endpoints for a machine.
uc machine update machine1 --wg-endpoint 203.0.113.10 --wg-endpoint 192.168.1.5
# Update multiple properties at once.
uc machine update machine1 --name web-server --public-ip 203.0.113.10
```
## Options
```
-h, --help help for update
--name string New name for the machine
--public-ip string Public IP address of the machine for ingress configuration. Use 'none' or '' to remove the public IP.
--wg-endpoint strings WireGuard endpoint address that other machines in the cluster should use to establish WireGuard connections
to this machine. This doesn't change the address/port WireGuard listens on the machine.
Format: IP, IP:PORT, IPv6, or [IPv6]:PORT. Default port is 51820 if omitted.
Multiple endpoints can be specified by repeating the flag or using a comma-separated list.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc machine](uc_machine.md) - Manage machines in the cluster.
---
### 9 Cli Reference/Uc Proxy
# uc proxy
Proxy a service port to a local port.
## Synopsis
Proxy a service port in the cluster to a local port on this machine.
If the service runs multiple containers, the command connects to the first running and healthy one.
If you don't provide a local port, the command picks a random one.
The connection stays open for as long as the command runs.
```
uc proxy SERVICE [LOCAL_PORT:]REMOTE_PORT [flags]
```
## Options
```
-h, --help help for proxy
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Ps
# uc ps
List all service containers.
## Synopsis
List all service containers across all machines in the cluster.
This command provides a comprehensive overview of all running containers that are part of a service,
making it easy to see the distribution and status of containers across the cluster.
```
uc ps [flags]
```
## Options
```
-h, --help help for ps
-s, --sort string Sort containers by 'service', 'machine', or 'health'. (default "service")
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Rm
# uc rm
Remove one or more services.
## Synopsis
Remove one or more services.
The volumes used by the services are preserved and should be removed separately
with 'uc volume rm'. Anonymous Docker volumes (automatically created from VOLUME
directives in image Dockerfiles) are automatically removed with their containers.
```
uc rm SERVICE [SERVICE...] [flags]
```
## Options
```
-h, --help help for rm
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Run
# uc run
Run a service.
```
uc run IMAGE [COMMAND...] [flags]
```
## Options
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Scale
# uc scale
Scale a replicated service by changing the number of replicas.
## Synopsis
Scale a replicated service by changing the number of replicas.
```
uc scale SERVICE REPLICAS [flags]
```
## Options
```
-h, --help help for scale
-y, --yes Auto-confirm scaling plan. Should be explicitly set when running non-interactively,
e.g., in CI/CD pipelines. [$UNCLOUD_AUTO_CONFIRM]
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
---
### 9 Cli Reference/Uc Service
# uc service
Manage services in the cluster.
## Options
```
-h, --help help for service
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc](uc.md) - A CLI tool for managing Uncloud resources such as machines, services, and volumes.
* [uc service exec](uc_service_exec.md) - Execute a command in a running service container.
* [uc service inspect](uc_service_inspect.md) - Display detailed information on a service.
* [uc service logs](uc_service_logs.md) - View service logs.
* [uc service ls](uc_service_ls.md) - List services.
* [uc service rm](uc_service_rm.md) - Remove one or more services.
* [uc service run](uc_service_run.md) - Run a service.
* [uc service scale](uc_service_scale.md) - Scale a replicated service by changing the number of replicas.
* [uc service start](uc_service_start.md) - Start one or more services.
* [uc service stop](uc_service_stop.md) - Stop one or more services.
---
### 9 Cli Reference/Uc Service Exec
# uc service exec
Execute a command in a running service container.
## Synopsis
Execute a command (interactive shell by default) in a running container within a service.
If the service has multiple replicas and no container ID is specified, the command will be executed in a random container.
```
uc service exec [OPTIONS] SERVICE [COMMAND ARGS...] [flags]
```
## Examples
```
# Start an interactive shell ("bash" or "sh" will be tried by default)
uc exec web-service
# Start an interactive shell with explicit command
uc exec web-service /bin/zsh
# List files in the specific container of the service; --container accepts full ID or a (unique) prefix
uc exec --container d792e web-service ls -la
# Pipe input to a command inside the service container
cat backup.sql | uc exec -T db-service psql -U postgres mydb
# Run a task in the background (detached mode)
uc exec -d web-service /scripts/cleanup.sh
```
## Options
```
--container string ID of the container to exec into. Accepts full ID or a unique prefix (default is the random container of the service)
-d, --detach Detached mode: run command in the background
-h, --help help for exec
-T, --no-tty Disable pseudo-TTY allocation. By default 'uc exec' allocates a TTY when connected to a terminal.
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc service](uc_service.md) - Manage services in the cluster.
---
### 9 Cli Reference/Uc Service Inspect
# uc service inspect
Display detailed information on a service.
```
uc service inspect SERVICE [flags]
```
## Options
```
-h, --help help for inspect
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc service](uc_service.md) - Manage services in the cluster.
---
### 9 Cli Reference/Uc Service Logs
# uc service logs
View service logs.
## Synopsis
View logs from all replicas of the specified service(s) across all machines in the cluster.
To view logs from specific replicas (containers) within a service, use the SERVICE/CONTAINER form,
where CONTAINER is a container name, full ID, or unique ID prefix.
If no services are specified, streams logs from all services defined in the Compose file
(compose.yaml by default or the file(s) specified with --file).
```
uc service logs [SERVICE[/CONTAINER]...] [flags]
```
## Examples
```
# View recent logs for a service.
uc logs web
# Stream logs in real-time (follow mode).
uc logs -f web
# View logs from multiple services.
uc logs web api db
# View logs from all services in compose.yaml.
uc logs
# Show last 20 lines per replica (default is 100).
uc logs -n 20 web
# Show all logs without line limit.
uc logs -n all web
# View logs from a specific time range.
uc logs --since 3h --until 1h30m web
# View logs only from specific replicas (containers).
uc logs web/61d57fd3428f api/2f60
# View logs only from replicas running on specific machines.
uc logs -m machine1,machine2 web api
```
## Options
```
/* Detailed source-code truncated for AI context efficiency. */
```
## Options inherited from parent commands
```
--connect string Connect to a remote cluster machine without using the Uncloud configuration file. [$UNCLOUD_CONNECT]
Format: [ssh://]user@host[:port], ssh+go://user@host[:port], tcp://host:port, or unix:///path/to/uncloud.sock
-c, --context string Name of the cluster context to use (default is the current context). [$UNCLOUD_CONTEXT]
--uncloud-config string Path to the Uncloud configuration file. [$UNCLOUD_CONFIG] (default "~/.config/uncloud/config.yaml")
```
## See also
* [uc service](uc_service.md) - Manage services in the cluster.
---