Skip to main content

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:

  1. Runs npm run build locally
  2. rsyncs build/ to ubuntu@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

SymptomLikely causeFix
Could not resolve host on first SSHDNS hasn't propagatedWait or set /etc/hosts entry temporarily
Permission denied (publickey)SSH key not in authorized_keysAdd the operator's pubkey on the server
404 on every page after deployFallbackResource directive missingConfirm mod_rewrite enabled and vhost has the directive
Mixed-content warningsSite loaded over HTTPThe :80 vhost should permanent-redirect to :443; confirm both VirtualHost blocks are enabled
Cert renewal failsApache wasn't reloaded after installsudo certbot renew --dry-run to test; add a cron/post-hook
403 ForbiddenDoc-root owner/perm issueRe-run the chown/chmod from step 4
Stale assets after deployBrowser cached aggressivelyHard 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_rewrite installed 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, and apache2ctl configtest is clean
  • apache2 reloaded