about summary refs log tree commit diff
path: root/nixos/modules/services/web-apps
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/web-apps')
-rw-r--r--nixos/modules/services/web-apps/code-server.nix2
-rw-r--r--nixos/modules/services/web-apps/freshrss.nix46
-rw-r--r--nixos/modules/services/web-apps/healthchecks.nix18
-rw-r--r--nixos/modules/services/web-apps/invidious.nix2
-rw-r--r--nixos/modules/services/web-apps/keycloak.nix6
-rw-r--r--nixos/modules/services/web-apps/limesurvey.nix78
-rw-r--r--nixos/modules/services/web-apps/nextcloud.md23
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix4
-rw-r--r--nixos/modules/services/web-apps/peering-manager.nix25
-rw-r--r--nixos/modules/services/web-apps/pixelfed.nix2
-rw-r--r--nixos/modules/services/web-apps/pretalx.nix2
-rw-r--r--nixos/modules/services/web-apps/shiori.nix80
-rw-r--r--nixos/modules/services/web-apps/silverbullet.nix2
-rw-r--r--nixos/modules/services/web-apps/slskd.nix2
-rw-r--r--nixos/modules/services/web-apps/suwayomi-server.nix2
15 files changed, 242 insertions, 52 deletions
diff --git a/nixos/modules/services/web-apps/code-server.nix b/nixos/modules/services/web-apps/code-server.nix
index abb5be50d353e..f94a1a8b53fa4 100644
--- a/nixos/modules/services/web-apps/code-server.nix
+++ b/nixos/modules/services/web-apps/code-server.nix
@@ -9,7 +9,7 @@ in {
     services.code-server = {
       enable = lib.mkEnableOption "code-server";
 
-      package = lib.mkPackageOptionMD pkgs "code-server" {
+      package = lib.mkPackageOption pkgs "code-server" {
         example = ''
           pkgs.vscode-with-extensions.override {
             vscode = pkgs.code-server;
diff --git a/nixos/modules/services/web-apps/freshrss.nix b/nixos/modules/services/web-apps/freshrss.nix
index 021101fecaa48..7a22e15231923 100644
--- a/nixos/modules/services/web-apps/freshrss.nix
+++ b/nixos/modules/services/web-apps/freshrss.nix
@@ -5,6 +5,15 @@ let
   cfg = config.services.freshrss;
 
   poolName = "freshrss";
+
+  extension-env = pkgs.buildEnv {
+    name = "freshrss-extensions";
+    paths = cfg.extensions;
+  };
+  env-vars = {
+    DATA_PATH = cfg.dataDir;
+    THIRDPARTY_EXTENSIONS_PATH = "${extension-env}/share/freshrss/";
+  };
 in
 {
   meta.maintainers = with maintainers; [ etu stunkymonkey mattchrist ];
@@ -14,6 +23,31 @@ in
 
     package = mkPackageOption pkgs "freshrss" { };
 
+    extensions = mkOption {
+      type = types.listOf types.package;
+      default = [ ];
+      defaultText = literalExpression "[]";
+      example = literalExpression ''
+        with freshrss-extensions; [
+          youtube
+        ] ++ [
+          (freshrss-extensions.buildFreshRssExtension {
+            FreshRssExtUniqueId = "ReadingTime";
+            pname = "reading-time";
+            version = "1.5";
+            src = pkgs.fetchFromGitLab {
+              domain = "framagit.org";
+              owner = "Lapineige";
+              repo = "FreshRSS_Extension-ReadingTime";
+              rev = "fb6e9e944ef6c5299fa56ffddbe04c41e5a34ebf";
+             hash = "sha256-C5cRfaphx4Qz2xg2z+v5qRji8WVSIpvzMbethTdSqsk=";
+           };
+          })
+        ]
+      '';
+      description = "Additional extensions to be used.";
+    };
+
     defaultUser = mkOption {
       type = types.str;
       default = "admin";
@@ -214,9 +248,7 @@ in
             "pm.max_spare_servers" = 5;
             "catch_workers_output" = true;
           };
-          phpEnv = {
-            DATA_PATH = "${cfg.dataDir}";
-          };
+          phpEnv = env-vars;
         };
       };
 
@@ -259,9 +291,7 @@ in
             RemainAfterExit = true;
           };
           restartIfChanged = true;
-          environment = {
-            DATA_PATH = cfg.dataDir;
-          };
+          environment = env-vars;
 
           script =
             let
@@ -293,9 +323,7 @@ in
         description = "FreshRSS feed updater";
         after = [ "freshrss-config.service" ];
         startAt = "*:0/5";
-        environment = {
-          DATA_PATH = cfg.dataDir;
-        };
+        environment = env-vars;
         serviceConfig = defaultServiceConfig // {
           ExecStart = "${cfg.package}/app/actualize_script.php";
         };
diff --git a/nixos/modules/services/web-apps/healthchecks.nix b/nixos/modules/services/web-apps/healthchecks.nix
index 5562b37e502c6..c7db999a62c21 100644
--- a/nixos/modules/services/web-apps/healthchecks.nix
+++ b/nixos/modules/services/web-apps/healthchecks.nix
@@ -11,7 +11,7 @@ let
   environment = {
     PYTHONPATH = pkg.pythonPath;
     STATIC_ROOT = cfg.dataDir + "/static";
-  } // cfg.settings;
+  } // lib.filterAttrs (_: v: !builtins.isNull v) cfg.settings;
 
   environmentFile = pkgs.writeText "healthchecks-environment" (lib.generators.toKeyValue { } environment);
 
@@ -21,6 +21,7 @@ let
       sudo='exec /run/wrappers/bin/sudo -u ${cfg.user} --preserve-env --preserve-env=PYTHONPATH'
     fi
     export $(cat ${environmentFile} | xargs)
+    ${lib.optionalString (cfg.settingsFile != null) "export $(cat ${cfg.settingsFile} | xargs)"}
     $sudo ${pkg}/opt/healthchecks/manage.py "$@"
   '';
 in
@@ -89,6 +90,12 @@ in
       '';
     };
 
+    settingsFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
+      default = null;
+      description = opt.settings.description;
+    };
+
     settings = lib.mkOption {
       description = ''
         Environment variables which are read by healthchecks `(local)_settings.py`.
@@ -109,6 +116,8 @@ in
           have support for a `_FILE` variant, run:
           - `nix-instantiate --eval --expr '(import <nixpkgs> {}).healthchecks.secrets'`
           - or `nix eval 'nixpkgs#healthchecks.secrets'` if the flake support has been enabled.
+
+        If the same variable is set in both `settings` and `settingsFile` the value from `settingsFile` has priority.
       '';
       type = types.submodule (settings: {
         freeformType = types.attrsOf types.str;
@@ -121,8 +130,9 @@ in
           };
 
           SECRET_KEY_FILE = mkOption {
-            type = types.path;
+            type = types.nullOr types.path;
             description = "Path to a file containing the secret key.";
+            default = null;
           };
 
           DEBUG = mkOption {
@@ -186,7 +196,9 @@ in
           WorkingDirectory = cfg.dataDir;
           User = cfg.user;
           Group = cfg.group;
-          EnvironmentFile = [ environmentFile ];
+          EnvironmentFile = [
+            environmentFile
+          ] ++ lib.optional (cfg.settingsFile != null) cfg.settingsFile;
           StateDirectory = mkIf (cfg.dataDir == "/var/lib/healthchecks") "healthchecks";
           StateDirectoryMode = mkIf (cfg.dataDir == "/var/lib/healthchecks") "0750";
         };
diff --git a/nixos/modules/services/web-apps/invidious.nix b/nixos/modules/services/web-apps/invidious.nix
index f0e860383a62c..7997ea1f36308 100644
--- a/nixos/modules/services/web-apps/invidious.nix
+++ b/nixos/modules/services/web-apps/invidious.nix
@@ -390,7 +390,7 @@ in
         '';
       };
 
-      package = lib.mkPackageOptionMD pkgs "http3-ytproxy" { };
+      package = lib.mkPackageOption pkgs "http3-ytproxy" { };
     };
   };
 
diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix
index 36bae2575974e..5d429675bafcf 100644
--- a/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixos/modules/services/web-apps/keycloak.nix
@@ -328,7 +328,7 @@ in
             };
 
             hostname = mkOption {
-              type = str;
+              type = nullOr str;
               example = "keycloak.example.com";
               description = ''
                 The hostname part of the public URL used as base for
@@ -478,6 +478,10 @@ in
             message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably";
           }
           {
+            assertion = cfg.settings.hostname != null || ! cfg.settings.hostname-strict or true;
+            message = "Setting the Keycloak hostname is required, see `services.keycloak.settings.hostname`";
+          }
+          {
             assertion = cfg.settings.hostname-url or null == null;
             message = ''
               The option `services.keycloak.settings.hostname-url' has been removed.
diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix
index cdd60f572b990..dbcd9eae2d29a 100644
--- a/nixos/modules/services/web-apps/limesurvey.nix
+++ b/nixos/modules/services/web-apps/limesurvey.nix
@@ -18,7 +18,15 @@ let
 
   limesurveyConfig = pkgs.writeText "config.php" ''
     <?php
-      return json_decode('${builtins.toJSON cfg.config}', true);
+      return \array_merge(
+        \json_decode('${builtins.toJSON cfg.config}', true),
+        [
+          'config' => [
+            'encryptionnonce' => \trim(\file_get_contents(\getenv('CREDENTIALS_DIRECTORY') . DIRECTORY_SEPARATOR . 'encryption_nonce')),
+            'encryptionsecretboxkey' => \trim(\file_get_contents(\getenv('CREDENTIALS_DIRECTORY') . DIRECTORY_SEPARATOR . 'encryption_key')),
+          ]
+        ]
+      );
     ?>
   '';
 
@@ -35,8 +43,9 @@ in
     package = mkPackageOption pkgs "limesurvey" { };
 
     encryptionKey = mkOption {
-      type = types.str;
-      default = "E17687FC77CEE247F0E22BB3ECF27FDE8BEC310A892347EC13013ABA11AA7EB5";
+      type = types.nullOr types.str;
+      default = null;
+      visible = false;
       description = ''
         This is a 32-byte key used to encrypt variables in the database.
         You _must_ change this from the default value.
@@ -44,14 +53,35 @@ in
     };
 
     encryptionNonce = mkOption {
-      type = types.str;
-      default = "1ACC8555619929DB91310BE848025A427B0F364A884FFA77";
+      type = types.nullOr types.str;
+      default = null;
+      visible = false;
       description = ''
         This is a 24-byte nonce used to encrypt variables in the database.
         You _must_ change this from the default value.
       '';
     };
 
+    encryptionKeyFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        32-byte key used to encrypt variables in the database.
+
+        Note: It should be string not a store path in order to prevent the password from being world readable
+      '';
+    };
+
+    encryptionNonceFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        24-byte used to encrypt variables in the database.
+
+        Note: It should be string not a store path in order to prevent the password from being world readable
+      '';
+    };
+
     database = {
       type = mkOption {
         type = types.enum [ "mysql" "pgsql" "odbc" "mssql" ];
@@ -183,6 +213,22 @@ in
       { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
         message = "a password cannot be specified if services.limesurvey.database.createLocally is set to true";
       }
+      { assertion = cfg.encryptionKey != null || cfg.encryptionKeyFile != null;
+        message = ''
+          You must set `services.limesurvey.encryptionKeyFile` to a file containing a 32-character uppercase hex string.
+
+          If this message appears when updating your system, please turn off encryption
+          in the LimeSurvey interface and create backups before filling the key.
+        '';
+      }
+      { assertion = cfg.encryptionNonce != null || cfg.encryptionNonceFile != null;
+        message = ''
+          You must set `services.limesurvey.encryptionNonceFile` to a file containing a 24-character uppercase hex string.
+
+          If this message appears when updating your system, please turn off encryption
+          in the LimeSurvey interface and create backups before filling the nonce.
+        '';
+      }
     ];
 
     services.limesurvey.config = mapAttrs (name: mkDefault) {
@@ -204,8 +250,6 @@ in
       config = {
         tempdir = "${stateDir}/tmp";
         uploaddir = "${stateDir}/upload";
-        encryptionnonce = cfg.encryptionNonce;
-        encryptionsecretboxkey = cfg.encryptionKey;
         force_ssl = mkIf (cfg.virtualHost.addSSL || cfg.virtualHost.forceSSL || cfg.virtualHost.onlySSL) "on";
         config.defaultlang = "en";
       };
@@ -229,11 +273,26 @@ in
       phpPackage = pkgs.php81;
       phpEnv.DBENGINE = "${cfg.database.dbEngine}";
       phpEnv.LIMESURVEY_CONFIG = "${limesurveyConfig}";
+      # App code cannot access credentials directly since the service starts
+      # with the root user so we copy the credentials to a place accessible to Limesurvey
+      phpEnv.CREDENTIALS_DIRECTORY = "${stateDir}/credentials";
       settings = {
         "listen.owner" = config.services.httpd.user;
         "listen.group" = config.services.httpd.group;
       } // cfg.poolConfig;
     };
+    systemd.services.phpfpm-limesurvey.serviceConfig = {
+      ExecStartPre = pkgs.writeShellScript "limesurvey-phpfpm-exec-pre" ''
+        cp -f "''${CREDENTIALS_DIRECTORY}"/encryption_key "${stateDir}/credentials/encryption_key"
+        chown ${user}:${group} "${stateDir}/credentials/encryption_key"
+        cp -f "''${CREDENTIALS_DIRECTORY}"/encryption_nonce "${stateDir}/credentials/encryption_nonce"
+        chown ${user}:${group} "${stateDir}/credentials/encryption_nonce"
+      '';
+      LoadCredential = [
+        "encryption_key:${if cfg.encryptionKeyFile != null then cfg.encryptionKeyFile else pkgs.writeText "key" cfg.encryptionKey}"
+        "encryption_nonce:${if cfg.encryptionNonceFile != null then cfg.encryptionNonceFile else pkgs.writeText "nonce" cfg.encryptionKey}"
+      ];
+    };
 
     services.httpd = {
       enable = true;
@@ -277,6 +336,7 @@ in
       "d ${stateDir}/tmp/assets 0750 ${user} ${group} - -"
       "d ${stateDir}/tmp/runtime 0750 ${user} ${group} - -"
       "d ${stateDir}/tmp/upload 0750 ${user} ${group} - -"
+      "d ${stateDir}/credentials 0700 ${user} ${group} - -"
       "C ${stateDir}/upload 0750 ${user} ${group} - ${cfg.package}/share/limesurvey/upload"
     ];
 
@@ -295,6 +355,10 @@ in
         User = user;
         Group = group;
         Type = "oneshot";
+        LoadCredential = [
+          "encryption_key:${if cfg.encryptionKeyFile != null then cfg.encryptionKeyFile else pkgs.writeText "key" cfg.encryptionKey}"
+          "encryption_nonce:${if cfg.encryptionNonceFile != null then cfg.encryptionNonceFile else pkgs.writeText "nonce" cfg.encryptionKey}"
+        ];
       };
     };
 
diff --git a/nixos/modules/services/web-apps/nextcloud.md b/nixos/modules/services/web-apps/nextcloud.md
index 0b615deae44be..c433be5350b53 100644
--- a/nixos/modules/services/web-apps/nextcloud.md
+++ b/nixos/modules/services/web-apps/nextcloud.md
@@ -121,6 +121,29 @@ Auto updates for Nextcloud apps can be enabled using
     This is not an end-to-end encryption, but can be used to encrypt files that will be persisted
     to external storage such as S3.
 
+  - **Issues with file permissions / unsafe path transitions**
+
+    {manpage}`systemd-tmpfiles(8)` makes sure that the paths for
+
+    * configuration (including declarative config)
+    * data
+    * app store
+    * home directory itself (usually `/var/lib/nextcloud`)
+
+    are properly set up. However, `systemd-tmpfiles` will refuse to do so
+    if it detects an unsafe path transition, i.e. creating files/directories
+    within a directory that is neither owned by `root` nor by `nextcloud`, the
+    owning user of the files/directories to be created.
+
+    Symptoms of that include
+
+    * `config/override.config.php` not being updated (and the config file
+      eventually being garbage-collected).
+    * failure to read from application data.
+
+    To work around that, please make sure that all directories in question
+    are owned by `nextcloud:nextcloud`.
+
 ## Using an alternative webserver as reverse-proxy (e.g. `httpd`) {#module-services-nextcloud-httpd}
 
 By default, `nginx` is used as reverse-proxy for `nextcloud`.
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index a4a1f399f4e22..bfb3e73e65102 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -300,7 +300,7 @@ in {
     package = mkOption {
       type = types.package;
       description = "Which package to use for the Nextcloud instance.";
-      relatedPackages = [ "nextcloud26" "nextcloud27" "nextcloud28" ];
+      relatedPackages = [ "nextcloud28" "nextcloud29" ];
     };
     phpPackage = mkPackageOption pkgs "php" {
       example = "php82";
@@ -861,8 +861,6 @@ in {
               nextcloud defined in an overlay, please set `services.nextcloud.package` to
               `pkgs.nextcloud`.
             ''
-          else if versionOlder stateVersion "23.05" then nextcloud25
-          else if versionOlder stateVersion "23.11" then nextcloud26
           else if versionOlder stateVersion "24.05" then nextcloud27
           else nextcloud29
         );
diff --git a/nixos/modules/services/web-apps/peering-manager.nix b/nixos/modules/services/web-apps/peering-manager.nix
index c85cb76e5ea11..acdc393745293 100644
--- a/nixos/modules/services/web-apps/peering-manager.nix
+++ b/nixos/modules/services/web-apps/peering-manager.nix
@@ -16,6 +16,8 @@ let
       ln -s ${configFile} $out/opt/peering-manager/peering_manager/configuration.py
     '' + lib.optionalString cfg.enableLdap ''
       ln -s ${cfg.ldapConfigPath} $out/opt/peering-manager/peering_manager/ldap_config.py
+    '' + lib.optionalString cfg.enableOidc ''
+      ln -s ${cfg.oidcConfigPath} $out/opt/peering-manager/peering_manager/oidc_config.py
     '';
   })).override {
     inherit (cfg) plugins;
@@ -139,6 +141,24 @@ in {
         See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6-ldap/#configuration) for possible options.
       '';
     };
+
+    enableOidc = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable OIDC-Authentication for Peering Manager.
+
+        This requires a configuration file being pass through `oidcConfigPath`.
+      '';
+    };
+
+    oidcConfigPath = mkOption {
+      type = types.path;
+      description = ''
+        Path to the Configuration-File for OIDC-Authentication, will be loaded as `oidc_config.py`.
+        See the [documentation](https://peering-manager.readthedocs.io/en/stable/setup/6b-oidc/#configuration) for possible options.
+      '';
+    };
   };
 
   config = lib.mkIf cfg.enable {
@@ -173,7 +193,10 @@ in {
           PEERINGDB_API_KEY = file.readline()
       '';
 
-      plugins = lib.mkIf cfg.enableLdap (ps: [ ps.django-auth-ldap ]);
+      plugins = (ps:
+        (lib.optionals cfg.enableLdap [ ps.django-auth-ldap ]) ++
+        (lib.optionals cfg.enableOidc (with ps; [ mozilla-django-oidc pyopenssl josepy ]))
+      );
     };
 
     system.build.peeringManagerPkg = pkg;
diff --git a/nixos/modules/services/web-apps/pixelfed.nix b/nixos/modules/services/web-apps/pixelfed.nix
index cd0e8f62b65c8..46d671f8504b6 100644
--- a/nixos/modules/services/web-apps/pixelfed.nix
+++ b/nixos/modules/services/web-apps/pixelfed.nix
@@ -40,7 +40,7 @@ in {
     pixelfed = {
       enable = mkEnableOption "a Pixelfed instance";
       package = mkPackageOption pkgs "pixelfed" { };
-      phpPackage = mkPackageOption pkgs "php81" { };
+      phpPackage = mkPackageOption pkgs "php82" { };
 
       user = mkOption {
         type = types.str;
diff --git a/nixos/modules/services/web-apps/pretalx.nix b/nixos/modules/services/web-apps/pretalx.nix
index 1411d11982c87..2280d9165b40b 100644
--- a/nixos/modules/services/web-apps/pretalx.nix
+++ b/nixos/modules/services/web-apps/pretalx.nix
@@ -35,7 +35,7 @@ in
   options.services.pretalx = {
     enable = lib.mkEnableOption "pretalx";
 
-    package = lib.mkPackageOptionMD pkgs "pretalx" {};
+    package = lib.mkPackageOption pkgs "pretalx" {};
 
     group = lib.mkOption {
       type = lib.types.str;
diff --git a/nixos/modules/services/web-apps/shiori.nix b/nixos/modules/services/web-apps/shiori.nix
index 022bb5e438812..df3eeaef16183 100644
--- a/nixos/modules/services/web-apps/shiori.nix
+++ b/nixos/modules/services/web-apps/shiori.nix
@@ -1,17 +1,15 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-let
-  cfg = config.services.shiori;
+let cfg = config.services.shiori;
 in {
   options = {
     services.shiori = {
-      enable = mkEnableOption "Shiori simple bookmarks manager";
+      enable = lib.mkEnableOption "Shiori simple bookmarks manager";
 
-      package = mkPackageOption pkgs "shiori" { };
+      package = lib.mkPackageOption pkgs "shiori" { };
 
-      address = mkOption {
-        type = types.str;
+      address = lib.mkOption {
+        type = lib.types.str;
         default = "";
         description = ''
           The IP address on which Shiori will listen.
@@ -19,30 +17,55 @@ in {
         '';
       };
 
-      port = mkOption {
-        type = types.port;
+      port = lib.mkOption {
+        type = lib.types.port;
         default = 8080;
         description = "The port of the Shiori web application";
       };
 
-      webRoot = mkOption {
-        type = types.str;
+      webRoot = lib.mkOption {
+        type = lib.types.str;
         default = "/";
         example = "/shiori";
         description = "The root of the Shiori web application";
       };
+
+      environmentFile = lib.mkOption {
+        type = lib.types.nullOr lib.types.path;
+        default = null;
+        example = "/path/to/environmentFile";
+        description = ''
+          Path to file containing environment variables.
+          Useful for passing down secrets.
+          <https://github.com/go-shiori/shiori/blob/master/docs/Configuration.md#overall-configuration>
+        '';
+      };
+
+      databaseUrl = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
+        default = null;
+        example = "postgres:///shiori?host=/run/postgresql";
+        description = "The connection URL to connect to MySQL or PostgreSQL";
+      };
     };
   };
 
-  config = mkIf cfg.enable {
-    systemd.services.shiori = with cfg; {
+  config = lib.mkIf cfg.enable {
+    systemd.services.shiori = {
       description = "Shiori simple bookmarks manager";
       wantedBy = [ "multi-user.target" ];
-
-      environment.SHIORI_DIR = "/var/lib/shiori";
+      after = [ "postgresql.service" "mysql.service" ];
+      environment = {
+        SHIORI_DIR = "/var/lib/shiori";
+      } // lib.optionalAttrs (cfg.databaseUrl != null) {
+        SHIORI_DATABASE_URL = cfg.databaseUrl;
+      };
 
       serviceConfig = {
-        ExecStart = "${package}/bin/shiori serve --address '${address}' --port '${toString port}' --webroot '${webRoot}'";
+        ExecStart =
+          "${cfg.package}/bin/shiori server --address '${cfg.address}' --port '${
+            toString cfg.port
+          }' --webroot '${cfg.webRoot}'";
 
         DynamicUser = true;
         StateDirectory = "shiori";
@@ -50,15 +73,24 @@ in {
         RuntimeDirectory = "shiori";
 
         # Security options
-
+        EnvironmentFile =
+          lib.optional (cfg.environmentFile != null) cfg.environmentFile;
         BindReadOnlyPaths = [
           "/nix/store"
 
           # For SSL certificates, and the resolv.conf
           "/etc"
-        ];
+        ] ++ lib.optional (config.services.postgresql.enable &&
+                           cfg.databaseUrl != null &&
+                           lib.strings.hasPrefix "postgres://" cfg.databaseUrl)
+            "/run/postgresql"
+          ++ lib.optional (config.services.mysql.enable &&
+                           cfg.databaseUrl != null &&
+                           lib.strings.hasPrefix "mysql://" cfg.databaseUrl)
+            "/var/run/mysqld";
 
         CapabilityBoundingSet = "";
+        AmbientCapabilities = "CAP_NET_BIND_SERVICE";
 
         DeviceAllow = "";
 
@@ -78,7 +110,7 @@ in {
         ProtectKernelTunables = true;
 
         RestrictNamespaces = true;
-        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
         RestrictRealtime = true;
         RestrictSUIDSGID = true;
 
@@ -88,11 +120,17 @@ in {
         SystemCallErrorNumber = "EPERM";
         SystemCallFilter = [
           "@system-service"
-          "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid"
+          "~@cpu-emulation"
+          "~@debug"
+          "~@keyring"
+          "~@memlock"
+          "~@obsolete"
+          "~@privileged"
+          "~@setuid"
         ];
       };
     };
   };
 
-  meta.maintainers = with maintainers; [ minijackson ];
+  meta.maintainers = with lib.maintainers; [ minijackson CaptainJawZ ];
 }
diff --git a/nixos/modules/services/web-apps/silverbullet.nix b/nixos/modules/services/web-apps/silverbullet.nix
index 5d5f950a9a661..a6a830e674b49 100644
--- a/nixos/modules/services/web-apps/silverbullet.nix
+++ b/nixos/modules/services/web-apps/silverbullet.nix
@@ -14,7 +14,7 @@ in
     services.silverbullet = {
       enable = lib.mkEnableOption "Silverbullet, an open-source, self-hosted, offline-capable Personal Knowledge Management (PKM) web application";
 
-      package = lib.mkPackageOptionMD pkgs "silverbullet" { };
+      package = lib.mkPackageOption pkgs "silverbullet" { };
 
       openFirewall = lib.mkOption {
         type = lib.types.bool;
diff --git a/nixos/modules/services/web-apps/slskd.nix b/nixos/modules/services/web-apps/slskd.nix
index 6254fe294eeed..7d4bc66c73998 100644
--- a/nixos/modules/services/web-apps/slskd.nix
+++ b/nixos/modules/services/web-apps/slskd.nix
@@ -7,7 +7,7 @@ in {
   options.services.slskd = with lib; with types; {
     enable = mkEnableOption "slskd";
 
-    package = mkPackageOptionMD pkgs "slskd" { };
+    package = mkPackageOption pkgs "slskd" { };
 
     user = mkOption {
       type = types.str;
diff --git a/nixos/modules/services/web-apps/suwayomi-server.nix b/nixos/modules/services/web-apps/suwayomi-server.nix
index ba2352d0e693f..caa091685d2fb 100644
--- a/nixos/modules/services/web-apps/suwayomi-server.nix
+++ b/nixos/modules/services/web-apps/suwayomi-server.nix
@@ -11,7 +11,7 @@ in
     services.suwayomi-server = {
       enable = mkEnableOption "Suwayomi, a free and open source manga reader server that runs extensions built for Tachiyomi";
 
-      package = lib.mkPackageOptionMD pkgs "suwayomi-server" { };
+      package = lib.mkPackageOption pkgs "suwayomi-server" { };
 
       dataDir = mkOption {
         type = types.path;