Deploy the Docs Site
This runbook covers everything needed to host docs.panville.com so that ./scripts/deploy.sh works on first run.
Target stack: Ubuntu + Apache + LetsEncrypt.
1. DNS
Point an A record at the production server's public IP:
docs.panville.com. A <server-public-ip>
Verify resolution before continuing:
dig +short docs.panville.com
# should return the server IP
2. SSH access
The deploy script assumes ubuntu@docs.panville.com on port 22 (edit scripts/deploy.sh if your host uses a different port or user).
On the server:
- Add the operator's public key to
/home/ubuntu/.ssh/authorized_keys
On your laptop, test:
ssh ubuntu@docs.panville.com 'echo ok'
3. Install Apache and required modules
sudo apt update
sudo apt install -y apache2
# Modules needed by the vhost:
sudo a2enmod ssl headers rewrite
sudo systemctl reload apache2
ssl for HTTPS, headers for Cache-Control rules, rewrite for the catch-all fallback.
4. Create the doc root with correct permissions
The deploy script rsyncs into /var/www/shell18-docs/build as the ubuntu user. Apache reads it as www-data. Set ownership and group bits so ubuntu can write and www-data can read:
sudo mkdir -p /var/www/shell18-docs/build
sudo chown -R ubuntu:www-data /var/www/shell18-docs/build
sudo chmod -R g+rwX /var/www/shell18-docs/build
sudo find /var/www/shell18-docs/build -type d -exec chmod g+s {} +
The g+s setgid bit on directories ensures any new files inherit the www-data group, so subsequent rsync deploys don't need sudo.
5. Issue the LetsEncrypt certificate
Install Certbot:
sudo apt install -y certbot python3-certbot-apache
Issue the cert:
sudo certbot certonly --apache -d docs.panville.com
The cert lands at:
/etc/letsencrypt/live/docs.panville.com/fullchain.pem
/etc/letsencrypt/live/docs.panville.com/privkey.pem
These exact paths are referenced in the vhost. Auto-renewal is set up by certbot's systemd timer.
6. Deploy the Apache vhost
# From your laptop
scp /Users/jsalinga/odoo/odoo18/custom/shell18/shell18-docs/scripts/docs.panville.com.conf \
ubuntu@docs.panville.com:/tmp/
# On the server
sudo mv /tmp/docs.panville.com.conf /etc/apache2/sites-available/
sudo a2ensite docs.panville.com
sudo apache2ctl configtest
sudo systemctl reload apache2
configtest should report Syntax OK before you reload.
7. First deploy
From your laptop, in the docs site root:
cd /Users/jsalinga/odoo/odoo18/custom/shell18/shell18-docs
./scripts/deploy.sh
This:
- Runs
npm run buildlocally - rsyncs
build/toubuntu@docs.panville.com:/var/www/shell18-docs/build/
Open https://docs.panville.com/ to verify.
8. Subsequent deploys
Just ./scripts/deploy.sh — that's the entire workflow. The --delete rsync flag ensures removed pages don't linger on the server.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Could not resolve host on first SSH | DNS hasn't propagated | Wait or set /etc/hosts entry temporarily |
Permission denied (publickey) | SSH key not in authorized_keys | Add the operator's pubkey on the server |
404 on every page after deploy | FallbackResource directive missing | Confirm mod_rewrite enabled and vhost has the directive |
| Mixed-content warnings | Site loaded over HTTP | The :80 vhost should permanent-redirect to :443; confirm both VirtualHost blocks are enabled |
| Cert renewal fails | Apache wasn't reloaded after install | sudo certbot renew --dry-run to test; add a cron/post-hook |
403 Forbidden | Doc-root owner/perm issue | Re-run the chown/chmod from step 4 |
| Stale assets after deploy | Browser cached aggressively | Hard refresh; vhost already sets immutable cache headers on hashed assets, no-cache on HTML |
Server prerequisites checklist
Quick sanity check before first deploy:
- DNS A record resolves to the server
- SSH works as
ubuntu -
apache2,mod_ssl,mod_headers,mod_rewriteinstalled and enabled -
/var/www/shell18-docs/build/exists with correct ownership (ubuntu:www-data, group setgid) - LetsEncrypt cert issued for the domain
- Vhost dropped in
sites-available/, enabled, andapache2ctl configtestis clean -
apache2reloaded