---
title: Proxmox CT/LXC Provisioning Runbook
type: runbook
tags:
  - proxmox
aliases: []
related:
  - [[proxmox-onboard-node]]
  - [[headscale-onboard-node]]
  - [[meshtasticd-sim-nodes-runbook]]
  - [[proxmox-create-ubuntu-vm]]
  - [[ots-setup]]
updated: 2026-06-18
---
# Proxmox CT/LXC Provisioning Runbook

Every container gets the same baseline: local user, Tailscale, SSH, Docker, and common tools. No exceptions.

---

## Prerequisites

- Proxmox VE host with Ubuntu 24.04 LXC template downloaded
- Tailscale auth key (reusable, from https://login.tailscale.com/admin/settings/keys)
- SSH access to Proxmox host

If you don't have the template cached yet:

```bash
pveam update
pveam download local system ubuntu-24.04-standard_24.04-2_amd64.tar.zst
```

---

## 1. Create the Container

Pick the next available CTID. Adjust `--memory`, `--cores`, and `--rootfs` to fit the workload.

```bash
# Variables — edit these per container
CTID=110
HOSTNAME="mycontainer"
STORAGE="local-lvm"          # or zfs-pool, ceph, etc.
DISK_SIZE=8                  # GB
MEMORY=2048                  # MB
CORES=2
BRIDGE="vmbr0"

pct create $CTID local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
  --hostname $HOSTNAME \
  --storage $STORAGE \
  --rootfs ${STORAGE}:${DISK_SIZE} \
  --memory $MEMORY \
  --cores $CORES \
  --net0 name=eth0,bridge=${BRIDGE},ip=dhcp \
  --unprivileged 1 \
  --features nesting=1,keyctl=1 \
  --onboot 1 \
  --start 1
```

`nesting=1` is required for Docker. `keyctl=1` prevents keyring errors in systemd containers.

Wait a few seconds for the container to boot, then enter it:

```bash
pct enter $CTID
```

Everything from here on runs **inside the container**.

---

## 2. Base System Update

```bash
apt update && apt upgrade -y
```

---

## 3. Common Tools

```bash
apt install -y \
  curl \
  wget \
  vim \
  htop \
  git \
  unzip \
  jq \
  net-tools \
  dnsutils \
  ca-certificates \
  gnupg \
  lsb-release \
  sudo \
  sshpass
```

---

## 4. Create User

```bash
useradd -m -s /bin/bash -G sudo zvx
echo "zvx:7redditGold" | chpasswd
```

Verify:

```bash
su - zvx -c "whoami && sudo -l"
```

---

## 5. SSH Configuration

SSH should already be running in the Ubuntu 24.04 template, but make sure password auth is enabled for sshpass workflows:

```bash
# Ensure SSH is installed and running
apt install -y openssh-server
systemctl enable --now ssh

# Allow password auth (needed for sshpass)
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config

systemctl restart ssh
```

Test from the Proxmox host (exit the container first):

```bash
CT_IP=$(pct exec $CTID -- hostname -I | awk '{print $1}')
sshpass -p '7redditGold' ssh -o StrictHostKeyChecking=accept-new zvx@$CT_IP "echo 'SSH OK'"
```

---

## 6. Install Docker

```bash
# Add Docker's official GPG key and repo
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  > /etc/apt/sources.list.d/docker.list

apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Add zvx to docker group (no sudo needed for docker commands)
usermod -aG docker zvx

# Verify
docker run --rm hello-world
```

If Docker fails to start with an AppArmor or permissions error, confirm `nesting=1` is set on the container (Step 1). You can check/fix from the Proxmox host:

```bash
pct set $CTID --features nesting=1,keyctl=1
pct reboot $CTID
```

---

## 7. Install Tailscale

```bash
curl -fsSL https://tailscale.com/install.sh | sh
```

Bring it up with your auth key:

```bash
# Replace with your actual auth key
tailscale up --authkey=tskey-auth-XXXXXXXXXXXX --ssh
```

If you don't have an auth key handy, run without `--authkey` and it will print a URL to authenticate in a browser:

```bash
tailscale up --ssh
```

Verify:

```bash
tailscale status
tailscale ip -4
```

The `--ssh` flag enables Tailscale SSH, which lets you SSH into the container over Tailscale without managing keys. The container will appear in your tailnet by its hostname.

---

## 8. Verification Checklist

Run this from inside the container to confirm everything:

```bash
echo "=== CT Provisioning Check ==="
echo ""
echo "Hostname:     $(hostname)"
echo "User zvx:     $(id zvx 2>/dev/null && echo 'OK' || echo 'MISSING')"
echo "sudo:         $(sudo -l -U zvx 2>/dev/null | grep -q ALL && echo 'OK' || echo 'MISSING')"
echo "sshpass:      $(which sshpass >/dev/null 2>&1 && echo 'OK' || echo 'MISSING')"
echo "SSH:          $(systemctl is-active ssh)"
echo "Docker:       $(docker --version 2>/dev/null || echo 'MISSING')"
echo "Tailscale:    $(tailscale status --self 2>/dev/null | head -1 || echo 'NOT CONNECTED')"
echo "Tailscale IP: $(tailscale ip -4 2>/dev/null || echo 'N/A')"
```

Expected output — everything should say OK/active with a Tailscale IP:

```
=== CT Provisioning Check ===

Hostname:     mycontainer
User zvx:     uid=1000(zvx) gid=1000(zvx) groups=1000(zvx),27(sudo),998(docker) OK
sudo:         OK
sshpass:      OK
SSH:          active
Docker:       Docker version 27.x.x, build xxxxxxx
Tailscale:    100.x.x.x  mycontainer  tagged-devices linux -
Tailscale IP: 100.x.x.x
```

---

## Quick Reference (Copy/Paste Block)

For the impatient — the whole thing end to end after `pct enter`:

```bash
# Update + tools
apt update && apt upgrade -y
apt install -y curl wget vim htop git unzip jq net-tools dnsutils \
  ca-certificates gnupg lsb-release sudo sshpass openssh-server

# User
useradd -m -s /bin/bash -G sudo zvx
echo "zvx:7redditGold" | chpasswd

# SSH
systemctl enable --now ssh
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart ssh

# Docker
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  > /etc/apt/sources.list.d/docker.list
apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
usermod -aG docker zvx

# Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up --ssh
```
