nginx — serve a subdomain from /var/www
Source: wiki.r-that.com nginx config — feat-wiki-deploy-001 Category: Snippet — nginx
nginx subdomain static site — one server block that serves a static build directory on a dedicated subdomain. Handles SPA-like URL patterns (/components/btn-icon/ → /components/btn-icon/index.html) and aggressively caches hashed asset directories.
What it is
Section titled “What it is”A single nginx site config that:
- Listens on port 80 for the subdomain
- Serves from
/var/www/<site> - Resolves clean URLs to
index.htmlfiles inside directories - Caches
/_astro/(or/assets/) with 1-year immutable headers - Returns 404 from a branded page if you have one, or nginx default
No TLS — Cloudflare handles it (see the Flexible SSL pattern when origin is HTTP-only).
Config
Section titled “Config”/etc/nginx/sites-available/<site>.com:
server { listen 80; listen [::]:80; server_name wiki.r-that.com;
root /var/www/wiki; index index.html;
# Clean-URL routing: /foo/bar → /foo/bar/index.html → 404 location / { try_files $uri $uri/ $uri/index.html =404; }
# Astro emits hashed filenames into /_astro/ — cache them forever location /_astro/ { expires 1y; add_header Cache-Control "public, immutable"; }}Enable it:
sudo ln -sf /etc/nginx/sites-available/wiki.r-that.com \ /etc/nginx/sites-enabled/wiki.r-that.comsudo nginx -t # validatesudo systemctl reload nginx # applyCoexistence with an existing site
Section titled “Coexistence with an existing site”If the same server_name context already has a root-domain proxy block (e.g. r-that.com -> localhost:3000), just add this subdomain block next to it in the same file or a sibling file. nginx matches by server_name; distinct subdomains get distinct blocks.
# Root domain — proxy to a Node serverserver { listen 80; server_name r-that.com www.r-that.com; location / { proxy_pass http://127.0.0.1:3000; ... }}
# Subdomain — static files (this snippet)server { listen 80; server_name wiki.r-that.com; root /var/www/wiki; # ...}How it’s used
Section titled “How it’s used”- wiki.r-that.com — serves the Astro build of
r-that-wiki - Pattern generalizes to any static-site-on-a-subdomain use case where you already have nginx running
Gotchas
Section titled “Gotchas”try_filesorder matters.$uribefore$uri/means files win over directories; handy if you have a file and a directory with the same name./_astro/is Astro-specific. For other build tools, swap the path: Vite emits/assets/, Next.js emits/_next/static/, etc.Cache-Control: immutableis only safe if filenames genuinely change when content changes. Astro, Vite, Next all do content-hashed filenames by default — don’t add immutable caching to a path that reuses filenames (e.g./images/).server_namecollisions between enabled site files cause nginx to pick one (usually the first-loaded) and warn at startup. One site = one server_name set.- Remove the default site. Fresh nginx installs enable
/etc/nginx/sites-enabled/defaultwhich catches everything. Delete the symlink to avoid accidental routing:sudo rm /etc/nginx/sites-enabled/default. - Permissions.
nginx(the user) needs read on/var/www/<site>and execute on every ancestor directory.chown -R www-data:www-data /var/www/<site>covers most cases. - Deploying updates. Swap
dist/atomically withrsync -a --delete. Don’t delete then copy — even a short empty window will serve 404s.
See also
Section titled “See also”- projects/cairn — where this subdomain lives next to the portfolio proxy
- snippets/systemd-drop-in-env-var — sibling infra snippet