diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml new file mode 100644 index 0000000..4609a9a --- /dev/null +++ b/.gitea/workflows/test.yml @@ -0,0 +1,53 @@ +name: Test nginx configuration + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +jobs: + static-analysis: + name: Static Analysis + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run static analysis + run: bash test.sh + + syntax-check: + name: nginx Syntax Check + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install nginx + run: | + sudo apt-get update -q + sudo apt-get install -y nginx-full + + - name: Deploy config to /etc/nginx + run: sudo cp -a nginx/nginx/. /etc/nginx/ + + - name: Create stub SSL certificates + run: | + openssl req -x509 -newkey rsa:2048 -keyout /tmp/stub.key \ + -out /tmp/stub.pem -days 1 -nodes -subj '/CN=stub' + + while IFS= read -r dir; do + sudo mkdir -p "$dir" + sudo cp /tmp/stub.pem "$dir/fullchain.pem" + sudo cp /tmp/stub.key "$dir/privkey.pem" + done < <(grep -rh 'ssl_certificate ' /etc/nginx/sites-available/ \ + | grep -v '#' \ + | grep -oP '/etc/letsencrypt/live/[^\s/]+' \ + | sort -u) + + - name: Run nginx syntax check + run: sudo nginx -t diff --git a/README.md b/README.md index 9ed3afe..5edf64a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,132 @@ # Nginx Configs -This repository holds our NGINX configs and offers a basic script for pulling the latest versions from our servers. +This repository holds the nginx configuration for NHCarrigan's production server, with scripts for deploying and pulling changes. -## Live Version +## Directory Structure -These can't really be viewed live... +``` +nginx/nginx/ # Maps directly to /etc/nginx/ on the server +├── nginx.conf # Global settings (workers, gzip, TLS, logging) +├── conf.d/ +│ ├── cloudflare_ips.conf # Real-IP trust for Cloudflare ranges (auto-updated by cron) +│ ├── logging.conf # Custom log formats (custom_format + json_analytics) +│ └── tuning.conf # Performance tweaks (server_names_hash_bucket_size) +├── sites-available/ # One .conf file per logical group of sites +│ └── *.conf +├── sites-enabled/ # Symlinks to active configs in sites-available/ +│ └── * -> ../sites-available/*.conf +└── ... # Standard nginx package files (mime.types, proxy_params, etc.) +``` + +## Adding a New Site + +1. **Identify the right file.** Each `sites-available/*.conf` has a comment at the top describing what belongs there. Pick the most appropriate file, or create a new one if the site does not fit anywhere. + +2. **Add the server block**, following this template for a proxied app: + ```nginx + server { + listen 443 ssl; + server_name yourapp.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/yourapp.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/yourapp.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:; + proxy_redirect off; + } + } + ``` + Or this template for a static site: + ```nginx + server { + listen 443 ssl; + server_name yoursite.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/yoursite.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/yoursite.nhcarrigan.com/privkey.pem; + + root /home/naomi/yoursite; + + location / { + index index.html; + } + } + ``` + +3. **Keep server blocks sorted alphabetically** by `server_name` within the file. The CI sort check will fail if they are out of order. Note that hyphenated names sort before the bare domain in C locale (e.g. `app-api` before `app`). + +4. **If you created a new `.conf` file**, create the corresponding symlink in `sites-enabled/`: + ```bash + cd nginx/nginx/sites-enabled + ln -s ../sites-available/newfile.conf newfile.conf + ``` + +5. **Get the SSL certificate** on the server before deploying: + ```bash + sudo certbot certonly --nginx -d yourapp.nhcarrigan.com + ``` + +6. **Run the tests** locally to verify everything passes: + ```bash + bash test.sh + ``` + +7. **Deploy** (see below). + +## Removing a Site + +1. Delete the server block from the relevant `sites-available/*.conf` file. +2. If the entire `.conf` file is now empty, delete the file and its `sites-enabled/` symlink. +3. Run `bash test.sh` to confirm nothing is broken. +4. Deploy. + +## Deploying Changes + +Push the local `nginx/nginx/` directory to the server (the `--delete` flag removes any files on the server that no longer exist locally): + +```bash +bash push.sh +``` + +Then reload nginx to apply the changes: + +```bash +ssh prod "sudo systemctl reload nginx" +``` + +To pull the current server config back into this repository: + +```bash +bash pull.sh +``` + +## Testing + +The test suite runs static analysis checks against the config files without requiring a live nginx instance: + +```bash +bash test.sh +``` + +The following checks are run: + +| # | Check | +|---|-------| +| 1 | No deprecated TLS versions (TLSv1 / TLSv1.1) | +| 2 | No duplicate `server_name` values | +| 3 | Every `sites-available/*.conf` has a `sites-enabled` symlink | +| 4 | No broken symlinks in `sites-enabled` | +| 5 | No orphaned symlinks in `sites-enabled` | +| 6 | No port-80 listeners in custom server blocks | +| 7 | `ssl_certificate` and `ssl_certificate_key` counts match per file | +| 8 | All plain-HTTP `proxy_pass` targets are local | +| 9 | All SSL cert paths use `/etc/letsencrypt/live/` | +| 10 | Certs use `fullchain.pem` / keys use `privkey.pem` | +| 11 | No raw IP addresses as `server_name` | +| 12 | `conf.d` contains only expected files | +| 13 | Server blocks are sorted alphabetically by `server_name` within each file | + +CI additionally runs an nginx syntax check (`nginx -t`) using stub SSL certificates, catching any configuration errors that static analysis cannot detect. ## Feedback and Bugs diff --git a/configs/prod.conf b/configs/prod.conf deleted file mode 100644 index df48ac3..0000000 --- a/configs/prod.conf +++ /dev/null @@ -1,953 +0,0 @@ -server { - listen 443 ssl; - server_name afp.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/afp.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/afp.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass https://127.0.0.1:10443; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name alerts.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/alerts.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/alerts.nhcarrigan.com/privkey.pem; - - # Redirect ONLY root `/` - location = / { - return 307 https://rosalia.nhcarrigan.com; - } - - # Proxy everything else - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5003; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name analytics.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/analytics.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/analytics.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:11080; - } - - location = /live/websocket { - proxy_pass http://127.0.0.1:11080; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - } -} - -server { - listen 443 ssl; - server_name announcements.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/announcements.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/announcements.nhcarrigan.com/privkey.pem; - - return 301 https://forum.nhcarrigan.com/c/announcements/14; -} - -server { - listen 443 ssl; - server_name aria.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/aria.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/aria.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5001; - } -} - -server { - listen 443 ssl; - server_name assistant.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/assistant.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/assistant.nhcarrigan.com/privkey.pem; - - location / { - return 301 https://cordelia.nhcarrigan.com$uri$is_args$args; - } -} - -server { - listen 443 ssl; - server_name beccalia.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/beccalia.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/beccalia.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/games/beccalia; - - location / { - index index.html; - } - - location /origins { - index index.html; - } - - location /prologue { - index index.html; - } -} - -server { - listen 443 ssl; - server_name becca.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/becca.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/becca.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5010; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name blog.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/blog.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/blog.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:3003; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name board.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/board.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/board.nhcarrigan.com/privkey.pem; - - location ~ /ws/* { - proxy_pass http://127.0.0.1:8111; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - client_max_body_size 50M; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Frame-Options SAMEORIGIN; - proxy_buffers 256 16k; - proxy_buffer_size 16k; - client_body_timeout 60; - send_timeout 300; - lingering_timeout 5; - proxy_connect_timeout 1d; - proxy_send_timeout 1d; - proxy_read_timeout 1d; - } - - location / { - proxy_pass http://127.0.0.1:8111; - client_max_body_size 50M; - proxy_set_header Connection ""; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Frame-Options SAMEORIGIN; - proxy_buffers 256 16k; - proxy_buffer_size 16k; - proxy_read_timeout 600s; - proxy_cache_revalidate on; - proxy_cache_min_uses 2; - proxy_cache_use_stale timeout; - proxy_cache_lock on; - proxy_http_version 1.1; - } -} - -server { - listen 443 ssl; - server_name books.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/books.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/books.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/books; - - location / { - index index.html; - } - - location /books.json { - try_files /books.json =404; - } -} - -server { - listen 443 ssl; - server_name chat.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/chat.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/chat.nhcarrigan.com/privkey.pem; - - location / { - return 301 https://discord.gg/KKe7BaEnQB; - } -} - -server { - listen 443 ssl; - server_name celestine.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/celestine.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/celestine.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:9080; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name contact.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/contact.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/contact.nhcarrigan.com/privkey.pem; - - return 301 https://docs.nhcarrigan.com/about/contact/; -} - -server { - listen 443 ssl; - server_name cordelia.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/cordelia.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/cordelia.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5002; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name docs.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/docs.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/docs.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/docs/dist; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name donate.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/donate.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/donate.nhcarrigan.com/privkey.pem; - - return 301 https://docs.nhcarrigan.com/about/donate/; -} - -server { - listen 443 ssl; - server_name elowyn.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/elowyn.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/elowyn.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/elowyn; - - location / { - index index.html; - try_files $uri $uri/ /index.html; - } - - location ~* \.(js|css)$ { - try_files $uri $uri/ @rewrite; - } -} - -server { - listen 443 ssl; - server_name forms-api.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/forms-api.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/forms-api.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:1234; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name forms.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/forms.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/forms.nhcarrigan.com/privkey.pem; - - # Upgrade websocket requests and route the api backend - location ~ ^/(api|ws)/ { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Real-IP $remote_addr; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_pass http://127.0.0.1:11111; - } - - location / { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $http_host; - proxy_http_version 1.1; - proxy_pass http://127.0.0.1:11111; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name games.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/games.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/games.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/games; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name goblin.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/goblin.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/goblin.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/games/goblin; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name gwen.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/gwen.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/gwen.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5012; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name hikari.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/hikari.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/hikari.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/hikari/client/dist/client/browser; - index index.html; - - location /api/ { - proxy_pass http://127.0.0.1:20000/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header cf-connecting-ip $http_cf_connecting_ip; - proxy_set_header origin $http_origin; - - # This removes /api from the forwarded URL - rewrite ^/api/(.*)$ /$1 break; - } - - location / { - try_files $uri $uri/ /index.html; - } -} - -server { - listen 443 ssl; - server_name hooks.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/hooks.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/hooks.nhcarrigan.com/privkey.pem; - - location / { - return 301 https://celestine.nhcarrigan.com$uri$is_args$args; - } -} - -server { - listen 443 ssl; - server_name incidents.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/incidents.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/incidents.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:3001; - } -} - -server { - listen 443 ssl; - server_name loan.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/loan.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/loan.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/games/loan; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name lucinda.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/lucinda.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/lucinda.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/lucinda/client/dist/client/browser; - index index.html; - - location /api/ { - proxy_pass http://127.0.0.1:12346/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - # This removes /api from the forwarded URL - rewrite ^/api/(.*)$ /$1 break; - } - - location / { - try_files $uri $uri/ /index.html; - } -} - -server { - listen 443 ssl; - server_name manual.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/manual.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/manual.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/manual; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name maylin.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/maylin.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/maylin.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5011; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name melody.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/melody.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/melody.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5443; - } -} - -server { - listen 443 ssl; - server_name mommy-bot.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/mommy-bot.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/mommy-bot.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:8009; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name mommy.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/mommy.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/mommy.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:8008; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name mommy-slack.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/mommy-slack.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/mommy-slack.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:8010; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name music.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/music.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/music.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/music; - - location / { - index index.html; - } - - location /songs.json { - try_files /songs.json =404; - } -} - -server { - listen 443 ssl; - server_name nails-api.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/nails-api.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/nails-api.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:1235; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name nails.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/nails.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/nails.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/nails/client/dist/client/browser; - - location / { - index index.html; - try_files $uri $uri/ /index.html; - } - - location ~* \.(js|css)$ { - try_files $uri $uri/ @rewrite; - } -} - -server { - listen 443 ssl; - server_name naomi.lgbt; - ssl_certificate /etc/letsencrypt/live/naomi.lgbt/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/naomi.lgbt/privkey.pem; - - root /home/nhcarrigan/portfolio/site; - - location / { - index index.html; - } - - location /ads.txt { - add_header Content-Type text/plain; - return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; - } - - location /games { - try_files /games.html =404; - } - - location /koikatsu { - try_files /koikatsu.html =404; - } -} - -server { - listen 443 ssl; - server_name naomi.party; - ssl_certificate /etc/letsencrypt/live/naomi.party/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/naomi.party/privkey.pem; - - root /home/nhcarrigan/bsky; - - location / { - index index.html; - } - - location /ads.txt { - add_header Content-Type text/plain; - return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; - } -} - -server { - listen 443 ssl; - server_name nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/portfolio/site; - - location /ads.txt { - add_header Content-Type text/plain; - return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; - } - - location / { - index index.html; - } - - location /games { - try_files /games.html =404; - } - - location /koikatsu { - try_files /koikatsu.html =404; - } -} - -server { - listen 443 ssl; - server_name nhcarrigan.link; - ssl_certificate /etc/letsencrypt/live/nhcarrigan.link/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/nhcarrigan.link/privkey.pem; - - root /home/nhcarrigan/link-redirector; - - location / { - index index.html; - } - - location /ads.txt { - add_header Content-Type text/plain; - return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; - } -} - -server { - listen 443 ssl; - server_name oogie.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/oogie.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/oogie.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass https://127.0.0.1:3443; - } -} - -server { - listen 443 ssl; - server_name products.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/products.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/products.nhcarrigan.com/privkey.pem; - - location / { - return 301 https://hikari.nhcarrigan.com/products; - } -} - -server { - listen 443 ssl; - server_name quality.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/quality.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/quality.nhcarrigan.com/privkey.pem; - - client_max_body_size 1g; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:9500; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name rosalia.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/rosalia.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/rosalia.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:5003; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name resume.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/resume.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/resume.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/resume/site; - - location /resume.yaml { - default_type text/plain; - add_header Content-Type "text/plain; charset=utf-8"; - } - - location / { - index index.html; - try_files $uri $uri/ /index.html; - } -} - -server { - listen 443 ssl; - server_name ruubot.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/ruubot.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/ruubot.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass https://127.0.0.1:4443; - } -} - -server { - listen 443 ssl; - server_name security.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/security.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/security.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/security; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name sitemap.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/sitemap.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/sitemap.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/sitemap; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name tasks.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/tasks.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/tasks.nhcarrigan.com/privkey.pem; - - location / { - return 301 https://melody.nhcarrigan.com$uri$is_args$args; - } -} - -server { - listen 443 ssl; - server_name testimonials.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/testimonials.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/testimonials.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/testimonials; - - location / { - index index.html; - } -} - -server { - listen 443 ssl; - server_name trans-bot.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/trans.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/trans.nhcarrigan.com/privkey.pem; - - location / { - return 301 https://aria.nhcarrigan.com; - } -} - -server { - listen 443 ssl; - server_name trans.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/trans.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/trans.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://0.0.0.0:5000; - } -} - -server { - listen 443 ssl; - server_name uptime.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/uptime.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/uptime.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:3001; - } -} - -server { - listen 443 ssl; - server_name vitalia-api.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/vitalia.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/vitalia.nhcarrigan.com/privkey.pem; - - location / { - proxy_set_header Host $host; - proxy_pass http://127.0.0.1:12345; - proxy_redirect off; - } -} - -server { - listen 443 ssl; - server_name vitalia.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/vitalia.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/vitalia.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/vitalia/client/dist/client/browser; - - location / { - index index.html; - try_files $uri $uri/ /index.html; - } - - location ~* \.(js|css)$ { - try_files $uri $uri/ @rewrite; - } -} - -server { - listen 443 ssl; - server_name www.naomi.lgbt; - ssl_certificate /etc/letsencrypt/live/www.naomi.lgbt/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/www.naomi.lgbt/privkey.pem; - - root /home/nhcarrigan/portfolio/site; - - location / { - index index.html; - } - - location /games { - try_files /games.html =404; - } - - location /koikatsu { - try_files /koikatsu.html =404; - } -} - -server { - listen 443 ssl; - server_name www.nhcarrigan.com; - ssl_certificate /etc/letsencrypt/live/www.nhcarrigan.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/www.nhcarrigan.com/privkey.pem; - - root /home/nhcarrigan/portfolio/site; - - location / { - index index.html; - } - - location /games { - try_files /games.html =404; - } - - location /koikatsu { - try_files /koikatsu.html =404; - } -} - -server { - listen 443 ssl; - server_name www.yurigpt.com; - ssl_certificate /etc/letsencrypt/live/www.yurigpt.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/www.yurigpt.com/privkey.pem; - - root /home/nhcarrigan/yurigpt/dist/yurigpt/browser; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } - - location /ads.txt { - add_header Content-Type text/plain; - return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; - } -} - -server { - listen 443 ssl; - server_name yurigpt.com; - ssl_certificate /etc/letsencrypt/live/yurigpt.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/yurigpt.com/privkey.pem; - - root /home/nhcarrigan/yurigpt/dist/yurigpt/browser; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } - - location /ads.txt { - add_header Content-Type text/plain; - return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; - } -} - -# This MUST be at the bottom so that dedicated subdomains are parsed first! - -server { - listen 443 ssl; - server_name ~^(?.+)\.naomi\.lgbt$; - - ssl_certificate /etc/letsencrypt/live/naomi.lgbt-0001/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/naomi.lgbt-0001/privkey.pem; - - location / { - return 301 https://$subdomain.nhcarrigan.com$request_uri; - } -} diff --git a/nginx/nginx/cloudflare_ips.conf b/nginx/nginx/cloudflare_ips.conf new file mode 100644 index 0000000..86e2b62 --- /dev/null +++ b/nginx/nginx/cloudflare_ips.conf @@ -0,0 +1,28 @@ +# Auto-generated Cloudflare IP ranges +# Updated: Mon Mar 2 09:45:19 PM PST 2026 + +real_ip_header CF-Connecting-IP; + +# IPv4 ranges +set_real_ip_from 173.245.48.0/20; +set_real_ip_from 103.21.244.0/22; +set_real_ip_from 103.22.200.0/22; +set_real_ip_from 103.31.4.0/22; +set_real_ip_from 141.101.64.0/18; +set_real_ip_from 108.162.192.0/18; +set_real_ip_from 190.93.240.0/20; +set_real_ip_from 188.114.96.0/20; +set_real_ip_from 197.234.240.0/22; +set_real_ip_from 198.41.128.0/17; +set_real_ip_from 162.158.0.0/15; +set_real_ip_from 104.16.0.0/13; +set_real_ip_from 104.24.0.0/14; +set_real_ip_from 172.64.0.0/13; + +# IPv6 ranges +set_real_ip_from 2400:cb00::/32; +set_real_ip_from 2606:4700::/32; +set_real_ip_from 2803:f800::/32; +set_real_ip_from 2405:b500::/32; +set_real_ip_from 2405:8100::/32; +set_real_ip_from 2a06:98c0::/29; diff --git a/nginx/nginx/conf.d/logging.conf b/nginx/nginx/conf.d/logging.conf new file mode 100644 index 0000000..5744453 --- /dev/null +++ b/nginx/nginx/conf.d/logging.conf @@ -0,0 +1,47 @@ +log_format custom_format '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '"$http_x_forwarded_for"'; + +access_log /var/log/nginx/access.log custom_format; + +log_format json_analytics escape=json '{' +'"msec": "$msec", ' # request unixtime in seconds with a milliseconds resolution +'"connection": "$connection", ' # connection serial number +'"connection_requests": "$connection_requests", ' # number of requests made in connection +'"pid": "$pid", ' # process pid +'"request_id": "$request_id", ' # the unique request id +'"request_length": "$request_length", ' # request length (including headers and body) +'"remote_addr": "$remote_addr", ' # client IP +'"remote_user": "$remote_user", ' # client HTTP username +'"remote_port": "$remote_port", ' # client port +'"time_local": "$time_local", ' +'"time_iso8601": "$time_iso8601", ' # local time in the ISO 8601 standard format +'"request": "$request", ' # full path no arguments if the request +'"request_uri": "$request_uri", ' # full path and arguments if the request +'"args": "$args", ' # args +'"status": "$status", ' # response status code +'"body_bytes_sent": "$body_bytes_sent", ' # the number of body bytes exclude headers sent to a client +'"bytes_sent": "$bytes_sent", ' # the number of bytes sent to a client +'"http_referer": "$http_referer", ' # HTTP referer +'"http_user_agent": "$http_user_agent", ' # user agent +'"http_x_forwarded_for": "$http_x_forwarded_for", ' # http_x_forwarded_for +'"http_host": "$http_host", ' # the request Host: header +'"server_name": "$server_name", ' # the name of the vhost serving the request +'"request_time": "$request_time", ' # request processing time in seconds with msec resolution +'"upstream": "$upstream_addr", ' # upstream backend server for proxied requests +'"upstream_connect_time": "$upstream_connect_time", ' # upstream handshake time incl. TLS +'"upstream_header_time": "$upstream_header_time", ' # time spent receiving upstream headers +'"upstream_response_time": "$upstream_response_time", ' # time spent receiving upstream body +'"upstream_response_length": "$upstream_response_length", ' # upstream response length +'"upstream_cache_status": "$upstream_cache_status", ' # cache HIT/MISS where applicable +'"ssl_protocol": "$ssl_protocol", ' # TLS protocol +'"ssl_cipher": "$ssl_cipher", ' # TLS cipher +'"scheme": "$scheme", ' # http or https +'"request_method": "$request_method", ' # request method +'"server_protocol": "$server_protocol", ' # request protocol, like HTTP/1.1 or HTTP/2.0 +'"pipe": "$pipe", ' # "p" if request was pipelined, "." otherwise +'"gzip_ratio": "$gzip_ratio", ' +'}'; + +access_log /var/log/nginx/json_access.log json_analytics; diff --git a/nginx/nginx/conf.d/tuning.conf b/nginx/nginx/conf.d/tuning.conf new file mode 100644 index 0000000..8e2d6b2 --- /dev/null +++ b/nginx/nginx/conf.d/tuning.conf @@ -0,0 +1 @@ +server_names_hash_bucket_size 128; diff --git a/nginx/nginx/fastcgi.conf b/nginx/nginx/fastcgi.conf new file mode 100644 index 0000000..d53a628 --- /dev/null +++ b/nginx/nginx/fastcgi.conf @@ -0,0 +1,27 @@ + +fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/nginx/nginx/fastcgi_params b/nginx/nginx/fastcgi_params new file mode 100644 index 0000000..69c4387 --- /dev/null +++ b/nginx/nginx/fastcgi_params @@ -0,0 +1,26 @@ + +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param REQUEST_SCHEME $scheme; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param REMOTE_USER $remote_user; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/nginx/nginx/koi-utf b/nginx/nginx/koi-utf new file mode 100644 index 0000000..e7974ff --- /dev/null +++ b/nginx/nginx/koi-utf @@ -0,0 +1,109 @@ + +# This map is not a full koi8-r <> utf8 map: it does not contain +# box-drawing and some other characters. Besides this map contains +# several koi8-u and Byelorussian letters which are not in koi8-r. +# If you need a full and standard map, use contrib/unicode2nginx/koi-utf +# map instead. + +charset_map koi8-r utf-8 { + + 80 E282AC ; # euro + + 95 E280A2 ; # bullet + + 9A C2A0 ; #   + + 9E C2B7 ; # · + + A3 D191 ; # small yo + A4 D194 ; # small Ukrainian ye + + A6 D196 ; # small Ukrainian i + A7 D197 ; # small Ukrainian yi + + AD D291 ; # small Ukrainian soft g + AE D19E ; # small Byelorussian short u + + B0 C2B0 ; # ° + + B3 D081 ; # capital YO + B4 D084 ; # capital Ukrainian YE + + B6 D086 ; # capital Ukrainian I + B7 D087 ; # capital Ukrainian YI + + B9 E28496 ; # numero sign + + BD D290 ; # capital Ukrainian soft G + BE D18E ; # capital Byelorussian short U + + BF C2A9 ; # (C) + + C0 D18E ; # small yu + C1 D0B0 ; # small a + C2 D0B1 ; # small b + C3 D186 ; # small ts + C4 D0B4 ; # small d + C5 D0B5 ; # small ye + C6 D184 ; # small f + C7 D0B3 ; # small g + C8 D185 ; # small kh + C9 D0B8 ; # small i + CA D0B9 ; # small j + CB D0BA ; # small k + CC D0BB ; # small l + CD D0BC ; # small m + CE D0BD ; # small n + CF D0BE ; # small o + + D0 D0BF ; # small p + D1 D18F ; # small ya + D2 D180 ; # small r + D3 D181 ; # small s + D4 D182 ; # small t + D5 D183 ; # small u + D6 D0B6 ; # small zh + D7 D0B2 ; # small v + D8 D18C ; # small soft sign + D9 D18B ; # small y + DA D0B7 ; # small z + DB D188 ; # small sh + DC D18D ; # small e + DD D189 ; # small shch + DE D187 ; # small ch + DF D18A ; # small hard sign + + E0 D0AE ; # capital YU + E1 D090 ; # capital A + E2 D091 ; # capital B + E3 D0A6 ; # capital TS + E4 D094 ; # capital D + E5 D095 ; # capital YE + E6 D0A4 ; # capital F + E7 D093 ; # capital G + E8 D0A5 ; # capital KH + E9 D098 ; # capital I + EA D099 ; # capital J + EB D09A ; # capital K + EC D09B ; # capital L + ED D09C ; # capital M + EE D09D ; # capital N + EF D09E ; # capital O + + F0 D09F ; # capital P + F1 D0AF ; # capital YA + F2 D0A0 ; # capital R + F3 D0A1 ; # capital S + F4 D0A2 ; # capital T + F5 D0A3 ; # capital U + F6 D096 ; # capital ZH + F7 D092 ; # capital V + F8 D0AC ; # capital soft sign + F9 D0AB ; # capital Y + FA D097 ; # capital Z + FB D0A8 ; # capital SH + FC D0AD ; # capital E + FD D0A9 ; # capital SHCH + FE D0A7 ; # capital CH + FF D0AA ; # capital hard sign +} diff --git a/nginx/nginx/koi-win b/nginx/nginx/koi-win new file mode 100644 index 0000000..72afabe --- /dev/null +++ b/nginx/nginx/koi-win @@ -0,0 +1,103 @@ + +charset_map koi8-r windows-1251 { + + 80 88 ; # euro + + 95 95 ; # bullet + + 9A A0 ; #   + + 9E B7 ; # · + + A3 B8 ; # small yo + A4 BA ; # small Ukrainian ye + + A6 B3 ; # small Ukrainian i + A7 BF ; # small Ukrainian yi + + AD B4 ; # small Ukrainian soft g + AE A2 ; # small Byelorussian short u + + B0 B0 ; # ° + + B3 A8 ; # capital YO + B4 AA ; # capital Ukrainian YE + + B6 B2 ; # capital Ukrainian I + B7 AF ; # capital Ukrainian YI + + B9 B9 ; # numero sign + + BD A5 ; # capital Ukrainian soft G + BE A1 ; # capital Byelorussian short U + + BF A9 ; # (C) + + C0 FE ; # small yu + C1 E0 ; # small a + C2 E1 ; # small b + C3 F6 ; # small ts + C4 E4 ; # small d + C5 E5 ; # small ye + C6 F4 ; # small f + C7 E3 ; # small g + C8 F5 ; # small kh + C9 E8 ; # small i + CA E9 ; # small j + CB EA ; # small k + CC EB ; # small l + CD EC ; # small m + CE ED ; # small n + CF EE ; # small o + + D0 EF ; # small p + D1 FF ; # small ya + D2 F0 ; # small r + D3 F1 ; # small s + D4 F2 ; # small t + D5 F3 ; # small u + D6 E6 ; # small zh + D7 E2 ; # small v + D8 FC ; # small soft sign + D9 FB ; # small y + DA E7 ; # small z + DB F8 ; # small sh + DC FD ; # small e + DD F9 ; # small shch + DE F7 ; # small ch + DF FA ; # small hard sign + + E0 DE ; # capital YU + E1 C0 ; # capital A + E2 C1 ; # capital B + E3 D6 ; # capital TS + E4 C4 ; # capital D + E5 C5 ; # capital YE + E6 D4 ; # capital F + E7 C3 ; # capital G + E8 D5 ; # capital KH + E9 C8 ; # capital I + EA C9 ; # capital J + EB CA ; # capital K + EC CB ; # capital L + ED CC ; # capital M + EE CD ; # capital N + EF CE ; # capital O + + F0 CF ; # capital P + F1 DF ; # capital YA + F2 D0 ; # capital R + F3 D1 ; # capital S + F4 D2 ; # capital T + F5 D3 ; # capital U + F6 C6 ; # capital ZH + F7 C2 ; # capital V + F8 DC ; # capital soft sign + F9 DB ; # capital Y + FA C7 ; # capital Z + FB D8 ; # capital SH + FC DD ; # capital E + FD D9 ; # capital SHCH + FE D7 ; # capital CH + FF DA ; # capital hard sign +} diff --git a/nginx/nginx/mime.types b/nginx/nginx/mime.types new file mode 100644 index 0000000..479781b --- /dev/null +++ b/nginx/nginx/mime.types @@ -0,0 +1,101 @@ + +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/avif avif; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + font/woff woff; + font/woff2 woff2; + + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/wasm wasm; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/ogg ogv; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-matroska mkv; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/nginx/nginx/nginx.conf b/nginx/nginx/nginx.conf new file mode 100644 index 0000000..9ec670c --- /dev/null +++ b/nginx/nginx/nginx.conf @@ -0,0 +1,52 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; +} + +http { + + ## + # Basic Settings + ## + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # SSL Settings + ## + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + ## + # Gzip Settings + ## + + gzip on; + + ## + # Virtual Host Configs + ## + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; + + # Look at the real IP, not the cloudflare IP. + include /etc/nginx/cloudflare_ips.conf; +} diff --git a/nginx/nginx/proxy_params b/nginx/nginx/proxy_params new file mode 100644 index 0000000..df75bc5 --- /dev/null +++ b/nginx/nginx/proxy_params @@ -0,0 +1,4 @@ +proxy_set_header Host $http_host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; diff --git a/nginx/nginx/scgi_params b/nginx/nginx/scgi_params new file mode 100644 index 0000000..6d4ce4f --- /dev/null +++ b/nginx/nginx/scgi_params @@ -0,0 +1,17 @@ + +scgi_param REQUEST_METHOD $request_method; +scgi_param REQUEST_URI $request_uri; +scgi_param QUERY_STRING $query_string; +scgi_param CONTENT_TYPE $content_type; + +scgi_param DOCUMENT_URI $document_uri; +scgi_param DOCUMENT_ROOT $document_root; +scgi_param SCGI 1; +scgi_param SERVER_PROTOCOL $server_protocol; +scgi_param REQUEST_SCHEME $scheme; +scgi_param HTTPS $https if_not_empty; + +scgi_param REMOTE_ADDR $remote_addr; +scgi_param REMOTE_PORT $remote_port; +scgi_param SERVER_PORT $server_port; +scgi_param SERVER_NAME $server_name; diff --git a/nginx/nginx/sites-available/afp.conf b/nginx/nginx/sites-available/afp.conf new file mode 100644 index 0000000..9834466 --- /dev/null +++ b/nginx/nginx/sites-available/afp.conf @@ -0,0 +1,13 @@ +# AFP service proxy. +server { + listen 443 ssl; + server_name afp.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/afp.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/afp.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:10080; + proxy_redirect off; + } +} diff --git a/nginx/nginx/sites-available/aria.conf b/nginx/nginx/sites-available/aria.conf new file mode 100644 index 0000000..a9be343 --- /dev/null +++ b/nginx/nginx/sites-available/aria.conf @@ -0,0 +1,59 @@ +# Aria bot, Cordelia AI assistant, trans-related services, and legacy redirects. +server { + listen 443 ssl; + server_name aria.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/aria.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/aria.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5001; + } +} + +server { + listen 443 ssl; + server_name assistant.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/assistant.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/assistant.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://cordelia.nhcarrigan.com$uri$is_args$args; + } +} + +server { + listen 443 ssl; + server_name cordelia.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/cordelia.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cordelia.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5002; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name trans-bot.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/trans.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/trans.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://aria.nhcarrigan.com; + } +} + +server { + listen 443 ssl; + server_name trans.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/trans.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/trans.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://0.0.0.0:5000; + } +} diff --git a/nginx/nginx/sites-available/bots.conf b/nginx/nginx/sites-available/bots.conf new file mode 100644 index 0000000..f8937e5 --- /dev/null +++ b/nginx/nginx/sites-available/bots.conf @@ -0,0 +1,252 @@ +# Discord bots and automated services (one entry per bot, sorted alphabetically). +server { + listen 443 ssl; + server_name altaria.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/altaria.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/altaria.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:6022; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name amari.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/amari.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/amari.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:7044; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name becca.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/becca.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/becca.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5010; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name caelia.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/caelia.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/caelia.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:7055; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name callista.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/callista.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/callista.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:6111; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name chibika.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/chibika.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/chibika.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5018; + } +} + +server { + listen 443 ssl; + server_name gwen.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/gwen.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/gwen.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5012; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name keiko.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/keiko.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/keiko.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3333; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name liora.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/liora.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/liora.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5022; + } +} + +server { + listen 443 ssl; + server_name maylin.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/maylin.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/maylin.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5011; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name melody.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/melody.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/melody.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5443; + } +} + +server { + listen 443 ssl; + server_name pavelle.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/pavelle.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/pavelle.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:6019; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name ruubot.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/ruubot.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ruubot.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass https://127.0.0.1:4443; + } +} + +server { + listen 443 ssl; + server_name saisoku.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/saisoku.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/saisoku.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:9100; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name serenya.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/serenya.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/serenya.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:7066; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name sorielle.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/sorielle.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/sorielle.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5019; + } +} + +server { + listen 443 ssl; + server_name tyche.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/tyche.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/tyche.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:8123; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name umbrelle.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/umbrelle.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/umbrelle.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:6088; + } +} + +server { + listen 443 ssl; + server_name valerium.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/valerium.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/valerium.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3443; + } +} + +server { + listen 443 ssl; + server_name veluna.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/veluna.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/veluna.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:6099; + } +} diff --git a/nginx/nginx/sites-available/cdn.conf b/nginx/nginx/sites-available/cdn.conf new file mode 100644 index 0000000..1d41f2f --- /dev/null +++ b/nginx/nginx/sites-available/cdn.conf @@ -0,0 +1,52 @@ +# CDN reverse proxy to Hetzner object storage, with legacy path redirects and CORS headers. +server { + listen 443 ssl; + listen [::]:443 ssl; + + server_name cdn.nhcarrigan.com; + + ssl_certificate /etc/letsencrypt/live/cdn.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cdn.nhcarrigan.com/privkey.pem; + + # Catches "/new-avatars/name-full.png" and redirects to "/avatars/name.png" + location ~ ^/new-avatars/(.+)-full\.png$ { + return 301 $scheme://$host/avatars/$1.png; + } + + # Catches anything else starting with "/new-avatars/" and moves it to "/avatars/" + location ~ ^/new-avatars/(.*)$ { + return 301 $scheme://$host/avatars/$1; + } + + location / { + proxy_pass https://nhcarrigan.hel1.your-objectstorage.com; + proxy_set_header Host nhcarrigan.hel1.your-objectstorage.com; + + proxy_ssl_server_name on; + proxy_ssl_name nhcarrigan.hel1.your-objectstorage.com; + + proxy_http_version 1.1; + proxy_set_header Connection ""; + + proxy_set_header Authorization ""; + proxy_set_header x-amz-date ""; + proxy_set_header x-amz-security-token ""; + + add_header X-Debug-Cdn "Proxy-Active" always; + + proxy_hide_header Access-Control-Allow-Origin; + + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" always; + + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin "*" always; + add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always; + add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range" always; + add_header Content-Type "text/plain; charset=utf-8"; + add_header Content-Length 0; + return 204; + } + } +} diff --git a/nginx/nginx/sites-available/celestine.conf b/nginx/nginx/sites-available/celestine.conf new file mode 100644 index 0000000..9eed0a5 --- /dev/null +++ b/nginx/nginx/sites-available/celestine.conf @@ -0,0 +1,24 @@ +# Celestine webhook handler and legacy hooks redirect. +server { + listen 443 ssl; + server_name celestine.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/celestine.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/celestine.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:9080; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name hooks.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/hooks.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/hooks.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://celestine.nhcarrigan.com$uri$is_args$args; + } +} diff --git a/nginx/nginx/sites-available/content.conf b/nginx/nginx/sites-available/content.conf new file mode 100644 index 0000000..4e1a06b --- /dev/null +++ b/nginx/nginx/sites-available/content.conf @@ -0,0 +1,99 @@ +# Static content and publishing sites: blog, books, donate, music, secrets, style, testimonials. +server { + listen 443 ssl; + server_name blog.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/blog.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/blog.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3003; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name books.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/books.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/books.nhcarrigan.com/privkey.pem; + + root /home/naomi/books; + + location / { + index index.html; + } + + location /books.json { + try_files /books.json =404; + } +} + +server { + listen 443 ssl; + server_name donate.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/donate.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/donate.nhcarrigan.com/privkey.pem; + + root /home/naomi/donate; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name music.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/music.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/music.nhcarrigan.com/privkey.pem; + + root /home/naomi/music; + + location / { + index index.html; + } + + location /songs.json { + try_files /songs.json =404; + } +} + +server { + listen 443 ssl; + server_name secrets.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/secrets.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/secrets.nhcarrigan.com/privkey.pem; + + root /home/naomi/secrets; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name style.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/style.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/style.nhcarrigan.com/privkey.pem; + + root /home/naomi/style; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name testimonials.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/testimonials.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/testimonials.nhcarrigan.com/privkey.pem; + + root /home/naomi/testimonials; + + location / { + index index.html; + } +} diff --git a/nginx/nginx/sites-available/data.conf b/nginx/nginx/sites-available/data.conf new file mode 100644 index 0000000..d6ef3c6 --- /dev/null +++ b/nginx/nginx/sites-available/data.conf @@ -0,0 +1,13 @@ +# Data service proxy. +server { + listen 443 ssl; + server_name data.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/data.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/data.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:9999; + proxy_redirect off; + } +} diff --git a/nginx/nginx/sites-available/default b/nginx/nginx/sites-available/default new file mode 100644 index 0000000..4876607 --- /dev/null +++ b/nginx/nginx/sites-available/default @@ -0,0 +1,18 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + root /var/www/html; + index index.html index.htm index.nginx-debian.html; + + server_name _; + + location / { + try_files $uri $uri/ =404; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} diff --git a/nginx/nginx/sites-available/docs.conf b/nginx/nginx/sites-available/docs.conf new file mode 100644 index 0000000..32bcafb --- /dev/null +++ b/nginx/nginx/sites-available/docs.conf @@ -0,0 +1,65 @@ +# Documentation and informational sites: contact, docs, manual, sitemap, socials. +server { + listen 443 ssl; + server_name contact.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/contact.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/contact.nhcarrigan.com/privkey.pem; + + root /home/naomi/socials; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name docs.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/docs.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/docs.nhcarrigan.com/privkey.pem; + + root /home/naomi/docs/dist; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name manual.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/manual.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/manual.nhcarrigan.com/privkey.pem; + + root /home/naomi/manual; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name sitemap.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/sitemap.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/sitemap.nhcarrigan.com/privkey.pem; + + root /home/naomi/sitemap; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name socials.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/socials.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/socials.nhcarrigan.com/privkey.pem; + + root /home/naomi/socials; + + location / { + index index.html; + } +} diff --git a/nginx/nginx/sites-available/eclaire.conf b/nginx/nginx/sites-available/eclaire.conf new file mode 100644 index 0000000..77998ac --- /dev/null +++ b/nginx/nginx/sites-available/eclaire.conf @@ -0,0 +1,14 @@ +# Eclaire Angular SPA. +server { + listen 443 ssl; + server_name eclaire.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/eclaire.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/eclaire.nhcarrigan.com/privkey.pem; + + root /home/naomi/eclaire/dist/eclaire/browser; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/nginx/nginx/sites-available/elowyn.conf b/nginx/nginx/sites-available/elowyn.conf new file mode 100644 index 0000000..48c1f51 --- /dev/null +++ b/nginx/nginx/sites-available/elowyn.conf @@ -0,0 +1,18 @@ +# Elowyn Angular SPA. +server { + listen 443 ssl; + server_name elowyn.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/elowyn.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/elowyn.nhcarrigan.com/privkey.pem; + + root /home/naomi/elowyn; + + location / { + index index.html; + try_files $uri $uri/ /index.html; + } + + location ~* \.(js|css)$ { + try_files $uri $uri/ @rewrite; + } +} diff --git a/nginx/nginx/sites-available/elysium.conf b/nginx/nginx/sites-available/elysium.conf new file mode 100644 index 0000000..f4b8885 --- /dev/null +++ b/nginx/nginx/sites-available/elysium.conf @@ -0,0 +1,24 @@ +# Elysium Vite SPA and Hono API backend. +server { + listen 443 ssl; + server_name elysium.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/elysium.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/elysium.nhcarrigan.com/privkey.pem; + + root /home/naomi/elysium/apps/web/dist; + + location /api/ { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3898; + proxy_redirect off; + } + + location / { + index index.html; + try_files $uri $uri/ /index.html; + } + + location ~* \.(js|css)$ { + try_files $uri $uri/ @rewrite; + } +} diff --git a/nginx/nginx/sites-available/forms.conf b/nginx/nginx/sites-available/forms.conf new file mode 100644 index 0000000..7c667d6 --- /dev/null +++ b/nginx/nginx/sites-available/forms.conf @@ -0,0 +1,151 @@ +# Grist forms platform (forms-api backend + forms frontend with CSS injection) and legacy form URL redirects. +server { + listen 443 ssl; + server_name forms-api.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/forms-api.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/forms-api.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:1234; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name forms.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/forms.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/forms.nhcarrigan.com/privkey.pem; + +########################### +# REDIRECTS FOR OLD FORMS # +########################### + + # Volunteer Application Form + location ~* ^/form/PEpB3gA79gxP8wmfEf4zou96opkpUTjssTcaeYjhoi8$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/mCxDu3snk9TzFiDjrT4Vc8/4; + } + + # Mentorship Application Form (now Discord self-selectable role) + location ~* ^/form/gNv4NYZmdiMWpkUcnknII2yYCvnYNGAmabG5O5He9Mo$ { + return 301 https://docs.nhcarrigan.com/about/mentorship; + } + + # Testimonials Form + location ~* ^/form/M_GrmqASymmO744axMOmu2LaMAaT5F0LmdVcU2c8-gQ$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/6kULn8zswT8vYcoC8wE1Zi/4; + } + + # Community Appeals Form + location ~* ^/form/l3PC15yalSWjdZASTQvGo22q_uj_7OtXAhZdcW35ev8$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/4w5VHsYiEkiS2mewvtuJYL/4; + } + + # Recognition/Nomination Form + location ~* ^/form/wksk-NuR3HBuovSixbXFEnkYq-3Gp-bZMH-n__PNRKw$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/to2oFocVgALyr23EC84xM9/4; + } + + # Community Feedback Form (now Discord forum channel) + location ~* ^/form/IDdo5e4OJS44QYFm9_aRJ36lY3Ox-BBTAM9zfnkhfoo$ { + return 301 https://docs.nhcarrigan.com/community/feedback; + } + + # Product Feedback Form (now Discord forum channel) + location ~* ^/form/jkcGg0hMIa4U0hDL2OMip5pMX2UujN5W5n4Qn8HReJ8$ { + return 301 https://docs.nhcarrigan.com/community/feedback; + } + + # Meeting Request Form (now Zcal scheduling) + location ~* ^/form/uUKZiJSDm6847iDOlpZkD5QF7cAjoTbTm0F4T0EdW0I$ { + return 301 https://zcal.co/nhcarrigan/meet; + } + + # Commission Request Form + location ~* ^/form/XRlQjeu8CbMrTA-v0IPOxlUPEPitLKXTWg70UUCIORA$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/a9K6uzJkpnTfnKgo19b4Rp/4; + } + + # Contact Form + location ~* ^/form/HyqoJ9Th5QDiOn_GPLNIRhe1a5ON7mDQf-O_ukM6R4g$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/8XTPmbrFtvDJAKSPgBgsvA/4; + } + + # Git Account Request Form (no longer available - now Discord forum channels) + location ~* ^/form/c0_N5hb-VcmC2ClzaGOvDxVirMN_coiWG7eoPhDPsZ0$ { + return 301 https://docs.nhcarrigan.com/about/contact; + } + + # Event/Publication Request Form + location ~* ^/form/Xqap3Q8hazzJd4Rrp9OOs9ip8Pa7C9zOVThlyFoPCbU$ { + return 301 https://forms.nhcarrigan.com/o/docs/forms/3xEKnDEbqQKG8GJp4kXRCs/4; + } + + # Match any path ending in /forms/ + location ~ /forms/([^/]+)(?:/(.*))?$ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_pass http://127.0.0.1:11111; + proxy_redirect off; + + # Disable Gzip from upstream so nginx can inject CSS + proxy_set_header Accept-Encoding ""; + + # Inject CSS and remove Grist branding + sub_filter '' ' +'; + + sub_filter_once on; + } + + # Upgrade websocket requests and route the api backend + location ~ ^/(api|ws)/ { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_pass http://127.0.0.1:11111; + } + + location / { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_pass http://127.0.0.1:11111; + proxy_redirect off; + } +} diff --git a/nginx/nginx/sites-available/games.conf b/nginx/nginx/sites-available/games.conf new file mode 100644 index 0000000..dcfa7ca --- /dev/null +++ b/nginx/nginx/sites-available/games.conf @@ -0,0 +1,165 @@ +# Games and gaming projects: beccalia, games hub, goblin, loan, lore, silly, wompwomp, yurigpt. +server { + listen 443 ssl; + server_name beccalia.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/beccalia.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/beccalia.nhcarrigan.com/privkey.pem; + + root /home/naomi/games/beccalia; + + location / { + index index.html; + } + + location /origins { + index index.html; + } + + location /prologue { + index index.html; + } +} + +server { + listen 443 ssl; + server_name games.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/games.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/games.nhcarrigan.com/privkey.pem; + + root /home/naomi/games; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name goblin.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/goblin.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/goblin.nhcarrigan.com/privkey.pem; + + root /home/naomi/games/goblin; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name loan.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/loan.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/loan.nhcarrigan.com/privkey.pem; + + root /home/naomi/games/loan; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name lore.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/lore.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/lore.nhcarrigan.com/privkey.pem; + + root /home/naomi/lore/dist/lore/browser; + + location / { + index index.html; + } +} + +server { + listen 443 ssl; + server_name silly.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/silly.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/silly.nhcarrigan.com/privkey.pem; + + root /home/naomi/silly; + index index.html; + + location = / { + try_files /index.html =404; + } + + location / { + try_files $uri $uri/ $uri.html $uri/index.html =404; + } + + location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|otf|eot|webp)$ { + expires 30d; + add_header Cache-Control "public, immutable"; + access_log off; + } + + location ~ /\.(?!well-known) { + deny all; + } +} + +server { + listen 443 ssl; + server_name wompwomp.club; + ssl_certificate /etc/letsencrypt/live/wompwomp.club/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/wompwomp.club/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5033; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name www.wompwomp.club; + ssl_certificate /etc/letsencrypt/live/www.wompwomp.club/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.wompwomp.club/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5033; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name www.yurigpt.com; + ssl_certificate /etc/letsencrypt/live/www.yurigpt.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.yurigpt.com/privkey.pem; + + root /home/naomi/yurigpt/dist/yurigpt/browser; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /ads.txt { + add_header Content-Type text/plain; + return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; + } +} + +server { + listen 443 ssl; + server_name yurigpt.com; + ssl_certificate /etc/letsencrypt/live/yurigpt.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/yurigpt.com/privkey.pem; + + root /home/naomi/yurigpt/dist/yurigpt/browser; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /ads.txt { + add_header Content-Type text/plain; + return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; + } +} diff --git a/configs/gitea.conf b/nginx/nginx/sites-available/git.conf similarity index 74% rename from configs/gitea.conf rename to nginx/nginx/sites-available/git.conf index b6d10b0..73f2498 100644 --- a/configs/gitea.conf +++ b/nginx/nginx/sites-available/git.conf @@ -1,3 +1,4 @@ +# Self-hosted Gitea instance. server { listen 443 ssl; server_name git.nhcarrigan.com; @@ -5,9 +6,9 @@ server { ssl_certificate_key /etc/letsencrypt/live/git.nhcarrigan.com/privkey.pem; location / { - client_max_body_size 1000M; + client_max_body_size 5000M; proxy_set_header Host $host; - proxy_pass http://127.0.0.1:3000; + proxy_pass http://127.0.0.1:53000; proxy_redirect off; } } diff --git a/nginx/nginx/sites-available/hikari.conf b/nginx/nginx/sites-available/hikari.conf new file mode 100644 index 0000000..e02cd8e --- /dev/null +++ b/nginx/nginx/sites-available/hikari.conf @@ -0,0 +1,47 @@ +# Hikari desktop app (Angular SPA + API backend) and legacy redirect subdomains. +server { + listen 443 ssl; + server_name announcements.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/announcements.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/announcements.nhcarrigan.com/privkey.pem; + + return 301 https://hikari.nhcarrigan.com/announcements; +} + +server { + listen 443 ssl; + server_name hikari.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/hikari.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/hikari.nhcarrigan.com/privkey.pem; + + root /home/naomi/hikari/client/dist/client/browser; + index index.html; + + location /api/ { + proxy_pass http://127.0.0.1:20000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header cf-connecting-ip $http_cf_connecting_ip; + proxy_set_header origin $http_origin; + + # This removes /api from the forwarded URL + rewrite ^/api/(.*)$ /$1 break; + } + + location / { + try_files $uri $uri/ /index.html; + } +} + +server { + listen 443 ssl; + server_name products.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/products.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/products.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://hikari.nhcarrigan.com/products; + } +} diff --git a/nginx/nginx/sites-available/library.conf b/nginx/nginx/sites-available/library.conf new file mode 100644 index 0000000..37b4ca1 --- /dev/null +++ b/nginx/nginx/sites-available/library.conf @@ -0,0 +1,13 @@ +# Library service proxy. +server { + listen 443 ssl; + server_name library.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/library.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/library.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:12321; + proxy_redirect off; + } +} diff --git a/nginx/nginx/sites-available/lucinda.conf b/nginx/nginx/sites-available/lucinda.conf new file mode 100644 index 0000000..7d8aebd --- /dev/null +++ b/nginx/nginx/sites-available/lucinda.conf @@ -0,0 +1,25 @@ +# Lucinda full-stack app (Angular SPA + API backend). +server { + listen 443 ssl; + server_name lucinda.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/lucinda.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/lucinda.nhcarrigan.com/privkey.pem; + + root /home/naomi/lucinda/client/dist/client/browser; + index index.html; + + location /api/ { + proxy_pass http://127.0.0.1:12346/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # This removes /api from the forwarded URL + rewrite ^/api/(.*)$ /$1 break; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/nginx/nginx/sites-available/lynira.conf b/nginx/nginx/sites-available/lynira.conf new file mode 100644 index 0000000..12efa5e --- /dev/null +++ b/nginx/nginx/sites-available/lynira.conf @@ -0,0 +1,24 @@ +# Lynira.link domain (bare + www). +server { + listen 443 ssl; + server_name lynira.link; + ssl_certificate /etc/letsencrypt/live/lynira.link/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/lynira.link/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5044; + } +} + +server { + listen 443 ssl; + server_name www.lynira.link; + ssl_certificate /etc/letsencrypt/live/www.lynira.link/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.lynira.link/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5044; + } +} diff --git a/nginx/nginx/sites-available/mommy.conf b/nginx/nginx/sites-available/mommy.conf new file mode 100644 index 0000000..844ba94 --- /dev/null +++ b/nginx/nginx/sites-available/mommy.conf @@ -0,0 +1,39 @@ +# Mommy bot suite: mommy-bot Discord bot, mommy-slack Slack bot, mommy web front-end. +server { + listen 443 ssl; + server_name mommy-bot.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/mommy-bot.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/mommy-bot.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:8009; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name mommy-slack.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/mommy-slack.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/mommy-slack.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:8010; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name mommy.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/mommy.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/mommy.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:8008; + proxy_redirect off; + } +} diff --git a/nginx/nginx/sites-available/monitoring.conf b/nginx/nginx/sites-available/monitoring.conf new file mode 100644 index 0000000..bb4d897 --- /dev/null +++ b/nginx/nginx/sites-available/monitoring.conf @@ -0,0 +1,80 @@ +# Monitoring stack: analytics, incidents, logs, telemetry, uptime. +server { + listen 443 ssl; + server_name analytics.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/analytics.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/analytics.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:11080; + } + + location = /live/websocket { + proxy_pass http://127.0.0.1:11080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + } +} + +server { + listen 443 ssl; + server_name incidents.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/incidents.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/incidents.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3001; + } +} + +server { + listen 443 ssl; + server_name logs.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/logs.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/logs.nhcarrigan.com/privkey.pem; + + location / { + proxy_pass http://127.0.0.1:9000; + proxy_set_header Host $host; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto http; + proxy_redirect http:// $scheme://; + + proxy_connect_timeout 1m; + proxy_send_timeout 1m; + proxy_read_timeout 1m; + } +} + +server { + listen 443 ssl; + server_name telemetry.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/telemetry.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/telemetry.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5080; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name uptime.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/uptime.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/uptime.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3001; + } +} diff --git a/nginx/nginx/sites-available/nails.conf b/nginx/nginx/sites-available/nails.conf new file mode 100644 index 0000000..b6dfe45 --- /dev/null +++ b/nginx/nginx/sites-available/nails.conf @@ -0,0 +1,31 @@ +# Nails app: Angular front-end SPA and API backend. +server { + listen 443 ssl; + server_name nails-api.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/nails-api.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/nails-api.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:1235; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name nails.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/nails.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/nails.nhcarrigan.com/privkey.pem; + + root /home/naomi/nails/client/dist/client/browser; + + location / { + index index.html; + try_files $uri $uri/ /index.html; + } + + location ~* \.(js|css)$ { + try_files $uri $uri/ @rewrite; + } +} diff --git a/nginx/nginx/sites-available/notes.conf b/nginx/nginx/sites-available/notes.conf new file mode 100644 index 0000000..5e825fe --- /dev/null +++ b/nginx/nginx/sites-available/notes.conf @@ -0,0 +1,92 @@ +# SilverBullet notes instance and Planka project board. +server { + listen 443 ssl; + server_name board.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/board.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/board.nhcarrigan.com/privkey.pem; + + location ~ /ws/* { + proxy_pass http://127.0.0.1:43333; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + client_max_body_size 50M; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + client_body_timeout 60; + send_timeout 300; + lingering_timeout 5; + proxy_connect_timeout 1d; + proxy_send_timeout 1d; + proxy_read_timeout 1d; + } + + location / { + proxy_pass http://127.0.0.1:43333; + client_max_body_size 50M; + proxy_set_header Connection ""; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + proxy_read_timeout 600s; + proxy_cache_revalidate on; + proxy_cache_min_uses 2; + proxy_cache_use_stale timeout; + proxy_cache_lock on; + proxy_http_version 1.1; + } +} + +server { + listen 443 ssl; + server_name notes.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/notes.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/notes.nhcarrigan.com/privkey.pem; + + location ~ ^/(collab|socket\.io)(/.*)?$ { + proxy_pass http://127.0.0.1:30000; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + client_max_body_size 50M; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + client_body_timeout 60; + send_timeout 300; + lingering_timeout 5; + proxy_connect_timeout 1d; + proxy_send_timeout 1d; + proxy_read_timeout 1d; + } + + location / { + proxy_pass http://127.0.0.1:30000; + client_max_body_size 50M; + proxy_set_header Connection ""; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + proxy_buffers 256 16k; + proxy_buffer_size 16k; + proxy_read_timeout 600s; + proxy_cache_revalidate on; + proxy_cache_min_uses 2; + proxy_cache_use_stale timeout; + proxy_cache_lock on; + proxy_http_version 1.1; + } +} diff --git a/nginx/nginx/sites-available/portfolio.conf b/nginx/nginx/sites-available/portfolio.conf new file mode 100644 index 0000000..642319e --- /dev/null +++ b/nginx/nginx/sites-available/portfolio.conf @@ -0,0 +1,163 @@ +# Personal portfolio and vanity domains (naomi.lgbt, naomi.party, nhcarrigan.com, nhcarrigan.link, resume) +# plus a wildcard catch-all that redirects *.naomi.lgbt → *.nhcarrigan.com. +server { + listen 443 ssl; + server_name naomi.lgbt; + ssl_certificate /etc/letsencrypt/live/naomi.lgbt/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/naomi.lgbt/privkey.pem; + + root /home/naomi/portfolio/site; + + location / { + index index.html; + } + + location /ads.txt { + add_header Content-Type text/plain; + return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; + } + + location /games { + try_files /games.html =404; + } + + location /koikatsu { + try_files /koikatsu.html =404; + } +} + +server { + listen 443 ssl; + server_name naomi.party; + ssl_certificate /etc/letsencrypt/live/naomi.party/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/naomi.party/privkey.pem; + + root /home/naomi/bsky; + + location / { + index index.html; + } + + location /ads.txt { + add_header Content-Type text/plain; + return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; + } +} + +server { + listen 443 ssl; + server_name nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/nhcarrigan.com/privkey.pem; + + root /home/naomi/portfolio/site; + + location /ads.txt { + add_header Content-Type text/plain; + return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; + } + + location / { + index index.html; + } + + location /games { + try_files /games.html =404; + } + + location /koikatsu { + try_files /koikatsu.html =404; + } +} + +server { + listen 443 ssl; + server_name nhcarrigan.link; + ssl_certificate /etc/letsencrypt/live/nhcarrigan.link/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/nhcarrigan.link/privkey.pem; + + root /home/naomi/link-redirector; + + location / { + index index.html; + } + + location /ads.txt { + add_header Content-Type text/plain; + return 200 "google.com, pub-3569924701890974, DIRECT, f08c47fec0942fa0"; + } +} + +server { + listen 443 ssl; + server_name resume.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/resume.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/resume.nhcarrigan.com/privkey.pem; + + root /home/naomi/resume/site; + + location /resume.yaml { + default_type text/plain; + add_header Content-Type "text/plain; charset=utf-8"; + } + + location / { + index index.html; + try_files $uri $uri/ /index.html; + } +} + +server { + listen 443 ssl; + server_name www.naomi.lgbt; + ssl_certificate /etc/letsencrypt/live/www.naomi.lgbt/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.naomi.lgbt/privkey.pem; + + root /home/naomi/portfolio/site; + + location / { + index index.html; + } + + location /games { + try_files /games.html =404; + } + + location /koikatsu { + try_files /koikatsu.html =404; + } +} + +server { + listen 443 ssl; + server_name www.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/www.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.nhcarrigan.com/privkey.pem; + + root /home/naomi/portfolio/site; + + location / { + index index.html; + } + + location /games { + try_files /games.html =404; + } + + location /koikatsu { + try_files /koikatsu.html =404; + } +} + +# Wildcard catch-all — must remain last so specific subdomains take priority +server { + listen 443 ssl; + server_name ~^(?.+)\.naomi\.lgbt$; + + ssl_certificate /etc/letsencrypt/live/*.naomi.lgbt/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/*.naomi.lgbt/privkey.pem; + + location / { + return 301 https://$subdomain.nhcarrigan.com$request_uri; + } +} diff --git a/nginx/nginx/sites-available/rosalia.conf b/nginx/nginx/sites-available/rosalia.conf new file mode 100644 index 0000000..7d397f6 --- /dev/null +++ b/nginx/nginx/sites-available/rosalia.conf @@ -0,0 +1,32 @@ +# Rosalia alerting service and legacy alerts redirect. +server { + listen 443 ssl; + server_name alerts.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/alerts.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/alerts.nhcarrigan.com/privkey.pem; + + # Redirect ONLY root `/` + location = / { + return 307 https://rosalia.nhcarrigan.com; + } + + # Proxy everything else + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5003; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name rosalia.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/rosalia.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/rosalia.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:5003; + proxy_redirect off; + } +} diff --git a/nginx/nginx/sites-available/scheduling.conf b/nginx/nginx/sites-available/scheduling.conf new file mode 100644 index 0000000..b313404 --- /dev/null +++ b/nginx/nginx/sites-available/scheduling.conf @@ -0,0 +1,29 @@ +# Scheduling shortcuts that redirect to zcal.co (cyc, meet) and tasks redirect. +server { + listen 443 ssl; + server_name cyc.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/cyc.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cyc.nhcarrigan.com/privkey.pem; + + return 301 https://zcal.co/nhcarrigan/cyc; +} + +server { + listen 443 ssl; + server_name meet.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/meet.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/meet.nhcarrigan.com/privkey.pem; + + return 301 https://zcal.co/nhcarrigan/meet; +} + +server { + listen 443 ssl; + server_name tasks.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/tasks.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/tasks.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://melody.nhcarrigan.com$uri$is_args$args; + } +} diff --git a/nginx/nginx/sites-available/security.conf b/nginx/nginx/sites-available/security.conf new file mode 100644 index 0000000..09d441c --- /dev/null +++ b/nginx/nginx/sites-available/security.conf @@ -0,0 +1,39 @@ +# Security tooling: SonarQube code quality gate and DefectDojo vulnerability management. +server { + listen 443 ssl; + server_name quality.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/quality.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/quality.nhcarrigan.com/privkey.pem; + + client_max_body_size 1g; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:9500; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name security.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/security.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/security.nhcarrigan.com/privkey.pem; + + location /report { + alias /home/naomi/defectdojo; + index report.html; + } + + location / { + proxy_pass http://127.0.0.1:43434; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + client_max_body_size 100M; + proxy_read_timeout 90; + } +} diff --git a/nginx/nginx/sites-available/support.conf b/nginx/nginx/sites-available/support.conf new file mode 100644 index 0000000..8b1f3cd --- /dev/null +++ b/nginx/nginx/sites-available/support.conf @@ -0,0 +1,47 @@ +# Discourse community support forum and legacy chat/forum redirects. +server { + listen 443 ssl; + server_name chat.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/chat.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/chat.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://discord.gg/KKe7BaEnQB; + } +} + +server { + listen 443 ssl; + server_name forum.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/forum.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/forum.nhcarrigan.com/privkey.pem; + + location / { + return 301 https://support.nhcarrigan.com; + } +} + +server { + listen 443 ssl http2; + server_name support.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/support.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/support.nhcarrigan.com/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 20M; + + location / { + proxy_pass http://localhost:32121; + + proxy_set_header Host $http_host; + proxy_http_version 1.1; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } +} diff --git a/nginx/nginx/sites-available/vitalia.conf b/nginx/nginx/sites-available/vitalia.conf new file mode 100644 index 0000000..7e47f4e --- /dev/null +++ b/nginx/nginx/sites-available/vitalia.conf @@ -0,0 +1,31 @@ +# Vitalia app: Angular front-end SPA and API backend. +server { + listen 443 ssl; + server_name vitalia-api.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/vitalia.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/vitalia.nhcarrigan.com/privkey.pem; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:12345; + proxy_redirect off; + } +} + +server { + listen 443 ssl; + server_name vitalia.nhcarrigan.com; + ssl_certificate /etc/letsencrypt/live/vitalia.nhcarrigan.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/vitalia.nhcarrigan.com/privkey.pem; + + root /home/naomi/vitalia/client/dist/client/browser; + + location / { + index index.html; + try_files $uri $uri/ /index.html; + } + + location ~* \.(js|css)$ { + try_files $uri $uri/ @rewrite; + } +} diff --git a/nginx/nginx/sites-available/wtf.conf b/nginx/nginx/sites-available/wtf.conf new file mode 100644 index 0000000..685b6fe --- /dev/null +++ b/nginx/nginx/sites-available/wtf.conf @@ -0,0 +1,17 @@ +# wtf.naomi.lgbt personal project. +server { + listen 443 ssl; + server_name wtf.naomi.lgbt; + ssl_certificate /etc/letsencrypt/live/wtf.naomi.lgbt/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/wtf.naomi.lgbt/privkey.pem; + client_max_body_size 100M; + + location / { + proxy_set_header Host $host; + proxy_pass http://127.0.0.1:3456; + proxy_redirect off; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/nginx/nginx/sites-enabled/afp.conf b/nginx/nginx/sites-enabled/afp.conf new file mode 120000 index 0000000..8f556ac --- /dev/null +++ b/nginx/nginx/sites-enabled/afp.conf @@ -0,0 +1 @@ +../sites-available/afp.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/aria.conf b/nginx/nginx/sites-enabled/aria.conf new file mode 120000 index 0000000..298f0fb --- /dev/null +++ b/nginx/nginx/sites-enabled/aria.conf @@ -0,0 +1 @@ +../sites-available/aria.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/bots.conf b/nginx/nginx/sites-enabled/bots.conf new file mode 120000 index 0000000..52a55db --- /dev/null +++ b/nginx/nginx/sites-enabled/bots.conf @@ -0,0 +1 @@ +../sites-available/bots.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/cdn.conf b/nginx/nginx/sites-enabled/cdn.conf new file mode 120000 index 0000000..eb70532 --- /dev/null +++ b/nginx/nginx/sites-enabled/cdn.conf @@ -0,0 +1 @@ +../sites-available/cdn.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/celestine.conf b/nginx/nginx/sites-enabled/celestine.conf new file mode 120000 index 0000000..e88a55b --- /dev/null +++ b/nginx/nginx/sites-enabled/celestine.conf @@ -0,0 +1 @@ +../sites-available/celestine.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/content.conf b/nginx/nginx/sites-enabled/content.conf new file mode 120000 index 0000000..e0b350e --- /dev/null +++ b/nginx/nginx/sites-enabled/content.conf @@ -0,0 +1 @@ +../sites-available/content.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/data.conf b/nginx/nginx/sites-enabled/data.conf new file mode 120000 index 0000000..aa7f98f --- /dev/null +++ b/nginx/nginx/sites-enabled/data.conf @@ -0,0 +1 @@ +../sites-available/data.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/default b/nginx/nginx/sites-enabled/default new file mode 120000 index 0000000..6d9ba33 --- /dev/null +++ b/nginx/nginx/sites-enabled/default @@ -0,0 +1 @@ +../sites-available/default \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/docs.conf b/nginx/nginx/sites-enabled/docs.conf new file mode 120000 index 0000000..d2890f7 --- /dev/null +++ b/nginx/nginx/sites-enabled/docs.conf @@ -0,0 +1 @@ +../sites-available/docs.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/eclaire.conf b/nginx/nginx/sites-enabled/eclaire.conf new file mode 120000 index 0000000..4027839 --- /dev/null +++ b/nginx/nginx/sites-enabled/eclaire.conf @@ -0,0 +1 @@ +../sites-available/eclaire.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/elowyn.conf b/nginx/nginx/sites-enabled/elowyn.conf new file mode 120000 index 0000000..55e1045 --- /dev/null +++ b/nginx/nginx/sites-enabled/elowyn.conf @@ -0,0 +1 @@ +../sites-available/elowyn.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/elysium.conf b/nginx/nginx/sites-enabled/elysium.conf new file mode 120000 index 0000000..a17f8e4 --- /dev/null +++ b/nginx/nginx/sites-enabled/elysium.conf @@ -0,0 +1 @@ +../sites-available/elysium.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/forms.conf b/nginx/nginx/sites-enabled/forms.conf new file mode 120000 index 0000000..42910d9 --- /dev/null +++ b/nginx/nginx/sites-enabled/forms.conf @@ -0,0 +1 @@ +../sites-available/forms.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/games.conf b/nginx/nginx/sites-enabled/games.conf new file mode 120000 index 0000000..d01bfa2 --- /dev/null +++ b/nginx/nginx/sites-enabled/games.conf @@ -0,0 +1 @@ +../sites-available/games.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/git.conf b/nginx/nginx/sites-enabled/git.conf new file mode 120000 index 0000000..3abc7b2 --- /dev/null +++ b/nginx/nginx/sites-enabled/git.conf @@ -0,0 +1 @@ +../sites-available/git.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/hikari.conf b/nginx/nginx/sites-enabled/hikari.conf new file mode 120000 index 0000000..780dd41 --- /dev/null +++ b/nginx/nginx/sites-enabled/hikari.conf @@ -0,0 +1 @@ +../sites-available/hikari.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/library.conf b/nginx/nginx/sites-enabled/library.conf new file mode 120000 index 0000000..6592987 --- /dev/null +++ b/nginx/nginx/sites-enabled/library.conf @@ -0,0 +1 @@ +../sites-available/library.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/lucinda.conf b/nginx/nginx/sites-enabled/lucinda.conf new file mode 120000 index 0000000..841b59d --- /dev/null +++ b/nginx/nginx/sites-enabled/lucinda.conf @@ -0,0 +1 @@ +../sites-available/lucinda.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/lynira.conf b/nginx/nginx/sites-enabled/lynira.conf new file mode 120000 index 0000000..bb535a0 --- /dev/null +++ b/nginx/nginx/sites-enabled/lynira.conf @@ -0,0 +1 @@ +../sites-available/lynira.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/mommy.conf b/nginx/nginx/sites-enabled/mommy.conf new file mode 120000 index 0000000..af528a3 --- /dev/null +++ b/nginx/nginx/sites-enabled/mommy.conf @@ -0,0 +1 @@ +../sites-available/mommy.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/monitoring.conf b/nginx/nginx/sites-enabled/monitoring.conf new file mode 120000 index 0000000..8cda051 --- /dev/null +++ b/nginx/nginx/sites-enabled/monitoring.conf @@ -0,0 +1 @@ +../sites-available/monitoring.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/nails.conf b/nginx/nginx/sites-enabled/nails.conf new file mode 120000 index 0000000..c2000b6 --- /dev/null +++ b/nginx/nginx/sites-enabled/nails.conf @@ -0,0 +1 @@ +../sites-available/nails.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/notes.conf b/nginx/nginx/sites-enabled/notes.conf new file mode 120000 index 0000000..f349177 --- /dev/null +++ b/nginx/nginx/sites-enabled/notes.conf @@ -0,0 +1 @@ +../sites-available/notes.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/portfolio.conf b/nginx/nginx/sites-enabled/portfolio.conf new file mode 120000 index 0000000..ee09510 --- /dev/null +++ b/nginx/nginx/sites-enabled/portfolio.conf @@ -0,0 +1 @@ +../sites-available/portfolio.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/rosalia.conf b/nginx/nginx/sites-enabled/rosalia.conf new file mode 120000 index 0000000..b74dc5b --- /dev/null +++ b/nginx/nginx/sites-enabled/rosalia.conf @@ -0,0 +1 @@ +../sites-available/rosalia.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/scheduling.conf b/nginx/nginx/sites-enabled/scheduling.conf new file mode 120000 index 0000000..9d38a39 --- /dev/null +++ b/nginx/nginx/sites-enabled/scheduling.conf @@ -0,0 +1 @@ +../sites-available/scheduling.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/security.conf b/nginx/nginx/sites-enabled/security.conf new file mode 120000 index 0000000..ddda831 --- /dev/null +++ b/nginx/nginx/sites-enabled/security.conf @@ -0,0 +1 @@ +../sites-available/security.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/support.conf b/nginx/nginx/sites-enabled/support.conf new file mode 120000 index 0000000..41db21b --- /dev/null +++ b/nginx/nginx/sites-enabled/support.conf @@ -0,0 +1 @@ +../sites-available/support.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/vitalia.conf b/nginx/nginx/sites-enabled/vitalia.conf new file mode 120000 index 0000000..01bf332 --- /dev/null +++ b/nginx/nginx/sites-enabled/vitalia.conf @@ -0,0 +1 @@ +../sites-available/vitalia.conf \ No newline at end of file diff --git a/nginx/nginx/sites-enabled/wtf.conf b/nginx/nginx/sites-enabled/wtf.conf new file mode 120000 index 0000000..583d565 --- /dev/null +++ b/nginx/nginx/sites-enabled/wtf.conf @@ -0,0 +1 @@ +../sites-available/wtf.conf \ No newline at end of file diff --git a/nginx/nginx/uwsgi_params b/nginx/nginx/uwsgi_params new file mode 100644 index 0000000..09c732c --- /dev/null +++ b/nginx/nginx/uwsgi_params @@ -0,0 +1,17 @@ + +uwsgi_param QUERY_STRING $query_string; +uwsgi_param REQUEST_METHOD $request_method; +uwsgi_param CONTENT_TYPE $content_type; +uwsgi_param CONTENT_LENGTH $content_length; + +uwsgi_param REQUEST_URI $request_uri; +uwsgi_param PATH_INFO $document_uri; +uwsgi_param DOCUMENT_ROOT $document_root; +uwsgi_param SERVER_PROTOCOL $server_protocol; +uwsgi_param REQUEST_SCHEME $scheme; +uwsgi_param HTTPS $https if_not_empty; + +uwsgi_param REMOTE_ADDR $remote_addr; +uwsgi_param REMOTE_PORT $remote_port; +uwsgi_param SERVER_PORT $server_port; +uwsgi_param SERVER_NAME $server_name; diff --git a/nginx/nginx/win-utf b/nginx/nginx/win-utf new file mode 100644 index 0000000..774fd9f --- /dev/null +++ b/nginx/nginx/win-utf @@ -0,0 +1,125 @@ +# This map is not a full windows-1251 <> utf8 map: it does not +# contain Serbian and Macedonian letters. If you need a full map, +# use contrib/unicode2nginx/win-utf map instead. + +charset_map windows-1251 utf-8 { + + 82 E2809A; # single low-9 quotation mark + + 84 E2809E; # double low-9 quotation mark + 85 E280A6; # ellipsis + 86 E280A0; # dagger + 87 E280A1; # double dagger + 88 E282AC; # euro + 89 E280B0; # per mille + + 91 E28098; # left single quotation mark + 92 E28099; # right single quotation mark + 93 E2809C; # left double quotation mark + 94 E2809D; # right double quotation mark + 95 E280A2; # bullet + 96 E28093; # en dash + 97 E28094; # em dash + + 99 E284A2; # trade mark sign + + A0 C2A0; #   + A1 D18E; # capital Byelorussian short U + A2 D19E; # small Byelorussian short u + + A4 C2A4; # currency sign + A5 D290; # capital Ukrainian soft G + A6 C2A6; # borken bar + A7 C2A7; # section sign + A8 D081; # capital YO + A9 C2A9; # (C) + AA D084; # capital Ukrainian YE + AB C2AB; # left-pointing double angle quotation mark + AC C2AC; # not sign + AD C2AD; # soft hypen + AE C2AE; # (R) + AF D087; # capital Ukrainian YI + + B0 C2B0; # ° + B1 C2B1; # plus-minus sign + B2 D086; # capital Ukrainian I + B3 D196; # small Ukrainian i + B4 D291; # small Ukrainian soft g + B5 C2B5; # micro sign + B6 C2B6; # pilcrow sign + B7 C2B7; # · + B8 D191; # small yo + B9 E28496; # numero sign + BA D194; # small Ukrainian ye + BB C2BB; # right-pointing double angle quotation mark + + BF D197; # small Ukrainian yi + + C0 D090; # capital A + C1 D091; # capital B + C2 D092; # capital V + C3 D093; # capital G + C4 D094; # capital D + C5 D095; # capital YE + C6 D096; # capital ZH + C7 D097; # capital Z + C8 D098; # capital I + C9 D099; # capital J + CA D09A; # capital K + CB D09B; # capital L + CC D09C; # capital M + CD D09D; # capital N + CE D09E; # capital O + CF D09F; # capital P + + D0 D0A0; # capital R + D1 D0A1; # capital S + D2 D0A2; # capital T + D3 D0A3; # capital U + D4 D0A4; # capital F + D5 D0A5; # capital KH + D6 D0A6; # capital TS + D7 D0A7; # capital CH + D8 D0A8; # capital SH + D9 D0A9; # capital SHCH + DA D0AA; # capital hard sign + DB D0AB; # capital Y + DC D0AC; # capital soft sign + DD D0AD; # capital E + DE D0AE; # capital YU + DF D0AF; # capital YA + + E0 D0B0; # small a + E1 D0B1; # small b + E2 D0B2; # small v + E3 D0B3; # small g + E4 D0B4; # small d + E5 D0B5; # small ye + E6 D0B6; # small zh + E7 D0B7; # small z + E8 D0B8; # small i + E9 D0B9; # small j + EA D0BA; # small k + EB D0BB; # small l + EC D0BC; # small m + ED D0BD; # small n + EE D0BE; # small o + EF D0BF; # small p + + F0 D180; # small r + F1 D181; # small s + F2 D182; # small t + F3 D183; # small u + F4 D184; # small f + F5 D185; # small kh + F6 D186; # small ts + F7 D187; # small ch + F8 D188; # small sh + F9 D189; # small shch + FA D18A; # small hard sign + FB D18B; # small y + FC D18C; # small soft sign + FD D18D; # small e + FE D18E; # small yu + FF D18F; # small ya +} diff --git a/pull.sh b/pull.sh index 91cf904..c3eacab 100755 --- a/pull.sh +++ b/pull.sh @@ -1,7 +1,3 @@ -servers=("prod" "gitea") - -for server in "${servers[@]}" -do - echo "Pulling $server" - rsync --archive --verbose $server:/etc/nginx/conf.d/server.conf configs/$server.conf -done +echo "Pulling prod nginx" +rsync --archive --verbose prod:/etc/nginx nginx +echo "All done!" \ No newline at end of file diff --git a/push.sh b/push.sh new file mode 100755 index 0000000..910c450 --- /dev/null +++ b/push.sh @@ -0,0 +1,3 @@ +echo "Pushing nginx to prod" +rsync --archive --verbose --delete --rsync-path="sudo rsync" nginx/nginx/ prod:/etc/nginx +echo "All done!" diff --git a/test.sh b/test.sh index a9b991d..5bbbfbb 100755 --- a/test.sh +++ b/test.sh @@ -1,24 +1,260 @@ #!/bin/bash -CONF="configs/prod.conf" +# Nginx configuration static analysis test suite. +# Usage: bash test.sh [nginx-dir] +# Defaults to nginx/nginx relative to the repo root. -# Extract server_name values in order, ignoring commented lines -mapfile -t domains < <(grep -oP '^\s*server_name\s+\K[^;]+' "$CONF") +NGINX_DIR="${1:-nginx/nginx}" +PASS=0 +FAIL=0 -sorted=($(printf "%s\n" "${domains[@]}" | sort)) +pass() { + printf " PASS: %s\n" "$1" + ((PASS++)) +} -# Print the sorted list for debugging -echo "Auditing servers:" -printf "%s " "${sorted[@]}" +fail() { + printf " FAIL: %s\n" "$1" + ((FAIL++)) +} + +echo "=== nginx config static analysis ===" +echo "Directory: $NGINX_DIR" echo "" -for i in "${!domains[@]}"; do - if [[ "${domains[$i]}" != "${sorted[$i]}" ]]; then - echo "Domain list is not sorted alphabetically." - echo "First out-of-order entry: '${domains[$i]}' (should be '${sorted[$i]}')" - exit 1 +# ────────────────────────────────────────────────────────────────── +# 1. No deprecated TLS versions +# ────────────────────────────────────────────────────────────────── +echo "--- TLS version check ---" +deprecated=$(grep -rnP 'TLSv1(?!\.[23])' "$NGINX_DIR" --include="*.conf" 2>/dev/null || true) +if [ -n "$deprecated" ]; then + fail "Deprecated TLS versions (TLSv1 or TLSv1.1) found:" + printf '%s\n' "$deprecated" | sed 's/^/ /' +else + pass "No deprecated TLS versions" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 2. No duplicate literal server_name values across all site configs +# ────────────────────────────────────────────────────────────────── +echo "--- Duplicate server_name check ---" +duplicates=$(grep -rh --include="*.conf" 'server_name' "$NGINX_DIR/sites-available/" \ + | grep -v '^\s*#' \ + | sed 's/.*server_name\s*//' \ + | sed 's/\s*;//' \ + | tr ' ' '\n' \ + | grep -vP '^\s*$|^_$|^~|^\*\.' \ + | sort | uniq -d) +if [ -n "$duplicates" ]; then + fail "Duplicate server_name values:" + printf '%s\n' "$duplicates" | sed 's/^/ /' +else + pass "No duplicate server_name values" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 3. Every sites-available/*.conf has a sites-enabled symlink +# ────────────────────────────────────────────────────────────────── +echo "--- sites-enabled coverage check ---" +missing_links=0 +for conf in "$NGINX_DIR/sites-available/"*.conf; do + name=$(basename "$conf") + if [ ! -L "$NGINX_DIR/sites-enabled/$name" ]; then + fail "No sites-enabled symlink for: $name" + missing_links=1 fi done +[ "$missing_links" -eq 0 ] && pass "All sites-available configs have sites-enabled symlinks" +echo "" -echo "All server_name entries are sorted alphabetically." -exit 0 \ No newline at end of file +# ────────────────────────────────────────────────────────────────── +# 4. No broken symlinks in sites-enabled +# ────────────────────────────────────────────────────────────────── +echo "--- Broken symlink check ---" +broken=0 +for link in "$NGINX_DIR/sites-enabled/"*; do + [ -L "$link" ] || continue + if [ ! -e "$link" ]; then + fail "Broken symlink: $(basename "$link")" + broken=1 + fi +done +[ "$broken" -eq 0 ] && pass "No broken symlinks in sites-enabled" +echo "" + +# ────────────────────────────────────────────────────────────────── +# 5. No orphaned sites-enabled symlinks (no matching sites-available file) +# ────────────────────────────────────────────────────────────────── +echo "--- Orphaned symlink check ---" +orphaned=0 +for link in "$NGINX_DIR/sites-enabled/"*.conf; do + [ -L "$link" ] || continue + name=$(basename "$link") + if [ ! -f "$NGINX_DIR/sites-available/$name" ]; then + fail "Orphaned sites-enabled symlink: $name" + orphaned=1 + fi +done +[ "$orphaned" -eq 0 ] && pass "No orphaned sites-enabled symlinks" +echo "" + +# ────────────────────────────────────────────────────────────────── +# 6. No port-80 listeners in any custom server block +# (port 80 is blocked at the firewall; all traffic is HTTPS only) +# ────────────────────────────────────────────────────────────────── +echo "--- Port 80 listener check ---" +http_blocks=$(grep -rnP 'listen\s.*\b80\b' "$NGINX_DIR/sites-available/" \ + | grep -v 'sites-available/default' \ + | grep -v '^\s*#' || true) +if [ -n "$http_blocks" ]; then + fail "Port 80 listeners found in custom site configs:" + printf '%s\n' "$http_blocks" | sed 's/^/ /' +else + pass "No port 80 listeners in custom server blocks" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 7. ssl_certificate and ssl_certificate_key counts match per file +# ────────────────────────────────────────────────────────────────── +echo "--- SSL certificate directive pairing check ---" +ssl_errors=0 +for conf in "$NGINX_DIR/sites-available/"*.conf; do + certs=$(grep -cP 'ssl_certificate\b(?!_key)' "$conf" 2>/dev/null || echo 0) + keys=$(grep -c 'ssl_certificate_key' "$conf" 2>/dev/null || echo 0) + if [ "$certs" != "$keys" ]; then + fail "$(basename "$conf"): $certs ssl_certificate vs $keys ssl_certificate_key (must match)" + ssl_errors=1 + fi +done +[ "$ssl_errors" -eq 0 ] && pass "All ssl_certificate directives are correctly paired" +echo "" + +# ────────────────────────────────────────────────────────────────── +# 8. All plain-HTTP proxy_pass targets are local +# (https:// proxy_pass is permitted for intentional external proxying, +# e.g. CDN reverse-proxying to object storage over TLS) +# ────────────────────────────────────────────────────────────────── +echo "--- proxy_pass locality check ---" +external=$(grep -rn 'proxy_pass\s\+http://' "$NGINX_DIR/sites-available/" \ + | grep -v '#' \ + | grep -vP 'proxy_pass\s+http://(127\.0\.0\.1|localhost|0\.0\.0\.0)' || true) +if [ -n "$external" ]; then + fail "Plain-HTTP proxy_pass to non-local target found:" + printf '%s\n' "$external" | sed 's/^/ /' +else + pass "All plain-HTTP proxy_pass targets are local" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 9. All SSL cert paths use /etc/letsencrypt/live/ +# ────────────────────────────────────────────────────────────────── +echo "--- SSL certificate path convention check ---" +nonstandard_certs=$(grep -rn 'ssl_certificate' "$NGINX_DIR/sites-available/" \ + | grep -v '#' \ + | grep -vP '/etc/letsencrypt/live/' || true) +if [ -n "$nonstandard_certs" ]; then + fail "SSL certs not under /etc/letsencrypt/live/:" + printf '%s\n' "$nonstandard_certs" | sed 's/^/ /' +else + pass "All SSL certificate paths use /etc/letsencrypt/live/" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 10. ssl_certificate uses fullchain.pem, ssl_certificate_key uses privkey.pem +# ────────────────────────────────────────────────────────────────── +echo "--- SSL certificate filename convention check ---" +cert_name_errors=0 +wrong_certs=$(grep -rnP 'ssl_certificate\b(?!_key)' "$NGINX_DIR/sites-available/" \ + | grep -v '#' \ + | grep -v 'fullchain\.pem' || true) +wrong_keys=$(grep -rn 'ssl_certificate_key' "$NGINX_DIR/sites-available/" \ + | grep -v '#' \ + | grep -v 'privkey\.pem' || true) +if [ -n "$wrong_certs" ]; then + fail "ssl_certificate not using fullchain.pem:" + printf '%s\n' "$wrong_certs" | sed 's/^/ /' + cert_name_errors=1 +fi +if [ -n "$wrong_keys" ]; then + fail "ssl_certificate_key not using privkey.pem:" + printf '%s\n' "$wrong_keys" | sed 's/^/ /' + cert_name_errors=1 +fi +[ "$cert_name_errors" -eq 0 ] && pass "All SSL certs use fullchain.pem / privkey.pem" +echo "" + +# ────────────────────────────────────────────────────────────────── +# 11. No server_name directives use raw IP addresses +# ────────────────────────────────────────────────────────────────── +echo "--- IP address as server_name check ---" +ip_names=$(grep -rh --include="*.conf" 'server_name' "$NGINX_DIR/sites-available/" \ + | grep -v '#' \ + | sed 's/.*server_name\s*//' \ + | sed 's/\s*;//' \ + | tr ' ' '\n' \ + | grep -P '^\d{1,3}(\.\d{1,3}){3}$' || true) +if [ -n "$ip_names" ]; then + fail "server_name uses raw IP addresses:" + printf '%s\n' "$ip_names" | sed 's/^/ /' +else + pass "No server_name directives use raw IP addresses" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 12. No conf.d files conflict with built-in nginx conf.d conventions +# (i.e. no stray default.conf or catch-all templates left over) +# ────────────────────────────────────────────────────────────────── +echo "--- conf.d stray file check ---" +stray=$(find "$NGINX_DIR/conf.d" -name "*.conf" \ + | grep -vP '/(logging|tuning|cloudflare_ips)\.conf$' || true) +if [ -n "$stray" ]; then + fail "Unexpected files in conf.d (only logging.conf, tuning.conf, cloudflare_ips.conf expected):" + printf '%s\n' "$stray" | sed 's/^/ /' +else + pass "conf.d contains only expected files" +fi +echo "" + +# ────────────────────────────────────────────────────────────────── +# 13. Server blocks within each sites-available file are sorted +# alphabetically by server_name (LC_ALL=C; regex/wildcard excluded) +# ────────────────────────────────────────────────────────────────── +echo "--- Alphabetical server_name order check ---" +sort_errors=0 +for conf in "$NGINX_DIR/sites-available/"*.conf; do + [ "$(basename "$conf")" = "default" ] && continue + + mapfile -t actual < <(grep -P '^\s*server_name\s' "$conf" \ + | grep -v '^\s*#' \ + | sed 's/.*server_name\s*//' \ + | sed 's/\s*;//' \ + | awk '{print $1}' \ + | grep -vP '^~|^\*\.|^_$') + + mapfile -t expected < <(printf '%s\n' "${actual[@]}" | LC_ALL=C sort) + + for ((i = 0; i < ${#actual[@]}; i++)); do + if [ "${actual[$i]}" != "${expected[$i]}" ]; then + fail "$(basename "$conf"): not sorted — found '${actual[$i]}', expected '${expected[$i]}'" + sort_errors=1 + break + fi + done +done +[ "$sort_errors" -eq 0 ] && pass "All sites-available files have alphabetically sorted server blocks" +echo "" + +# ────────────────────────────────────────────────────────────────── +# Summary +# ────────────────────────────────────────────────────────────────── +echo "===================================" +printf "Results: %d passed, %d failed\n" "$PASS" "$FAIL" +echo "===================================" +[ "$FAIL" -gt 0 ] && exit 1 +exit 0