diff options
Diffstat (limited to '')
-rw-r--r-- | modules/by-name/ba/back/module.nix | 163 | ||||
-rw-r--r-- | modules/by-name/ba/backup/module.nix | 91 |
2 files changed, 158 insertions, 96 deletions
diff --git a/modules/by-name/ba/back/module.nix b/modules/by-name/ba/back/module.nix index 520acdb..d47ffce 100644 --- a/modules/by-name/ba/back/module.nix +++ b/modules/by-name/ba/back/module.nix @@ -6,116 +6,87 @@ ... }: let cfg = config.vhack.back; +in { + options.vhack.back = { + enable = lib.mkEnableOption "Back issue tracker (inspired by tvix's panettone)"; - mkConfigFile = repoPath: domain: - (pkgs.formats.json {}).generate "config.json" - { - inherit (cfg) source_code_repository_url; - repository_path = repoPath; - root_url = "https://${domain}"; - }; - - mkUnit = repoPath: port: domain: { - description = "Back service for ${repoPath}"; - wants = ["network-online.target"]; - after = ["network-online.target"]; - wantedBy = ["default.target"]; - - environment = { - ROCKET_PORT = builtins.toString port; + domain = lib.mkOption { + type = lib.types.str; + description = "The domain to host this `back` instance on."; }; - serviceConfig = { - ExecStart = "${lib.getExe vhackPackages.back} ${mkConfigFile repoPath domain}"; + settings = { + scan_path = lib.mkOption { + type = lib.types.path; + description = "The path to the directory under which all the repositories reside"; + }; + project_list = lib.mkOption { + type = lib.types.path; + description = "The path to the `projects.list` file."; + }; - # Ensure that the service can read the repository - # FIXME(@bpeetz): This has the implied assumption, that all the exposed git - # repositories are readable for the git group. This should not be necessary. <2024-12-23> - User = "git"; - Group = "git"; + source_code_repository_url = lib.mkOption { + description = "The url to the source code of this instance of back"; + default = "https://git.foss-syndicate.org/vhack.eu/nixos-server/tree/pkgs/by-name/ba/back"; + type = lib.types.str; + }; - DynamicUser = true; - Restart = "always"; - - # Sandboxing - ProtectSystem = "strict"; - ProtectHome = true; - PrivateTmp = true; - PrivateDevices = true; - ProtectHostname = true; - ProtectClock = true; - ProtectKernelTunables = true; - ProtectKernelModules = true; - ProtectKernelLogs = true; - ProtectControlGroups = true; - RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"]; - RestrictNamespaces = true; - LockPersonality = true; - MemoryDenyWriteExecute = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - RemoveIPC = true; - PrivateMounts = true; - # System Call Filtering - SystemCallArchitectures = "native"; - SystemCallFilter = ["~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid"]; + root_url = lib.mkOption { + type = lib.types.str; + description = "The url to this instance of back."; + default = "https://${cfg.domain}"; + }; }; }; - mkVirtalHost = port: { - locations."/".proxyPass = "http://127.0.0.1:${builtins.toString port}"; + config = lib.mkIf cfg.enable { + systemd.services."back" = { + description = "Back issue tracking system."; + requires = ["network-online.target"]; + after = ["network-online.target"]; + wantedBy = ["default.target"]; - enableACME = true; - forceSSL = true; - }; + serviceConfig = { + ExecStart = "${lib.getExe vhackPackages.back} ${(pkgs.formats.json {}).generate "config.json" cfg.settings}"; - services = - lib.mapAttrs' (gitPath: config: { - name = builtins.replaceStrings ["/"] ["_"] "back-${config.domain}"; - value = mkUnit gitPath config.port config.domain; - }) - cfg.repositories; + # Ensure that the service can read the repository + # FIXME(@bpeetz): This has the implied assumption, that all the exposed git + # repositories are readable for the git group. This should not be necessary. <2024-12-23> + User = "git"; + Group = "git"; - virtualHosts = - lib.mapAttrs' (gitPath: config: { - name = config.domain; - value = mkVirtalHost config.port; - }) - cfg.repositories; -in { - options.vhack.back = { - enable = lib.mkEnableOption "Back issue tracker (inspired by tvix's panettone)"; + DynamicUser = true; + Restart = "always"; - source_code_repository_url = lib.mkOption { - description = "The url to the source code of this instance of back"; - default = "https://git.foss-syndicate.org/vhack.eu/nixos-server/tree/pkgs/by-name/ba/back"; - type = lib.types.str; + # Sandboxing + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + PrivateDevices = true; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"]; + RestrictNamespaces = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + PrivateMounts = true; + # System Call Filtering + SystemCallArchitectures = "native"; + SystemCallFilter = ["~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid"]; + }; }; + services.nginx.virtualHosts."${cfg.domain}" = { + locations."/".proxyPass = "http://127.0.0.1:8000"; - repositories = lib.mkOption { - description = "An attibute set of repos to launch `back` services for."; - type = lib.types.attrsOf (lib.types.submodule { - options = { - enable = (lib.mkEnableOption "`back` for this repository.") // {default = true;}; - domain = lib.mkOption { - type = lib.types.str; - description = "The domain to host this `back` instance on."; - }; - port = lib.mkOption { - type = lib.types.port; - - # TODO: This _should_ be an implementation detail, but I've no real approach to - # automatically generate them without encountering weird bugs. <2024-12-23> - description = "The port to use for this back instance. This must be unique."; - }; - }; - }); - default = {}; + enableACME = true; + forceSSL = true; }; }; - - config = lib.mkIf cfg.enable { - systemd = {inherit services;}; - services.nginx = {inherit virtualHosts;}; - }; } diff --git a/modules/by-name/ba/backup/module.nix b/modules/by-name/ba/backup/module.nix new file mode 100644 index 0000000..856a1c3 --- /dev/null +++ b/modules/by-name/ba/backup/module.nix @@ -0,0 +1,91 @@ +{ + config, + pkgs, + lib, + ... +}: let + cfg = config.vhack.backup; + snapshots = "/srv/snapshots"; + postgresUser = "postgres"; +in { + options.vhack.backup = { + enable = lib.mkEnableOption "backups with restic"; + user = lib.mkOption { + type = lib.types.str; + description = "The storagebox-user to use"; + example = "u384702-sub2"; + }; + privateSshKey = lib.mkOption { + type = lib.types.path; + description = "The age-encrypted ssh-key, passed to agenix"; + }; + privatePassword = lib.mkOption { + type = lib.types.path; + description = "The age-encrypted restic password, passed to agenix"; + }; + }; + config = lib.mkIf cfg.enable { + vhack.persist.directories = [ + { + directory = "/root/.ssh"; + user = "root"; + group = "root"; + mode = "0700"; + } + ]; + age.secrets = { + resticpass = { + file = cfg.privatePassword; + mode = "0700"; + owner = "root"; + group = "root"; + }; + resticssh = { + file = cfg.privateSshKey; + mode = "0700"; + owner = "root"; + group = "root"; + }; + }; + services.restic.backups = { + storagebox = { + initialize = true; + backupPrepareCommand = '' + ${pkgs.sudo}/bin/sudo -u ${postgresUser} ${pkgs.postgresql}/bin/pg_dumpall --clean --if-exists --quote-all-identifiers > /srv/db_backup.sql + + [ -d /srv/snapshots ] || ${pkgs.btrfs-progs}/bin/btrfs subvolume create /srv/snapshots; + [ -d /srv/snapshots/srv ] && ${pkgs.btrfs-progs}/bin/btrfs subvolume delete /srv/snapshots/srv; + ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /srv /srv/snapshots/srv; + + # dump() { + # # compression: + # # pg_dump -F t -v "$1" | xz -z -9 -e -T0 > "db_$1.tar.xz" + # pg_dump -v "$1" > "db_$1.tar.xz" + # } + # # List all databases, and dump each of them in its own file + # # psql --list --csv | while read -r line; do echo "$line" | grep ','; done | while IFS=, read -r name _; do echo "$name"; done | sed '1d' | while read -r db_name; do dump "$db_name"; done + ''; + paths = [ + snapshots + ]; + exclude = [ + ".snapshots" + "/var/lib/postgresql" # included in the db dump + ]; + extraBackupArgs = [ + "--verbose" # spam log + ]; + passwordFile = config.age.secrets.resticpass.path; + extraOptions = [ + "rclone.program='ssh -p 23 ${cfg.user}@${cfg.user}.your-storagebox.de -i ${config.age.secrets.resticssh.path}'" + ]; + repository = "rclone: "; # There is only one repository served + timerConfig = { + Requires = "network-online.target"; + OnCalendar = "daily"; + Persistent = true; + }; + }; + }; + }; +} |