🚀 Deploy

The approved deployment target is one Bun application at pwiz.loca.zone and one public Quartz wiki at wiki.pwiz.loca.zone. The app is protected by Authelia; the wiki is not.

Service contract

  • service name: pwiz.service
  • service type: simple
  • user and group: app operator account
  • working directory: ${APP_ROOT}
  • environment:
    • NODE_ENV=production
    • HOST=${BIND_HOST}
    • PORT=52222
    • HOME=${OPERATOR_HOME}
    • PATH=${OMP_BIN_DIR}:${BUN_BIN_DIR}:/usr/local/bin:/usr/bin:/bin
  • exec:
    • ${BUN} run server/index.ts
  • restart:
    • always
    • restart delay: 5 seconds
    • stop timeout: 20 seconds
[Unit]
Description=Prompt Wizard application
After=network-online.target
Wants=network-online.target
 
[Service]
Type=simple
User=${APP_USER}
Group=${APP_GROUP}
WorkingDirectory=${APP_ROOT}
Environment=NODE_ENV=production
Environment=HOST=${BIND_HOST}
Environment=PORT=52222
Environment=HOME=${OPERATOR_HOME}
Environment=PATH=${OMP_BIN_DIR}:${BUN_BIN_DIR}:/usr/local/bin:/usr/bin:/bin
ExecStart=${BUN} run server/index.ts
Restart=always
RestartSec=5
TimeoutStopSec=20
 
[Install]
WantedBy=multi-user.target

App nginx contract

  • host: pwiz.loca.zone
  • app backend: ${BACKEND_ORIGIN}
  • app is behind Authelia:
    • include app security headers
    • include Authelia server-level location snippet
    • include Authelia authrequest in proxied locations
  • upload limit:
    • client_max_body_size 8m
  • SSE route:
    • /api/events
    • proxy buffering off
    • read timeout 3600 seconds
  • AI route:
    • /api/ai/
    • read timeout 600 seconds
  • general route:
    • proxy HTTP 1.1
    • upgrade headers retained for compatibility
    • forwarded host and protocol headers retained
server {
  listen 443 ssl;
  server_name pwiz.loca.zone;
 
  include snippets/security-headers-app.conf;
  include snippets/authelia-location.conf;
  client_max_body_size 8m;
 
  location /api/events {
    include snippets/authelia-authrequest.conf;
    proxy_pass ${BACKEND_ORIGIN};
    proxy_buffering off;
    proxy_read_timeout 3600s;
  }
 
  location /api/ai/ {
    include snippets/authelia-authrequest.conf;
    proxy_pass ${BACKEND_ORIGIN};
    proxy_read_timeout 600s;
  }
 
  location / {
    include snippets/authelia-authrequest.conf;
    proxy_pass ${BACKEND_ORIGIN};
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Wiki nginx contract

  • host: wiki.pwiz.loca.zone
  • root: ${WIKI_ROOT}/current
  • no Authelia
  • immutable cache for assets
  • route fallback:
    • try exact file
    • try generated .html
    • try directory
    • otherwise 404
server {
  listen 443 ssl;
  server_name wiki.pwiz.loca.zone;
 
  include snippets/security-headers.conf;
  root ${WIKI_ROOT}/current;
  index index.html;
 
  location ~* \.(css|js|png|webp|ico|json|woff2?|svg|map)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    try_files $uri =404;
  }
 
  location / {
    try_files $uri $uri.html $uri/ =404;
  }
}

Certificate and registration

  • certificate:
    • one SAN certificate for app and wiki hosts
    • nginx authenticator and installer
    • ECDSA key type
  • port registry:
    • app port: 52222
    • reserve adjacent future port: 52223
  • startup order:
    • install dependencies
    • build app
    • seed app data
    • install service file
    • enable and start service
    • publish wiki
    • reload nginx after valid config

See verification before declaring deploy complete.