Files
hsjobeki 9c8e19cf58
buildbot/nix-eval Build done.
buildbot/nix-build Build done.
gitea-mq Already up to date with target branch
web01/nginx: forward to 26.05 by default
2026-06-23 10:10:32 +02:00

211 lines
8.1 KiB
Nix

{ config, pkgs, ... }:
{
# www user to push website artifacts via ssh
users.users.www = {
openssh.authorizedKeys.keys = config.users.users.root.openssh.authorizedKeys.keys ++ [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICyHjnmRUbCw8EP350+4K0KOHPiTzTpTBrOQUzNINOrx gitea-ci"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOGmAw62wkSAvzAKwZn3xFvCj+jUkOgp2arABA6PEbc8 clan-www2" # key for git.clan.lol/clan/data-mesher gitea-ci
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKHHl5kgMDNQA/zqK+AzT4SO09rfAp+y/EeUC+Ow5XqyNid5lm6sgLGM+AqZDx0jOrMKWhd5lhzGDdtsSf0Y8g4= brian@saturn"
];
isSystemUser = true;
shell = pkgs.bash;
group = "www";
};
users.groups.www = { };
# ensure /var/www can be accessed by nginx and www user
systemd.tmpfiles.rules = [
"d /var/www 0755 www nginx"
"d /var/www/static.clan.lol 0755 www nginx"
"d /var/www/vpnbench 0755 www nginx"
"d /var/www/versioned-docs 0755 www nginx"
];
services.nginx = {
virtualHosts."clan.lol" = {
forceSSL = true;
enableACME = true;
# to be deployed via rsync
root = "/var/www/clan.lol";
extraConfig = ''
charset utf-8;
source_charset utf-8;
'';
locations."/".extraConfig = ''
set $cors "false";
# Allow cross-origin requests from localhost IPs with port 8000
if ($http_origin = "http://localhost:8000") {
set $cors "true";
}
if ($http_origin = "http://127.0.0.1:8000") {
set $cors "true";
}
if ($http_origin = "http://[::1]:8000") {
set $cors "true";
}
if ($cors = "true") {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
}
if ($cors = "true") {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
}
'';
# Versioned docs: /docs/<VERSION>/* serves from /var/www/versioned-docs/<VERSION>/docs/<VERSION>/*
# Each release branch deploys via rsync into /var/www/versioned-docs/<VERSION>/
# Assets are referenced as absolute paths /_assets/<VERSION>/... and /_app/...
# Redirect to latest version
locations."= /docs".return = "301 /docs/26.05";
locations."= /docs/".return = "301 /docs/25.05";
locations."^~ /docs/main".extraConfig = ''
rewrite ^/docs/main(.*)$ /docs/unstable$1 permanent;
'';
# Served same-origin from a file the docs deploy writes, so the version
# switcher has no cross-service dependency on git.clan.lol / Anubis.
locations."= /docs/versions" = {
alias = "/var/www/versioned-docs/versions";
extraConfig = ''
default_type text/plain;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
'';
};
# Serve versioned docs from /var/www/versioned-docs/<VERSION>/
# URL: /docs/<VERSION>/path → /var/www/versioned-docs/<VERSION>/docs/<VERSION>/path
# URL: /_assets/<VERSION>/path → /var/www/versioned-docs/<VERSION>/_assets/<VERSION>/path
#
# The entire versioned site tree lives under /var/www/versioned-docs/<VERSION>/
# so we set root to that and rewrite to the internal path.
# We use an internal named location for .html fallback.
locations."~ ^/(docs|_assets)/(?<version>[^/]+)(?<vpath>/.*)?$".extraConfig = ''
root /var/www/versioned-docs/$version;
set $section $1;
# Redirect trailing slash to non-trailing slash for clean URLs
# (except for bare /docs/<version>/ which is fine)
rewrite ^(.+)/$ $1 permanent;
# try_files paths are relative to root
# e.g. for /docs/unstable/getting-started with root=/var/www/versioned-docs/unstable
# tries: /docs/unstable/getting-started, /docs/unstable/getting-started.html, /docs/unstable/getting-started/index.html
try_files /$section/$version$vpath /$section/$version''${vpath}.html /$section/$version$vpath/index.html @fallback;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
'';
locations."@fallback".extraConfig = ''
# If we had a subpath (e.g. /docs/unstable/nonexistent), redirect to version root
# If already at version root (e.g. /docs/99.99), redirect to /docs
if ($vpath = "") {
return 302 /docs;
}
return 302 /docs/$version;
'';
locations."/wclan".return = "307 https://clan.lol/";
locations."/what-is-clan".return = "307 https://clan.lol";
locations."/thaigersprint".return = "307 https://pad.lassul.us/s/clan-thaigersprint";
locations."/blog/hello-world/".return = "307 https://clan.lol/blog/introduction-clan/";
# unstable is a special case that maps to the main branch.
locations."= /install/unstable".return =
"301 https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
# All other versions pass through, assuming the archive exists.
locations."~ ^/install/(?<version>[A-Za-z0-9._-]+)$".return =
"301 https://git.clan.lol/clan/clan-core/archive/$version.tar.gz";
};
virtualHosts."data-mesher.docs.clan.lol" = {
forceSSL = true;
enableACME = true;
# to be deployed via rsync
root = "/var/www/data-mesher.docs.clan.lol";
extraConfig = ''
charset utf-8;
source_charset utf-8;
'';
# Make sure to expire the cache after 12 hour
locations."/".extraConfig = ''
add_header Cache-Control "public, max-age=43200";
'';
};
virtualHosts."docs.clan.lol" = {
forceSSL = true;
enableACME = true;
locations."/blog/2024/03/19/introducing-clan-full-stack-computing-redefined/".return =
"301 https://clan.lol/blog/introduction-clan/";
locations."/blog/2024/05/25/jsonschema-converter/".return =
"301 https://clan.lol/blog/json-schema-converter/";
locations."/blog/2024/06/24/backups/".return =
"301 https://clan.lol/blog/declarative-backups-and-restore/";
locations."/blog/2024/07/19/nixos-facter/".return = "301 https://clan.lol/blog/nixos-facter/";
locations."/blog/2024/09/11/interfaces/".return = "301 https://clan.lol/blog/interfaces/";
locations."^~ /blog".return = "301 https://clan.lol/blog";
# Old docs.clan.lol used /<version>/... paths (no /docs/ prefix)
locations."^~ /main/".extraConfig = ''
rewrite ^/main/(.*)$ https://clan.lol/docs/unstable/$1 permanent;
'';
locations."= /main".return = "301 https://clan.lol/docs/unstable";
locations."/".extraConfig = ''
rewrite ^/([0-9]+\.[0-9]+)/(.*)$ https://clan.lol/docs/$1/$2 permanent;
rewrite ^/([0-9]+\.[0-9]+)/?$ https://clan.lol/docs/$1 permanent;
return 301 https://clan.lol/docs;
'';
};
virtualHosts."www.clan.lol" = {
forceSSL = true;
enableACME = true;
globalRedirect = "clan.lol";
};
virtualHosts."static.clan.lol" = {
forceSSL = true;
enableACME = true;
root = "/var/www/static.clan.lol";
extraConfig = ''
charset utf-8;
source_charset utf-8;
autoindex off;
'';
# Cache static files for 1 week
locations."/".extraConfig = ''
add_header Cache-Control "public, max-age=604800, immutable";
add_header Access-Control-Allow-Origin "https://clan.lol" always;
'';
};
virtualHosts."blog.clan.lol" = {
forceSSL = true;
enableACME = true;
globalRedirect = "clan.lol/blog";
};
virtualHosts."vpnbench.clan.lol" = {
forceSSL = true;
enableACME = true;
root = "/var/www/vpnbench";
extraConfig = ''
charset utf-8;
source_charset utf-8;
'';
locations."/".extraConfig = ''
try_files $uri $uri/ /index.html;
'';
};
};
}