summary refs log tree commit diff
path: root/nixos/modules/services/security
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/security')
-rw-r--r--nixos/modules/services/security/aesmd.nix20
-rw-r--r--nixos/modules/services/security/certmgr.nix22
-rw-r--r--nixos/modules/services/security/cfssl.nix42
-rw-r--r--nixos/modules/services/security/clamav.nix12
-rw-r--r--nixos/modules/services/security/fail2ban.nix48
-rw-r--r--nixos/modules/services/security/fprintd.nix4
-rw-r--r--nixos/modules/services/security/haka.nix12
-rw-r--r--nixos/modules/services/security/haveged.nix2
-rw-r--r--nixos/modules/services/security/hockeypuck.nix2
-rw-r--r--nixos/modules/services/security/hologram-agent.nix6
-rw-r--r--nixos/modules/services/security/hologram-server.nix30
-rw-r--r--nixos/modules/services/security/kanidm.nix46
-rw-r--r--nixos/modules/services/security/munge.nix2
-rw-r--r--nixos/modules/services/security/nginx-sso.nix6
-rw-r--r--nixos/modules/services/security/oauth2_proxy.nix108
-rw-r--r--nixos/modules/services/security/oauth2_proxy_nginx.nix4
-rw-r--r--nixos/modules/services/security/opensnitch.nix24
-rw-r--r--nixos/modules/services/security/pass-secret-service.nix2
-rw-r--r--nixos/modules/services/security/physlock.nix22
-rw-r--r--nixos/modules/services/security/privacyidea.nix30
-rw-r--r--nixos/modules/services/security/shibboleth-sp.nix10
-rw-r--r--nixos/modules/services/security/sks.nix12
-rw-r--r--nixos/modules/services/security/sshguard.nix16
-rw-r--r--nixos/modules/services/security/step-ca.nix10
-rw-r--r--nixos/modules/services/security/tor.nix34
-rw-r--r--nixos/modules/services/security/torify.nix4
-rw-r--r--nixos/modules/services/security/torsocks.nix22
-rw-r--r--nixos/modules/services/security/usbguard.nix20
-rw-r--r--nixos/modules/services/security/vault.nix24
-rw-r--r--nixos/modules/services/security/vaultwarden/default.nix8
-rw-r--r--nixos/modules/services/security/yubikey-agent.nix4
31 files changed, 304 insertions, 304 deletions
diff --git a/nixos/modules/services/security/aesmd.nix b/nixos/modules/services/security/aesmd.nix
index 8268b034a15..2f7deb7c849 100644
--- a/nixos/modules/services/security/aesmd.nix
+++ b/nixos/modules/services/security/aesmd.nix
@@ -23,23 +23,23 @@ in
     debug = mkOption {
       type = types.bool;
       default = false;
-      description = "Whether to build the PSW package in debug mode.";
+      description = lib.mdDoc "Whether to build the PSW package in debug mode.";
     };
     settings = mkOption {
-      description = "AESM configuration";
+      description = lib.mdDoc "AESM configuration";
       default = { };
       type = types.submodule {
         options.whitelistUrl = mkOption {
           type = with types; nullOr str;
           default = null;
           example = "http://whitelist.trustedservices.intel.com/SGX/LCWL/Linux/sgx_white_list_cert.bin";
-          description = "URL to retrieve authorized Intel SGX enclave signers.";
+          description = lib.mdDoc "URL to retrieve authorized Intel SGX enclave signers.";
         };
         options.proxy = mkOption {
           type = with types; nullOr str;
           default = null;
           example = "http://proxy_url:1234";
-          description = "HTTP network proxy.";
+          description = lib.mdDoc "HTTP network proxy.";
         };
         options.proxyType = mkOption {
           type = with types; nullOr (enum [ "default" "direct" "manual" ]);
@@ -48,18 +48,18 @@ in
             if (config.${opt.settings}.proxy != null) then "manual" else null
           '';
           example = "default";
-          description = ''
-            Type of proxy to use. The <literal>default</literal> uses the system's default proxy.
-            If <literal>direct</literal> is given, uses no proxy.
-            A value of <literal>manual</literal> uses the proxy from
-            <option>services.aesmd.settings.proxy</option>.
+          description = lib.mdDoc ''
+            Type of proxy to use. The `default` uses the system's default proxy.
+            If `direct` is given, uses no proxy.
+            A value of `manual` uses the proxy from
+            {option}`services.aesmd.settings.proxy`.
           '';
         };
         options.defaultQuotingType = mkOption {
           type = with types; nullOr (enum [ "ecdsa_256" "epid_linkable" "epid_unlinkable" ]);
           default = null;
           example = "ecdsa_256";
-          description = "Attestation quote type.";
+          description = lib.mdDoc "Attestation quote type.";
         };
       };
     };
diff --git a/nixos/modules/services/security/certmgr.nix b/nixos/modules/services/security/certmgr.nix
index d302a4e0002..40a566bc960 100644
--- a/nixos/modules/services/security/certmgr.nix
+++ b/nixos/modules/services/security/certmgr.nix
@@ -41,37 +41,37 @@ in
       type = types.package;
       default = pkgs.certmgr;
       defaultText = literalExpression "pkgs.certmgr";
-      description = "Which certmgr package to use in the service.";
+      description = lib.mdDoc "Which certmgr package to use in the service.";
     };
 
     defaultRemote = mkOption {
       type = types.str;
       default = "127.0.0.1:8888";
-      description = "The default CA host:port to use.";
+      description = lib.mdDoc "The default CA host:port to use.";
     };
 
     validMin = mkOption {
       default = "72h";
       type = types.str;
-      description = "The interval before a certificate expires to start attempting to renew it.";
+      description = lib.mdDoc "The interval before a certificate expires to start attempting to renew it.";
     };
 
     renewInterval = mkOption {
       default = "30m";
       type = types.str;
-      description = "How often to check certificate expirations and how often to update the cert_next_expires metric.";
+      description = lib.mdDoc "How often to check certificate expirations and how often to update the cert_next_expires metric.";
     };
 
     metricsAddress = mkOption {
       default = "127.0.0.1";
       type = types.str;
-      description = "The address for the Prometheus HTTP endpoint.";
+      description = lib.mdDoc "The address for the Prometheus HTTP endpoint.";
     };
 
     metricsPort = mkOption {
       default = 9488;
       type = types.ints.u16;
-      description = "The port for the Prometheus HTTP endpoint.";
+      description = lib.mdDoc "The port for the Prometheus HTTP endpoint.";
     };
 
     specs = mkOption {
@@ -149,9 +149,9 @@ in
           };
         };
     }));
-      description = ''
+      description = lib.mdDoc ''
         Certificate specs as described by:
-        <link xlink:href="https://github.com/cloudflare/certmgr#certificate-specs" />
+        <https://github.com/cloudflare/certmgr#certificate-specs>
         These will be added to the Nix store, so they will be world readable.
       '';
     };
@@ -159,11 +159,11 @@ in
     svcManager = mkOption {
       default = "systemd";
       type = types.enum [ "circus" "command" "dummy" "openrc" "systemd" "sysv" ];
-      description = ''
+      description = lib.mdDoc ''
         This specifies the service manager to use for restarting or reloading services.
-        See: <link xlink:href="https://github.com/cloudflare/certmgr#certmgryaml" />.
+        See: <https://github.com/cloudflare/certmgr#certmgryaml>.
         For how to use the "command" service manager in particular,
-        see: <link xlink:href="https://github.com/cloudflare/certmgr#command-svcmgr-and-how-to-use-it" />.
+        see: <https://github.com/cloudflare/certmgr#command-svcmgr-and-how-to-use-it>.
       '';
     };
 
diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix
index 6df2343b84d..9408a602f13 100644
--- a/nixos/modules/services/security/cfssl.nix
+++ b/nixos/modules/services/security/cfssl.nix
@@ -26,49 +26,49 @@ in {
     address = mkOption {
       default = "127.0.0.1";
       type = types.str;
-      description = "Address to bind.";
+      description = lib.mdDoc "Address to bind.";
     };
 
     port = mkOption {
       default = 8888;
       type = types.port;
-      description = "Port to bind.";
+      description = lib.mdDoc "Port to bind.";
     };
 
     ca = mkOption {
       defaultText = literalExpression ''"''${cfg.dataDir}/ca.pem"'';
       type = types.str;
-      description = "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'.";
+      description = lib.mdDoc "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'.";
     };
 
     caKey = mkOption {
       defaultText = literalExpression ''"file:''${cfg.dataDir}/ca-key.pem"'';
       type = types.str;
-      description = "CA private key -- accepts '[file:]fname' or 'env:varname'.";
+      description = lib.mdDoc "CA private key -- accepts '[file:]fname' or 'env:varname'.";
     };
 
     caBundle = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Path to root certificate store.";
+      description = lib.mdDoc "Path to root certificate store.";
     };
 
     intBundle = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Path to intermediate certificate store.";
+      description = lib.mdDoc "Path to intermediate certificate store.";
     };
 
     intDir = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Intermediates directory.";
+      description = lib.mdDoc "Intermediates directory.";
     };
 
     metadata = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = ''
+      description = lib.mdDoc ''
         Metadata file for root certificate presence.
         The content of the file is a json dictionary (k,v): each key k is
         a SHA-1 digest of a root certificate while value v is a list of key
@@ -79,79 +79,79 @@ in {
     remote = mkOption {
       default = null;
       type = types.nullOr types.str;
-      description = "Remote CFSSL server.";
+      description = lib.mdDoc "Remote CFSSL server.";
     };
 
     configFile = mkOption {
       default = null;
       type = types.nullOr types.str;
-      description = "Path to configuration file. Do not put this in nix-store as it might contain secrets.";
+      description = lib.mdDoc "Path to configuration file. Do not put this in nix-store as it might contain secrets.";
     };
 
     responder = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Certificate for OCSP responder.";
+      description = lib.mdDoc "Certificate for OCSP responder.";
     };
 
     responderKey = mkOption {
       default = null;
       type = types.nullOr types.str;
-      description = "Private key for OCSP responder certificate. Do not put this in nix-store.";
+      description = lib.mdDoc "Private key for OCSP responder certificate. Do not put this in nix-store.";
     };
 
     tlsKey = mkOption {
       default = null;
       type = types.nullOr types.str;
-      description = "Other endpoint's CA private key. Do not put this in nix-store.";
+      description = lib.mdDoc "Other endpoint's CA private key. Do not put this in nix-store.";
     };
 
     tlsCert = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Other endpoint's CA to set up TLS protocol.";
+      description = lib.mdDoc "Other endpoint's CA to set up TLS protocol.";
     };
 
     mutualTlsCa = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Mutual TLS - require clients be signed by this CA.";
+      description = lib.mdDoc "Mutual TLS - require clients be signed by this CA.";
     };
 
     mutualTlsCn = mkOption {
       default = null;
       type = types.nullOr types.str;
-      description = "Mutual TLS - regex for whitelist of allowed client CNs.";
+      description = lib.mdDoc "Mutual TLS - regex for whitelist of allowed client CNs.";
     };
 
     tlsRemoteCa = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "CAs to trust for remote TLS requests.";
+      description = lib.mdDoc "CAs to trust for remote TLS requests.";
     };
 
     mutualTlsClientCert = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Mutual TLS - client certificate to call remote instance requiring client certs.";
+      description = lib.mdDoc "Mutual TLS - client certificate to call remote instance requiring client certs.";
     };
 
     mutualTlsClientKey = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Mutual TLS - client key to call remote instance requiring client certs. Do not put this in nix-store.";
+      description = lib.mdDoc "Mutual TLS - client key to call remote instance requiring client certs. Do not put this in nix-store.";
     };
 
     dbConfig = mkOption {
       default = null;
       type = types.nullOr types.path;
-      description = "Certificate db configuration file. Path must be writeable.";
+      description = lib.mdDoc "Certificate db configuration file. Path must be writeable.";
     };
 
     logLevel = mkOption {
       default = 1;
       type = types.enum [ 0 1 2 3 4 5 ];
-      description = "Log level (0 = DEBUG, 5 = FATAL).";
+      description = lib.mdDoc "Log level (0 = DEBUG, 5 = FATAL).";
     };
   };
 
diff --git a/nixos/modules/services/security/clamav.nix b/nixos/modules/services/security/clamav.nix
index 95a0ad8770e..1b1194d3113 100644
--- a/nixos/modules/services/security/clamav.nix
+++ b/nixos/modules/services/security/clamav.nix
@@ -31,8 +31,8 @@ in
         settings = mkOption {
           type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
           default = { };
-          description = ''
-            ClamAV configuration. Refer to <link xlink:href="https://linux.die.net/man/5/clamd.conf"/>,
+          description = lib.mdDoc ''
+            ClamAV configuration. Refer to <https://linux.die.net/man/5/clamd.conf>,
             for details on supported values.
           '';
         };
@@ -43,7 +43,7 @@ in
         frequency = mkOption {
           type = types.int;
           default = 12;
-          description = ''
+          description = lib.mdDoc ''
             Number of database checks per day.
           '';
         };
@@ -51,7 +51,7 @@ in
         interval = mkOption {
           type = types.str;
           default = "hourly";
-          description = ''
+          description = lib.mdDoc ''
             How often freshclam is invoked. See systemd.time(7) for more
             information about the format.
           '';
@@ -60,8 +60,8 @@ in
         settings = mkOption {
           type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
           default = { };
-          description = ''
-            freshclam configuration. Refer to <link xlink:href="https://linux.die.net/man/5/freshclam.conf"/>,
+          description = lib.mdDoc ''
+            freshclam configuration. Refer to <https://linux.die.net/man/5/freshclam.conf>,
             for details on supported values.
           '';
         };
diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix
index 67e1026dcef..24c84151bc7 100644
--- a/nixos/modules/services/security/fail2ban.nix
+++ b/nixos/modules/services/security/fail2ban.nix
@@ -45,10 +45,10 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
+        description = lib.mdDoc ''
           Whether to enable the fail2ban service.
 
-          See the documentation of <option>services.fail2ban.jails</option>
+          See the documentation of {option}`services.fail2ban.jails`
           for what jails are enabled by default.
         '';
       };
@@ -58,7 +58,7 @@ in
         defaultText = literalExpression "pkgs.fail2ban";
         type = types.package;
         example = literalExpression "pkgs.fail2ban_0_11";
-        description = "The fail2ban package to use for running the fail2ban service.";
+        description = lib.mdDoc "The fail2ban package to use for running the fail2ban service.";
       };
 
       packageFirewall = mkOption {
@@ -66,7 +66,7 @@ in
         defaultText = literalExpression "pkgs.iptables";
         type = types.package;
         example = literalExpression "pkgs.nftables";
-        description = "The firewall package used by fail2ban service.";
+        description = lib.mdDoc "The firewall package used by fail2ban service.";
       };
 
       extraPackages = mkOption {
@@ -82,14 +82,14 @@ in
       maxretry = mkOption {
         default = 3;
         type = types.ints.unsigned;
-        description = "Number of failures before a host gets banned.";
+        description = lib.mdDoc "Number of failures before a host gets banned.";
       };
 
       banaction = mkOption {
         default = "iptables-multiport";
         type = types.str;
         example = "nftables-multiport";
-        description = ''
+        description = lib.mdDoc ''
           Default banning action (e.g. iptables, iptables-new, iptables-multiport,
           shorewall, etc) It is used to define action_* variables. Can be overridden
           globally or per section within jail.local file
@@ -100,7 +100,7 @@ in
         default = "iptables-allport";
         type = types.str;
         example = "nftables-allport";
-        description = ''
+        description = lib.mdDoc ''
           Default banning action (e.g. iptables, iptables-new, iptables-multiport,
           shorewall, etc) It is used to define action_* variables. Can be overridden
           globally or per section within jail.local file
@@ -110,7 +110,7 @@ in
       bantime-increment.enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
+        description = lib.mdDoc ''
           Allows to use database for searching of previously banned ip's to increase
           a default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
         '';
@@ -120,7 +120,7 @@ in
         default = "4m";
         type = types.str;
         example = "8m";
-        description = ''
+        description = lib.mdDoc ''
           "bantime-increment.rndtime" is the max number of seconds using for mixing with random time
           to prevent "clever" botnets calculate exact time IP can be unbanned again
         '';
@@ -130,7 +130,7 @@ in
         default = "10h";
         type = types.str;
         example = "48h";
-        description = ''
+        description = lib.mdDoc ''
           "bantime-increment.maxtime" is the max number of seconds using the ban time can reach (don't grows further)
         '';
       };
@@ -139,7 +139,7 @@ in
         default = "1";
         type = types.str;
         example = "4";
-        description = ''
+        description = lib.mdDoc ''
           "bantime-increment.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
           default value of factor is 1 and with default value of formula, the ban time grows by 1, 2, 4, 8, 16 ...
         '';
@@ -149,7 +149,7 @@ in
         default = "ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor";
         type = types.str;
         example = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
-        description = ''
+        description = lib.mdDoc ''
           "bantime-increment.formula" used by default to calculate next value of ban time, default value bellow,
           the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32...
         '';
@@ -159,7 +159,7 @@ in
         default = "1 2 4 8 16 32 64";
         type = types.str;
         example = "2 4 16 128";
-        description = ''
+        description = lib.mdDoc ''
           "bantime-increment.multipliers" used to calculate next value of ban time instead of formula, coresponding
           previously ban count and given "bantime.factor" (for multipliers default is 1);
           following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count,
@@ -171,7 +171,7 @@ in
         default = false;
         type = types.bool;
         example = true;
-        description = ''
+        description = lib.mdDoc ''
           "bantime-increment.overalljails"  (if true) specifies the search of IP in the database will be executed
           cross over all jails, if false (dafault), only current jail of the ban IP will be searched
         '';
@@ -181,7 +181,7 @@ in
         default = [ ];
         type = types.listOf types.str;
         example = [ "192.168.0.0/16" "2001:DB8::42" ];
-        description = ''
+        description = lib.mdDoc ''
           "ignoreIP" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban will not ban a host which
           matches an address in this list. Several addresses can be defined using space (and/or comma) separator.
         '';
@@ -196,7 +196,7 @@ in
           dbfile    = /var/lib/fail2ban/fail2ban.sqlite3
         '';
         type = types.lines;
-        description = ''
+        description = lib.mdDoc ''
           The contents of Fail2ban's main configuration file.  It's
           generally not necessary to change it.
        '';
@@ -219,22 +219,22 @@ in
           }
         '';
         type = types.attrsOf types.lines;
-        description = ''
+        description = lib.mdDoc ''
           The configuration of each Fail2ban “jail”.  A jail
           consists of an action (such as blocking a port using
-          <command>iptables</command>) that is triggered when a
+          {command}`iptables`) that is triggered when a
           filter applied to a log file triggers more than a certain
           number of times in a certain time period.  Actions are
-          defined in <filename>/etc/fail2ban/action.d</filename>,
+          defined in {file}`/etc/fail2ban/action.d`,
           while filters are defined in
-          <filename>/etc/fail2ban/filter.d</filename>.
+          {file}`/etc/fail2ban/filter.d`.
 
-          NixOS comes with a default <literal>sshd</literal> jail;
+          NixOS comes with a default `sshd` jail;
           for it to work well,
-          <option>services.openssh.logLevel</option> should be set to
-          <literal>"VERBOSE"</literal> or higher so that fail2ban
+          {option}`services.openssh.logLevel` should be set to
+          `"VERBOSE"` or higher so that fail2ban
           can observe failed login attempts.
-          This module sets it to <literal>"VERBOSE"</literal> if
+          This module sets it to `"VERBOSE"` if
           not set otherwise, so enabling fail2ban can make SSH logs
           more verbose.
         '';
diff --git a/nixos/modules/services/security/fprintd.nix b/nixos/modules/services/security/fprintd.nix
index 87c3f1f6f9e..45b370009c3 100644
--- a/nixos/modules/services/security/fprintd.nix
+++ b/nixos/modules/services/security/fprintd.nix
@@ -24,7 +24,7 @@ in
         type = types.package;
         default = fprintdPkg;
         defaultText = literalExpression "if config.services.fprintd.tod.enable then pkgs.fprintd-tod else pkgs.fprintd";
-        description = ''
+        description = lib.mdDoc ''
           fprintd package to use.
         '';
       };
@@ -36,7 +36,7 @@ in
         driver = mkOption {
           type = types.package;
           example = literalExpression "pkgs.libfprint-2-tod1-goodix";
-          description = ''
+          description = lib.mdDoc ''
             Touch OEM Drivers (TOD) package to use.
           '';
         };
diff --git a/nixos/modules/services/security/haka.nix b/nixos/modules/services/security/haka.nix
index 2cfc05f3033..10b7cef54d3 100644
--- a/nixos/modules/services/security/haka.nix
+++ b/nixos/modules/services/security/haka.nix
@@ -70,7 +70,7 @@ in
         default = "empty.lua";
         example = "/srv/haka/myfilter.lua";
         type = types.str;
-        description = ''
+        description = lib.mdDoc ''
           Specify which configuration file Haka uses.
           It can be absolute path or a path relative to the sample directory of
           the haka git repo.
@@ -81,7 +81,7 @@ in
         default = [ "eth0" ];
         example = [ "any" ];
         type = with types; listOf str;
-        description = ''
+        description = lib.mdDoc ''
           Specify which interface(s) Haka listens to.
           Use 'any' to listen to all interfaces.
         '';
@@ -91,7 +91,7 @@ in
         default = 0;
         example = 4;
         type = types.int;
-        description = ''
+        description = lib.mdDoc ''
           The number of threads that will be used.
           All system threads are used by default.
         '';
@@ -100,7 +100,7 @@ in
       pcap = mkOption {
         default = true;
         type = types.bool;
-        description = "Whether to enable pcap";
+        description = lib.mdDoc "Whether to enable pcap";
       };
 
       nfqueue = mkEnableOption "nfqueue";
@@ -110,14 +110,14 @@ in
         default = "/tmp/input.pcap";
         example = "/path/to/file.pcap";
         type = types.path;
-        description = "Path to file where incoming packets are dumped";
+        description = lib.mdDoc "Path to file where incoming packets are dumped";
       };
 
       dump.output  = mkOption {
         default = "/tmp/output.pcap";
         example = "/path/to/file.pcap";
         type = types.path;
-        description = "Path to file where outgoing packets are dumped";
+        description = lib.mdDoc "Path to file where outgoing packets are dumped";
       };
     };
   };
diff --git a/nixos/modules/services/security/haveged.nix b/nixos/modules/services/security/haveged.nix
index 57cef7e44d5..c65d5ab2923 100644
--- a/nixos/modules/services/security/haveged.nix
+++ b/nixos/modules/services/security/haveged.nix
@@ -24,7 +24,7 @@ in
       refill_threshold = mkOption {
         type = types.int;
         default = 1024;
-        description = ''
+        description = lib.mdDoc ''
           The number of bits of available entropy beneath which
           haveged should refill the entropy pool.
         '';
diff --git a/nixos/modules/services/security/hockeypuck.nix b/nixos/modules/services/security/hockeypuck.nix
index d0e152934f5..6fdad13f255 100644
--- a/nixos/modules/services/security/hockeypuck.nix
+++ b/nixos/modules/services/security/hockeypuck.nix
@@ -12,7 +12,7 @@ in {
     port = lib.mkOption {
       default = 11371;
       type = lib.types.port;
-      description = "HKP port to listen on.";
+      description = lib.mdDoc "HKP port to listen on.";
     };
 
     settings = lib.mkOption {
diff --git a/nixos/modules/services/security/hologram-agent.nix b/nixos/modules/services/security/hologram-agent.nix
index e29267e5000..666d95b9b94 100644
--- a/nixos/modules/services/security/hologram-agent.nix
+++ b/nixos/modules/services/security/hologram-agent.nix
@@ -14,19 +14,19 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = "Whether to enable the Hologram agent for AWS instance credentials";
+        description = lib.mdDoc "Whether to enable the Hologram agent for AWS instance credentials";
       };
 
       dialAddress = mkOption {
         type        = types.str;
         default     = "localhost:3100";
-        description = "Hologram server and port.";
+        description = lib.mdDoc "Hologram server and port.";
       };
 
       httpPort = mkOption {
         type        = types.str;
         default     = "80";
-        description = "Port for metadata service to listen on.";
+        description = lib.mdDoc "Port for metadata service to listen on.";
       };
 
     };
diff --git a/nixos/modules/services/security/hologram-server.nix b/nixos/modules/services/security/hologram-server.nix
index 4acf6ae0e21..e995bc79b11 100644
--- a/nixos/modules/services/security/hologram-server.nix
+++ b/nixos/modules/services/security/hologram-server.nix
@@ -33,85 +33,85 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = "Whether to enable the Hologram server for AWS instance credentials";
+        description = lib.mdDoc "Whether to enable the Hologram server for AWS instance credentials";
       };
 
       listenAddress = mkOption {
         type        = types.str;
         default     = "0.0.0.0:3100";
-        description = "Address and port to listen on";
+        description = lib.mdDoc "Address and port to listen on";
       };
 
       ldapHost = mkOption {
         type        = types.str;
-        description = "Address of the LDAP server to use";
+        description = lib.mdDoc "Address of the LDAP server to use";
       };
 
       ldapInsecure = mkOption {
         type        = types.bool;
         default     = false;
-        description = "Whether to connect to LDAP over SSL or not";
+        description = lib.mdDoc "Whether to connect to LDAP over SSL or not";
       };
 
       ldapUserAttr = mkOption {
         type        = types.str;
         default     = "cn";
-        description = "The LDAP attribute for usernames";
+        description = lib.mdDoc "The LDAP attribute for usernames";
       };
 
       ldapBaseDN = mkOption {
         type        = types.str;
-        description = "The base DN for your Hologram users";
+        description = lib.mdDoc "The base DN for your Hologram users";
       };
 
       ldapBindDN = mkOption {
         type        = types.str;
-        description = "DN of account to use to query the LDAP server";
+        description = lib.mdDoc "DN of account to use to query the LDAP server";
       };
 
       ldapBindPassword = mkOption {
         type        = types.str;
-        description = "Password of account to use to query the LDAP server";
+        description = lib.mdDoc "Password of account to use to query the LDAP server";
       };
 
       enableLdapRoles = mkOption {
         type        = types.bool;
         default     = false;
-        description = "Whether to assign user roles based on the user's LDAP group memberships";
+        description = lib.mdDoc "Whether to assign user roles based on the user's LDAP group memberships";
       };
 
       groupClassAttr = mkOption {
         type = types.str;
         default = "groupOfNames";
-        description = "The objectclass attribute to search for groups when enableLdapRoles is true";
+        description = lib.mdDoc "The objectclass attribute to search for groups when enableLdapRoles is true";
       };
 
       roleAttr = mkOption {
         type        = types.str;
         default     = "businessCategory";
-        description = "Which LDAP group attribute to search for authorized role ARNs";
+        description = lib.mdDoc "Which LDAP group attribute to search for authorized role ARNs";
       };
 
       awsAccount = mkOption {
         type        = types.str;
-        description = "AWS account number";
+        description = lib.mdDoc "AWS account number";
       };
 
       awsDefaultRole = mkOption {
         type        = types.str;
-        description = "AWS default role";
+        description = lib.mdDoc "AWS default role";
       };
 
       statsAddress = mkOption {
         type        = types.str;
         default     = "";
-        description = "Address of statsd server";
+        description = lib.mdDoc "Address of statsd server";
       };
 
       cacheTimeoutSeconds = mkOption {
         type        = types.int;
         default     = 3600;
-        description = "How often (in seconds) to refresh the LDAP cache";
+        description = lib.mdDoc "How often (in seconds) to refresh the LDAP cache";
       };
     };
   };
diff --git a/nixos/modules/services/security/kanidm.nix b/nixos/modules/services/security/kanidm.nix
index a7c51b9a877..6429273705d 100644
--- a/nixos/modules/services/security/kanidm.nix
+++ b/nixos/modules/services/security/kanidm.nix
@@ -63,60 +63,60 @@ in
 
         options = {
           bindaddress = lib.mkOption {
-            description = "Address/port combination the webserver binds to.";
+            description = lib.mdDoc "Address/port combination the webserver binds to.";
             example = "[::1]:8443";
             type = lib.types.str;
           };
           # Should be optional but toml does not accept null
           ldapbindaddress = lib.mkOption {
-            description = ''
-              Address and port the LDAP server is bound to. Setting this to <literal>null</literal> disables the LDAP interface.
+            description = lib.mdDoc ''
+              Address and port the LDAP server is bound to. Setting this to `null` disables the LDAP interface.
             '';
             example = "[::1]:636";
             default = null;
             type = lib.types.nullOr lib.types.str;
           };
           origin = lib.mkOption {
-            description = "The origin of your Kanidm instance. Must have https as protocol.";
+            description = lib.mdDoc "The origin of your Kanidm instance. Must have https as protocol.";
             example = "https://idm.example.org";
             type = lib.types.strMatching "^https://.*";
           };
           domain = lib.mkOption {
-            description = ''
-              The <literal>domain</literal> that Kanidm manages. Must be below or equal to the domain
-              specified in <literal>serverSettings.origin</literal>.
-              This can be left at <literal>null</literal>, only if your instance has the role <literal>ReadOnlyReplica</literal>.
+            description = lib.mdDoc ''
+              The `domain` that Kanidm manages. Must be below or equal to the domain
+              specified in `serverSettings.origin`.
+              This can be left at `null`, only if your instance has the role `ReadOnlyReplica`.
               While it is possible to change the domain later on, it requires extra steps!
               Please consider the warnings and execute the steps described
-              <link xlink:href="https://kanidm.github.io/kanidm/stable/administrivia.html#rename-the-domain">in the documentation</link>.
+              [in the documentation](https://kanidm.github.io/kanidm/stable/administrivia.html#rename-the-domain).
             '';
             example = "example.org";
             default = null;
             type = lib.types.nullOr lib.types.str;
           };
           db_path = lib.mkOption {
-            description = "Path to Kanidm database.";
+            description = lib.mdDoc "Path to Kanidm database.";
             default = "/var/lib/kanidm/kanidm.db";
             readOnly = true;
             type = lib.types.path;
           };
           log_level = lib.mkOption {
-            description = "Log level of the server.";
+            description = lib.mdDoc "Log level of the server.";
             default = "default";
             type = lib.types.enum [ "default" "verbose" "perfbasic" "perffull" ];
           };
           role = lib.mkOption {
-            description = "The role of this server. This affects the replication relationship and thereby available features.";
+            description = lib.mdDoc "The role of this server. This affects the replication relationship and thereby available features.";
             default = "WriteReplica";
             type = lib.types.enum [ "WriteReplica" "WriteReplicaNoUI" "ReadOnlyReplica" ];
           };
         };
       };
       default = { };
-      description = ''
+      description = lib.mdDoc ''
         Settings for Kanidm, see
-        <link xlink:href="https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/server_configuration.md">the documentation</link>
-        and <link xlink:href="https://github.com/kanidm/kanidm/blob/master/examples/server.toml">example configuration</link>
+        [the documentation](https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/server_configuration.md)
+        and [example configuration](https://github.com/kanidm/kanidm/blob/master/examples/server.toml)
         for possible values.
       '';
     };
@@ -126,15 +126,15 @@ in
         freeformType = settingsFormat.type;
 
         options.uri = lib.mkOption {
-          description = "Address of the Kanidm server.";
+          description = lib.mdDoc "Address of the Kanidm server.";
           example = "http://127.0.0.1:8080";
           type = lib.types.str;
         };
       };
-      description = ''
+      description = lib.mdDoc ''
         Configure Kanidm clients, needed for the PAM daemon. See
-        <link xlink:href="https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/client_tools.md#kanidm-configuration">the documentation</link>
-        and <link xlink:href="https://github.com/kanidm/kanidm/blob/master/examples/config">example configuration</link>
+        [the documentation](https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/client_tools.md#kanidm-configuration)
+        and [example configuration](https://github.com/kanidm/kanidm/blob/master/examples/config)
         for possible values.
       '';
     };
@@ -144,15 +144,15 @@ in
         freeformType = settingsFormat.type;
 
         options.pam_allowed_login_groups = lib.mkOption {
-          description = "Kanidm groups that are allowed to login using PAM.";
+          description = lib.mdDoc "Kanidm groups that are allowed to login using PAM.";
           example = "my_pam_group";
           type = lib.types.listOf lib.types.str;
         };
       };
-      description = ''
+      description = lib.mdDoc ''
         Configure Kanidm unix daemon.
-        See <link xlink:href="https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/pam_and_nsswitch.md#the-unix-daemon">the documentation</link>
-        and <link xlink:href="https://github.com/kanidm/kanidm/blob/master/examples/unixd">example configuration</link>
+        See [the documentation](https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/pam_and_nsswitch.md#the-unix-daemon)
+        and [example configuration](https://github.com/kanidm/kanidm/blob/master/examples/unixd)
         for possible values.
       '';
     };
diff --git a/nixos/modules/services/security/munge.nix b/nixos/modules/services/security/munge.nix
index 89178886471..e2b0921b4bc 100644
--- a/nixos/modules/services/security/munge.nix
+++ b/nixos/modules/services/security/munge.nix
@@ -20,7 +20,7 @@ in
       password = mkOption {
         default = "/etc/munge/munge.key";
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
           The path to a daemon's secret key.
         '';
       };
diff --git a/nixos/modules/services/security/nginx-sso.nix b/nixos/modules/services/security/nginx-sso.nix
index b4de1d36edd..1c23c29781c 100644
--- a/nixos/modules/services/security/nginx-sso.nix
+++ b/nixos/modules/services/security/nginx-sso.nix
@@ -14,7 +14,7 @@ in {
       type = types.package;
       default = pkgs.nginx-sso;
       defaultText = literalExpression "pkgs.nginx-sso";
-      description = ''
+      description = lib.mdDoc ''
         The nginx-sso package that should be used.
       '';
     };
@@ -40,9 +40,9 @@ in {
           };
         }
       '';
-      description = ''
+      description = lib.mdDoc ''
         nginx-sso configuration
-        (<link xlink:href="https://github.com/Luzifer/nginx-sso/wiki/Main-Configuration">documentation</link>)
+        ([documentation](https://github.com/Luzifer/nginx-sso/wiki/Main-Configuration))
         as a Nix attribute set.
       '';
     };
diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2_proxy.nix
index 5c89d587237..8b2c7fa2140 100644
--- a/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixos/modules/services/security/oauth2_proxy.nix
@@ -92,7 +92,7 @@ in
       type = types.package;
       default = pkgs.oauth2-proxy;
       defaultText = literalExpression "pkgs.oauth2-proxy";
-      description = ''
+      description = lib.mdDoc ''
         The package that provides oauth2-proxy.
       '';
     };
@@ -118,7 +118,7 @@ in
         "oidc"
       ];
       default = "google";
-      description = ''
+      description = lib.mdDoc ''
         OAuth provider.
       '';
     };
@@ -126,14 +126,14 @@ in
     approvalPrompt = mkOption {
       type = types.enum ["force" "auto"];
       default = "force";
-      description = ''
+      description = lib.mdDoc ''
         OAuth approval_prompt.
       '';
     };
 
     clientID = mkOption {
       type = types.nullOr types.str;
-      description = ''
+      description = lib.mdDoc ''
         The OAuth Client ID.
       '';
       example = "123456.apps.googleusercontent.com";
@@ -141,7 +141,7 @@ in
 
     clientSecret = mkOption {
       type = types.nullOr types.str;
-      description = ''
+      description = lib.mdDoc ''
         The OAuth Client Secret.
       '';
     };
@@ -149,7 +149,7 @@ in
     skipAuthRegexes = mkOption {
      type = types.listOf types.str;
      default = [];
-     description = ''
+     description = lib.mdDoc ''
        Skip authentication for requests matching any of these regular
        expressions.
      '';
@@ -169,7 +169,7 @@ in
       addresses = mkOption {
         type = types.nullOr types.lines;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           Line-separated email addresses that are allowed to authenticate.
         '';
       };
@@ -178,7 +178,7 @@ in
     loginURL = mkOption {
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Authentication endpoint.
 
         You only need to set this if you are using a self-hosted provider (e.g.
@@ -191,7 +191,7 @@ in
     redeemURL = mkOption {
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Token redemption endpoint.
 
         You only need to set this if you are using a self-hosted provider (e.g.
@@ -204,7 +204,7 @@ in
     validateURL = mkOption {
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Access token validation endpoint.
 
         You only need to set this if you are using a self-hosted provider (e.g.
@@ -219,7 +219,7 @@ in
       # doesn't require it so making it optional.
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         The OAuth2 redirect URL.
       '';
       example = "https://internalapp.yourcompany.com/oauth2/callback";
@@ -229,14 +229,14 @@ in
       tenant = mkOption {
         type = types.str;
         default = "common";
-        description = ''
+        description = lib.mdDoc ''
           Go to a tenant-specific or common (tenant-independent) endpoint.
         '';
       };
 
       resource = mkOption {
         type = types.str;
-        description = ''
+        description = lib.mdDoc ''
           The resource that is protected.
         '';
       };
@@ -245,28 +245,28 @@ in
     google = {
       adminEmail = mkOption {
         type = types.str;
-        description = ''
+        description = lib.mdDoc ''
           The Google Admin to impersonate for API calls.
 
           Only users with access to the Admin APIs can access the Admin SDK
           Directory API, thus the service account needs to impersonate one of
           those users to access the Admin SDK Directory API.
 
-          See <link xlink:href="https://developers.google.com/admin-sdk/directory/v1/guides/delegation#delegate_domain-wide_authority_to_your_service_account" />.
+          See <https://developers.google.com/admin-sdk/directory/v1/guides/delegation#delegate_domain-wide_authority_to_your_service_account>.
         '';
       };
 
       groups = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = ''
+        description = lib.mdDoc ''
           Restrict logins to members of these Google groups.
         '';
       };
 
       serviceAccountJSON = mkOption {
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
           The path to the service account JSON credentials.
         '';
       };
@@ -276,7 +276,7 @@ in
       org = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           Restrict logins to members of this organisation.
         '';
       };
@@ -284,7 +284,7 @@ in
       team = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           Restrict logins to members of this team.
         '';
       };
@@ -296,8 +296,8 @@ in
     upstream = mkOption {
       type = with types; coercedTo str (x: [x]) (listOf str);
       default = [];
-      description = ''
-        The http url(s) of the upstream endpoint or <literal>file://</literal>
+      description = lib.mdDoc ''
+        The http url(s) of the upstream endpoint or `file://`
         paths for static files. Routing is based on the path.
       '';
     };
@@ -305,7 +305,7 @@ in
     passAccessToken = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         Pass OAuth access_token to upstream via X-Forwarded-Access-Token header.
       '';
     };
@@ -313,7 +313,7 @@ in
     passBasicAuth = mkOption {
       type = types.bool;
       default = true;
-      description = ''
+      description = lib.mdDoc ''
         Pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream.
       '';
     };
@@ -321,7 +321,7 @@ in
     basicAuthPassword = mkOption {
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         The password to set when passing the HTTP Basic Auth header.
       '';
     };
@@ -329,7 +329,7 @@ in
     passHostHeader = mkOption {
       type = types.bool;
       default = true;
-      description = ''
+      description = lib.mdDoc ''
         Pass the request Host Header to upstream.
       '';
     };
@@ -337,7 +337,7 @@ in
     signatureKey = mkOption {
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         GAP-Signature request signature key.
       '';
       example = "sha1:secret0";
@@ -358,7 +358,7 @@ in
       expire = mkOption {
         type = types.str;
         default = "168h0m0s";
-        description = ''
+        description = lib.mdDoc ''
           Expire timeframe for cookie.
         '';
       };
@@ -366,7 +366,7 @@ in
       httpOnly = mkOption {
         type = types.bool;
         default = true;
-        description = ''
+        description = lib.mdDoc ''
           Set HttpOnly cookie flag.
         '';
       };
@@ -374,7 +374,7 @@ in
       name = mkOption {
         type = types.str;
         default = "_oauth2_proxy";
-        description = ''
+        description = lib.mdDoc ''
           The name of the cookie that the oauth_proxy creates.
         '';
       };
@@ -383,7 +383,7 @@ in
         # XXX: Unclear what the behavior is when this is not specified.
         type = types.nullOr types.str;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           Refresh the cookie after this duration; 0 to disable.
         '';
         example = "168h0m0s";
@@ -391,7 +391,7 @@ in
 
       secret = mkOption {
         type = types.nullOr types.str;
-        description = ''
+        description = lib.mdDoc ''
           The seed string for secure cookies.
         '';
       };
@@ -399,7 +399,7 @@ in
       secure = mkOption {
         type = types.bool;
         default = true;
-        description = ''
+        description = lib.mdDoc ''
           Set secure (HTTPS) cookie flag.
         '';
       };
@@ -411,10 +411,10 @@ in
     httpAddress = mkOption {
       type = types.str;
       default = "http://127.0.0.1:4180";
-      description = ''
+      description = lib.mdDoc ''
         HTTPS listening address.  This module does not expose the port by
         default. If you want this URL to be accessible to other machines, please
-        add the port to <literal>networking.firewall.allowedTCPPorts</literal>.
+        add the port to `networking.firewall.allowedTCPPorts`.
       '';
     };
 
@@ -422,16 +422,16 @@ in
       file = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           Additionally authenticate against a htpasswd file. Entries must be
-          created with <literal>htpasswd -s</literal> for SHA encryption.
+          created with `htpasswd -s` for SHA encryption.
         '';
       };
 
       displayForm = mkOption {
         type = types.bool;
         default = true;
-        description = ''
+        description = lib.mdDoc ''
           Display username / password login form if an htpasswd file is provided.
         '';
       };
@@ -440,7 +440,7 @@ in
     customTemplatesDir = mkOption {
       type = types.nullOr types.path;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Path to custom HTML templates.
       '';
     };
@@ -448,9 +448,9 @@ in
     reverseProxy = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         In case when running behind a reverse proxy, controls whether headers
-        like <literal>X-Real-Ip</literal> are accepted. Usage behind a reverse
+        like `X-Real-Ip` are accepted. Usage behind a reverse
         proxy will require this flag to be set to avoid logging the reverse
         proxy IP address.
       '';
@@ -459,7 +459,7 @@ in
     proxyPrefix = mkOption {
       type = types.str;
       default = "/oauth2";
-      description = ''
+      description = lib.mdDoc ''
         The url root path that this proxy should be nested under.
       '';
     };
@@ -468,21 +468,21 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to serve over TLS.
         '';
       };
 
       certificate = mkOption {
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
           Path to certificate file.
         '';
       };
 
       key = mkOption {
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
           Path to private key file.
         '';
       };
@@ -490,11 +490,11 @@ in
       httpsAddress = mkOption {
         type = types.str;
         default = ":443";
-        description = ''
-          <literal>addr:port</literal> to listen on for HTTPS clients.
+        description = lib.mdDoc ''
+          `addr:port` to listen on for HTTPS clients.
 
-          Remember to add <literal>port</literal> to
-          <literal>allowedTCPPorts</literal> if you want other machines to be
+          Remember to add `port` to
+          `allowedTCPPorts` if you want other machines to be
           able to connect to it.
         '';
       };
@@ -503,7 +503,7 @@ in
     requestLogging = mkOption {
       type = types.bool;
       default = true;
-      description = ''
+      description = lib.mdDoc ''
         Log requests to stdout.
       '';
     };
@@ -517,7 +517,7 @@ in
       # doesn't require it so making it optional.
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         OAuth scope specification.
       '';
     };
@@ -525,7 +525,7 @@ in
     profileURL = mkOption {
       type = types.nullOr types.str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Profile access endpoint.
       '';
     };
@@ -533,7 +533,7 @@ in
     setXauthrequest = mkOption {
       type = types.nullOr types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         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).
       '';
     };
@@ -541,7 +541,7 @@ in
     extraConfig = mkOption {
       default = {};
       type = types.attrsOf types.anything;
-      description = ''
+      description = lib.mdDoc ''
         Extra config to pass to oauth2-proxy.
       '';
     };
@@ -549,7 +549,7 @@ in
     keyFile = mkOption {
       type = types.nullOr types.path;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         oauth2-proxy allows passing sensitive configuration via environment variables.
         Make a file that contains lines like
         OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
diff --git a/nixos/modules/services/security/oauth2_proxy_nginx.nix b/nixos/modules/services/security/oauth2_proxy_nginx.nix
index 5853c5a123c..b8e45f67cf7 100644
--- a/nixos/modules/services/security/oauth2_proxy_nginx.nix
+++ b/nixos/modules/services/security/oauth2_proxy_nginx.nix
@@ -9,14 +9,14 @@ in
       type = types.str;
       default = config.services.oauth2_proxy.httpAddress;
       defaultText = literalExpression "config.services.oauth2_proxy.httpAddress";
-      description = ''
+      description = lib.mdDoc ''
         The address of the reverse proxy endpoint for oauth2_proxy
       '';
     };
     virtualHosts = mkOption {
       type = types.listOf types.str;
       default = [];
-      description = ''
+      description = lib.mdDoc ''
         A list of nginx virtual hosts to put behind the oauth2 proxy
       '';
     };
diff --git a/nixos/modules/services/security/opensnitch.nix b/nixos/modules/services/security/opensnitch.nix
index f9b4985e199..4558236339e 100644
--- a/nixos/modules/services/security/opensnitch.nix
+++ b/nixos/modules/services/security/opensnitch.nix
@@ -18,7 +18,7 @@ in {
 
               Address = mkOption {
                 type = types.str;
-                description = ''
+                description = lib.mdDoc ''
                   Unix socket path (unix:///tmp/osui.sock, the "unix:///" part is
                   mandatory) or TCP socket (192.168.1.100:50051).
                 '';
@@ -26,7 +26,7 @@ in {
 
               LogFile = mkOption {
                 type = types.path;
-                description = ''
+                description = lib.mdDoc ''
                   File to write logs to (use /dev/stdout to write logs to standard
                   output).
                 '';
@@ -36,7 +36,7 @@ in {
 
             DefaultAction = mkOption {
               type = types.enum [ "allow" "deny" ];
-              description = ''
+              description = lib.mdDoc ''
                 Default action whether to block or allow application internet
                 access.
               '';
@@ -46,28 +46,28 @@ in {
               type = types.enum [
                 "once" "always" "until restart" "30s" "5m" "15m" "30m" "1h"
               ];
-              description = ''
+              description = lib.mdDoc ''
                 Default duration of firewall rule.
               '';
             };
 
             InterceptUnknown = mkOption {
               type = types.bool;
-              description = ''
+              description = lib.mdDoc ''
                 Wheter to intercept spare connections.
               '';
             };
 
             ProcMonitorMethod = mkOption {
               type = types.enum [ "ebpf" "proc" "ftrace" "audit" ];
-              description = ''
+              description = lib.mdDoc ''
                 Which process monitoring method to use.
               '';
             };
 
             LogLevel = mkOption {
               type = types.enum [ 0 1 2 3 4 ];
-              description = ''
+              description = lib.mdDoc ''
                 Default log level from 0 to 4 (debug, info, important, warning,
                 error).
               '';
@@ -75,7 +75,7 @@ in {
 
             Firewall = mkOption {
               type = types.enum [ "iptables" "nftables" ];
-              description = ''
+              description = lib.mdDoc ''
                 Which firewall backend to use.
               '';
             };
@@ -84,14 +84,14 @@ in {
 
               MaxEvents = mkOption {
                 type = types.int;
-                description = ''
+                description = lib.mdDoc ''
                   Max events to send to the GUI.
                 '';
               };
 
               MaxStats = mkOption {
                 type = types.int;
-                description = ''
+                description = lib.mdDoc ''
                   Max stats per item to keep in backlog.
                 '';
               };
@@ -99,9 +99,9 @@ in {
             };
           };
         };
-        description = ''
+        description = lib.mdDoc ''
           opensnitchd configuration. Refer to
-          <link xlink:href="https://github.com/evilsocket/opensnitch/wiki/Configurations"/>
+          <https://github.com/evilsocket/opensnitch/wiki/Configurations>
           for details on supported values.
         '';
       };
diff --git a/nixos/modules/services/security/pass-secret-service.nix b/nixos/modules/services/security/pass-secret-service.nix
index 6ae190eb95e..611cea48ee6 100644
--- a/nixos/modules/services/security/pass-secret-service.nix
+++ b/nixos/modules/services/security/pass-secret-service.nix
@@ -13,7 +13,7 @@ in
       type = types.package;
       default = pkgs.pass-secret-service;
       defaultText = literalExpression "pkgs.pass-secret-service";
-      description = "Which pass-secret-service package to use.";
+      description = lib.mdDoc "Which pass-secret-service package to use.";
       example = literalExpression "pkgs.pass-secret-service.override { python3 = pkgs.python310 }";
     };
   };
diff --git a/nixos/modules/services/security/physlock.nix b/nixos/modules/services/security/physlock.nix
index 760e80f147f..3db9e0ac445 100644
--- a/nixos/modules/services/security/physlock.nix
+++ b/nixos/modules/services/security/physlock.nix
@@ -17,15 +17,15 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
-          Whether to enable the <command>physlock</command> screen locking mechanism.
+        description = lib.mdDoc ''
+          Whether to enable the {command}`physlock` screen locking mechanism.
 
-          Enable this and then run <command>systemctl start physlock</command>
+          Enable this and then run {command}`systemctl start physlock`
           to securely lock the screen.
 
           This will switch to a new virtual terminal, turn off console
           switching and disable SysRq mechanism (when
-          <option>services.physlock.disableSysRq</option> is set)
+          {option}`services.physlock.disableSysRq` is set)
           until the root or user password is given.
         '';
       };
@@ -33,7 +33,7 @@ in
       allowAnyUser = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to allow any user to lock the screen. This will install a
           setuid wrapper to allow any user to start physlock as root, which
           is a minor security risk. Call the physlock binary to use this instead
@@ -44,7 +44,7 @@ in
       disableSysRq = mkOption {
         type = types.bool;
         default = true;
-        description = ''
+        description = lib.mdDoc ''
           Whether to disable SysRq when locked with physlock.
         '';
       };
@@ -52,7 +52,7 @@ in
       lockMessage = mkOption {
         type = types.str;
         default = "";
-        description = ''
+        description = lib.mdDoc ''
           Message to show on physlock login terminal.
         '';
       };
@@ -62,7 +62,7 @@ in
         suspend = mkOption {
           type = types.bool;
           default = true;
-          description = ''
+          description = lib.mdDoc ''
             Whether to lock screen with physlock just before suspend.
           '';
         };
@@ -70,7 +70,7 @@ in
         hibernate = mkOption {
           type = types.bool;
           default = true;
-          description = ''
+          description = lib.mdDoc ''
             Whether to lock screen with physlock just before hibernate.
           '';
         };
@@ -79,11 +79,11 @@ in
           type = types.listOf types.str;
           default = [];
           example = [ "display-manager.service" ];
-          description = ''
+          description = lib.mdDoc ''
             Other targets to lock the screen just before.
 
             Useful if you want to e.g. both autologin to X11 so that
-            your <filename>~/.xsession</filename> gets executed and
+            your {file}`~/.xsession` gets executed and
             still to have the screen locked so that the system can be
             booted relatively unattended.
           '';
diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix
index 1f5639d475e..599ade003c0 100644
--- a/nixos/modules/services/security/privacyidea.nix
+++ b/nixos/modules/services/security/privacyidea.nix
@@ -91,7 +91,7 @@ in
       stateDir = mkOption {
         type = types.str;
         default = "/var/lib/privacyidea";
-        description = ''
+        description = lib.mdDoc ''
           Directory where all PrivacyIDEA files will be placed by default.
         '';
       };
@@ -99,7 +99,7 @@ in
       superuserRealm = mkOption {
         type = types.listOf types.str;
         default = [ "super" "administrators" ];
-        description = ''
+        description = lib.mdDoc ''
           The realm where users are allowed to login as administrators.
         '';
       };
@@ -107,7 +107,7 @@ in
       secretKey = mkOption {
         type = types.str;
         example = "t0p s3cr3t";
-        description = ''
+        description = lib.mdDoc ''
           This is used to encrypt the auth_token.
         '';
       };
@@ -115,7 +115,7 @@ in
       pepper = mkOption {
         type = types.str;
         example = "Never know...";
-        description = ''
+        description = lib.mdDoc ''
           This is used to encrypt the admin passwords.
         '';
       };
@@ -124,7 +124,7 @@ in
         type = types.str;
         default = "${cfg.stateDir}/enckey";
         defaultText = literalExpression ''"''${config.${opt.stateDir}}/enckey"'';
-        description = ''
+        description = lib.mdDoc ''
           This is used to encrypt the token data and token passwords
         '';
       };
@@ -133,7 +133,7 @@ in
         type = types.str;
         default = "${cfg.stateDir}/private.pem";
         defaultText = literalExpression ''"''${config.${opt.stateDir}}/private.pem"'';
-        description = ''
+        description = lib.mdDoc ''
           Private Key for signing the audit log.
         '';
       };
@@ -142,26 +142,26 @@ in
         type = types.str;
         default = "${cfg.stateDir}/public.pem";
         defaultText = literalExpression ''"''${config.${opt.stateDir}}/public.pem"'';
-        description = ''
+        description = lib.mdDoc ''
           Public key for checking signatures of the audit log.
         '';
       };
 
       adminPasswordFile = mkOption {
         type = types.path;
-        description = "File containing password for the admin user";
+        description = lib.mdDoc "File containing password for the admin user";
       };
 
       adminEmail = mkOption {
         type = types.str;
         example = "admin@example.com";
-        description = "Mail address for the admin user";
+        description = lib.mdDoc "Mail address for the admin user";
       };
 
       extraConfig = mkOption {
         type = types.lines;
         default = "";
-        description = ''
+        description = lib.mdDoc ''
           Extra configuration options for pi.cfg.
         '';
       };
@@ -169,13 +169,13 @@ in
       user = mkOption {
         type = types.str;
         default = "privacyidea";
-        description = "User account under which PrivacyIDEA runs.";
+        description = lib.mdDoc "User account under which PrivacyIDEA runs.";
       };
 
       group = mkOption {
         type = types.str;
         default = "privacyidea";
-        description = "Group account under which PrivacyIDEA runs.";
+        description = lib.mdDoc "Group account under which PrivacyIDEA runs.";
       };
 
       ldap-proxy = {
@@ -184,7 +184,7 @@ in
         configFile = mkOption {
           type = types.nullOr types.path;
           default = null;
-          description = ''
+          description = lib.mdDoc ''
             Path to PrivacyIDEA LDAP Proxy configuration (proxy.ini).
           '';
         };
@@ -192,13 +192,13 @@ in
         user = mkOption {
           type = types.str;
           default = "pi-ldap-proxy";
-          description = "User account under which PrivacyIDEA LDAP proxy runs.";
+          description = lib.mdDoc "User account under which PrivacyIDEA LDAP proxy runs.";
         };
 
         group = mkOption {
           type = types.str;
           default = "pi-ldap-proxy";
-          description = "Group account under which PrivacyIDEA LDAP proxy runs.";
+          description = lib.mdDoc "Group account under which PrivacyIDEA LDAP proxy runs.";
         };
 
         settings = mkOption {
diff --git a/nixos/modules/services/security/shibboleth-sp.nix b/nixos/modules/services/security/shibboleth-sp.nix
index fea2a855e20..6626ea21362 100644
--- a/nixos/modules/services/security/shibboleth-sp.nix
+++ b/nixos/modules/services/security/shibboleth-sp.nix
@@ -9,31 +9,31 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = "Whether to enable the shibboleth service";
+        description = lib.mdDoc "Whether to enable the shibboleth service";
       };
 
       configFile = mkOption {
         type = types.path;
         example = literalExpression ''"''${pkgs.shibboleth-sp}/etc/shibboleth/shibboleth2.xml"'';
-        description = "Path to shibboleth config file";
+        description = lib.mdDoc "Path to shibboleth config file";
       };
 
       fastcgi.enable = mkOption {
         type = types.bool;
         default = false;
-        description = "Whether to include the shibauthorizer and shibresponder FastCGI processes";
+        description = lib.mdDoc "Whether to include the shibauthorizer and shibresponder FastCGI processes";
       };
 
       fastcgi.shibAuthorizerPort = mkOption {
         type = types.int;
         default = 9100;
-        description = "Port for shibauthorizer FastCGI proccess to bind to";
+        description = lib.mdDoc "Port for shibauthorizer FastCGI proccess to bind to";
       };
 
       fastcgi.shibResponderPort = mkOption {
         type = types.int;
         default = 9101;
-        description = "Port for shibauthorizer FastCGI proccess to bind to";
+        description = lib.mdDoc "Port for shibauthorizer FastCGI proccess to bind to";
       };
     };
   };
diff --git a/nixos/modules/services/security/sks.nix b/nixos/modules/services/security/sks.nix
index f4911597564..e9205e4855e 100644
--- a/nixos/modules/services/security/sks.nix
+++ b/nixos/modules/services/security/sks.nix
@@ -25,7 +25,7 @@ in {
         default = pkgs.sks;
         defaultText = literalExpression "pkgs.sks";
         type = types.package;
-        description = "Which SKS derivation to use.";
+        description = lib.mdDoc "Which SKS derivation to use.";
       };
 
       dataDir = mkOption {
@@ -35,7 +35,7 @@ in {
         # TODO: The default might change to "/var/lib/sks" as this is more
         # common. There's also https://github.com/NixOS/nixpkgs/issues/26256
         # and "/var/db" is not FHS compliant (seems to come from BSD).
-        description = ''
+        description = lib.mdDoc ''
           Data directory (-basedir) for SKS, where the database and all
           configuration files are located (e.g. KDB, PTree, membership and
           sksconf).
@@ -45,7 +45,7 @@ in {
       extraDbConfig = mkOption {
         type = types.str;
         default = "";
-        description = ''
+        description = lib.mdDoc ''
           Set contents of the files "KDB/DB_CONFIG" and "PTree/DB_CONFIG" within
           the ''${dataDir} directory. This is used to configure options for the
           database for the sks key server.
@@ -59,7 +59,7 @@ in {
       hkpAddress = mkOption {
         default = [ "127.0.0.1" "::1" ];
         type = types.listOf types.str;
-        description = ''
+        description = lib.mdDoc ''
           Domain names, IPv4 and/or IPv6 addresses to listen on for HKP
           requests.
         '';
@@ -68,14 +68,14 @@ in {
       hkpPort = mkOption {
         default = 11371;
         type = types.ints.u16;
-        description = "HKP port to listen on.";
+        description = lib.mdDoc "HKP port to listen on.";
       };
 
       webroot = mkOption {
         type = types.nullOr types.path;
         default = "${sksPkg.webSamples}/OpenPKG";
         defaultText = literalExpression ''"''${package.webSamples}/OpenPKG"'';
-        description = ''
+        description = lib.mdDoc ''
           Source directory (will be symlinked, if not null) for the files the
           built-in webserver should serve. SKS (''${pkgs.sks.webSamples})
           provides the following examples: "HTML5", "OpenPKG", and "XHTML+ES".
diff --git a/nixos/modules/services/security/sshguard.nix b/nixos/modules/services/security/sshguard.nix
index 3be0a8c700b..4e9d9571de5 100644
--- a/nixos/modules/services/security/sshguard.nix
+++ b/nixos/modules/services/security/sshguard.nix
@@ -30,13 +30,13 @@ in {
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = "Whether to enable the sshguard service.";
+        description = lib.mdDoc "Whether to enable the sshguard service.";
       };
 
       attack_threshold = mkOption {
         default = 30;
         type = types.int;
-        description = ''
+        description = lib.mdDoc ''
             Block attackers when their cumulative attack score exceeds threshold. Most attacks have a score of 10.
           '';
       };
@@ -45,7 +45,7 @@ in {
         default = null;
         example = 120;
         type = types.nullOr types.int;
-        description = ''
+        description = lib.mdDoc ''
             Blacklist an attacker when its score exceeds threshold. Blacklisted addresses are loaded from and added to blacklist-file.
           '';
       };
@@ -53,7 +53,7 @@ in {
       blacklist_file = mkOption {
         default = "/var/lib/sshguard/blacklist.db";
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
             Blacklist an attacker when its score exceeds threshold. Blacklisted addresses are loaded from and added to blacklist-file.
           '';
       };
@@ -61,7 +61,7 @@ in {
       blocktime = mkOption {
         default = 120;
         type = types.int;
-        description = ''
+        description = lib.mdDoc ''
             Block attackers for initially blocktime seconds after exceeding threshold. Subsequent blocks increase by a factor of 1.5.
 
             sshguard unblocks attacks at random intervals, so actual block times will be longer.
@@ -71,7 +71,7 @@ in {
       detection_time = mkOption {
         default = 1800;
         type = types.int;
-        description = ''
+        description = lib.mdDoc ''
             Remember potential attackers for up to detection_time seconds before resetting their score.
           '';
       };
@@ -80,7 +80,7 @@ in {
         default = [ ];
         example = [ "198.51.100.56" "198.51.100.2" ];
         type = types.listOf types.str;
-        description = ''
+        description = lib.mdDoc ''
             Whitelist a list of addresses, hostnames, or address blocks.
           '';
       };
@@ -89,7 +89,7 @@ in {
         default = [ "sshd" ];
         example = [ "sshd" "exim" ];
         type = types.listOf types.str;
-        description = ''
+        description = lib.mdDoc ''
             Systemd services sshguard should receive logs of.
           '';
       };
diff --git a/nixos/modules/services/security/step-ca.nix b/nixos/modules/services/security/step-ca.nix
index 95183078d7b..9b9b53f1351 100644
--- a/nixos/modules/services/security/step-ca.nix
+++ b/nixos/modules/services/security/step-ca.nix
@@ -14,22 +14,22 @@ in
         type = lib.types.package;
         default = pkgs.step-ca;
         defaultText = lib.literalExpression "pkgs.step-ca";
-        description = "Which step-ca package to use.";
+        description = lib.mdDoc "Which step-ca package to use.";
       };
       address = lib.mkOption {
         type = lib.types.str;
         example = "127.0.0.1";
-        description = ''
+        description = lib.mdDoc ''
           The address (without port) the certificate authority should listen at.
-          This combined with <option>services.step-ca.port</option> overrides <option>services.step-ca.settings.address</option>.
+          This combined with {option}`services.step-ca.port` overrides {option}`services.step-ca.settings.address`.
         '';
       };
       port = lib.mkOption {
         type = lib.types.port;
         example = 8443;
-        description = ''
+        description = lib.mdDoc ''
           The port the certificate authority should listen on.
-          This combined with <option>services.step-ca.address</option> overrides <option>services.step-ca.settings.address</option>.
+          This combined with {option}`services.step-ca.address` overrides {option}`services.step-ca.settings.address`.
         '';
       };
       settings = lib.mkOption {
diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix
index a5822c02794..f611fee6908 100644
--- a/nixos/modules/services/security/tor.nix
+++ b/nixos/modules/services/security/tor.nix
@@ -234,7 +234,7 @@ in
         type = types.package;
         default = pkgs.tor;
         defaultText = literalExpression "pkgs.tor";
-        description = "Tor package to use.";
+        description = lib.mdDoc "Tor package to use.";
       };
 
       enableGeoIP = mkEnableOption ''use of GeoIP databases.
@@ -255,7 +255,7 @@ in
           type = optionSOCKSPort false;
           default = {addr = "127.0.0.1"; port = 9050; IsolateDestAddr = true;};
           example = {addr = "192.168.0.1"; port = 9090; IsolateDestAddr = true;};
-          description = ''
+          description = lib.mdDoc ''
             Bind to this address to listen for connections from
             Socks-speaking applications.
           '';
@@ -442,20 +442,20 @@ in
           type = types.attrsOf (types.submodule ({name, config, ...}: {
             options.path = mkOption {
               type = types.path;
-              description = ''
+              description = lib.mdDoc ''
                 Path where to store the data files of the hidden service.
-                If the <option>secretKey</option> is null
-                this defaults to <literal>${stateDir}/onion/$onion</literal>,
-                otherwise to <literal>${runDir}/onion/$onion</literal>.
+                If the {option}`secretKey` is null
+                this defaults to `${stateDir}/onion/$onion`,
+                otherwise to `${runDir}/onion/$onion`.
               '';
             };
             options.secretKey = mkOption {
               type = with types; nullOr path;
               default = null;
               example = "/run/keys/tor/onion/expyuzz4wqqyqhjn/hs_ed25519_secret_key";
-              description = ''
+              description = lib.mdDoc ''
                 Secret key of the onion service.
-                If null, Tor reuses any preexisting secret key (in <option>path</option>)
+                If null, Tor reuses any preexisting secret key (in {option}`path`)
                 or generates a new one.
                 The associated public key and hostname are deterministically regenerated
                 from this file if they do not exist.
@@ -468,9 +468,9 @@ in
                 options = {
                   authType = mkOption {
                     type = types.enum [ "basic" "stealth" ];
-                    description = ''
-                      Either <literal>"basic"</literal> for a general-purpose authorization protocol
-                      or <literal>"stealth"</literal> for a less scalable protocol
+                    description = lib.mdDoc ''
+                      Either `"basic"` for a general-purpose authorization protocol
+                      or `"stealth"` for a less scalable protocol
                       that also hides service activity from unauthorized clients.
                     '';
                   };
@@ -569,8 +569,8 @@ in
       };
 
       settings = mkOption {
-        description = ''
-          See <link xlink:href="https://2019.www.torproject.org/docs/tor-manual.html.en">torrc manual</link>
+        description = lib.mdDoc ''
+          See [torrc manual](https://2019.www.torproject.org/docs/tor-manual.html.en)
           for documentation.
         '';
         default = {};
@@ -716,12 +716,12 @@ in
                 options = {
                   onion = mkOption {
                     type = strMatching "[a-z2-7]{16}\\.onion";
-                    description = "Onion address.";
+                    description = lib.mdDoc "Onion address.";
                     example = "xxxxxxxxxxxxxxxx.onion";
                   };
                   auth = mkOption {
                     type = strMatching "[A-Za-z0-9+/]{22}";
-                    description = "Authentication cookie.";
+                    description = lib.mdDoc "Authentication cookie.";
                   };
                 };
               })
@@ -783,13 +783,13 @@ in
             type = with types; nullOr (submodule ({...}: {
               options = {
                 transports = mkOption {
-                  description = "List of pluggable transports.";
+                  description = lib.mdDoc "List of pluggable transports.";
                   type = listOf str;
                   example = ["obfs2" "obfs3" "obfs4" "scramblesuit"];
                 };
                 exec = mkOption {
                   type = types.str;
-                  description = "Command of pluggable transport.";
+                  description = lib.mdDoc "Command of pluggable transport.";
                 };
               };
             }));
diff --git a/nixos/modules/services/security/torify.nix b/nixos/modules/services/security/torify.nix
index 39551190dd3..770e445d733 100644
--- a/nixos/modules/services/security/torify.nix
+++ b/nixos/modules/services/security/torify.nix
@@ -44,7 +44,7 @@ in
         type = types.str;
         default = "localhost:9050";
         example = "192.168.0.20";
-        description = ''
+        description = lib.mdDoc ''
           IP address of TOR client to use.
         '';
       };
@@ -52,7 +52,7 @@ in
       config = mkOption {
         type = types.lines;
         default = "";
-        description = ''
+        description = lib.mdDoc ''
           Extra configuration. Contents will be added verbatim to TSocks
           configuration file.
         '';
diff --git a/nixos/modules/services/security/torsocks.nix b/nixos/modules/services/security/torsocks.nix
index fdd6ac32cc6..0647d7eb49b 100644
--- a/nixos/modules/services/security/torsocks.nix
+++ b/nixos/modules/services/security/torsocks.nix
@@ -38,8 +38,8 @@ in
         type        = types.bool;
         default     = config.services.tor.enable && config.services.tor.client.enable;
         defaultText = literalExpression "config.services.tor.enable && config.services.tor.client.enable";
-        description = ''
-          Whether to build <literal>/etc/tor/torsocks.conf</literal>
+        description = lib.mdDoc ''
+          Whether to build `/etc/tor/torsocks.conf`
           containing the specified global torsocks configuration.
         '';
       };
@@ -48,7 +48,7 @@ in
         type    = types.str;
         default = "127.0.0.1:9050";
         example = "192.168.0.20:1234";
-        description = ''
+        description = lib.mdDoc ''
           IP/Port of the Tor SOCKS server. Currently, hostnames are
           NOT supported by torsocks.
         '';
@@ -58,7 +58,7 @@ in
         type    = types.str;
         default = "127.0.0.1:9063";
         example = "192.168.0.20:1234";
-        description = ''
+        description = lib.mdDoc ''
           IP/Port of the Tor SOCKS server for torsocks-faster wrapper suitable for HTTP.
           Currently, hostnames are NOT supported by torsocks.
         '';
@@ -67,7 +67,7 @@ in
       onionAddrRange = mkOption {
         type    = types.str;
         default = "127.42.42.0/24";
-        description = ''
+        description = lib.mdDoc ''
           Tor hidden sites do not have real IP addresses. This
           specifies what range of IP addresses will be handed to the
           application as "cookies" for .onion names.  Of course, you
@@ -81,8 +81,8 @@ in
         type    = types.nullOr types.str;
         default = null;
         example = "bob";
-        description = ''
-          SOCKS5 username. The <literal>TORSOCKS_USERNAME</literal>
+        description = lib.mdDoc ''
+          SOCKS5 username. The `TORSOCKS_USERNAME`
           environment variable overrides this option if it is set.
         '';
       };
@@ -91,8 +91,8 @@ in
         type    = types.nullOr types.str;
         default = null;
         example = "sekret";
-        description = ''
-          SOCKS5 password. The <literal>TORSOCKS_PASSWORD</literal>
+        description = lib.mdDoc ''
+          SOCKS5 password. The `TORSOCKS_PASSWORD`
           environment variable overrides this option if it is set.
         '';
       };
@@ -100,9 +100,9 @@ in
       allowInbound = mkOption {
         type    = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Set Torsocks to accept inbound connections. If set to
-          <literal>true</literal>, listen() and accept() will be
+          `true`, listen() and accept() will be
           allowed to be used with non localhost address.
         '';
       };
diff --git a/nixos/modules/services/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix
index 201b37f17ba..eb3c335d974 100644
--- a/nixos/modules/services/security/usbguard.nix
+++ b/nixos/modules/services/security/usbguard.nix
@@ -45,9 +45,9 @@ in
         type = types.package;
         default = pkgs.usbguard;
         defaultText = literalExpression "pkgs.usbguard";
-        description = ''
+        description = lib.mdDoc ''
           The usbguard package to use. If you do not need the Qt GUI, use
-          <literal>pkgs.usbguard-nox</literal> to save disk space.
+          `pkgs.usbguard-nox` to save disk space.
         '';
       };
 
@@ -78,7 +78,7 @@ in
       implictPolicyTarget = mkOption {
         type = policy;
         default = "block";
-        description = ''
+        description = lib.mdDoc ''
           How to treat USB devices that don't match any rule in the policy.
           Target should be one of allow, block or reject (logically remove the
           device node from the system).
@@ -88,7 +88,7 @@ in
       presentDevicePolicy = mkOption {
         type = policy;
         default = "apply-policy";
-        description = ''
+        description = lib.mdDoc ''
           How to treat USB devices that are already connected when the daemon
           starts. Policy should be one of allow, block, reject, keep (keep
           whatever state the device is currently in) or apply-policy (evaluate
@@ -99,7 +99,7 @@ in
       presentControllerPolicy = mkOption {
         type = policy;
         default = "keep";
-        description = ''
+        description = lib.mdDoc ''
           How to treat USB controller devices that are already connected when
           the daemon starts. One of allow, block, reject, keep or apply-policy.
         '';
@@ -108,7 +108,7 @@ in
       insertedDevicePolicy = mkOption {
         type = policy;
         default = "apply-policy";
-        description = ''
+        description = lib.mdDoc ''
           How to treat USB devices that are already connected after the daemon
           starts. One of block, reject, apply-policy.
         '';
@@ -117,7 +117,7 @@ in
       restoreControllerDeviceState = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           The  USBGuard  daemon  modifies  some attributes of controller
           devices like the default authorization state of new child device
           instances. Using this setting, you can controll whether the daemon
@@ -130,7 +130,7 @@ in
         type = types.listOf types.str;
         default = [ "root" ];
         example = [ "root" "yourusername" ];
-        description = ''
+        description = lib.mdDoc ''
           A list of usernames that the daemon will accept IPC connections from.
         '';
       };
@@ -139,7 +139,7 @@ in
         type = types.listOf types.str;
         default = [ ];
         example = [ "wheel" ];
-        description = ''
+        description = lib.mdDoc ''
           A list of groupnames that the daemon will accept IPC connections
           from.
         '';
@@ -148,7 +148,7 @@ in
       deviceRulesWithPort = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Generate device specific rules including the "via-port" attribute.
         '';
       };
diff --git a/nixos/modules/services/security/vault.nix b/nixos/modules/services/security/vault.nix
index 4942a05fe73..e4777910b6d 100644
--- a/nixos/modules/services/security/vault.nix
+++ b/nixos/modules/services/security/vault.nix
@@ -49,13 +49,13 @@ in
         type = types.package;
         default = pkgs.vault;
         defaultText = literalExpression "pkgs.vault";
-        description = "This option specifies the vault package to use.";
+        description = lib.mdDoc "This option specifies the vault package to use.";
       };
 
       dev = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           In this mode, Vault runs in-memory and starts unsealed. This option is not meant production but for development and testing i.e. for nixos tests.
         '';
       };
@@ -63,29 +63,29 @@ in
       devRootTokenID = mkOption {
         type = types.str;
         default = false;
-        description = ''
-          Initial root token. This only applies when <option>services.vault.dev</option> is true
+        description = lib.mdDoc ''
+          Initial root token. This only applies when {option}`services.vault.dev` is true
         '';
       };
 
       address = mkOption {
         type = types.str;
         default = "127.0.0.1:8200";
-        description = "The name of the ip interface to listen to";
+        description = lib.mdDoc "The name of the ip interface to listen to";
       };
 
       tlsCertFile = mkOption {
         type = types.nullOr types.str;
         default = null;
         example = "/path/to/your/cert.pem";
-        description = "TLS certificate file. TLS will be disabled unless this option is set";
+        description = lib.mdDoc "TLS certificate file. TLS will be disabled unless this option is set";
       };
 
       tlsKeyFile = mkOption {
         type = types.nullOr types.str;
         default = null;
         example = "/path/to/your/key.pem";
-        description = "TLS private key file. TLS will be disabled unless this option is set";
+        description = lib.mdDoc "TLS private key file. TLS will be disabled unless this option is set";
       };
 
       listenerExtraConfig = mkOption {
@@ -93,13 +93,13 @@ in
         default = ''
           tls_min_version = "tls12"
         '';
-        description = "Extra text appended to the listener section.";
+        description = lib.mdDoc "Extra text appended to the listener section.";
       };
 
       storageBackend = mkOption {
         type = types.enum [ "inmem" "file" "consul" "zookeeper" "s3" "azure" "dynamodb" "etcd" "mssql" "mysql" "postgresql" "swift" "gcs" "raft" ];
         default = "inmem";
-        description = "The name of the type of storage backend";
+        description = lib.mdDoc "The name of the type of storage backend";
       };
 
       storagePath = mkOption {
@@ -110,7 +110,7 @@ in
           then "/var/lib/vault"
           else null
         '';
-        description = "Data directory for file backend";
+        description = lib.mdDoc "Data directory for file backend";
       };
 
       storageConfig = mkOption {
@@ -129,13 +129,13 @@ in
       telemetryConfig = mkOption {
         type = types.lines;
         default = "";
-        description = "Telemetry configuration";
+        description = lib.mdDoc "Telemetry configuration";
       };
 
       extraConfig = mkOption {
         type = types.lines;
         default = "";
-        description = "Extra text appended to <filename>vault.hcl</filename>.";
+        description = lib.mdDoc "Extra text appended to {file}`vault.hcl`.";
       };
 
       extraSettingsPaths = mkOption {
diff --git a/nixos/modules/services/security/vaultwarden/default.nix b/nixos/modules/services/security/vaultwarden/default.nix
index 756e0ee93b2..7e5389d78f4 100644
--- a/nixos/modules/services/security/vaultwarden/default.nix
+++ b/nixos/modules/services/security/vaultwarden/default.nix
@@ -44,7 +44,7 @@ in {
     dbBackend = mkOption {
       type = enum [ "sqlite" "mysql" "postgresql" ];
       default = "sqlite";
-      description = ''
+      description = lib.mdDoc ''
         Which database backend vaultwarden will be using.
       '';
     };
@@ -52,7 +52,7 @@ in {
     backupDir = mkOption {
       type = nullOr str;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         The directory under which vaultwarden will backup its persistent data.
       '';
     };
@@ -159,14 +159,14 @@ ADMIN_TOKEN=...copy-paste a unique generated secret token here...
       type = package;
       default = pkgs.vaultwarden;
       defaultText = literalExpression "pkgs.vaultwarden";
-      description = "Vaultwarden package to use.";
+      description = lib.mdDoc "Vaultwarden package to use.";
     };
 
     webVaultPackage = mkOption {
       type = package;
       default = pkgs.vaultwarden-vault;
       defaultText = literalExpression "pkgs.vaultwarden-vault";
-      description = "Web vault package to use.";
+      description = lib.mdDoc "Web vault package to use.";
     };
   };
 
diff --git a/nixos/modules/services/security/yubikey-agent.nix b/nixos/modules/services/security/yubikey-agent.nix
index 8be2457e1e2..c91ff3e69a0 100644
--- a/nixos/modules/services/security/yubikey-agent.nix
+++ b/nixos/modules/services/security/yubikey-agent.nix
@@ -21,7 +21,7 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to start yubikey-agent when you log in.  Also sets
           SSH_AUTH_SOCK to point at yubikey-agent.
 
@@ -34,7 +34,7 @@ in
         type = types.package;
         default = pkgs.yubikey-agent;
         defaultText = literalExpression "pkgs.yubikey-agent";
-        description = ''
+        description = lib.mdDoc ''
           The package used for the yubikey-agent daemon.
         '';
       };