From 78e428f3f3c21bfe5d1e41c71024492ae9b5b6a9 Mon Sep 17 00:00:00 2001 From: Dennis Wuitz Date: Wed, 27 Dec 2023 10:03:13 +0100 Subject: [PATCH] reconfigure photon --- .sops.yaml | 2 +- flake.nix | 130 ++++++++-------- modules/backup.nix | 16 +- modules/website.nix | 192 ++++++++++++++++++++++++ systems/configuration.nix | 24 ++- systems/palatine-hill/configuration.nix | 4 +- systems/programs.nix | 2 +- users/alice/default.nix | 2 +- users/alice/secrets.yaml | 52 +++---- users/default.nix | 16 +- 10 files changed, 325 insertions(+), 115 deletions(-) create mode 100644 modules/website.nix diff --git a/.sops.yaml b/.sops.yaml index 9fdee2c..bcf6d12 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -6,7 +6,7 @@ keys: # Generate AGE keys from SSH keys with: # nix-shell -p ssh-to-age --run 'ssh some.ssh.wavelens.io cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age' - &palatine-hill age1z8q02wdp0a2ep5uuffgfeqlfam4ztl95frhw5qhnn6knn0rrmcnqk5evej - - &photon age1rjlc6vwnz2lcrpshtd9rldlxels6l2utwmnmf3prus8drfefeywq5ljrdg + - &photon age13aqs2mx66dmnyd74sygnwavufv6a4pwnvcqj4ud4l94jk0tjgu6ss57slw # update keys by executing: sops updatekeys secrets.yaml creation_rules: diff --git a/flake.nix b/flake.nix index 1d24cf1..671b182 100644 --- a/flake.nix +++ b/flake.nix @@ -25,70 +25,78 @@ }; outputs = { nixpkgs, nixos-hardware, nixos-modules, home-manager, sops-nix, ... }: - let - inherit (nixpkgs) lib; - src = builtins.filterSource (path: type: type == "directory" || lib.hasSuffix ".nix" (baseNameOf path)) ./.; - ls = dir: lib.attrNames (builtins.readDir (src + "/${dir}")); - fileList = dir: map (file: ./. + "/${dir}/${file}") (ls dir); - in { - nixosConfigurations = let - constructSystem = { - hostname, - system ? "x86_64-linux", - modules ? [], - users ? ["dennis"], - }: lib.nixosSystem { - inherit system; + let + inherit (nixpkgs) lib; + src = builtins.filterSource (path: type: type == "directory" || lib.hasSuffix ".nix" (baseNameOf path)) ./.; + ls = dir: lib.attrNames (builtins.readDir (src + "/${dir}")); + fileList = dir: map (file: ./. + "/${dir}/${file}") (ls dir); + in + { + nixosConfigurations = + let + constructSystem = + { hostname + , system ? "x86_64-linux" + , modules ? [ ] + , users ? [ "dennis" ] + , + }: lib.nixosSystem { + inherit system; - modules = [ - nixos-modules.nixosModule - home-manager.nixosModules.home-manager - sops-nix.nixosModules.sops - ./systems/programs.nix - ./systems/configuration.nix - ./systems/${hostname}/hardware.nix - ./systems/${hostname}/configuration.nix - { config.networking.hostName = "${hostname}"; } - ] ++ modules ++ fileList "modules" - ++ map(user: { config, lib, pkgs, ... }@args: { - users.users.${user} = import ./users/${user} (args // { name = "${user}"; }); - boot.initrd.network.ssh.authorizedKeys = config.users.users.${user}.openssh.authorizedKeys.keys; - sops = { - secrets."${user}/user-password" = { - sopsFile = ./users/${user}/secrets.yaml; - neededForUsers = true; + modules = [ + nixos-modules.nixosModule + home-manager.nixosModules.home-manager + sops-nix.nixosModules.sops + ./systems/programs.nix + ./systems/configuration.nix + ./systems/${hostname}/hardware.nix + ./systems/${hostname}/configuration.nix + { config.networking.hostName = "${hostname}"; } + ] ++ modules ++ fileList "modules" + ++ map + (user: { config, lib, pkgs, ... }@args: { + users.users.${user} = import ./users/${user} (args // { name = "${user}"; }); + boot.initrd.network.ssh.authorizedKeys = config.users.users.${user}.openssh.authorizedKeys.keys; + sops = { + secrets."${user}/user-password" = { + sopsFile = ./users/${user}/secrets.yaml; + neededForUsers = true; + }; + }; + }) + users + ++ map (user: { home-manager.users.${user} = import ./users/${user}/home.nix; }) users; }; + in + { + photon = constructSystem { + hostname = "photon"; + users = [ + "alice" + "dennis" + ]; }; - }) users - ++ map(user: { home-manager.users.${user} = import ./users/${user}/home.nix; }) users; - }; - in { - photon = constructSystem { - hostname = "photon"; - users = [ - "alice" - "dennis" - ]; - }; - palatine-hill = constructSystem { - hostname = "palatine-hill"; - users = [ - "alice" - "dennis" - ]; - }; + palatine-hill = constructSystem { + hostname = "palatine-hill"; + users = [ + "alice" + "dennis" + ]; + }; + }; + + devShell = lib.mapAttrs + (system: sopsPkgs: + with nixpkgs.legacyPackages.${system}; + mkShell { + sopsPGPKeyDirs = [ "./keys" ]; + nativeBuildInputs = [ + apacheHttpd + sopsPkgs.sops-import-keys-hook + ]; + } + ) + sops-nix.packages; }; - - devShell = lib.mapAttrs (system: sopsPkgs: - with nixpkgs.legacyPackages.${system}; - mkShell { - sopsPGPKeyDirs = [ "./keys" ]; - nativeBuildInputs = [ - apacheHttpd - sopsPkgs.sops-import-keys-hook - ]; - } - ) sops-nix.packages; - }; } diff --git a/modules/backup.nix b/modules/backup.nix index 0f07a60..d976e62 100644 --- a/modules/backup.nix +++ b/modules/backup.nix @@ -9,22 +9,22 @@ in paths = lib.mkOption { type = with lib.types; listOf str; - default = []; + default = [ ]; description = "Extra paths to include in backup."; }; exclude = lib.mkOption { type = with lib.types; listOf str; - default = []; + default = [ ]; description = "Extra paths to exclude in backup."; }; }; config = { - assertions = [ { + assertions = [{ assertion = cfg.paths != [ ] -> cfg.enable; message = "Configuring backup services.backup.paths without enabling services.backup.enable is useless!"; - } ]; + }]; services = { postgresqlBackup = { @@ -54,9 +54,9 @@ in "/etc/subuid" "/var/lib/nixos/" ] ++ cfg.paths - ++ lib.optional config.services.postgresql.enable "/var/backup/postgresql/" - ++ lib.optional (config.security.acme.certs != {}) "/var/lib/acme/" - ++ lib.optional config.security.dhparams.enable "/var/lib/dhparams/"; + ++ lib.optional config.services.postgresql.enable "/var/backup/postgresql/" + ++ lib.optional (config.security.acme.certs != { }) "/var/lib/acme/" + ++ lib.optional config.security.dhparams.enable "/var/lib/dhparams/"; pruneOpts = [ "--group-by host" "--keep-daily 7" @@ -119,4 +119,4 @@ in }; }; }; -} \ No newline at end of file +} diff --git a/modules/website.nix b/modules/website.nix new file mode 100644 index 0000000..5306383 --- /dev/null +++ b/modules/website.nix @@ -0,0 +1,192 @@ +{ config, pkgs, lib, ... }: +let + eachSite = config.services.staticpage.sites; + + siteOpts = { lib, name, config, ... }: + { + options = { + package = lib.mkPackageOption pkgs "page" { }; + + root = lib.mkOption { + type = lib.types.str; + description = "The Document-Root folder in /var/lib"; + }; + + domain = lib.mkOption { + type = lib.types.str; + example = "example.com"; + description = "The staticpage's domain."; + }; + + subdomain = lib.mkOption { + type = with lib.types; nullOr str; + default = null; + example = "app"; + description = "The staticpage subdomain."; + }; + + usePHP = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Configure the Nginx Server to use PHP"; + }; + + configureNginx = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Configure the Nginx Server to serve the site with acne"; + }; + }; + }; +in +{ + options.services.staticpage = { + enable = lib.mkEnableOption "staticpage"; + + sites = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule siteOpts); + default = { }; + description = lib.mdDoc "Specification of one or more Staticpages sites to serve"; + }; + }; + + config = lib.mkIf (eachSite != { }) (lib.mkMerge [{ + services.nginx = { + virtualHosts = lib.mkMerge [ + (lib.mapAttrs' + (name: cfg: { + name = "${(if (cfg.subdomain == null) then "${cfg.domain}" else "${cfg.subdomain}.${cfg.domain}")}"; + value = { + root = "/var/lib/www/${cfg.root}"; + + forceSSL = true; + enableACME = true; + serverAliases = lib.mkIf (cfg.subdomain == null) [ "www.${cfg.domain}" ]; + + locations."= /favicon.ico" = { + extraConfig = '' + log_not_found off; + access_log off; + ''; + }; + locations."= /robots.txt" = { + extraConfig = '' + allow all; + log_not_found off; + access_log off; + ''; + }; + locations."~* ^/.well-known/" = { + extraConfig = '' + allow all; + ''; + }; + locations."~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$" = { + extraConfig = '' + try_files $uri @rewrite; + expires max; + log_not_found off; + ''; + }; + locations."~ ^/sites/.*/files/styles/" = { + extraConfig = '' + try_files $uri @rewrite; + ''; + }; + } // lib.optionalAttrs cfg.usePHP { + locations."~ '\.php$|^/update.php'" = { + extraConfig = '' + include ${pkgs.nginx}/conf/fastcgi_params; + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_pass unix:${config.services.phpfpm.pools.${name}.socket}; + fastcgi_index index.php; + + fastcgi_split_path_info ^(.+?\.php)(|/.*)$; + # Ensure the php file exists. Mitigates CVE-2019-11043 + try_files $fastcgi_script_name =404; + + # Block httpoxy attacks. See https://httpoxy.org/. + fastcgi_param HTTP_PROXY ""; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param QUERY_STRING $query_string; + fastcgi_intercept_errors on; + ''; + }; + + locations."~ \..*/.*\.php$" = { + extraConfig = '' + return 403; + ''; + }; + locations."~ ^/sites/.*/private/" = { + extraConfig = '' + return 403; + ''; + }; + locations."~ ^/sites/[^/]+/files/.*\.php$" = { + extraConfig = '' + deny all; + ''; + }; + locations."/" = { + extraConfig = '' + try_files $uri /index.php?$query_string; + ''; + }; + locations."@rewrite" = { + extraConfig = '' + rewrite ^ /index.php; + ''; + }; + locations."~ /vendor/.*\.php$" = { + extraConfig = '' + deny all; + return 404; + ''; + }; + locations."~ ^/sites/.*/files/styles/" = { + extraConfig = '' + try_files $uri @rewrite; + ''; + }; + locations."~ ^(/[a-z\-]+)?/system/files/" = { + extraConfig = '' + try_files $uri /index.php?$query_string; + ''; + }; + } // lib.optionalAttrs (!cfg.usePHP) { + locations."/" = { + extraConfig = '' + index index.html; + try_files $uri $uri/ $uri.html =404; + ''; + }; + }; + }) + (lib.filterAttrs (n: v: v.configureNginx) eachSite)) + ]; + }; + + services.phpfpm.pools = lib.mkMerge [ + (lib.mapAttrs + (name: cfg: { + user = "nginx"; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 5; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + }) + (lib.filterAttrs (n: v: v.usePHP) eachSite)) + ]; + }]); +} diff --git a/systems/configuration.nix b/systems/configuration.nix index a801b32..0b2df0c 100644 --- a/systems/configuration.nix +++ b/systems/configuration.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ lib, pkgs, ... }: { i18n = { defaultLocale = "en_US.utf8"; @@ -7,6 +7,9 @@ boot = { default = true; + kernel.sysctl = { + "net.ipv6.conf.ens3.accept_ra" = 1; + }; }; home-manager = { @@ -14,7 +17,12 @@ useUserPackages = true; }; - networking.firewall.allowedTCPPorts = [ 22 ]; + networking = { + firewall = { + enable = lib.mkDefault true; + allowedTCPPorts = [ 22 ]; + }; + }; services = { openssh = { @@ -46,13 +54,13 @@ defaultEditor = true; configure = { customRC = '' - set undofile " save undo file after quit - set undolevels=1000 " number of steps to save - set undoreload=10000 " number of lines to save + set undofile " save undo file after quit + set undolevels=1000 " number of steps to save + set undoreload=10000 " number of lines to save - " Save Cursor Position - au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif - ''; + " Save Cursor Position + au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif + ''; }; }; diff --git a/systems/palatine-hill/configuration.nix b/systems/palatine-hill/configuration.nix index 07b10c2..a1efed3 100644 --- a/systems/palatine-hill/configuration.nix +++ b/systems/palatine-hill/configuration.nix @@ -5,7 +5,9 @@ networking.hostId = "dc2f9781"; boot = { zfs.extraPools = [ "ZFS-primary" ]; - loader.grub.device = "/dev/sda"; + loader.grub.device = "/dev/sda"; + filesystem = "zfs"; + useSystemdBoot = true; }; virtualisation = { diff --git a/systems/programs.nix b/systems/programs.nix index 65b97ff..102d1a0 100644 --- a/systems/programs.nix +++ b/systems/programs.nix @@ -33,4 +33,4 @@ zoxide zsh-nix-shell ]; -} \ No newline at end of file +} diff --git a/users/alice/default.nix b/users/alice/default.nix index b056544..f75a58c 100644 --- a/users/alice/default.nix +++ b/users/alice/default.nix @@ -4,4 +4,4 @@ import ../default.nix { publicKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOGcqhLaKsjwAnb6plDavAhEyQHNvFS9Uh5lMTuwMhGF alice@parthenon-7588" ]; -} \ No newline at end of file +} diff --git a/users/alice/secrets.yaml b/users/alice/secrets.yaml index 0720f95..cff33c5 100644 --- a/users/alice/secrets.yaml +++ b/users/alice/secrets.yaml @@ -9,42 +9,42 @@ sops: - recipient: age1z8q02wdp0a2ep5uuffgfeqlfam4ztl95frhw5qhnn6knn0rrmcnqk5evej enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBubjhKaWVMdTRVaFM0OXBR - NGdSQTYxRG5rYk11SHRsR01IbnUwb1gvc1FZCmtXVGxTYVozOXFmalE1MXdETmJ3 - Z3Y1Q0pqd0xYSHdGWExqdkh2YjhscUkKLS0tIE9Ub1Mybk90bXVDcnFBTUpFeXpK - aUQvdCtHVi9DYzk2dk5rM1g4M2FOSGsKxtWFgL9S6cdQ91pJurSD/i/3f2tWsjIT - Tqw9JoTErhO8aY12LgX6iXHpCQnHvsknN4XL1DZllBNzKJ5XLrJBHA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkZnlZNmFXVVFaSks5R0ds + SWtXTitBY1BmWHltVkxtanpaMkt5S1N4ZzBRCkpkQ2Z2Sld0U3BnVXIyZFNEUHdn + RDBaMklHZXk1VTk2ZUIxMGQrbkJZZ0kKLS0tIGVDQ2cxQ2d1TWptSUZCOW9BanlJ + UzNxS0I4NEdGcTNNdUcwamZTRDBXcVEKgin2jqp4tEBnKYnQF5Ki2Btt/+lP3zEJ + FlcK7rU3pe8AijwWx3Ybgzv/10/YOzDn6dL6MYwtB80ZFe6NOavBlQ== -----END AGE ENCRYPTED FILE----- - - recipient: age1rjlc6vwnz2lcrpshtd9rldlxels6l2utwmnmf3prus8drfefeywq5ljrdg + - recipient: age13aqs2mx66dmnyd74sygnwavufv6a4pwnvcqj4ud4l94jk0tjgu6ss57slw enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6bEVmeVdXcUZEc3VjZzJU - Z2JsTHM0dzRleXJwRWxNei9aUC9oQWh0T1ZvCkdyWENHa1NXZHJNS25DZ1JWMFkv - cWhrQVUxYUpYVmhYeEV0NzBrY2ZuVVkKLS0tIFU0R2JlNkhtN2dmcmZxUExXRitW - SXV2OEI1QlIxVjRUVGJQZ3doSUllRk0KAd5xczxDAGqYf+e91UbtOc4A0dlf7Fir - hYEfG1Bcn7Sb5lab6DoNrj+KMh2ZnB/Kl6uVAtZ6Rscfs6N6s9KFhQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrUTN1UHlpeXBxYWtUQis0 + MDZFc3BPai9xWmVVWkRxdjNYNlo2R3IzbUNjCncyRlczNTdXcnpMMkxzdU5BTEs3 + NDVGb3ROL2xaWUthUDA5Y3V2c0Z4a1UKLS0tIEJYSHN3eEFBQ2JkK2tJZld5Y3Fz + aVZVTnBGNGpadFdVOFlTdkZ3TDJmSjAKF1d47FC7hCdLbqfzqK5LqB3xfMCpEU8R + XThuRWwRHWKqmG19K5GMaHMZp9sYVMW8dVPh/LG/3gbiMploUDmK0w== -----END AGE ENCRYPTED FILE----- lastmodified: "2023-12-27T08:22:15Z" mac: ENC[AES256_GCM,data:kYrqx4qv7C8seyenaIDBPLaYog/LNTVd8qfFqUW2vsP7P6v8GMyQSCzi8UN22WXBnlZq0K5Fria4ZknIYB3ImqKuvdFfP40E6wK4IRAJhlLwukDAdNdMxS39ZcYiMud3mjPWyDKkoxx3ldBzdQSelAPVpQourWsiauVkM9clKNw=,iv:hoDUPBsDEjflZn+TK47u5jXWktFl5zj8CtBBC2PUFrs=,tag:JyLcTHZXyIzc6gwKzwtAzQ==,type:str] pgp: - - created_at: "2023-12-27T07:38:50Z" + - created_at: "2023-12-28T18:03:08Z" enc: |- -----BEGIN PGP MESSAGE----- - hQIMA84hNUGIgI/nAQ//TBHE0gHfS4c7EbDRCQbPEL0XwZje06yW+ZNMHUWJWAwX - knxFPGXnlVyUF30ghkd1rCaQXrdtawg1Gml+Wpc9mG+IK7VTPM/O3Mb9QsWlvNiA - K8esjZMQ0Aq53Mb16OQolk3WuZ1toogkirzex+KMhpFvXDcEfOmV+MI1HosBv7Y1 - UJP+9vcAimuMAgG2nLF8NLGKeWARfL8sRE9Lz6RrYrljAzPH4KdVRhN8ye11ZYul - odNKRi0/gjdC2+zUfhJnDN4h+mxxybKfTFSaXIQgN5oVlR1wpxpsSAf8lNyEztIo - fB9M8K0g18h9Q1r0SASaxt3QA7CkXyu/oclvu2Qoa3P4z0GCQKur+6ednV28pzYG - tlMjuKl3InrTvtowc8ehYWNsmIkiLFQc9j0/ZEGTnmtMU/EDgQqA++oKK8iI0Gbl - FY1058k5VfI95b2dOenJ1FOAzX4krlJFveZr0Bo7RIWJA1L5zSohu5wpVJj3vmVu - ss2t3qOLSog3YcAEP5bibejPxojb/DAmhoZTK6RumRA9r2ZVu4ZnqDsIPS7SzxS6 - y9Bm8SDHrzEzQlRWQKYYI5jieEXfUAKOJwV2xOZOlgZ1tVJZEzHH+FW0ro1zaLJt - zk5BoqpHgTQLQYcSLyODvrFR/8Menx85PHty5fChbipekWx08IbSHwqhbxd8phzS - XgECotBGOy1Da7RtHHuZsJ+PBnk9oY/dZJz7Rn3UMLEgNd2DF1X0fD/PUvzZiGtL - U0CANiRypGLxDEVXcguMDDz//2UltjiuKZ6AXJ8Hij7GshBp0Wjpmc9W+MzvCqM= - =jZCc + hQIMA84hNUGIgI/nAQ/+OTWLMMznF7u83v2fDUjvRtG6Zf5dR1wsJjeYUFZzxQoF + wJwKPbOPNP4HuEIbvXANFfuuUEZNwq+czUPSPqjmeEjf3DfE/JcIzQ8J6AP7Q2b4 + OstgK5MGKo9/IXrIDUK2fRuwGaXKyq/TG2fP10ljTlXzMlfm9OZA71QPZYBpwtSe + 1lR3gDIpha1yYTQP0STsnusvQkbNyKHNiIwjmkitjgdkreLPqhXlfwievcYcwOCp + 8UKAqAWJIQVZfHAZJzDWcmnWPK+wR2/pjNKklgYLcSn961o5GMu+6Z64pP3c9BXh + GRogv1f3bvH1aDcP+cB0eaQCyDLFkWKbRgBWubyCGJbJFovzpHNmcYkrlwNmGXoe + 9yrUICQB52gMOSSNCIM39T/yWLOV9O/ga20BUwaoR4duvFNrxktmJXGBGMCfhR2p + y74vVhm54Lqw5hwW54eLq14qQzOGhDIyeuuboFGm2BAYgdp4gUmOqTDMWS8Vt1lU + oKJOEeT83h2cxXnb0hJ6IWLyEns37+/aB4LWIvnQOgq8yaYEVI4JksKsM+cLVQVZ + V3FKWZBTNvCZd6jiWjZdfd3q+Q9QbSQEg1DrKwNXQuF9DMrxg+3xyzQVMYpRbGKr + pfB6u1CB6jw/NdajgCyHLJN44QELfcWhqriLWP7uEz9jl8di5g5NCP0l+agJjNzS + XgEaZapnHWm3E2v+1IQ8xrMdTl9t/cRLtIG71Y+rz3DH6jtixNv9pZn7BNqdeKlR + K1wloUtBbLjgHwDvPIGiUB+dcrHPo2OQTVO5bgax8mAyKuPDKQBLjLsWn2+H6eI= + =8fVd -----END PGP MESSAGE----- fp: F63832C3080D6E1AC77EECF80B4245FFE305BC82 unencrypted_suffix: _unencrypted diff --git a/users/default.nix b/users/default.nix index 4370194..a065d59 100644 --- a/users/default.nix +++ b/users/default.nix @@ -1,10 +1,10 @@ -{ - lib, - config, - pkgs, - name, - publicKeys ? [], - defaultShell ? "zsh", +{ lib +, config +, pkgs +, name +, publicKeys ? [ ] +, defaultShell ? "zsh" +, }: { @@ -25,4 +25,4 @@ shell = pkgs.${defaultShell}; hashedPasswordFile = config.sops.secrets."${name}/user-password".path; openssh.authorizedKeys.keys = publicKeys; -} \ No newline at end of file +}