diff --git a/README.md b/README.md index 788e76e..3261b2a 100644 --- a/README.md +++ b/README.md @@ -41,17 +41,43 @@ The build output is **static files** - no application server, no socket, nothing for nginx to proxy to. The app does all its work in the browser, which is why upstream can live on GitHub Pages. -One-time setup on the server: +One-time setup on the server. It is in two stages because of a chicken and egg: +the real config names a certificate, and nginx refuses to load a config whose +certificate does not exist yet - so nginx first comes up on port 80 only, just +far enough for certbot to answer the challenge there. ```sh -sudo mkdir -p /var/www/brevyscribe +sudo mkdir -p /var/www/brevyscribe /var/www/certbot sudo chown "$USER" /var/www/brevyscribe -sudo cp deploy/nginx-scribe.luxick.de.conf /etc/nginx/sites-available/scribe.luxick.de + +# Stage 1: HTTP only, so nginx starts without a certificate. +sudo tee /etc/nginx/sites-available/scribe.luxick.de >/dev/null <<'EOF' +server { + listen 80; + listen [::]:80; + server_name scribe.luxick.de; + location /.well-known/acme-challenge/ { root /var/www/certbot; } +} +EOF sudo ln -s /etc/nginx/sites-available/scribe.luxick.de /etc/nginx/sites-enabled/ +sudo nginx -t && sudo systemctl reload nginx + sudo certbot --nginx -d scribe.luxick.de + +# Stage 2: the real config, now that the certificate is on disk. +sudo cp deploy/nginx-scribe.luxick.de.conf /etc/nginx/sites-available/scribe.luxick.de sudo nginx -t && sudo systemctl reload nginx ``` +`certonly --webroot` rather than `--nginx`: the config already carries its own +redirect and TLS block, and the nginx plugin would rewrite the installed file, +leaving it drifted from the one in the repo. The port 80 block keeps its +`acme-challenge` location for exactly this reason, so renewals go on working +unattended - but certbot's timer will not reload nginx by itself, so drop a +one-line hook in `/etc/letsencrypt/renewal-hooks/deploy/` that runs +`systemctl reload nginx`, or a renewed certificate will not be served until the +next restart. + Then every deploy is one command from a checkout on your own machine - it runs the tests, builds, and rsyncs `dist/` over. The server needs no Node.