about summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2024-05-02 12:01:36 +0000
committerGitHub <noreply@github.com>2024-05-02 12:01:36 +0000
commitc4dfa193ac2b134c6b4f3ee611fd34158ad61aae (patch)
tree362783cd99afd7c75dd43086e24df4d23ef6743e /nixos/modules
parent172376596cabacc4dd0bafa97aa3b85a75948a35 (diff)
parent3be507be1e2ea19b8d53450bac494e2ac30a642c (diff)
Merge master into staging-next
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/module-list.nix5
-rw-r--r--nixos/modules/services/backup/znapzend.nix10
-rw-r--r--nixos/modules/services/monitoring/parsedmarc.nix8
-rw-r--r--nixos/modules/services/networking/jotta-cli.md27
-rw-r--r--nixos/modules/services/networking/jotta-cli.nix43
-rw-r--r--nixos/modules/services/security/oauth2-proxy-nginx.nix (renamed from nixos/modules/services/security/oauth2_proxy_nginx.nix)55
-rw-r--r--nixos/modules/services/security/oauth2-proxy.nix (renamed from nixos/modules/services/security/oauth2_proxy.nix)249
7 files changed, 238 insertions, 159 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index ef25a7f3e75a2..90a2170349e93 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1029,6 +1029,7 @@
   ./services/networking/jigasi.nix
   ./services/networking/jitsi-videobridge.nix
   ./services/networking/jool.nix
+  ./services/networking/jotta-cli.nix
   ./services/networking/kea.nix
   ./services/networking/keepalived/default.nix
   ./services/networking/keybase.nix
@@ -1256,8 +1257,8 @@
   ./services/security/kanidm.nix
   ./services/security/munge.nix
   ./services/security/nginx-sso.nix
-  ./services/security/oauth2_proxy.nix
-  ./services/security/oauth2_proxy_nginx.nix
+  ./services/security/oauth2-proxy.nix
+  ./services/security/oauth2-proxy-nginx.nix
   ./services/security/opensnitch.nix
   ./services/security/pass-secret-service.nix
   ./services/security/physlock.nix
diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix
index 71e5977c44640..7f2c89edbf374 100644
--- a/nixos/modules/services/backup/znapzend.nix
+++ b/nixos/modules/services/backup/znapzend.nix
@@ -315,6 +315,14 @@ in
         '';
       };
 
+      mailErrorSummaryTo = mkOption {
+        type = singleLineStr;
+        default = "";
+        description = ''
+          Email address to send a summary to if "send task(s) failed".
+        '';
+      };
+
       noDestroy = mkOption {
         type = bool;
         default = false;
@@ -455,6 +463,8 @@ in
               "--loglevel=${cfg.logLevel}"
               (optionalString cfg.noDestroy "--nodestroy")
               (optionalString cfg.autoCreation "--autoCreation")
+              (optionalString (cfg.mailErrorSummaryTo != "")
+                "--mailErrorSummaryTo=${cfg.mailErrorSummaryTo}")
               (optionalString (enabledFeatures != [])
                 "--features=${concatStringsSep "," enabledFeatures}")
             ]; in "${pkgs.znapzend}/bin/znapzend ${args}";
diff --git a/nixos/modules/services/monitoring/parsedmarc.nix b/nixos/modules/services/monitoring/parsedmarc.nix
index 9191a4a697e0b..a14ade59c29eb 100644
--- a/nixos/modules/services/monitoring/parsedmarc.nix
+++ b/nixos/modules/services/monitoring/parsedmarc.nix
@@ -301,7 +301,7 @@ in
               description = ''
                 The addresses to send outgoing mail to.
               '';
-              apply = x: if x == [] then null else lib.concatStringsSep "," x;
+              apply = x: if x == [] || x == null then null else lib.concatStringsSep "," x;
             };
           };
 
@@ -438,7 +438,7 @@ in
             ];
         dashboards.settings.providers = lib.mkIf cfg.provision.grafana.dashboard [{
           name = "parsedmarc";
-          options.path = "${pkgs.python3Packages.parsedmarc.dashboard}";
+          options.path = "${pkgs.parsedmarc.dashboard}";
         }];
       };
     };
@@ -446,7 +446,7 @@ in
     services.parsedmarc.settings = lib.mkMerge [
       (lib.mkIf cfg.provision.elasticsearch {
         elasticsearch = {
-          hosts = [ "localhost:9200" ];
+          hosts = [ "http://localhost:9200" ];
           ssl = false;
         };
       })
@@ -530,7 +530,7 @@ in
             MemoryDenyWriteExecute = true;
             LockPersonality = true;
             SystemCallArchitectures = "native";
-            ExecStart = "${pkgs.python3Packages.parsedmarc}/bin/parsedmarc -c /run/parsedmarc/parsedmarc.ini";
+            ExecStart = "${lib.getExe pkgs.parsedmarc} -c /run/parsedmarc/parsedmarc.ini";
           };
         };
 
diff --git a/nixos/modules/services/networking/jotta-cli.md b/nixos/modules/services/networking/jotta-cli.md
new file mode 100644
index 0000000000000..fee002a4e6046
--- /dev/null
+++ b/nixos/modules/services/networking/jotta-cli.md
@@ -0,0 +1,27 @@
+# Jottacloud Command-line Tool {#module-services-jotta-cli}
+
+The [Jottacloud Command-line Tool](https://docs.jottacloud.com/en/articles/1436834-jottacloud-command-line-tool) is a headless [Jottacloud](https://jottacloud.com) client.
+
+## Quick Start {#module-services-jotta-cli-quick-start}
+
+```nix
+{
+  user.services.jotta-cli.enable = true;
+}
+```
+
+This adds `jotta-cli` to `environment.systemPackages` and starts a user service that runs `jottad` with the default options.
+
+## Example Configuration {#module-services-jotta-cli-example-configuration}
+
+```nix
+user.services.jotta-cli = {
+  enable = true;
+  options = [ "slow" ];
+  package = pkgs.jotta-cli;
+};
+```
+
+This uses `jotta-cli` and `jottad` from the `pkgs.jotta-cli` package and starts `jottad` in low memory mode.
+
+`jottad` is also added to `environment.systemPackages`, so `jottad --help` can be used to explore options.
diff --git a/nixos/modules/services/networking/jotta-cli.nix b/nixos/modules/services/networking/jotta-cli.nix
new file mode 100644
index 0000000000000..c7e6dad5453ca
--- /dev/null
+++ b/nixos/modules/services/networking/jotta-cli.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.user.services.jotta-cli;
+in {
+  options = {
+    user.services.jotta-cli = {
+
+      enable = mkEnableOption "Jottacloud Command-line Tool";
+
+      options = mkOption {
+        default = [ "stdoutlog" "datadir" "%h/.jottad/" ];
+        example = [ ];
+        type = with types; listOf str;
+        description = "Command-line options passed to jottad.";
+      };
+
+      package = lib.mkPackageOption pkgs "jotta-cli" { };
+    };
+  };
+  config = mkIf cfg.enable {
+    systemd.user.services.jottad = {
+
+      description = "Jottacloud Command-line Tool daemon";
+
+      serviceConfig = {
+        Type = "notify";
+        EnvironmentFile = "-%h/.config/jotta-cli/jotta-cli.env";
+        ExecStart = "${lib.getExe' cfg.package "jottad"} ${concatStringsSep " " cfg.options}";
+        Restart = "on-failure";
+      };
+
+      wantedBy = [ "default.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "network-online.target" ];
+    };
+    environment.systemPackages = [ pkgs.jotta-cli ];
+  };
+
+  meta.maintainers = with lib.maintainers; [ evenbrenden ];
+  meta.doc = ./jotta-cli.md;
+}
diff --git a/nixos/modules/services/security/oauth2_proxy_nginx.nix b/nixos/modules/services/security/oauth2-proxy-nginx.nix
index 91d846abb36e6..c05bd304752d1 100644
--- a/nixos/modules/services/security/oauth2_proxy_nginx.nix
+++ b/nixos/modules/services/security/oauth2-proxy-nginx.nix
@@ -1,56 +1,55 @@
 { config, lib, ... }:
-with lib;
 let
-  cfg = config.services.oauth2_proxy.nginx;
+  cfg = config.services.oauth2-proxy.nginx;
 in
 {
-  options.services.oauth2_proxy.nginx = {
-    proxy = mkOption {
-      type = types.str;
-      default = config.services.oauth2_proxy.httpAddress;
-      defaultText = literalExpression "config.services.oauth2_proxy.httpAddress";
+  options.services.oauth2-proxy.nginx = {
+    proxy = lib.mkOption {
+      type = lib.types.str;
+      default = config.services.oauth2-proxy.httpAddress;
+      defaultText = lib.literalExpression "config.services.oauth2-proxy.httpAddress";
       description = ''
-        The address of the reverse proxy endpoint for oauth2_proxy
+        The address of the reverse proxy endpoint for oauth2-proxy
       '';
     };
 
-    domain = mkOption {
-      type = types.str;
+    domain = lib.mkOption {
+      type = lib.types.str;
       description = ''
-        The domain under which the oauth2_proxy will be accesible and the path of cookies are set to.
+        The domain under which the oauth2-proxy will be accesible and the path of cookies are set to.
         This setting must be set to ensure back-redirects are working properly
-        if oauth2-proxy is configured with {option}`services.oauth2_proxy.cookie.domain`
-        or multiple {option}`services.oauth2_proxy.nginx.virtualHosts` that are not on the same domain.
+        if oauth2-proxy is configured with {option}`services.oauth2-proxy.cookie.domain`
+        or multiple {option}`services.oauth2-proxy.nginx.virtualHosts` that are not on the same domain.
       '';
     };
 
-    virtualHosts = mkOption {
+    virtualHosts = lib.mkOption {
       type = let
-        vhostSubmodule = types.submodule {
+        vhostSubmodule = lib.types.submodule {
           options = {
-            allowed_groups = mkOption {
-              type = types.nullOr (types.listOf types.str);
+            allowed_groups = lib.mkOption {
+              type = lib.types.nullOr (lib.types.listOf lib.types.str);
               description = "List of groups to allow access to this vhost, or null to allow all.";
               default = null;
             };
-            allowed_emails = mkOption {
-              type = types.nullOr (types.listOf types.str);
+            allowed_emails = lib.mkOption {
+              type = lib.types.nullOr (lib.types.listOf lib.types.str);
               description = "List of emails to allow access to this vhost, or null to allow all.";
               default = null;
             };
-            allowed_email_domains = mkOption {
-              type = types.nullOr (types.listOf types.str);
+            allowed_email_domains = lib.mkOption {
+              type = lib.types.nullOr (lib.types.listOf lib.types.str);
               description = "List of email domains to allow access to this vhost, or null to allow all.";
               default = null;
             };
           };
         };
-        oldType = types.listOf types.str;
+        oldType = lib.types.listOf lib.types.str;
         convertFunc = x:
-          lib.warn "services.oauth2_proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty {} x}"
+          lib.warn "services.oauth2-proxy.nginx.virtualHosts should be an attrset, found ${lib.generators.toPretty {} x}"
           lib.genAttrs x (_: {});
-        newType = types.attrsOf vhostSubmodule;
-      in types.coercedTo oldType convertFunc newType;
+        newType = lib.types.attrsOf vhostSubmodule;
+      in lib.types.coercedTo oldType convertFunc newType;
       default = {};
       example = {
         "protected.foo.com" = {
@@ -65,11 +64,11 @@ in
     };
   };
 
-  config.services.oauth2_proxy = mkIf (cfg.virtualHosts != [] && (hasPrefix "127.0.0.1:" cfg.proxy)) {
+  config.services.oauth2-proxy = lib.mkIf (cfg.virtualHosts != [] && (lib.hasPrefix "127.0.0.1:" cfg.proxy)) {
     enable = true;
   };
 
-  config.services.nginx = mkIf (cfg.virtualHosts != [] && config.services.oauth2_proxy.enable) (mkMerge ([
+  config.services.nginx = lib.mkIf (cfg.virtualHosts != [] && config.services.oauth2-proxy.enable) (lib.mkMerge ([
     {
       virtualHosts.${cfg.domain}.locations."/oauth2/" = {
         proxyPass = cfg.proxy;
@@ -79,7 +78,7 @@ in
         '';
       };
     }
-  ] ++ optional (cfg.virtualHosts != []) {
+  ] ++ lib.optional (cfg.virtualHosts != []) {
     recommendedProxySettings = true; # needed because duplicate headers
   } ++ (lib.mapAttrsToList (vhost: conf: {
     virtualHosts.${vhost} = {
diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2-proxy.nix
index d2992a196bf87..075e64b743b1e 100644
--- a/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixos/modules/services/security/oauth2-proxy.nix
@@ -1,15 +1,12 @@
-# NixOS module for oauth2_proxy.
-
 { config, lib, pkgs, ... }:
 
-with lib;
 let
-  cfg = config.services.oauth2_proxy;
+  cfg = config.services.oauth2-proxy;
 
-  # oauth2_proxy provides many options that are only relevant if you are using
+  # oauth2-proxy provides many options that are only relevant if you are using
   # a certain provider. This set maps from provider name to a function that
   # takes the configuration and returns a string that can be inserted into the
-  # command-line to launch oauth2_proxy.
+  # command-line to launch oauth2-proxy.
   providerSpecificOptions = {
     azure = cfg: {
       azure-tenant = cfg.azure.tenant;
@@ -73,28 +70,28 @@ let
   } // (getProviderOptions cfg cfg.provider) // cfg.extraConfig;
 
   mapConfig = key: attr:
-  optionalString (attr != null && attr != []) (
-    if isDerivation attr then mapConfig key (toString attr) else
-    if (builtins.typeOf attr) == "set" then concatStringsSep " "
-      (mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
-    if (builtins.typeOf attr) == "list" then concatMapStringsSep " " (mapConfig key) attr else
-    if (builtins.typeOf attr) == "bool" then "--${key}=${boolToString attr}" else
+  lib.optionalString (attr != null && attr != []) (
+    if lib.isDerivation attr then mapConfig key (toString attr) else
+    if (builtins.typeOf attr) == "set" then lib.concatStringsSep " "
+      (lib.mapAttrsToList (name: value: mapConfig (key + "-" + name) value) attr) else
+    if (builtins.typeOf attr) == "list" then lib.concatMapStringsSep " " (mapConfig key) attr else
+    if (builtins.typeOf attr) == "bool" then "--${key}=${lib.boolToString attr}" else
     if (builtins.typeOf attr) == "string" then "--${key}='${attr}'" else
     "--${key}=${toString attr}");
 
-  configString = concatStringsSep " " (mapAttrsToList mapConfig allConfig);
+  configString = lib.concatStringsSep " " (lib.mapAttrsToList mapConfig allConfig);
 in
 {
-  options.services.oauth2_proxy = {
-    enable = mkEnableOption "oauth2_proxy";
+  options.services.oauth2-proxy = {
+    enable = lib.mkEnableOption "oauth2-proxy";
 
-    package = mkPackageOption pkgs "oauth2-proxy" { };
+    package = lib.mkPackageOption pkgs "oauth2-proxy" { };
 
     ##############################################
     # PROVIDER configuration
     # Taken from: https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/providers.go
-    provider = mkOption {
-      type = types.enum [
+    provider = lib.mkOption {
+      type = lib.types.enum [
         "adfs"
         "azure"
         "bitbucket"
@@ -116,24 +113,24 @@ in
       '';
     };
 
-    approvalPrompt = mkOption {
-      type = types.enum ["force" "auto"];
+    approvalPrompt = lib.mkOption {
+      type = lib.types.enum ["force" "auto"];
       default = "force";
       description = ''
         OAuth approval_prompt.
       '';
     };
 
-    clientID = mkOption {
-      type = types.nullOr types.str;
+    clientID = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       description = ''
         The OAuth Client ID.
       '';
       example = "123456.apps.googleusercontent.com";
     };
 
-    oidcIssuerUrl = mkOption {
-      type = types.nullOr types.str;
+    oidcIssuerUrl = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         The OAuth issuer URL.
@@ -141,15 +138,15 @@ in
       example = "https://login.microsoftonline.com/{TENANT_ID}/v2.0";
     };
 
-    clientSecret = mkOption {
-      type = types.nullOr types.str;
+    clientSecret = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       description = ''
         The OAuth Client Secret.
       '';
     };
 
-    skipAuthRegexes = mkOption {
-     type = types.listOf types.str;
+    skipAuthRegexes = lib.mkOption {
+     type = lib.types.listOf lib.types.str;
      default = [];
      description = ''
        Skip authentication for requests matching any of these regular
@@ -159,8 +156,8 @@ in
 
     # XXX: Not clear whether these two options are mutually exclusive or not.
     email = {
-      domains = mkOption {
-        type = types.listOf types.str;
+      domains = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [];
         description = ''
           Authenticate emails with the specified domains. Use
@@ -168,8 +165,8 @@ in
         '';
       };
 
-      addresses = mkOption {
-        type = types.nullOr types.lines;
+      addresses = lib.mkOption {
+        type = lib.types.nullOr lib.types.lines;
         default = null;
         description = ''
           Line-separated email addresses that are allowed to authenticate.
@@ -177,8 +174,8 @@ in
       };
     };
 
-    loginURL = mkOption {
-      type = types.nullOr types.str;
+    loginURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Authentication endpoint.
@@ -190,8 +187,8 @@ in
       example = "https://provider.example.com/oauth/authorize";
     };
 
-    redeemURL = mkOption {
-      type = types.nullOr types.str;
+    redeemURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Token redemption endpoint.
@@ -203,8 +200,8 @@ in
       example = "https://provider.example.com/oauth/token";
     };
 
-    validateURL = mkOption {
-      type = types.nullOr types.str;
+    validateURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Access token validation endpoint.
@@ -216,10 +213,10 @@ in
       example = "https://provider.example.com/user/emails";
     };
 
-    redirectURL = mkOption {
+    redirectURL = lib.mkOption {
       # XXX: jml suspects this is always necessary, but the command-line
       # doesn't require it so making it optional.
-      type = types.nullOr types.str;
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         The OAuth2 redirect URL.
@@ -228,16 +225,16 @@ in
     };
 
     azure = {
-      tenant = mkOption {
-        type = types.str;
+      tenant = lib.mkOption {
+        type = lib.types.str;
         default = "common";
         description = ''
           Go to a tenant-specific or common (tenant-independent) endpoint.
         '';
       };
 
-      resource = mkOption {
-        type = types.str;
+      resource = lib.mkOption {
+        type = lib.types.str;
         description = ''
           The resource that is protected.
         '';
@@ -245,8 +242,8 @@ in
     };
 
     google = {
-      adminEmail = mkOption {
-        type = types.str;
+      adminEmail = lib.mkOption {
+        type = lib.types.str;
         description = ''
           The Google Admin to impersonate for API calls.
 
@@ -258,16 +255,16 @@ in
         '';
       };
 
-      groups = mkOption {
-        type = types.listOf types.str;
+      groups = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
         default = [];
         description = ''
           Restrict logins to members of these Google groups.
         '';
       };
 
-      serviceAccountJSON = mkOption {
-        type = types.path;
+      serviceAccountJSON = lib.mkOption {
+        type = lib.types.path;
         description = ''
           The path to the service account JSON credentials.
         '';
@@ -275,16 +272,16 @@ in
     };
 
     github = {
-      org = mkOption {
-        type = types.nullOr types.str;
+      org = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Restrict logins to members of this organisation.
         '';
       };
 
-      team = mkOption {
-        type = types.nullOr types.str;
+      team = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Restrict logins to members of this team.
@@ -295,8 +292,8 @@ in
 
     ####################################################
     # UPSTREAM Configuration
-    upstream = mkOption {
-      type = with types; coercedTo str (x: [x]) (listOf str);
+    upstream = lib.mkOption {
+      type = with lib.types; coercedTo str (x: [x]) (listOf str);
       default = [];
       description = ''
         The http url(s) of the upstream endpoint or `file://`
@@ -304,40 +301,40 @@ in
       '';
     };
 
-    passAccessToken = mkOption {
-      type = types.bool;
+    passAccessToken = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         Pass OAuth access_token to upstream via X-Forwarded-Access-Token header.
       '';
     };
 
-    passBasicAuth = mkOption {
-      type = types.bool;
+    passBasicAuth = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream.
       '';
     };
 
-    basicAuthPassword = mkOption {
-      type = types.nullOr types.str;
+    basicAuthPassword = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         The password to set when passing the HTTP Basic Auth header.
       '';
     };
 
-    passHostHeader = mkOption {
-      type = types.bool;
+    passHostHeader = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Pass the request Host Header to upstream.
       '';
     };
 
-    signatureKey = mkOption {
-      type = types.nullOr types.str;
+    signatureKey = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         GAP-Signature request signature key.
@@ -346,8 +343,8 @@ in
     };
 
     cookie = {
-      domain = mkOption {
-        type = types.nullOr types.str;
+      domain = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Optional cookie domains to force cookies to (ie: `.yourcompany.com`).
@@ -357,33 +354,33 @@ in
         example = ".yourcompany.com";
       };
 
-      expire = mkOption {
-        type = types.str;
+      expire = lib.mkOption {
+        type = lib.types.str;
         default = "168h0m0s";
         description = ''
           Expire timeframe for cookie.
         '';
       };
 
-      httpOnly = mkOption {
-        type = types.bool;
+      httpOnly = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Set HttpOnly cookie flag.
         '';
       };
 
-      name = mkOption {
-        type = types.str;
+      name = lib.mkOption {
+        type = lib.types.str;
         default = "_oauth2_proxy";
         description = ''
           The name of the cookie that the oauth_proxy creates.
         '';
       };
 
-      refresh = mkOption {
+      refresh = lib.mkOption {
         # XXX: Unclear what the behavior is when this is not specified.
-        type = types.nullOr types.str;
+        type = lib.types.nullOr lib.types.str;
         default = null;
         description = ''
           Refresh the cookie after this duration; 0 to disable.
@@ -391,15 +388,15 @@ in
         example = "168h0m0s";
       };
 
-      secret = mkOption {
-        type = types.nullOr types.str;
+      secret = lib.mkOption {
+        type = lib.types.nullOr lib.types.str;
         description = ''
           The seed string for secure cookies.
         '';
       };
 
-      secure = mkOption {
-        type = types.bool;
+      secure = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Set secure (HTTPS) cookie flag.
@@ -410,8 +407,8 @@ in
     ####################################################
     # OAUTH2 PROXY configuration
 
-    httpAddress = mkOption {
-      type = types.str;
+    httpAddress = lib.mkOption {
+      type = lib.types.str;
       default = "http://127.0.0.1:4180";
       description = ''
         HTTPS listening address.  This module does not expose the port by
@@ -421,8 +418,8 @@ in
     };
 
     htpasswd = {
-      file = mkOption {
-        type = types.nullOr types.path;
+      file = lib.mkOption {
+        type = lib.types.nullOr lib.types.path;
         default = null;
         description = ''
           Additionally authenticate against a htpasswd file. Entries must be
@@ -430,8 +427,8 @@ in
         '';
       };
 
-      displayForm = mkOption {
-        type = types.bool;
+      displayForm = lib.mkOption {
+        type = lib.types.bool;
         default = true;
         description = ''
           Display username / password login form if an htpasswd file is provided.
@@ -439,16 +436,16 @@ in
       };
     };
 
-    customTemplatesDir = mkOption {
-      type = types.nullOr types.path;
+    customTemplatesDir = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
       default = null;
       description = ''
         Path to custom HTML templates.
       '';
     };
 
-    reverseProxy = mkOption {
-      type = types.bool;
+    reverseProxy = lib.mkOption {
+      type = lib.types.bool;
       default = false;
       description = ''
         In case when running behind a reverse proxy, controls whether headers
@@ -458,8 +455,8 @@ in
       '';
     };
 
-    proxyPrefix = mkOption {
-      type = types.str;
+    proxyPrefix = lib.mkOption {
+      type = lib.types.str;
       default = "/oauth2";
       description = ''
         The url root path that this proxy should be nested under.
@@ -467,30 +464,30 @@ in
     };
 
     tls = {
-      enable = mkOption {
-        type = types.bool;
+      enable = lib.mkOption {
+        type = lib.types.bool;
         default = false;
         description = ''
           Whether to serve over TLS.
         '';
       };
 
-      certificate = mkOption {
-        type = types.path;
+      certificate = lib.mkOption {
+        type = lib.types.path;
         description = ''
           Path to certificate file.
         '';
       };
 
-      key = mkOption {
-        type = types.path;
+      key = lib.mkOption {
+        type = lib.types.path;
         description = ''
           Path to private key file.
         '';
       };
 
-      httpsAddress = mkOption {
-        type = types.str;
+      httpsAddress = lib.mkOption {
+        type = lib.types.str;
         default = ":443";
         description = ''
           `addr:port` to listen on for HTTPS clients.
@@ -502,8 +499,8 @@ in
       };
     };
 
-    requestLogging = mkOption {
-      type = types.bool;
+    requestLogging = lib.mkOption {
+      type = lib.types.bool;
       default = true;
       description = ''
         Log requests to stdout.
@@ -514,42 +511,42 @@ in
     # UNKNOWN
 
     # XXX: Is this mandatory? Is it part of another group? Is it part of the provider specification?
-    scope = mkOption {
+    scope = lib.mkOption {
       # XXX: jml suspects this is always necessary, but the command-line
       # doesn't require it so making it optional.
-      type = types.nullOr types.str;
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         OAuth scope specification.
       '';
     };
 
-    profileURL = mkOption {
-      type = types.nullOr types.str;
+    profileURL = lib.mkOption {
+      type = lib.types.nullOr lib.types.str;
       default = null;
       description = ''
         Profile access endpoint.
       '';
     };
 
-    setXauthrequest = mkOption {
-      type = types.nullOr types.bool;
+    setXauthrequest = lib.mkOption {
+      type = lib.types.nullOr lib.types.bool;
       default = false;
       description = ''
         Set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode). Setting this to 'null' means using the upstream default (false).
       '';
     };
 
-    extraConfig = mkOption {
+    extraConfig = lib.mkOption {
       default = {};
-      type = types.attrsOf types.anything;
+      type = lib.types.attrsOf lib.types.anything;
       description = ''
         Extra config to pass to oauth2-proxy.
       '';
     };
 
-    keyFile = mkOption {
-      type = types.nullOr types.path;
+    keyFile = lib.mkOption {
+      type = lib.types.nullOr lib.types.path;
       default = null;
       description = ''
         oauth2-proxy allows passing sensitive configuration via environment variables.
@@ -557,28 +554,30 @@ in
         OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
         and specify the path here.
       '';
-      example = "/run/keys/oauth2_proxy";
+      example = "/run/keys/oauth2-proxy";
     };
-
   };
 
-  config = mkIf cfg.enable {
+  imports = [
+    (lib.mkRenamedOptionModule [ "services" "oauth2_proxy" ] [ "services" "oauth2-proxy" ])
+  ];
 
-    services.oauth2_proxy = mkIf (cfg.keyFile != null) {
-      clientID = mkDefault null;
-      clientSecret = mkDefault null;
-      cookie.secret = mkDefault null;
+  config = lib.mkIf cfg.enable {
+    services.oauth2-proxy = lib.mkIf (cfg.keyFile != null) {
+      clientID = lib.mkDefault null;
+      clientSecret = lib.mkDefault null;
+      cookie.secret = lib.mkDefault null;
     };
 
-    users.users.oauth2_proxy = {
+    users.users.oauth2-proxy = {
       description = "OAuth2 Proxy";
       isSystemUser = true;
-      group = "oauth2_proxy";
+      group = "oauth2-proxy";
     };
 
-    users.groups.oauth2_proxy = {};
+    users.groups.oauth2-proxy = {};
 
-    systemd.services.oauth2_proxy = {
+    systemd.services.oauth2-proxy = {
       description = "OAuth2 Proxy";
       path = [ cfg.package ];
       wantedBy = [ "multi-user.target" ];
@@ -586,10 +585,10 @@ in
       after = [ "network-online.target" ];
 
       serviceConfig = {
-        User = "oauth2_proxy";
+        User = "oauth2-proxy";
         Restart = "always";
         ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
-        EnvironmentFile = mkIf (cfg.keyFile != null) cfg.keyFile;
+        EnvironmentFile = lib.mkIf (cfg.keyFile != null) cfg.keyFile;
       };
     };