summary refs log tree commit diff stats
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/linde.nix304
-rw-r--r--system/marvin.nix2
2 files changed, 134 insertions, 172 deletions
diff --git a/system/linde.nix b/system/linde.nix
index 2ca59842..29260c21 100644
--- a/system/linde.nix
+++ b/system/linde.nix
@@ -12,7 +12,6 @@ let
   net-mask4 = "32";
   net-gw = "172.31.1.1";
   net-ip6 = "2a01:4f8:c012:23a4::1";
-  net-rdnsip = "2a01:4f8:c012:23a4::53";
   net-redisip = "2a01:4f8:c012:23a4::6379";
   net-mask6 = "64";
   net-gw6 = "fe80::1";
@@ -45,6 +44,9 @@ in
     dex.file = ../secrets/dex.age;
     powerdns.file = ../secrets/powerdns.age;
     redis-website.file = ../secrets/redis-website.age;
+    photoprism.file = ../secrets/photoprism.age;
+    cifs-photoprism.file = ../secrets/cifs-photoprism.age;
+    cifs-paperless.file = ../secrets/cifs-paperless.age;
     golink = let golink = config.services.golink; in {
       # hope this doesn't collide...
       path = "${golink.dataDir}/.config/tsnet-golink/auth.key";
@@ -64,10 +66,10 @@ in
 
   i18n.defaultLocale = "en_GB.UTF-8";
 
-  environment.enableAllTerminfo = true;
   environment.homeBinInPath = true;
   environment.localBinInPath = true;
   environment.systemPackages = with pkgs; [
+    cifs-utils
     htop
     lsof
     powerdns
@@ -99,14 +101,14 @@ in
     dates = "02:10";
     randomizedDelaySec = "59 min";
     allowReboot = true;
-    flake = "git+file://${config.services.gitolite.dataDir}/repositories/nixfiles.git";
+    flake = "git+file://${config.services.gitolite.dataDir}/repositories/nixfiles.git?submodules=1";
     flags = [
       "--no-write-lock-file"
       "--impure"
       "--update-input"
-      "nixpkgs-small"
+      "--nixpkgs"
       "--update-input"
-      "searchix"
+      "nixpkgs-small"
     ];
   };
 
@@ -152,9 +154,8 @@ in
       "1.0.0.1"
     ];
     hosts = lib.mkForce {
-      ${net-ip4} = [ "${hostname}.alanpearce.eu" hostname ];
-      ${net-ip6} = [ "${hostname}.alanpearce.eu" hostname ];
-      ${net-rdnsip} = [ "dns" ];
+      ${net-ip4} = [ "${hostname}.${domain}" hostname ];
+      ${net-ip6} = [ "${hostname}.${domain}" hostname ];
       ${net-redisip} = [ "redis" ];
     };
     firewall = {
@@ -213,7 +214,6 @@ in
         ];
         address = [
           "${net-ip6}/${net-mask6}"
-          "${net-rdnsip}/${net-mask6}"
           "${net-redisip}/${net-mask6}"
         ];
         addresses = [{
@@ -297,7 +297,6 @@ in
       set --universal fish_greeting ""
     '';
   };
-  programs.zsh.enable = true;
   users.users.root = {
     shell = "/run/current-system/sw/bin/fish";
     openssh.authorizedKeys.keys = [
@@ -400,59 +399,6 @@ in
       '';
     };
 
-  systemd.services.hagezi-blocklist-update = {
-    enable = true;
-    startAt = "daily";
-    serviceConfig = {
-      CacheDirectory = "blocklist";
-      UMask = "0077";
-      DynamicUser = "yes";
-      ProtectSystem = "strict";
-      ProtectHome = true;
-      PrivateTmp = true;
-      PrivateDevices = true;
-      PrivateUsers = true;
-      ProtectClock = true;
-      ProtectKernelTunables = true;
-      ProtectKernelModules = true;
-      ProtectKernelLogs = true;
-      ProtectControlGroups = true;
-      ProtectProc = "invisible";
-      RestrictAddressFamilies = "AF_INET AF_INET6";
-      RestrictNamespaces = true;
-      RestrictRealtime = true;
-      LockPersonality = true;
-      MemoryDenyWriteExecute = "true";
-      SystemCallFilter = [
-        "~@clock"
-        "~@cpu-emulation"
-        "~@debug"
-        "~@module"
-        "~@mount"
-        "~@obsolete"
-        "~@privileged"
-        "~@raw-io"
-        "~@reboot"
-        "~@resources"
-        "~@swap"
-      ];
-      SystemCallArchitectures = "native";
-      CapabilityBoundingSet = "";
-      DevicePolicy = "closed";
-      ProcSubset = "pid";
-      NoNewPrivileges = true;
-      ExecStart = "${pkgs.curl}/bin/curl --no-progress-meter --output %C/blocklist/hagezi.rpz https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/pro.plus.txt";
-      #  https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/pro.plus.txt"
-      ExecStartPost = [
-        "+/bin/sh -c 'exec install --compare --mode=644 %C/blocklist/hagezi.rpz /etc/knot-resolver/blocklist.rpz'"
-        "-/bin/sh -c 'exec rm -f %C/blocklist/hagezi.rpz'"
-      ];
-      Environment = [
-        "HOME=%C/blocklist"
-      ];
-    };
-  };
-
   services.postfix =
     let
       localUser = "alan";
@@ -471,75 +417,6 @@ in
       };
     };
 
-  services.kresd = {
-    enable = true;
-    # package = pkgs.knot-resolver.override { extraFeatures = true; };
-    listenPlain = [
-      "[${net-rdnsip}]:53"
-    ];
-    listenTLS = [
-      "127.0.0.1:853"
-      "[::1]:853"
-      "${net-ip4}:853"
-      "[${net-ip6}]:853"
-    ];
-    listenDoH = [
-      "[::1]:443"
-      "127.0.0.1:443"
-    ];
-    instances = 2;
-    extraConfig = ''
-      modules = {
-        'rebinding < iterate',
-        'hints > iterate',
-        'serve_stale < cache',
-        'stats',
-        predict = {
-          window = 30,
-          period = 24 * (60/30),
-        },
-        'nsid',
-      }
-
-      local systemd_instance = os.getenv("SYSTEMD_INSTANCE")
-      nsid.name(systemd_instance)
-
-      log_groups({ 'policy' })
-
-      cache.size = 500 * MB
-
-      net.tls(
-        '/var/lib/acme/dns.alanpearce.eu/cert.pem',
-        '/var/lib/acme/dns.alanpearce.eu/key.pem'
-      )
-
-      -- override blocklist
-      policy.add(policy.suffix(policy.PASS, policy.todnames({
-      })))
-
-      policy.add(policy.rpz(
-        policy.DENY_MSG('domain blocked by hagezi'),
-        '/etc/knot-resolver/blocklist.rpz',
-        false -- needs wrapped kresd
-        -- true -- will watch the file for updates
-      ))
-
-      policy.add(policy.domains(policy.REFUSE, policy.todnames({
-        'use-application-dns.net',
-        'telemetry.astro.build',
-      })))
-
-      -- disable DNSSEC when using Quad9 since they do it
-      -- trust_anchors.remove('.')
-      -- policy.add(policy.all(policy.TLS_FORWARD({
-      --   {'2620:fe::fe', hostname='dns.quad9.net'},
-      --   {'2620:fe::9', hostname='dns.quad9.net'},
-      --   {'9.9.9.9', hostname='dns.quad9.net'},
-      --   {'149.112.122.122', hostname='dns.quad9.net'},
-      -- })))
-    '';
-  };
-
   users.groups.ntfy = { };
   users.users.ntfy = {
     isSystemUser = true;
@@ -578,31 +455,28 @@ in
   systemd.services.backup-gitolite = {
     startAt = "daily";
     path = with pkgs; [
-      rdiff-backup
       openssh
     ];
-    script = ''
-      rdiff-backup --api-version 201 backup ${config.services.gitolite.dataDir} ${hostname}@home.alanpearce.eu::gitolite
-      rdiff-backup --api-version 201 remove increments --older-than 3M ${hostname}@home.alanpearce.eu::gitolite
-    '';
-    serviceConfig.Type = "oneshot";
+    serviceConfig = {
+      Type = "oneshot";
+      ExecStart = "${lib.getExe pkgs.rdiff-backup} --api-version 201 backup ${config.services.gitolite.dataDir} ${hostname}@nano.${ts-domain}::gitolite";
+      ExecStartPost = "-${lib.getExe pkgs.rdiff-backup} --api-version 201 remove increments --older-than 3M ${hostname}@nano.${ts-domain}::gitolite";
+    };
   };
 
   systemd.services.backup-paperless = {
     startAt = "daily";
     path = with pkgs; [
-      sudo
-      rdiff-backup
       openssh
     ];
-    script = ''
-      sudo -u paperless ./paperless-manage document_exporter --delete --use-filename-format --no-archive --no-thumbnail --no-progress-bar ./export
-      rdiff-backup --api-version 201 backup ./export ${hostname}@home.alanpearce.eu::paperless
-      rdiff-backup --api-version 201 remove increments --older-than 3M ${hostname}@home.alanpearce.eu::paperless
-    '';
     serviceConfig = {
       Type = "oneshot";
       WorkingDirectory = config.services.paperless.dataDir;
+      ExecStart = [
+        "systemd-run --machine=papers sudo -u paperless ./paperless-manage document_exporter --delete --use-filename-format --no-archive --no-thumbnail --no-progress-bar ./export  "
+        "${lib.getExe pkgs.rdiff-backup} --api-version 201 backup /srv/paperless/export ${hostname}@nano.${ts-domain}::paperless"
+      ];
+      ExecStartPost = "-${lib.getExe pkgs.rdiff-backup} --api-version 201 remove increments --older-than 3M ${hostname}@nano.${ts-domain}::paperless";
     };
   };
 
@@ -619,10 +493,6 @@ in
     certs."alanpearce.eu" = {
       extraDomainNames = [ "*.alanpearce.eu" "*.linde.alanpearce.eu" ];
     };
-    certs."dns.alanpearce.eu" = {
-      reloadServices = map (x: "kresd@${toString x}") (range 1 config.services.kresd.instances);
-      group = "knot-resolver";
-    };
     certs."stats.alanpearce.eu" = {
       extraDomainNames = [ "*.stats.alanpearce.eu" ];
     };
@@ -783,6 +653,21 @@ in
             file_server
           '';
         };
+        "photos.alanpearce.eu" =
+          let
+            srv = config.services.photoprism;
+          in
+          {
+            useACMEHost = "alanpearce.eu";
+            extraConfig = ''
+              encode zstd gzip
+              ${security-headers {}}
+              reverse_proxy ${srv.address}:${toString srv.port}
+              handle_errors {
+                respond "{err.status_code} {err.status_text}"
+              }
+            '';
+          };
       };
   };
   systemd.services.caddy.serviceConfig = {
@@ -802,15 +687,41 @@ in
     home = "/srv/paperless";
   };
   users.groups.paperless.members = [ "alan" "syncthing" ];
+
+  fileSystems."/srv/paperless" = {
+    device = "//u439959-sub3.your-storagebox.de/u439959-sub3";
+    fsType = "smb3";
+    options =
+      let
+        # prevents hanging on network split
+        automount_opts = [
+          "x-systemd.automount"
+          "noauto"
+          "x-systemd.idle-timeout=1h"
+          "x-systemd.mount-timeout=5s"
+        ];
+        uid = config.ids.uids.paperless;
+      in
+      automount_opts ++ [
+        "credentials=${config.age.secrets.cifs-paperless.path}"
+        "seal"
+        "multichannel"
+        "nobrl" # needed for sqlite
+        "forceuid"
+        "forcegid"
+        "uid=${toString uid}"
+        "gid=${toString uid}"
+      ];
+  };
   containers.papers =
     let
-      hostDataDir = config.users.users.paperless.home;
+      externalDir = "/srv/paperless";
       localAddress6 = "fc00::2";
       tsHostname = "papers.${ts-domain}";
       tsPort = 41642;
+      hostConfig = config;
     in
     {
-      # or maybe socket activated?
       autoStart = true;
       # does TS need this?
       enableTun = true;
@@ -822,11 +733,15 @@ in
       }];
       bindMounts = {
         ${config.services.paperless.dataDir} = {
-          hostPath = hostDataDir;
+          hostPath = hostConfig.services.paperless.dataDir;
+          isReadOnly = false;
+        };
+        ${externalDir} = {
+          hostPath = externalDir;
           isReadOnly = false;
         };
       };
-      config = {
+      config = { config, lib, pkgs, ... }: {
         environment.systemPackages = with pkgs; [
           lsof
         ];
@@ -835,7 +750,7 @@ in
           resolvconf.enable = false;
           firewall.trustedInterfaces = [ "tailscale0" ];
           firewall.rejectPackets = true;
-          nameservers = config.networking.nameservers;
+          nameservers = hostConfig.networking.nameservers;
         };
         services.resolved = {
           enable = true;
@@ -894,6 +809,7 @@ in
         services.paperless = {
           enable = true;
           address = "[::1]";
+          mediaDir = "${externalDir}/media";
           settings = {
             PAPERLESS_DBENGINE = "sqlite";
             PAPERLESS_TIME_ZONE = "Europe/Berlin";
@@ -926,15 +842,13 @@ in
       };
     };
 
-  services.etcd = {
-    enable = true;
-    initialClusterState = "existing";
-    dataDir = "/var/lib/etcd"; # TODO backup
-    extraConf = {
-      AUTO_COMPACTION_RETENTION = "1h";
-    };
+  users.users.dex = {
+    home = "/var/lib/dex";
+    createHome = true;
+    isSystemUser = true;
+    group = "dex";
   };
-
+  users.groups.dex = { };
   services.dex =
     let
       issuer = "https://id.alanpearce.eu/";
@@ -945,11 +859,8 @@ in
       settings = {
         inherit issuer;
         storage = {
-          type = "etcd";
-          config = {
-            endpoints = config.services.etcd.listenClientUrls;
-            namespace = "dex/";
-          };
+          type = "sqlite3";
+          config.file = "/var/lib/dex/storage.sqlite";
         };
         web.http = "127.0.0.1:5556";
         connectors = [{
@@ -977,10 +888,16 @@ in
         ];
       };
     };
-  systemd.services.dex.unitConfig = {
-    After = [ "etcd.service" ];
-    Requires = [ "etcd.service" ];
-  };
+  systemd.services.dex.serviceConfig =
+    let
+      user = config.users.users.dex;
+    in
+    {
+      ReadWritePaths = [ user.home ];
+      DynamicUser = lib.mkForce false;
+      User = user.name;
+      Group = user.group;
+    };
 
   services.redis = {
     servers = {
@@ -1124,4 +1041,49 @@ in
       default = [{ type = "insecureAcceptAnything"; }];
     };
   };
+
+  fileSystems."/srv/photoprism" = {
+    device = "//u439959-sub1.your-storagebox.de/u439959-sub1";
+    fsType = "smb3";
+    options =
+      let
+        # prevents hanging on network split
+        automount_opts = [
+          "x-systemd.automount"
+          "noauto"
+          "x-systemd.idle-timeout=1h"
+          "x-systemd.mount-timeout=5s"
+        ];
+        uid = 64600;
+      in
+      automount_opts ++ [
+        "credentials=${config.age.secrets.cifs-photoprism.path}"
+        "seal"
+        "multichannel"
+        "nobrl" # needed for sqlite
+        "forceuid"
+        "forcegid"
+        "uid=${toString uid}"
+        "gid=${toString uid}"
+      ];
+  };
+  services.photoprism = {
+    enable = true;
+    passwordFile = config.age.secrets.photoprism.path;
+    originalsPath = "/srv/photoprism/originals";
+    importPath = "/srv/photoprism/import";
+    settings = {
+      PHOTOPRISM_SITE_URL = "https://photos.alanpearce.eu";
+      PHOTOPRISM_SITE_CAPTION = "Alan‘s Photos";
+      PHOTOPRISM_DISABLE_TLS = "true";
+      PHOTOPRISM_SIDECAR_PATH = "/srv/photoprism/sidecar";
+      PHOTOPRISM_SPONSOR = "true";
+    };
+  };
+  systemd.services.photoprism = {
+    unitConfig.RequiresMountsFor = "/srv/photoprism";
+    serviceConfig.ReadWritePaths = [
+      "/srv/photoprism/sidecar"
+    ];
+  };
 }
diff --git a/system/marvin.nix b/system/marvin.nix
index 2dd7986a..c4a13e93 100644
--- a/system/marvin.nix
+++ b/system/marvin.nix
@@ -53,7 +53,7 @@
         system = "aarch64-linux";
         maxJobs = 2;
         speedFactor = 1;
-        supportedFeatures = [ ];
+        supportedFeatures = [ "kvm" ];
       }
     ];
   };