# Deploy - VPS Deployment CLI Simple CLI tool for deploying Go apps and static sites to a VPS with automatic HTTPS via Caddy. ## Features - Single command deployment from your laptop - Automatic HTTPS via Caddy + Let's Encrypt - Automatic port allocation (no manual tracking) - Environment variable management - Systemd process management with auto-restart - Support for multiple apps/sites on one VPS - State stored locally (VPS is stateless and easily recreatable) - Zero dependencies on VPS (just installs Caddy) ## Installation ```bash # Build the CLI go build -o ~/bin/deploy ./cmd/deploy # Or install to GOPATH go install ./cmd/deploy ``` ## Quick Start ### 1. Initialize Your VPS (One-time) ```bash # Initialize a fresh VPS (this sets it as the default host) deploy host init user@your-vps-ip ``` This will: - Install Caddy - Configure Caddy for automatic HTTPS - Create necessary directories - Set up the VPS for deployments ### 2. Deploy a Go App ```bash # Build your app for Linux GOOS=linux GOARCH=amd64 go build -o myapp # Deploy it deploy --binary ./myapp --domain api.example.com # With environment variables deploy --binary ./myapp --domain api.example.com \ --env DB_HOST=localhost \ --env API_KEY=secret # Or from an env file deploy --binary ./myapp --domain api.example.com \ --env-file .env.production ``` ### 3. Deploy a Static Site ```bash # Build your site npm run build # Deploy it deploy --static --dir ./dist --domain example.com ``` ## App Requirements Your Go app must: 1. Listen on HTTP (not HTTPS - Caddy handles that) 2. Accept port via `--port` flag or `PORT` environment variable 3. Bind to `localhost` or `127.0.0.1` only Example: ```go package main import ( "flag" "fmt" "net/http" "os" ) func main() { port := flag.String("port", os.Getenv("PORT"), "port to listen on") flag.Parse() if *port == "" { *port = "8080" // fallback for local dev } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello World")) }) addr := "127.0.0.1:" + *port fmt.Printf("Listening on %s\n", addr) http.ListenAndServe(addr, nil) } ``` ## Commands ### Host Management ```bash # Initialize a fresh VPS (one-time setup, sets as default) deploy host init user@vps-ip # Update system packages (apt update && apt upgrade) deploy host update # Check host status deploy host status # SSH into the host deploy host ssh ``` ### Deploy App/Site ```bash # Go app deploy --binary ./myapp --domain api.example.com # Static site deploy --static --dir ./dist --domain example.com # Custom name (defaults to binary/directory name) deploy --name myapi --binary ./myapp --domain api.example.com ``` ### List Deployments ```bash deploy list ``` ### Manage Deployments ```bash # View logs deploy logs myapp # View status deploy status myapp # Restart app deploy restart myapp # Remove deployment deploy remove myapp ``` ### Environment Variables ```bash # View current env vars (secrets are masked) deploy env list myapi # Set env vars deploy env set myapi DB_HOST=localhost API_KEY=secret # Load from file deploy env set myapi -f .env.production # Unset env var deploy env unset myapi API_KEY ``` ## Configuration The host you initialize becomes the default, so you don't need to specify `--host` for every command. The default host is stored in `~/.config/deploy/state.json`. ## How It Works 1. **State on Laptop**: All deployment state lives at `~/.config/deploy/state.json` on your laptop 2. **SSH Orchestration**: The CLI uses SSH to run commands on your VPS 3. **File Transfer**: Binaries transferred via SCP, static sites via rsync 4. **Caddy for HTTPS**: Caddy automatically handles HTTPS certificates 5. **Systemd for Processes**: Apps run as systemd services with auto-restart 6. **Dumb VPS**: The VPS is stateless - you can recreate it by redeploying from local state ## File Structure ### On Laptop ``` ~/.config/deploy/state.json # All deployment state (including default host) ``` ### On VPS ``` /usr/local/bin/myapp # Go binary /var/lib/myapp/ # Working directory /etc/systemd/system/myapp.service # Systemd unit /etc/caddy/sites-enabled/myapp.caddy # Caddy config /etc/deploy/env/myapp.env # Environment variables /var/www/mysite/ # Static site files /etc/caddy/sites-enabled/mysite.caddy # Caddy config ``` ## Security - Each Go app runs as dedicated system user - Systemd security hardening enabled (NoNewPrivileges, PrivateTmp) - Static sites served as www-data - Caddy automatically manages TLS certificates - Environment files stored with 0600 permissions - Secrets masked when displaying environment variables ## Supported OS - Ubuntu 20.04+ - Debian 11+ ## License MIT