cg-devplan
Generate a structured development plan (devplan) for software projects. Use this skill whenever the user wants to plan a new app,…
Deploy an application to a single VPS with reverse proxy, automatic TLS, systemd process supervision, firewall, and basic health checks. Use when the user mentions deploying to a server, VPS setup, going to production, Hetzner/DigitalOcean/Vultr/Linode deployment, setting up
How it fires
How this command gets triggered: by you, by Claude, or both.
/cg-indie-deployContext preview
What this command does when you run it.
Deploy an application to a single VPS with reverse proxy, automatic TLS, systemd process supervision, firewall, and basic health checks. Use when the user mentions deploying to a server, VPS setup, going to production, Hetzner/DigitalOcean/Vultr/Linode deployment, setting up
name: cg-indie-deploy description: Deploy an application to a single VPS with reverse proxy, automatic TLS, systemd process supervision, firewall, and basic health checks. Use when the user mentions deploying to a server, VPS setup, going to production, Hetzner/DigitalOcean/Vultr/Linode deployment, setting up Caddy or nginx, writing a systemd service, or any "how do I put this app online" question. NOT for Kubernetes, managed cloud services (AWS ECS, Cloud Run, App Engine), or serverless platforms.
Deploy an application to one VPS with production-grade defaults. Targets indie developers and small teams shipping to a single server — not enterprise infrastructure, not container orchestration, not managed cloud services.
**This skill covers:**
**This skill does NOT cover:**
If the user needs any of the excluded items, say so and suggest a better-matching tool.
MUST have answers to these before producing commands. Ask the user directly if unclear; do not guess.
1. **Application type** — determines artifact and service config:
2. **VPS provider** — affects only initial setup commands and DNS instructions. Core workflow is identical across: Hetzner, DigitalOcean, Linode/Akamai, Vultr, OVH, or any generic Ubuntu/Debian host.
3. **Reverse proxy preference** — default to Caddy unless user asks otherwise:
4. **Domain state** — MUST verify before attempting TLS:
5. **Listening port** — what port does the app bind to locally? Default by type if user doesn't know: Go 8080, Node 3000, Python 8000. This is internal only; the reverse proxy handles 80/443.
Execute phases in order. Do not skip. Each phase has verification — do not proceed if verification fails.
Skip if the server already has a non-root `deploy` user, UFW enabled, and root SSH disabled.
# Update apt update && apt upgrade -y apt install -y ufw curl ca-certificates # Deploy user adduser --disabled-password --gecos "" deploy usermod -aG sudo deploy mkdir -p /home/deploy/.ssh cp ~/.ssh/authorized_keys /home/deploy/.ssh/ chown -R deploy:deploy /home/deploy/.ssh chmod 700 /home/deploy/.ssh chmod 600 /home/deploy/.ssh/authorized_keys # Firewall — only SSH, HTTP, HTTPS ufw allow OpenSSH ufw allow 80/tcp ufw allow 443/tcp ufw --force enable # Disable root SSH and password auth sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config systemctl restart ssh # fail2ban — reduces brute-force noise, blocks repeat offenders apt install -y fail2ban systemctl enable fail2ban systemctl start fail2ban # Default config bans IPs after 5 failed SSH attempts for 10 minutes. Good enough. # Unattended security upgrades — auto-install security patches only apt install -y unattended-upgrades dpkg-reconfigure -plow unattended-upgrades # answer Yes # Verify: cat /etc/apt/apt.conf.d/20auto-upgrades should show "1" for both lines # This only installs security patches, not all upgrades. Low risk, high value.
**CRITICAL**: Before disabling root login, verify the deploy user can SSH in from a separate terminal. Never close the only working session until you have tested the replacement.
**Optional — Tailscale for SSH**: If you want to eliminate public SSH exposure entirely, install [Tailscale](https://tailscale.com/) on the server and your local machine. Then change UFW to only allow SSH from the Tailscale interface:
ufw delete allow OpenSSH ufw allow in on tailscale0 to any port 22
This is the single strongest SSH hardening measure — no public SSH port means no brute-force attacks, no fail2ban needed, no port scanning. Free for personal use.
**Verification**: `ssh deploy@server` works, `ufw status` shows active, `curl https://example.com` from outside reaches the server (or times out because nothing is listening yet — that's fine, firewall is not blocking).
**Caddy** (default):
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith
A minimal rule system for Claude Code. Gives Claude the structural discipline it lacks by default — phase tracking, decision logging, honest pushback, debug discipline, language-specific best practices, and reusable skills.
Generate a structured development plan (devplan) for software projects. Use this skill whenever the user wants to plan a new app,…
Set up production observability for indie-scale apps — structured logging, uptime monitoring, error tracking, and basic metrics.…
Build, sign, notarize, and publish a macOS app as a GitHub release with a professional DMG
Set up an open source repository for healthy long-term maintenance — branch protection, commit signing, tag immutability, issue…
Harden an indie-scale production app against common attacks — rate limiting, CORS, security headers, input validation, secrets…
Perform deep, findings-first senior engineering code reviews of any change in any language or stack. Use when reviewing a phase,…