# Deploying CluPilot on a fresh server Developed locally, deployed by pulling. Two scripts do the work: ```bash # once, on a fresh Debian/Ubuntu server as root bash deploy/install.sh # afterwards, to bring it up to date cd /opt/clupilot && bash deploy/update.sh ``` ## What the installer does Docker, git and `wireguard-tools`; clone into `/opt/clupilot`; generate every secret (`APP_KEY`, `VPN_CONFIG_KEY`, database password, Reverb keys); start the stack; migrate; create the WireGuard hub and print its public key; create your Owner account; close the firewall down to 22, 80, 443 and 51820/udp. It is safe to re-run: an existing `.env` is kept and the hub key is never regenerated — doing so would silently disconnect every onboarded host. Every prompt has an environment variable, so it can also run unattended: ```bash GIT_TOKEN=… ADMIN_EMAIL=… ADMIN_PASSWORD=… APP_DOMAIN=app.clupilot.com \ ADMIN_DOMAIN=admin.clupilot.com bash deploy/install.sh ``` ## Order of the update Migrations run **before** the new containers take traffic: code that expects a column the database does not have yet answers with 500s. The image is rebuilt only when `docker/`, composer or npm manifests actually changed. Queue workers are restarted at the end — they are long-running PHP processes and keep the old classes in memory otherwise. That one bit us during development: a fixed job kept failing until the worker was restarted. ## What the installer deliberately leaves to you - **DNS and TLS.** Put a reverse proxy in front (Zoraxy, Caddy, nginx). The console hostname must not be publicly resolvable: `/admin` answers only on the hostnames in `ADMIN_HOSTS` and 404s everywhere else, but keeping it out of public DNS is the layer above that. - **`STRIPE_WEBHOOK_SECRET`.** Stripe dashboard → Developers → Webhooks → `https:///webhooks/stripe`, events `checkout.session.completed` and `checkout.session.async_payment_succeeded`. The secret starts with `whsec_` and differs between test and live mode. - **Backups.** At minimum the MariaDB volume and `/etc/wireguard` in the `wireguard` volume — losing the hub key means re-peering every host. ## Hiding the site while you build Settings → Website visibility. Outsiders then get a placeholder (503, `noindex`), while anyone on the management VPN and any signed-in operator keeps seeing the real thing. The console stays reachable either way, so the switch can always be flipped back.