From f507cf44c2db74a4d01dc4263fe513149e5a17db Mon Sep 17 00:00:00 2001 From: Mathias STRASSER Date: Tue, 10 Mar 2026 18:30:45 +0100 Subject: [PATCH] feat(deploy): add vps deployment assets --- deploy/vps/.env.example | 26 ++++++++++++++++++++++ deploy/vps/Caddyfile | 15 +++++++++++++ deploy/vps/generate-jwt.sh | 24 ++++++++++++++++++++ deploy/vps/postgres/01-create-tenant-db.sh | 15 +++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 deploy/vps/.env.example create mode 100644 deploy/vps/Caddyfile create mode 100644 deploy/vps/generate-jwt.sh create mode 100644 deploy/vps/postgres/01-create-tenant-db.sh diff --git a/deploy/vps/.env.example b/deploy/vps/.env.example new file mode 100644 index 0000000..ea52556 --- /dev/null +++ b/deploy/vps/.env.example @@ -0,0 +1,26 @@ +APP_DOMAIN=demo.example.com +PUBLIC_BASE_DOMAIN=example.com + +TENANT_ID=11111111-1111-1111-1111-111111111111 +TENANT_SUBDOMAIN=demo +MASTER_DATABASE_NAME=classeo_master +TENANT_DATABASE_NAME=classeo_tenant_demo +POSTGRES_USER=classeo +POSTGRES_PASSWORD=change-this-db-password + +APP_SECRET=change-this-app-secret +JWT_PASSPHRASE=change-this-jwt-passphrase + +TRUSTED_PROXIES='127.0.0.1/32,172.16.0.0/12' +TRUSTED_HOSTS='^(.+\.)?example\.com$' +CORS_ALLOW_ORIGIN='^https://([\w-]+\.)?example\.com$' + +MAILER_DSN=null://null +ADMIN_ALERT_EMAIL=admin@example.com + +TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA +TURNSTILE_FAIL_OPEN=true +PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA + +SENTRY_DSN= +SENTRY_ENVIRONMENT=production diff --git a/deploy/vps/Caddyfile b/deploy/vps/Caddyfile new file mode 100644 index 0000000..0eacf78 --- /dev/null +++ b/deploy/vps/Caddyfile @@ -0,0 +1,15 @@ +{$APP_DOMAIN} { + encode zstd gzip + + handle /api/* { + reverse_proxy php:8000 + } + + handle /uploads/* { + reverse_proxy php:8000 + } + + handle { + reverse_proxy frontend:3000 + } +} diff --git a/deploy/vps/generate-jwt.sh b/deploy/vps/generate-jwt.sh new file mode 100644 index 0000000..3a5f989 --- /dev/null +++ b/deploy/vps/generate-jwt.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -eu + +if [ ! -f deploy/vps/.env ]; then + echo "Missing deploy/vps/.env" + exit 1 +fi + +JWT_PASSPHRASE=$(grep '^JWT_PASSPHRASE=' deploy/vps/.env | cut -d= -f2-) + +if [ -z "$JWT_PASSPHRASE" ]; then + echo "JWT_PASSPHRASE is empty in deploy/vps/.env" + exit 1 +fi + +mkdir -p backend/config/jwt + +openssl genrsa -aes256 -passout "pass:${JWT_PASSPHRASE}" -out backend/config/jwt/private.pem 4096 +openssl rsa -pubout -passin "pass:${JWT_PASSPHRASE}" -in backend/config/jwt/private.pem -out backend/config/jwt/public.pem + +chmod 600 backend/config/jwt/private.pem +chmod 644 backend/config/jwt/public.pem + +echo "JWT keypair generated in backend/config/jwt" diff --git a/deploy/vps/postgres/01-create-tenant-db.sh b/deploy/vps/postgres/01-create-tenant-db.sh new file mode 100644 index 0000000..33f0e89 --- /dev/null +++ b/deploy/vps/postgres/01-create-tenant-db.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -eu + +if [ -z "${TENANT_DATABASE_NAME:-}" ] || [ "${TENANT_DATABASE_NAME}" = "${POSTGRES_DB}" ]; then + exit 0 +fi + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<-EOSQL + SELECT format('CREATE DATABASE %I', '${TENANT_DATABASE_NAME}') + WHERE NOT EXISTS ( + SELECT 1 + FROM pg_database + WHERE datname = '${TENANT_DATABASE_NAME}' + ) \gexec +EOSQL