diff --git a/package/photoview/nixos.nix b/package/photoview/nixos.nix new file mode 100644 index 00000000..08c7d167 --- /dev/null +++ b/package/photoview/nixos.nix @@ -0,0 +1,148 @@ +{ pkgs +, lib +, config +, ... }: with lib; let + cfg = config.services.photoview; +in { + options.services.photoview = { + enable = mkEnableOption "photoview server"; + + package = mkOption { + type = with types; package; + default = pkgs.photoview; + description = "photoview package"; + }; + + user = mkOption { + type = with types; str; + default = "photoview"; + description = "user under which photoview runs"; + }; + group = mkOption { + type = with types; str; + default = "photoview"; + description = "group under which photoview runs"; + }; + + listen = { + host = mkOption { + type = with types; str; + default = "127.0.0.1"; + description = "host to listen on"; + }; + port = mkOption { + type = with types; port; + default = 8000; + description = "port to listen on"; + }; + }; + + database = { + driver = mkOption { + type = with types; enum [ "sqlite" "mysql" "postgres" ]; + default = "sqlite"; + description = "database driver"; + }; + string = mkOption { + type = with types; str; + description = "database connection string"; + }; + }; + + stateDir = mkOption { + type = with types; str; + default = "/var/lib/photoview"; + description = "path to photoview state directory"; + }; + + cacheDir = mkOption { + type = with types; str; + default = "${cfg.stateDir}/media_cache"; + description = "path to photoview media cache"; + }; + + secrets = mkOption { + type = with types; nullOr str; + default = null; + description = "path to secrets environment file"; + example = '' + MAPBOX_TOKEN= + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.photoview = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "Photoview - Photo gallery for self-hosted personal servers"; + environment = with cfg; { + PHOTOVIEW_LISTEN_IP = listen.host; + PHOTOVIEW_LISTEN_PORT = toString listen.port; + PHOTOVIEW_MEDIA_CACHE = cacheDir; + PHOTOVIEW_DATABASE_DRIVER = database.driver; + "PHOTOVIEW_${toUpper database.driver}_URL" = database.string; + }; + serviceConfig = { + ExecStartPre = pkgs.writeShellScript "photoview-pre" '' + rm -f "${cfg.stateDir}/data" + ln -s "${cfg.package}/lib/photoview/data" "${cfg.stateDir}/data" + ''; + ExecStart = "${cfg.package}/bin/photoview"; + WorkingDirectory = cfg.stateDir; + User = cfg.user; + Group = cfg.group; + EnvironmentFile = mkIf (cfg.secrets != null) cfg.secrets; + + DevicePolicy = "closed"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProcSubset = "all"; + ProtectSystem = "strict"; + RemoveIPC = true; + ReadWritePaths = [ cfg.stateDir ]; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_NETLINK" + "AF_UNIX" + ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + ]; + UMask = "0077"; + }; + }; + + users.users = mkIf (cfg.user == "photoview") { + photoview = { + description = "photoview service account"; + group = cfg.group; + uid = config.ids.uids.photoview; + }; + }; + + users.groups = mkIf (cfg.group == "photoview") { + photoview.gid = config.ids.gids.photoview; + }; + + ids.uids.photoview = 287; + ids.gids.photoview = 287; + }; +}