Files
private_image/deploy/DEPLOYMENT_GUIDE.md
nobswebdev 4a534a8007 Add production deployment guide and restrict CORS to development.
Document clearnet, TLS, and Tor setup; enable Nest CORS only in development and skip CORS_ORIGINS validation in production.
2026-10-28 22:07:32 +01:00

3.5 KiB

Deployment guide

1. Requirements

  • Ubuntu 22.04+ or similar Linux with Docker Engine and the Compose plugin — follow Install Docker Engine on Ubuntu. Tested and recommended on Ubuntu 22.04 LTS.
  • A domain name pointing at your server (A records for apex and www)

2. Server setup

Deploy as root on the VPS. Docker Engine and Compose plugin must be installed — Install Docker Engine on Ubuntu.

Verify:

docker compose version

3. Clone the repository

cd /root
git clone https://git.nobswebdev.com/nobswebdev/private_image.git private_image
cd private_image

4. Configure environment

cd /root/private_image
cp .env.example .env.prod
chmod 600 .env.prod

Edit .env.prod. Mandatory configuration:

Variable Production value
COMPOSE_PROJECT_NAME private_image_prod
POSTGRES_PASSWORD strong random password
POSTGRES_MIGRATIONS_RUN true
PGADMIN_DEFAULT_PASSWORD strong random password
NODE_ENV production
CLEARNET_DOMAIN your-domain.com
ONION_HOSTNAME set after step 8 (Tor); use placeholder until then
ALTCHA_HMAC_KEY strong random secret
VITE_API_BASE_URL /api
VITE_CLEARNET_SCHEME https
VITE_CLEARNET_DOMAIN your-domain.com (same host as CLEARNET_DOMAIN)
VITE_ONION_HOSTNAME same as ONION_HOSTNAME after step 8

Keep VITE_VALIDATION_* and VITE_UPLOAD_* aligned with backend VALIDATION_* caps in the same file.

5. Bootstrap TLS certificates

Nginx needs certificate files before it can start on port 443. For the first deploy, create a temporary self-signed pair (replaced after Let's Encrypt):

./deploy/scripts/bootstrap-certs.sh

After the stack is running, obtain real certificates (step 7).

6. Start the stack

./deploy/scripts/deploy.sh

Wait until backend and nginx are healthy:

docker compose --env-file .env.prod -f docker-compose.prod.yml ps

7. Issue Let's Encrypt certificates

Remove the temporary bootstrap certificates under deploy/certs/live/ (Certbot cannot issue into the layout created by bootstrap-certs.sh):

rm -rf deploy/certs/live/*

Request the real certificate (apex + www):

./deploy/scripts/issue-certs.sh --email you@example.com

Reload nginx:

docker compose --env-file .env.prod -f docker-compose.prod.yml exec nginx nginx -s reload

Automatic renewal

Open root's crontab:

crontab -e

Add a weekly job (/root/private_image is the standard deploy path):

0 3 * * 0 /root/private_image/deploy/scripts/renew-certs.sh >> /var/log/private_image-cert-renew.log 2>&1

Save and exit the editor. Optional — run once manually to verify:

/root/private_image/deploy/scripts/renew-certs.sh

8. Tor onion address

./deploy/scripts/show-onion.sh

Copy the hostname into .env.prod as ONION_HOSTNAME and VITE_ONION_HOSTNAME, then rebuild and recreate nginx (frontend share links and Onion-Location are baked at build / entrypoint):

docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --build --force-recreate nginx

Tor Browser will then show ".onion available" when visitors open the clearnet site over HTTPS.

9. Updates

./deploy/scripts/update.sh

This pulls the latest code and rebuilds the stack (deploy.sh).