From c2ae8ec261c4e6aecb48c0e903308d70eba99a68 Mon Sep 17 00:00:00 2001 From: DIY Smart Code Date: Wed, 8 Apr 2026 11:25:01 +0200 Subject: [PATCH] deploy: harden cloud-init with archon user, swap, and fixes (#981) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deploy: harden cloud-init with archon user, swap, and fixes - Create dedicated 'archon' user (sudo + docker groups, passwordless sudo, locked password) and copy SSH authorized_keys from default cloud user (with root fallback) so login works immediately. - Run docker pulls and the image build as the archon user via sudo -u. - Add 2GB swapfile to prevent OOM during docker build on small VPS (<2GB RAM). - Remove package_upgrade to speed up boot and avoid surprise kernel updates. - Drop redundant systemctl enable/start docker (get.docker.com handles it). - ufw allow 443/tcp for consistency with 22/80. - set -e before clone for fail-fast on network errors. - Update docs link to https://archon.diy/deployment/docker/. - SETUP_COMPLETE now instructs ssh archon@. - Header lists supported providers (incl. Hostinger) and notes the archon user + swap behavior. * deploy: address PR review feedback on cloud-init - Fix set -e regression: merge clone/cp/chown into single shell block so fail-fast actually applies (CodeRabbit). - Drop passwordless sudo from archon user — docker group only. Removes trivial privilege escalation path (Wirasm). - Remove non-existent 'docker' group from initial users.groups list; it is added via usermod later (CodeRabbit). - Restore package_upgrade: true to patch CVEs in the base image before anything else runs (Wirasm). - Add ufw allow 443/udp for HTTP/3 QUIC — Caddy exposes 443:443/udp in docker-compose (CodeRabbit). - Update SETUP_COMPLETE and header comment to note archon user has no sudo (use default cloud user / root for maintenance). --- deploy/cloud-init.yml | 90 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/deploy/cloud-init.yml b/deploy/cloud-init.yml index 9a689e98..90566651 100644 --- a/deploy/cloud-init.yml +++ b/deploy/cloud-init.yml @@ -6,20 +6,30 @@ # # Paste this into your VPS provider's "User Data" field when creating a server. # Tested on: Ubuntu 22.04+, Debian 12+ +# Works with any cloud-init compatible provider (DigitalOcean, Hetzner, Linode, +# Vultr, AWS EC2, Hostinger, etc.) # # What this does: # 1. Installs Docker + Docker Compose plugin # 2. Opens firewall ports (SSH, HTTP, HTTPS) -# 3. Clones the repo to /opt/archon -# 4. Prepares .env and Caddyfile from examples -# 5. Builds the Docker image (~5 min) +# 3. Creates a 2GB swapfile (helps small VPS builds avoid OOM) +# 4. Clones the repo to /opt/archon +# 5. Prepares .env and Caddyfile from examples +# 6. Creates a dedicated 'archon' user (docker group only, no sudo) +# 7. Builds the Docker image (~5 min) as the archon user # -# After the server boots (~5-8 min), SSH in and: +# Note: On VPS with <2GB RAM, the docker build step can OOM without swap. +# Note: The 'archon' user has docker access but NOT sudo. For administrative +# tasks (updates, reboots), use the default cloud user or root. +# +# After the server boots (~5-8 min), SSH in as the archon user: +# ssh archon@your-server-ip # 1. Edit /opt/archon/.env — set your AI credentials, DOMAIN, DATABASE_URL # 2. cd /opt/archon && docker compose --profile with-db --profile cloud up -d # 3. Open https://your-domain.com # # IMPORTANT: Before starting, point your domain's DNS A record to this server's IP. +# SSH keys from the default cloud user are copied to 'archon'. # package_update: true @@ -30,29 +40,66 @@ packages: - git - ufw +users: + - default + - name: archon + gecos: Archon Service User + shell: /bin/bash + lock_passwd: true + runcmd: + # --- Swap (helps small VPS avoid OOM during docker build) --- + - | + if [ ! -f /swapfile ]; then + fallocate -l 2G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=2048 + chmod 600 /swapfile + mkswap /swapfile + swapon /swapfile + echo '/swapfile none swap sw 0 0' >> /etc/fstab + fi + # --- Docker --- - curl -fsSL https://get.docker.com | sh - - systemctl enable docker - - systemctl start docker + - usermod -aG docker archon - # --- Firewall --- + # --- Copy SSH keys from default user to archon (so login works immediately) --- + - | + DEFAULT_USER=$(getent passwd 1000 | cut -d: -f1) + if [ -n "$DEFAULT_USER" ] && [ -f /home/$DEFAULT_USER/.ssh/authorized_keys ]; then + mkdir -p /home/archon/.ssh + cp /home/$DEFAULT_USER/.ssh/authorized_keys /home/archon/.ssh/authorized_keys + chmod 700 /home/archon/.ssh + chmod 600 /home/archon/.ssh/authorized_keys + chown -R archon:archon /home/archon/.ssh + elif [ -f /root/.ssh/authorized_keys ]; then + mkdir -p /home/archon/.ssh + cp /root/.ssh/authorized_keys /home/archon/.ssh/authorized_keys + chmod 700 /home/archon/.ssh + chmod 600 /home/archon/.ssh/authorized_keys + chown -R archon:archon /home/archon/.ssh + fi + + # --- Firewall (443/udp needed for HTTP/3 QUIC via Caddy) --- - ufw allow 22/tcp - ufw allow 80/tcp - - ufw allow 443 + - ufw allow 443/tcp + - ufw allow 443/udp - ufw --force enable - # --- Clone and configure --- - - git clone https://github.com/coleam00/Archon.git /opt/archon - - cp /opt/archon/.env.example /opt/archon/.env - - cp /opt/archon/Caddyfile.example /opt/archon/Caddyfile + # --- Clone and configure (fail fast — single shell so set -e applies) --- + - | + set -e + git clone https://github.com/coleam00/Archon.git /opt/archon + cp /opt/archon/.env.example /opt/archon/.env + cp /opt/archon/Caddyfile.example /opt/archon/Caddyfile + chown -R archon:archon /opt/archon - # --- Pre-pull external images --- - - docker pull postgres:17-alpine - - docker pull caddy:2-alpine + # --- Pre-pull external images (as archon, via docker group) --- + - sudo -u archon docker pull postgres:17-alpine + - sudo -u archon docker pull caddy:2-alpine - # --- Build the app image --- - - cd /opt/archon && docker compose build + # --- Build the app image as archon --- + - sudo -u archon -H bash -c 'cd /opt/archon && docker compose build' # --- Signal completion --- - | @@ -61,6 +108,13 @@ runcmd: Archon server setup complete! ============================================ + Log in as the 'archon' user (not root): + ssh archon@ + + Note: the 'archon' user has docker access but no sudo. For system + maintenance (apt upgrade, reboots), log in as the default cloud user + or root. + Next steps: 1. Edit credentials and domain: @@ -85,7 +139,7 @@ runcmd: Logs: docker compose logs -f Health: curl https://your-domain.com/api/health - Docs: https://github.com/coleam00/Archon/blob/main/docs/docker.md + Docs: https://archon.diy/deployment/docker/ ============================================ DONE - echo "[archon] Setup complete. Edit /opt/archon/.env and run docker compose up."