diff --git a/deploy.sh b/deploy.sh index b2d4dc7..e8a5a68 100755 --- a/deploy.sh +++ b/deploy.sh @@ -37,11 +37,8 @@ case $ENV in # Set proper ownership sudo chown -R nginx:nginx ${STAGING_PATH}/ - - # Copy nginx config - sudo cp -t /etc/nixos/ staging.nginx.nix - - printf "✓ Staging deployment complete!\n Files deployed to: %s\n Nginx config: /etc/nixos/staging.nginx.nix\n\nTo activate, update your NixOS configuration to import staging.nginx.nix\nand run: sudo nixos-rebuild switch\n" "${STAGING_PATH}" + + printf "✓ Staging deployment complete!\n Files deployed to: %s\n\nTo activate nginx, import staging.nginx.nix into your local NixOS config\nand run: sudo nixos-rebuild switch\n" "${STAGING_PATH}" ;; prod) @@ -51,7 +48,6 @@ case $ENV in REMOTE_HOST="crossbox" REMOTE_USER="m3b" REMOTE_PATH="/srv/www/binning.net" - REMOTE_NIXOS="/etc/nixos/" # Check if SSH key is set up if ! ssh -o BatchMode=yes -o ConnectTimeout=5 ${REMOTE_USER}@${REMOTE_HOST} exit 2>/dev/null; then @@ -67,17 +63,8 @@ case $ENV in ssh ${REMOTE_HOST} "sudo rsync -avz --delete /tmp/${REMOTE_PATH}/ ${REMOTE_PATH} && \ sudo chown -R nginx:nginx ${REMOTE_PATH}/ && \ printf 'Content deployed.\n'" - - # Deploy nginx configuration - printf "Deploying nginx configuration...\n" - scp prod.nginx.nix ${REMOTE_HOST}:/tmp/nginx.nix - - # Set proper permissions and move config on remote server - ssh ${REMOTE_HOST} "sudo mv /tmp/nginx.nix ${REMOTE_NIXOS}nginx.nix && \ - sudo chown -R nginx:nginx ${REMOTE_PATH}/ && \ - printf 'Configuration deployed. Run sudo nixos-rebuild switch to activate.\n'" - - printf "✓ Production deployment complete!\n\nSSH into %s and run: sudo nixos-rebuild switch\n" "${REMOTE_HOST}" + + printf "✓ Production deployment complete!\n\nNginx configuration is managed by the nixos-config flake (hosts/crossbox/nginx.nix).\n" "${REMOTE_HOST}" ;; *) diff --git a/prod.nginx.nix b/prod.nginx.nix deleted file mode 100644 index d3f84ff..0000000 --- a/prod.nginx.nix +++ /dev/null @@ -1,151 +0,0 @@ -{ config, pkgs, lib, ... }: - -let - # Read multiple API keys from the secrets file at build time - # Note: This embeds the secrets in the Nix store, which is a trade-off - # Alternative: Keep secrets file and read via njs module or external auth service - secretsFile = "/srv/nginx/secrets"; - - # Read API keys from file (one key per line, will be evaluated at build time) - # If the file doesn't exist yet, this will fail - create it first - apiKeysRaw = builtins.readFile secretsFile; - apiKeys = lib.filter (k: k != "") (lib.splitString "\n" apiKeysRaw); - - # Generate map entries for each key - mapEntries = lib.concatMapStringsSep "\n " - (key: ''"Bearer ${key}" "authorized";'') - apiKeys; - -in -{ - services.nginx = { - enable = true; - - # Recommended settings - recommendedGzipSettings = true; - recommendedOptimisation = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - - # Increase bucket size for long Bearer tokens - mapHashBucketSize = 128; - - # Map directive to check Authorization header against multiple keys - appendHttpConfig = '' - # Check if the Authorization header matches any expected value - map $http_authorization $auth_status { - default "unauthorized"; - "" "no_auth"; - ${mapEntries} - } - ''; - - # Virtual hosts configuration - virtualHosts = { - - # Main website - Static HTML/CSS - "www.binning.net" = { - enableACME = true; - forceSSL = true; - - root = "/srv/www/binning.net"; - - locations."/" = { - index = "index.html"; - tryFiles = "$uri $uri/ =404"; - extraConfig = '' - # Enable Server Side Includes for navbar/footer includes - ssi on; - ''; - }; - - # Private blog articles with HTTP basic authentication - locations."/blog/private/" = { - extraConfig = '' - auth_basic "Private Articles"; - auth_basic_user_file /srv/nginx/.htpasswd; - - # Enable Server Side Includes - ssi on; - ''; - }; - - # Optional: Custom 404 page - extraConfig = '' - error_page 404 /404.html; - ''; - }; - - # Ollama with Bearer token authentication - "ollama.binning.net" = { - enableACME = true; - forceSSL = true; - - locations."/" = { - extraConfig = '' - # Check auth status - if ($auth_status = "no_auth") { - return 401 "Unauthorized: Bearer token required\n"; - } - if ($auth_status = "unauthorized") { - return 403 "Forbidden: Invalid API key\n"; - } - - # Proxy to Ollama (only if authorized) - proxy_pass http://localhost:11434; - 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; - - # Timeouts for long-running requests - proxy_read_timeout 300s; - proxy_connect_timeout 300s; - proxy_send_timeout 300s; - - # Allow large request bodies - client_max_body_size 100M; - - # Logging - access_log /var/log/nginx/ollama_access.log; - error_log /var/log/nginx/ollama_error.log; - ''; - }; - }; - - # Forgejo - "forgejo.binning.net" = { - enableACME = true; - forceSSL = true; - - locations."/" = { - proxyPass = "http://127.0.0.1:3000"; - # No extraConfig needed - recommendedProxySettings handles headers - }; - }; - - # Radicale - "radicale.binning.net" = { - enableACME = true; - forceSSL = true; - - locations."/" = { - proxyPass = "http://127.0.0.1:5232"; - # recommendedProxySettings handles most headers - extraConfig = '' - proxy_set_header X-Script-Name ""; - ''; - }; - }; - }; - }; - - # Firewall - networking.firewall.allowedTCPPorts = [ 80 443 ]; - - # ACME/Let's Encrypt - security.acme = { - acceptTerms = true; - defaults.email = "hvanb@pm.me"; - }; -}