Deployment Guide
For system administrators with Linux experience, deploying on a single host from scratch.
Prerequisites
- Ubuntu 22.04+ / Debian 12+ (or equivalent systemd-based Linux)
- Root or sudo access
- Public IP (for bootstrap endpoint and user SSH access)
- At least one proxy config for an exit IP
1. Environment Setup
1.1 Dependency Check
bash
sudo bash deploy/scripts/host-preflight.sh| Dependency | Min Version | Purpose |
|---|---|---|
| Docker Engine | 28.x+ | Container runtime |
| FUSE | kernel module | Container sshfs directory mapping |
nftables (nft) | -- | Container firewall rules |
nsenter | -- | Network namespace verification |
curl | -- | Egress IP verification and health checks |
ip | -- | Network configuration |
systemctl | -- | Service management |
| Go | 1.26+ | Build control-plane and host-agent |
| PostgreSQL | 18.x | Persistent storage |
| Node.js | 24 LTS | Frontend build (optional) |
1.2 Install Missing Dependencies
Docker Engine:
bash
curl -fsSL https://get.docker.com | sh
systemctl enable --now dockerFUSE kernel module:
bash
modprobe fuse
echo fuse >> /etc/modules-load.d/fuse.confVerify:
ls -la /dev/fuseshould show a character device withcrw-rw-rw-permissions.
Go 1.26:
bash
wget https://go.dev/dl/go1.26.1.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.26.1.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile.d/go.sh
source /etc/profile.d/go.sh1.3 FUSE and AppArmor Compatibility
Container-based sshfs directory mapping requires FUSE. Docker's default AppArmor profile (docker-default) includes a deny mount rule that blocks FUSE mount operations inside containers. The system automatically adds --security-opt apparmor=unconfined when creating containers.
Known limitations:
| Host OS | Impact | Handling |
|---|---|---|
| Ubuntu 24.04 LTS | Default AppArmor blocks FUSE mount | Handled automatically (apparmor=unconfined) |
| Ubuntu 25.04+ | Additional fusermount3 AppArmor profile may block | Run aa-disable /usr/bin/fusermount3 if needed |
| Debian 12+ | No AppArmor by default | No extra configuration needed |
| Distros without AppArmor | No impact | No extra configuration needed |
Verify FUSE compatibility:
bash
sudo bash scripts/verify-fuse-compat.sh2. PostgreSQL Configuration
bash
sudo -u postgres psql <<'SQL'
CREATE DATABASE cloudproxy;
CREATE USER cloudproxy WITH PASSWORD 'replace-with-strong-password';
GRANT ALL PRIVILEGES ON DATABASE cloudproxy TO cloudproxy;
ALTER DATABASE cloudproxy OWNER TO cloudproxy;
\c cloudproxy
GRANT ALL ON SCHEMA public TO cloudproxy;
SQL3. Build
bash
git clone https://github.com/ZaneL1u/cloud-cli-proxy.git /opt/cloud-cli-proxy
cd /opt/cloud-cli-proxy
# Control plane
go build -o /opt/cloud-cli-proxy/bin/control-plane ./cmd/control-plane
# Host agent
go build -o /opt/cloud-cli-proxy/bin/host-agent ./cmd/host-agent
# Managed user image
bash deploy/docker/managed-user/build-managed-image.sh4. Configuration
System User
bash
useradd --system --no-create-home --shell /usr/sbin/nologin cloudproxy
usermod -aG docker cloudproxyDirectories
bash
mkdir -p /var/lib/cloud-cli-proxy /run/cloud-cli-proxy /etc/cloud-cli-proxy
chown cloudproxy:cloudproxy /var/lib/cloud-cli-proxy /run/cloud-cli-proxy /etc/cloud-cli-proxyEnvironment Variables
Create /etc/cloud-cli-proxy/env. See Configuration for the full reference.
5. Install systemd Services
bash
cp deploy/systemd/cloud-cli-proxy-control-plane.service /etc/systemd/system/
cp deploy/systemd/cloud-cli-proxy-host-agent.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now cloud-cli-proxy-control-plane
systemctl enable --now cloud-cli-proxy-host-agentOr use the automated deploy script:
bash
sudo bash deploy/scripts/deploy.sh6. Verify
bash
systemctl status cloud-cli-proxy-control-plane
systemctl status cloud-cli-proxy-host-agent
curl -s http://127.0.0.1:8080/healthz
# {"status":"ok"}Post-deploy Layout
/opt/cloud-cli-proxy/bin/ # control-plane, host-agent binaries
/etc/cloud-cli-proxy/env # Environment variables (chmod 600)
/var/lib/cloud-cli-proxy/ # Data directory
/run/cloud-cli-proxy/ # Runtime Unix socket