Skip to main content

What is a Machine?

In Uncloud, a machine is any Linux server (VM, bare metal, or cloud instance) that has been added to your cluster. Machines are the compute resources where your containers run. Each machine:
  • Runs Docker for container execution
  • Has the uncloudd daemon and Corrosion database installed
  • Gets a unique /24 subnet from the cluster address space
  • Participates in the WireGuard mesh network
  • Maintains a complete copy of cluster state
Unlike Kubernetes nodes, Uncloud machines are completely equal peers. There are no master or worker roles - every machine can accept commands and manage the cluster.

Machine Lifecycle

Initializing the First Machine

When you initialize a new cluster on the first machine:
uc machine init root@your-server-ip
Uncloud performs these steps:
  1. Install dependencies - Installs Docker if not already present
  2. Create system user - Creates uncloud user and group for service isolation
  3. Install binaries - Downloads uncloudd and uncloud-corrosion to /usr/local/bin
  4. Generate keys - Creates WireGuard private/public key pair
  5. Allocate subnet - Assigns 10.210.0.0/24 subnet to the first machine
  6. Configure services - Creates systemd units and starts services
  7. Setup networking - Configures WireGuard interface and Docker bridge
  8. Initialize database - Creates Corrosion database with initial cluster state
  9. Deploy Caddy - Starts Caddy reverse proxy container
  10. Register cluster domain - Reserves *.xxxxxx.uncld.dev subdomain
The first machine gets IP 10.210.0.1/24 and becomes the initial entry point in your cluster config at ~/.config/uncloud/.

Adding More Machines

To add another machine to your cluster:
uc machine add --name my-server root@server-ip
The process is similar to initialization, with these differences:
  1. A new subnet is allocated (e.g., 10.210.1.0/24 for the second machine)
  2. WireGuard keys are exchanged with existing machines
  3. The new machine establishes tunnels to existing peers
  4. Corrosion syncs the complete cluster state to the new machine
  5. The new machine is added as an alternative entry point in your local config
  6. Caddy is deployed in global mode, automatically starting on the new machine
The new machine only needs to connect to one existing machine initially. It will learn about all other machines through state synchronization and establish tunnels automatically.

Listing Machines

View all machines in your cluster:
uc machine ls
Output shows:
  • Machine name and state (Up, Down, Unknown)
  • Mesh network address (e.g., 10.210.0.1/24)
  • Public IP address
  • WireGuard endpoints for connectivity

Removing Machines

To remove a machine from the cluster:
uc machine rm machine-name
This:
  1. Stops all containers running on the machine
  2. Removes the machine from cluster state
  3. Other machines remove WireGuard tunnels to it
  4. Updates are propagated through Corrosion
Removing a machine does not uninstall Uncloud from the physical server. To fully uninstall, SSH into the machine and run uncloud-uninstall.

Subnet Allocation

Uncloud uses a simple subnet allocation scheme within the 10.210.0.0/16 address space.

How Subnets are Assigned

Each machine gets a /24 subnet that provides:
  • 1 IP for the machine itself (.1)
  • 253 IPs for containers (.2 to .254)
  • .0 is the network address
  • .255 is the broadcast address
Subnets are allocated sequentially:
  • First machine: 10.210.0.0/24 (IP: 10.210.0.1)
  • Second machine: 10.210.1.0/24 (IP: 10.210.1.1)
  • Third machine: 10.210.2.0/24 (IP: 10.210.2.1)
  • And so on…
This provides address space for up to 256 machines in a cluster.

Container IP Assignment

Containers running on a machine get IPs from that machine’s subnet. For example, on the first machine (10.210.0.0/24):
  • First container: 10.210.0.2
  • Second container: 10.210.0.3
  • Third container: 10.210.0.4
  • And so on up to 10.210.0.254
This addressing scheme allows containers to communicate directly across machines without NAT or port mapping.
Each machine can run up to 253 containers. This is typically more than sufficient for practical deployments.

Machine Roles and Placement

While all machines are equal peers in the control plane, you can influence where containers run using placement constraints.

Service Placement

When deploying services, you can specify which machines should run containers:
services:
  api:
    image: myapp/api
    deploy:
      replicas: 3
      placement:
        constraints:
          - machine.name == production-1
          - machine.name == production-2
See the Deploying Services guide for more details.

Global Services

Some services (like Caddy) run in global mode, automatically deploying one container to every machine:
services:
  caddy:
    image: caddy:latest
    deploy:
      mode: global
This is useful for ingress proxies, monitoring agents, and other infrastructure services.

Machine State and Health

Machines can be in several states:
  • Up - Machine is reachable and healthy
  • Down - Machine is not responding (offline, network issue, or daemon stopped)
  • Unknown - State cannot be determined
If a machine goes down, containers on other machines continue running normally. Services in global mode won’t have a container on the down machine, but other replicas remain available.

Adding Machines Behind NAT

Uncloud works seamlessly with machines behind NAT or firewalls. The WireGuard mesh uses NAT traversal techniques to establish connections. Requirements:
  • Outbound UDP port 51820 must be allowed
  • At least one machine should have a public IP (for initial bootstrapping)
  • If all machines are behind NAT, you may need to configure port forwarding
WireGuard uses a 25-second keepalive interval to maintain tunnels through NAT devices and firewalls.

Machine Configuration

Machine configuration is stored in:
  • Cluster state (Corrosion database) - Machine metadata, IPs, keys
  • Local systemd units - Service configuration at /etc/systemd/system/
  • Local config files - WireGuard config, Docker bridge settings

Checking Daemon Status

On any machine, you can check service status:
# Main daemon
sudo systemctl status uncloud

# Corrosion database  
sudo systemctl status uncloud-corrosion

# View daemon logs
journalctl -u uncloud -f

Resource Requirements

Minimum requirements per machine:
  • OS: Linux (Ubuntu 20.04+, Debian 11+, or similar)
  • RAM: 512 MB (1 GB+ recommended)
  • CPU: 1 core (2+ recommended)
  • Disk: 10 GB (more if running stateful services)
  • Network: Outbound UDP port 51820 for WireGuard
Uncloud itself uses about 150 MB of RAM per machine, leaving the rest available for your containers.

Further Reading

Networking

Deep dive into WireGuard mesh and routing

Services

Learn how services are deployed across machines

Machine Management

Add, list, update, and remove machines

Architecture

Understand the overall system design

Build docs developers (and LLMs) love