Deployment and Operations

Deployment-and-Operations.md

Deployment and Operations

Deployment Flow

deployment is GitHub Actions driven.

current chain:

  1. push to main
  2. code lint workflow runs
  3. if lint passes, deploy to fridg3.org runs from the successful workflow event
  4. repo is rsynced to /var/www/fridg3.org

Deploy Workflow

/.github/workflows/deploy.yml

main details:

  • triggered by successful code lint workflow completion
  • only deploys pushes to main
  • installs rsync and openssh-client
  • uses DEPLOY_KEY
  • deploy target is deploy@45.76.134.105:/var/www/fridg3.org

What Does Not Deploy

deployment uses .rsyncignore, so these are excluded:

  • /data/**
  • sitemap.xml
  • repo docs and local config files
  • .github/**
  • /scripts/**
  • local editor/codex folders
  • /others/toast-discord-bot/bot/venv/**

that means production runtime data is expected to already exist on the server.

Server Permissions

from README.md:

  • project files should belong to deploy:http
  • directories should be 755
  • files should be 644
  • /data and sitemap.xml need http:http ownership for webserver writes

Nginx Config Source

the repo-tracked files in .nginx/ are the source for the production nginx config.

  • .nginx/nginx.conf corresponds to /etc/nginx/nginx.conf
  • .nginx/fridg3.org corresponds to /etc/nginx/sites-enabled/fridg3.org
  • production uses these through symlinks, so edits here are real server config edits, not examples

when adding routes, APIs, uploads, redirects, or private data folders, check .nginx/fridg3.org as part of the feature. a correct PHP route can still fail if nginx redirects POSTs, misses a clean-url rewrite, or accidentally exposes/blocklists the wrong /data path.

Nginx Clean URLs

production nginx needs explicit rewrites for PHP routes that accept path-style ids. without these, nginx falls through to the root /index.php fallback before the route can parse the URL.

the contact route is configured POST-safe at /contact, old /email paths redirect to /contact, and /data/contact/ is blocked from direct web access.

mdpaste share links use /others/mdpaste/s/{id} and need this block before the generic location / fallback. keep the regexes quoted, because nginx treats unquoted {16} like cursed config syntax.

# mdpaste clean URLs
location ~ "^/others/mdpaste/s/[a-fA-F0-9]{16}/?$" {
    rewrite "^/others/mdpaste/s/([a-fA-F0-9]{16})/?$" /others/mdpaste/s/index.php?id=$1 last;
}
location /others/mdpaste/s/ { try_files $uri $uri/ /others/mdpaste/s/index.php?$args; }
location /others/mdpaste/   { try_files $uri $uri/ /others/mdpaste/index.php?$args; }

Backup Workflow

/.github/workflows/backup-data.yml

what it does:

  1. ssh to the server
  2. zip /var/www/fridg3.org/data
  3. download the archive to the runner
  4. upload it to Google Drive using rclone
  5. keep only the 10 newest backups
  6. delete temp archives from runner and server

triggers:

  • manual workflow_dispatch
  • scheduled daily cron at 0 0 *

required secrets:

  • DEPLOY_KEY
  • GDRIVE_BACKUP_FOLDER_ID
  • RCLONE_CONFIG

setup notes live in /.github/workflows/backup-data-setup.md.

Sitemap Generation

sitemap.xml is not deployed from git. it is generated by /api/sitemap, which means:

  • the file must be writable by the server
  • the server copy is the one that matters

Operational Truths

  • this repo is source code, not a full backup
  • /data is operational state
  • if prod data disappears, git will not magically save you
  • if file permissions are wrong, deploys and runtime writes will get weird fast