summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/config/i18n.nix6
-rw-r--r--nixos/modules/config/resolvconf.nix6
-rw-r--r--nixos/modules/config/shells-environment.nix4
-rw-r--r--nixos/modules/config/system-environment.nix8
-rw-r--r--nixos/modules/config/users-groups.nix38
-rw-r--r--nixos/modules/hardware/logitech.nix2
-rw-r--r--nixos/modules/hardware/video/uvcvideo/default.nix12
-rw-r--r--nixos/modules/programs/adb.nix4
-rw-r--r--nixos/modules/programs/firejail.nix4
-rw-r--r--nixos/modules/programs/gphoto2.nix4
-rw-r--r--nixos/modules/programs/neovim.nix4
-rw-r--r--nixos/modules/programs/nncp.nix18
-rw-r--r--nixos/modules/programs/turbovnc.nix6
-rw-r--r--nixos/modules/security/acme/default.nix4
-rw-r--r--nixos/modules/security/doas.nix60
-rw-r--r--nixos/modules/security/misc.nix4
-rw-r--r--nixos/modules/security/pam.nix100
-rw-r--r--nixos/modules/security/pam_mount.nix12
-rw-r--r--nixos/modules/security/pam_usb.nix4
-rw-r--r--nixos/modules/security/sudo.nix20
-rw-r--r--nixos/modules/services/backup/restic.nix2
-rw-r--r--nixos/modules/services/backup/syncoid.nix2
-rw-r--r--nixos/modules/services/backup/zrepl.nix4
-rw-r--r--nixos/modules/services/continuous-integration/github-runner.nix4
-rw-r--r--nixos/modules/services/continuous-integration/gitlab-runner.nix94
-rw-r--r--nixos/modules/services/databases/firebird.nix6
-rw-r--r--nixos/modules/services/databases/mysql.nix6
-rw-r--r--nixos/modules/services/databases/neo4j.nix86
-rw-r--r--nixos/modules/services/databases/openldap.nix10
-rw-r--r--nixos/modules/services/databases/pgmanage.nix4
-rw-r--r--nixos/modules/services/databases/postgresql.nix6
-rw-r--r--nixos/modules/services/databases/victoriametrics.nix6
-rw-r--r--nixos/modules/services/games/asf.nix4
-rw-r--r--nixos/modules/services/hardware/kanata.nix14
-rw-r--r--nixos/modules/services/hardware/udev.nix16
-rw-r--r--nixos/modules/services/logging/filebeat.nix20
-rw-r--r--nixos/modules/services/logging/logrotate.nix10
-rw-r--r--nixos/modules/services/mail/mailman.nix4
-rw-r--r--nixos/modules/services/mail/nullmailer.nix12
-rw-r--r--nixos/modules/services/mail/postfixadmin.nix6
-rw-r--r--nixos/modules/services/mail/public-inbox.nix10
-rw-r--r--nixos/modules/services/mail/roundcube.nix10
-rw-r--r--nixos/modules/services/mail/sympa.nix16
-rw-r--r--nixos/modules/services/matrix/appservice-discord.nix10
-rw-r--r--nixos/modules/services/matrix/mautrix-facebook.nix8
-rw-r--r--nixos/modules/services/matrix/mautrix-telegram.nix8
-rw-r--r--nixos/modules/services/misc/autorandr.nix4
-rw-r--r--nixos/modules/services/misc/bees.nix4
-rw-r--r--nixos/modules/services/misc/etcd.nix4
-rw-r--r--nixos/modules/services/misc/klipper.nix2
-rw-r--r--nixos/modules/services/misc/sssd.nix2
-rw-r--r--nixos/modules/services/monitoring/cadvisor.nix14
-rw-r--r--nixos/modules/services/monitoring/graphite.nix4
-rw-r--r--nixos/modules/services/monitoring/metricbeat.nix10
-rw-r--r--nixos/modules/services/monitoring/munin.nix28
-rw-r--r--nixos/modules/services/monitoring/netdata.nix4
-rw-r--r--nixos/modules/services/monitoring/parsedmarc.nix34
-rw-r--r--nixos/modules/services/networking/biboumi.nix10
-rw-r--r--nixos/modules/services/networking/bird-lg.nix8
-rw-r--r--nixos/modules/services/networking/bird.nix12
-rw-r--r--nixos/modules/services/networking/coredns.nix4
-rw-r--r--nixos/modules/services/networking/ghostunnel.nix14
-rw-r--r--nixos/modules/services/networking/hans.nix4
-rw-r--r--nixos/modules/services/networking/iodine.nix4
-rw-r--r--nixos/modules/services/networking/kea.nix32
-rw-r--r--nixos/modules/services/networking/ncdns.nix4
-rw-r--r--nixos/modules/services/networking/networkmanager.nix6
-rw-r--r--nixos/modules/services/networking/nntp-proxy.nix4
-rw-r--r--nixos/modules/services/networking/nsd.nix4
-rw-r--r--nixos/modules/services/networking/ntp/ntpd.nix8
-rw-r--r--nixos/modules/services/networking/openconnect.nix14
-rw-r--r--nixos/modules/services/networking/openvpn.nix4
-rw-r--r--nixos/modules/services/networking/pleroma.nix8
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix24
-rw-r--r--nixos/modules/services/networking/wireguard.nix16
-rw-r--r--nixos/modules/services/networking/yggdrasil.nix12
-rw-r--r--nixos/modules/services/security/privacyidea.nix4
-rw-r--r--nixos/modules/services/security/tor.nix6
-rw-r--r--nixos/modules/services/security/vault.nix4
-rw-r--r--nixos/modules/services/system/dbus.nix14
-rw-r--r--nixos/modules/services/system/earlyoom.nix16
-rw-r--r--nixos/modules/services/torrent/transmission.nix56
-rw-r--r--nixos/modules/services/web-apps/dokuwiki.nix10
-rw-r--r--nixos/modules/services/web-apps/hedgedoc.nix4
-rw-r--r--nixos/modules/services/web-apps/keycloak.nix26
-rw-r--r--nixos/modules/services/web-apps/mastodon.nix18
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix24
-rw-r--r--nixos/modules/services/web-apps/node-red.nix4
-rw-r--r--nixos/modules/services/web-apps/trilium.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix4
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix4
-rw-r--r--nixos/modules/services/x11/window-managers/fvwm2.nix2
-rw-r--r--nixos/modules/system/boot/initrd-network.nix10
-rw-r--r--nixos/modules/system/boot/luksroot.nix4
-rw-r--r--nixos/modules/system/boot/networkd.nix6
-rw-r--r--nixos/modules/system/boot/systemd/logind.nix6
-rw-r--r--nixos/modules/system/boot/systemd/tmpfiles.nix10
-rw-r--r--nixos/modules/tasks/auto-upgrade.nix6
-rw-r--r--nixos/modules/tasks/scsi-link-power-management.nix2
-rw-r--r--nixos/modules/virtualisation/nixos-containers.nix12
101 files changed, 628 insertions, 628 deletions
diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix
index dad06c1b44c..f73f10f0f36 100644
--- a/nixos/modules/config/i18n.nix
+++ b/nixos/modules/config/i18n.nix
@@ -71,11 +71,11 @@ with lib;
             ))
         '';
         example = ["en_US.UTF-8/UTF-8" "nl_NL.UTF-8/UTF-8" "nl_NL/ISO-8859-1"];
-        description = ''
+        description = lib.mdDoc ''
           List of locales that the system should support.  The value
-          <literal>"all"</literal> means that all locales supported by
+          `"all"` means that all locales supported by
           Glibc will be installed.  A full list of supported locales
-          can be found at <link xlink:href="https://sourceware.org/git/?p=glibc.git;a=blob;f=localedata/SUPPORTED"/>.
+          can be found at <https://sourceware.org/git/?p=glibc.git;a=blob;f=localedata/SUPPORTED>.
         '';
       };
 
diff --git a/nixos/modules/config/resolvconf.nix b/nixos/modules/config/resolvconf.nix
index ef291ce5aaf..76605a063a4 100644
--- a/nixos/modules/config/resolvconf.nix
+++ b/nixos/modules/config/resolvconf.nix
@@ -83,9 +83,9 @@ in
       dnsExtensionMechanism = mkOption {
         type = types.bool;
         default = true;
-        description = ''
-          Enable the <literal>edns0</literal> option in <filename>resolv.conf</filename>. With
-          that option set, <literal>glibc</literal> supports use of the extension mechanisms for
+        description = lib.mdDoc ''
+          Enable the `edns0` option in {file}`resolv.conf`. With
+          that option set, `glibc` supports use of the extension mechanisms for
           DNS (EDNS) specified in RFC 2671. The most popular user of that feature is DNSSEC,
           which does not work without it.
         '';
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index 3dc202327c2..2fda71749c0 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -109,11 +109,11 @@ in
 
     environment.shellAliases = mkOption {
       example = { l = null; ll = "ls -l"; };
-      description = ''
+      description = lib.mdDoc ''
         An attribute set that maps aliases (the top level attribute names in
         this option) to command strings or directly to build outputs. The
         aliases are added to all users' shells.
-        Aliases mapped to <literal>null</literal> are ignored.
+        Aliases mapped to `null` are ignored.
       '';
       type = with types; attrsOf (nullOr (either str path));
     };
diff --git a/nixos/modules/config/system-environment.nix b/nixos/modules/config/system-environment.nix
index a299fdceaf1..1e05ab7d0f2 100644
--- a/nixos/modules/config/system-environment.nix
+++ b/nixos/modules/config/system-environment.nix
@@ -16,7 +16,7 @@ in
 
     environment.sessionVariables = mkOption {
       default = {};
-      description = ''
+      description = lib.mdDoc ''
         A set of environment variables used in the global environment.
         These variables will be set by PAM early in the login process.
 
@@ -25,12 +25,12 @@ in
         colon characters.
 
         Note, due to limitations in the PAM format values may not
-        contain the <literal>"</literal> character.
+        contain the `"` character.
 
         Also, these variables are merged into
-        <xref linkend="opt-environment.variables"/> and it is
+        [](#opt-environment.variables) and it is
         therefore not possible to use PAM style variables such as
-        <literal>@{HOME}</literal>.
+        `@{HOME}`.
       '';
       type = with types; attrsOf (either str (listOf str));
       apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v);
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 2e5984b55cc..915687d1799 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -100,17 +100,17 @@ let
       isNormalUser = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Indicates whether this is an account for a “real” user. This
-          automatically sets <option>group</option> to
-          <literal>users</literal>, <option>createHome</option> to
-          <literal>true</literal>, <option>home</option> to
-          <filename>/home/«username»</filename>,
-          <option>useDefaultShell</option> to <literal>true</literal>,
-          and <option>isSystemUser</option> to
-          <literal>false</literal>.
-          Exactly one of <literal>isNormalUser</literal> and
-          <literal>isSystemUser</literal> must be true.
+          automatically sets {option}`group` to
+          `users`, {option}`createHome` to
+          `true`, {option}`home` to
+          {file}`/home/«username»`,
+          {option}`useDefaultShell` to `true`,
+          and {option}`isSystemUser` to
+          `false`.
+          Exactly one of `isNormalUser` and
+          `isSystemUser` must be true.
         '';
       };
 
@@ -151,12 +151,12 @@ let
       pamMount = mkOption {
         type = with types; attrsOf str;
         default = {};
-        description = ''
+        description = lib.mdDoc ''
           Attributes for user's entry in
-          <filename>pam_mount.conf.xml</filename>.
-          Useful attributes might include <literal>path</literal>,
-          <literal>options</literal>, <literal>fstype</literal>, and <literal>server</literal>.
-          See <link xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html"/>
+          {file}`pam_mount.conf.xml`.
+          Useful attributes might include `path`,
+          `options`, `fstype`, and `server`.
+          See <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>
           for more information.
         '';
       };
@@ -166,12 +166,12 @@ let
         default = pkgs.shadow;
         defaultText = literalExpression "pkgs.shadow";
         example = literalExpression "pkgs.bashInteractive";
-        description = ''
+        description = lib.mdDoc ''
           The path to the user's shell. Can use shell derivations,
-          like <literal>pkgs.bashInteractive</literal>. Don’t
+          like `pkgs.bashInteractive`. Don’t
           forget to enable your shell in
-          <literal>programs</literal> if necessary,
-          like <literal>programs.zsh.enable = true;</literal>.
+          `programs` if necessary,
+          like `programs.zsh.enable = true;`.
         '';
       };
 
diff --git a/nixos/modules/hardware/logitech.nix b/nixos/modules/hardware/logitech.nix
index 1c3556320e3..70ca59a7dd3 100644
--- a/nixos/modules/hardware/logitech.nix
+++ b/nixos/modules/hardware/logitech.nix
@@ -32,7 +32,7 @@ in
       devices = mkOption {
         type = types.listOf types.str;
         default = [ "0a07" "c222" "c225" "c227" "c251" ];
-        description = ''
+        description = lib.mdDoc ''
           List of USB device ids supported by g15daemon.
 
           You most likely do not need to change this.
diff --git a/nixos/modules/hardware/video/uvcvideo/default.nix b/nixos/modules/hardware/video/uvcvideo/default.nix
index 5d1699e6395..6cfb8cc6ad2 100644
--- a/nixos/modules/hardware/video/uvcvideo/default.nix
+++ b/nixos/modules/hardware/video/uvcvideo/default.nix
@@ -34,15 +34,15 @@ in
       packages = mkOption {
         type = types.listOf types.path;
         example = literalExpression "[ pkgs.tiscamera ]";
-        description = ''
-          List of packages containing <command>uvcvideo</command> dynamic controls
+        description = lib.mdDoc ''
+          List of packages containing {command}`uvcvideo` dynamic controls
           rules. All files found in
-          <filename>«pkg»/share/uvcdynctrl/data</filename>
+          {file}`«pkg»/share/uvcdynctrl/data`
           will be included.
 
-          Note that these will serve as input to the <command>libwebcam</command>
-          package which through its own <command>udev</command> rule will register
-          the dynamic controls from specified packages to the <command>uvcvideo</command>
+          Note that these will serve as input to the {command}`libwebcam`
+          package which through its own {command}`udev` rule will register
+          the dynamic controls from specified packages to the {command}`uvcvideo`
           driver.
         '';
         apply = map getBin;
diff --git a/nixos/modules/programs/adb.nix b/nixos/modules/programs/adb.nix
index 63403193920..e5b0abd9fcf 100644
--- a/nixos/modules/programs/adb.nix
+++ b/nixos/modules/programs/adb.nix
@@ -11,10 +11,10 @@ with lib;
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
+        description = lib.mdDoc ''
           Whether to configure system to use Android Debug Bridge (adb).
           To grant access to a user, it must be part of adbusers group:
-          <literal>users.users.alice.extraGroups = ["adbusers"];</literal>
+          `users.users.alice.extraGroups = ["adbusers"];`
         '';
       };
     };
diff --git a/nixos/modules/programs/firejail.nix b/nixos/modules/programs/firejail.nix
index b9a0f9a6911..417eff91d3c 100644
--- a/nixos/modules/programs/firejail.nix
+++ b/nixos/modules/programs/firejail.nix
@@ -69,12 +69,12 @@ in {
           };
         }
       '';
-      description = ''
+      description = lib.mdDoc ''
         Wrap the binaries in firejail and place them in the global path.
 
         You will get file collisions if you put the actual application binary in
         the global environment (such as by adding the application package to
-        <literal>environment.systemPackages</literal>), and applications started via
+        `environment.systemPackages`), and applications started via
         .desktop files are not wrapped if they specify the absolute path to the
         binary.
       '';
diff --git a/nixos/modules/programs/gphoto2.nix b/nixos/modules/programs/gphoto2.nix
index 373b53495f7..f31b1863963 100644
--- a/nixos/modules/programs/gphoto2.nix
+++ b/nixos/modules/programs/gphoto2.nix
@@ -11,11 +11,11 @@ with lib;
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
+        description = lib.mdDoc ''
           Whether to configure system to use gphoto2.
           To grant digital camera access to a user, the user must
           be part of the camera group:
-          <literal>users.users.alice.extraGroups = ["camera"];</literal>
+          `users.users.alice.extraGroups = ["camera"];`
         '';
       };
     };
diff --git a/nixos/modules/programs/neovim.nix b/nixos/modules/programs/neovim.nix
index 2c39456895f..85963159a72 100644
--- a/nixos/modules/programs/neovim.nix
+++ b/nixos/modules/programs/neovim.nix
@@ -72,9 +72,9 @@ in {
           };
         }
       '';
-      description = ''
+      description = lib.mdDoc ''
         Generate your init file from your list of plugins and custom commands.
-        Neovim will then be wrapped to load <command>nvim -u /nix/store/«hash»-vimrc</command>
+        Neovim will then be wrapped to load {command}`nvim -u /nix/store/«hash»-vimrc`
       '';
     };
 
diff --git a/nixos/modules/programs/nncp.nix b/nixos/modules/programs/nncp.nix
index f40e888dad8..a58748d2fe6 100644
--- a/nixos/modules/programs/nncp.nix
+++ b/nixos/modules/programs/nncp.nix
@@ -33,24 +33,24 @@ in {
     secrets = mkOption {
       type = with types; listOf str;
       example = [ "/run/keys/nncp.hjson" ];
-      description = ''
+      description = lib.mdDoc ''
         A list of paths to NNCP configuration files that should not be
         in the Nix store. These files are layered on top of the values at
-        <xref linkend="opt-programs.nncp.settings"/>.
+        [](#opt-programs.nncp.settings).
       '';
     };
 
     settings = mkOption {
       type = settingsFormat.type;
-      description = ''
+      description = lib.mdDoc ''
         NNCP configuration, see
-        <link xlink:href="http://www.nncpgo.org/Configuration.html"/>.
+        <http://www.nncpgo.org/Configuration.html>.
         At runtime these settings will be overlayed by the contents of
-        <xref linkend="opt-programs.nncp.secrets"/> into the file
-        <literal>${nncpCfgFile}</literal>. Node keypairs go in
-        <literal>secrets</literal>, do not specify them in
-        <literal>settings</literal> as they will be leaked into
-        <literal>/nix/store</literal>!
+        [](#opt-programs.nncp.secrets) into the file
+        `${nncpCfgFile}`. Node keypairs go in
+        `secrets`, do not specify them in
+        `settings` as they will be leaked into
+        `/nix/store`!
       '';
       default = { };
     };
diff --git a/nixos/modules/programs/turbovnc.nix b/nixos/modules/programs/turbovnc.nix
index eb09c554290..a0e4a36cfd9 100644
--- a/nixos/modules/programs/turbovnc.nix
+++ b/nixos/modules/programs/turbovnc.nix
@@ -15,14 +15,14 @@ in
       ensureHeadlessSoftwareOpenGL = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to set up NixOS such that TurboVNC's built-in software OpenGL
           implementation works.
 
-          This will enable <option>hardware.opengl.enable</option> so that OpenGL
+          This will enable {option}`hardware.opengl.enable` so that OpenGL
           programs can find Mesa's llvmpipe drivers.
 
-          Setting this option to <literal>false</literal> does not mean that software
+          Setting this option to `false` does not mean that software
           OpenGL won't work; it may still work depending on your system
           configuration.
 
diff --git a/nixos/modules/security/acme/default.nix b/nixos/modules/security/acme/default.nix
index 4bc3d8e743d..a1d8c533304 100644
--- a/nixos/modules/security/acme/default.nix
+++ b/nixos/modules/security/acme/default.nix
@@ -504,8 +504,8 @@ let
       reloadServices = mkOption {
         type = types.listOf types.str;
         inherit (defaultAndText "reloadServices" []) default defaultText;
-        description = ''
-          The list of systemd services to call <literal>systemctl try-reload-or-restart</literal>
+        description = lib.mdDoc ''
+          The list of systemd services to call `systemctl try-reload-or-restart`
           on.
         '';
       };
diff --git a/nixos/modules/security/doas.nix b/nixos/modules/security/doas.nix
index 2641548221a..4d15ed9a802 100644
--- a/nixos/modules/security/doas.nix
+++ b/nixos/modules/security/doas.nix
@@ -62,19 +62,19 @@ in
     wheelNeedsPassword = mkOption {
       type = with types; bool;
       default = true;
-      description = ''
-        Whether users of the <literal>wheel</literal> group must provide a password to
-        run commands as super user via <command>doas</command>.
+      description = lib.mdDoc ''
+        Whether users of the `wheel` group must provide a password to
+        run commands as super user via {command}`doas`.
       '';
     };
 
     extraRules = mkOption {
       default = [];
-      description = ''
+      description = lib.mdDoc ''
         Define specific rules to be set in the
-        <filename>/etc/doas.conf</filename> file. More specific rules should
+        {file}`/etc/doas.conf` file. More specific rules should
         come after more general ones in order to yield the expected behavior.
-        You can use <literal>mkBefore</literal> and/or <literal>mkAfter</literal> to ensure
+        You can use `mkBefore` and/or `mkAfter` to ensure
         this is the case when configuration options are merged.
       '';
       example = literalExpression ''
@@ -113,8 +113,8 @@ in
             noPass = mkOption {
               type = with types; bool;
               default = false;
-              description = ''
-                If <literal>true</literal>, the user is not required to enter a
+              description = lib.mdDoc ''
+                If `true`, the user is not required to enter a
                 password.
               '';
             };
@@ -122,18 +122,18 @@ in
             noLog = mkOption {
               type = with types; bool;
               default = false;
-              description = ''
-                If <literal>true</literal>, successful executions will not be logged
+              description = lib.mdDoc ''
+                If `true`, successful executions will not be logged
                 to
-                <citerefentry><refentrytitle>syslogd</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+                {manpage}`syslogd(8)`.
               '';
             };
 
             persist = mkOption {
               type = with types; bool;
               default = false;
-              description = ''
-                If <literal>true</literal>, do not ask for a password again for some
+              description = lib.mdDoc ''
+                If `true`, do not ask for a password again for some
                 time after the user successfully authenticates.
               '';
             };
@@ -141,10 +141,10 @@ in
             keepEnv = mkOption {
               type = with types; bool;
               default = false;
-              description = ''
-                If <literal>true</literal>, environment variables other than those
+              description = lib.mdDoc ''
+                If `true`, environment variables other than those
                 listed in
-                <citerefentry><refentrytitle>doas</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                {manpage}`doas(1)`
                 are kept when creating the environment for the new process.
               '';
             };
@@ -152,18 +152,18 @@ in
             setEnv = mkOption {
               type = with types; listOf str;
               default = [];
-              description = ''
+              description = lib.mdDoc ''
                 Keep or set the specified variables. Variables may also be
                 removed with a leading '-' or set using
-                <literal>variable=value</literal>. If the first character of
-                <literal>value</literal> is a '$', the value to be set is taken from
+                `variable=value`. If the first character of
+                `value` is a '$', the value to be set is taken from
                 the existing environment variable of the indicated name. This
                 option is processed after the default environment has been
                 created.
 
-                NOTE: All rules have <literal>setenv { SSH_AUTH_SOCK }</literal> by
-                default. To prevent <literal>SSH_AUTH_SOCK</literal> from being
-                inherited, add <literal>"-SSH_AUTH_SOCK"</literal> anywhere in this
+                NOTE: All rules have `setenv { SSH_AUTH_SOCK }` by
+                default. To prevent `SSH_AUTH_SOCK` from being
+                inherited, add `"-SSH_AUTH_SOCK"` anywhere in this
                 list.
               '';
             };
@@ -183,23 +183,23 @@ in
             runAs = mkOption {
               type = with types; nullOr str;
               default = null;
-              description = ''
+              description = lib.mdDoc ''
                 Which user or group the specified command is allowed to run as.
-                When set to <literal>null</literal> (the default), all users are
+                When set to `null` (the default), all users are
                 allowed.
 
                 A user can be specified using just the username:
-                <literal>"foo"</literal>. It is also possible to only allow running as
-                a specific group with <literal>":bar"</literal>.
+                `"foo"`. It is also possible to only allow running as
+                a specific group with `":bar"`.
               '';
             };
 
             cmd = mkOption {
               type = with types; nullOr str;
               default = null;
-              description = ''
+              description = lib.mdDoc ''
                 The command the user is allowed to run. When set to
-                <literal>null</literal> (the default), all commands are allowed.
+                `null` (the default), all commands are allowed.
 
                 NOTE: It is best practice to specify absolute paths. If a
                 relative path is specified, only a restricted PATH will be
@@ -210,9 +210,9 @@ in
             args = mkOption {
               type = with types; nullOr (listOf str);
               default = null;
-              description = ''
+              description = lib.mdDoc ''
                 Arguments that must be provided to the command. When set to
-                <literal>[]</literal>, the command must be run without any arguments.
+                `[]`, the command must be run without any arguments.
               '';
             };
           };
diff --git a/nixos/modules/security/misc.nix b/nixos/modules/security/misc.nix
index 3c83ff8d773..6833452a570 100644
--- a/nixos/modules/security/misc.nix
+++ b/nixos/modules/security/misc.nix
@@ -52,7 +52,7 @@ with lib;
     security.allowSimultaneousMultithreading = mkOption {
       type = types.bool;
       default = true;
-      description = ''
+      description = lib.mdDoc ''
         Whether to allow SMT/hyperthreading.  Disabling SMT means that only
         physical CPU cores will be usable at runtime, potentially at
         significant performance cost.
@@ -62,7 +62,7 @@ with lib;
         e.g., shared caches).  This attack vector is unproven.
 
         Disabling SMT is a supplement to the L1 data cache flushing mitigation
-        (see <xref linkend="opt-security.virtualisation.flushL1DataCache"/>)
+        (see [](#opt-security.virtualisation.flushL1DataCache))
         versus malicious VM guests (SMT could "bring back" previously flushed
         data).
       '';
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 8a70e5f3adb..2d0f2568978 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -807,14 +807,14 @@ in
         default = config.krb5.enable;
         defaultText = literalExpression "config.krb5.enable";
         type = types.bool;
-        description = ''
-          Enables Kerberos PAM modules (<literal>pam-krb5</literal>,
-          <literal>pam-ccreds</literal>).
+        description = lib.mdDoc ''
+          Enables Kerberos PAM modules (`pam-krb5`,
+          `pam-ccreds`).
 
           If set, users can authenticate with their Kerberos password.
           This requires a valid Kerberos configuration
-          (<literal>config.krb5.enable</literal> should be set to
-          <literal>true</literal>).
+          (`config.krb5.enable` should be set to
+          `true`).
 
           Note that the Kerberos PAM modules are not necessary when using SSS
           to handle Kerberos authentication.
@@ -826,12 +826,12 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
-          Enables P11 PAM (<literal>pam_p11</literal>) module.
+        description = lib.mdDoc ''
+          Enables P11 PAM (`pam_p11`) module.
 
           If set, users can log in with SSH keys and PKCS#11 tokens.
 
-          More information can be found <link xlink:href="https://github.com/OpenSC/pam_p11">here</link>.
+          More information can be found [here](https://github.com/OpenSC/pam_p11).
         '';
       };
 
@@ -858,71 +858,71 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
-          Enables U2F PAM (<literal>pam-u2f</literal>) module.
+        description = lib.mdDoc ''
+          Enables U2F PAM (`pam-u2f`) module.
 
           If set, users listed in
-          <filename>$XDG_CONFIG_HOME/Yubico/u2f_keys</filename> (or
-          <filename>$HOME/.config/Yubico/u2f_keys</filename> if XDG variable is
+          {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
+          {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
           not set) are able to log in with the associated U2F key. The path can
-          be changed using <option>security.pam.u2f.authFile</option> option.
+          be changed using {option}`security.pam.u2f.authFile` option.
 
           File format is:
-          <literal>username:first_keyHandle,first_public_key: second_keyHandle,second_public_key</literal>
-          This file can be generated using <command>pamu2fcfg</command> command.
+          `username:first_keyHandle,first_public_key: second_keyHandle,second_public_key`
+          This file can be generated using {command}`pamu2fcfg` command.
 
-          More information can be found <link xlink:href="https://developers.yubico.com/pam-u2f/">here</link>.
+          More information can be found [here](https://developers.yubico.com/pam-u2f/).
         '';
       };
 
       authFile = mkOption {
         default = null;
         type = with types; nullOr path;
-        description = ''
-          By default <literal>pam-u2f</literal> module reads the keys from
-          <filename>$XDG_CONFIG_HOME/Yubico/u2f_keys</filename> (or
-          <filename>$HOME/.config/Yubico/u2f_keys</filename> if XDG variable is
+        description = lib.mdDoc ''
+          By default `pam-u2f` module reads the keys from
+          {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
+          {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
           not set).
 
           If you want to change auth file locations or centralize database (for
-          example use <filename>/etc/u2f-mappings</filename>) you can set this
+          example use {file}`/etc/u2f-mappings`) you can set this
           option.
 
           File format is:
-          <literal>username:first_keyHandle,first_public_key: second_keyHandle,second_public_key</literal>
-          This file can be generated using <command>pamu2fcfg</command> command.
+          `username:first_keyHandle,first_public_key: second_keyHandle,second_public_key`
+          This file can be generated using {command}`pamu2fcfg` command.
 
-          More information can be found <link xlink:href="https://developers.yubico.com/pam-u2f/">here</link>.
+          More information can be found [here](https://developers.yubico.com/pam-u2f/).
         '';
       };
 
       appId = mkOption {
         default = null;
         type = with types; nullOr str;
-        description = ''
-            By default <literal>pam-u2f</literal> module sets the application
-            ID to <literal>pam://$HOSTNAME</literal>.
+        description = lib.mdDoc ''
+            By default `pam-u2f` module sets the application
+            ID to `pam://$HOSTNAME`.
 
-            When using <command>pamu2fcfg</command>, you can specify your
-            application ID with the <literal>-i</literal> flag.
+            When using {command}`pamu2fcfg`, you can specify your
+            application ID with the `-i` flag.
 
-            More information can be found <link xlink:href="https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html">here</link>
+            More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
         '';
       };
 
       origin = mkOption {
         default = null;
         type = with types; nullOr str;
-        description = ''
-            By default <literal>pam-u2f</literal> module sets the origin
-            to <literal>pam://$HOSTNAME</literal>.
+        description = lib.mdDoc ''
+            By default `pam-u2f` module sets the origin
+            to `pam://$HOSTNAME`.
             Setting origin to an host independent value will allow you to
             reuse credentials across machines
 
-            When using <command>pamu2fcfg</command>, you can specify your
-            application ID with the <literal>-o</literal> flag.
+            When using {command}`pamu2fcfg`, you can specify your
+            application ID with the `-o` flag.
 
-            More information can be found <link xlink:href="https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html">here</link>
+            More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
         '';
       };
 
@@ -978,17 +978,17 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
-          Enables Uber's USSH PAM (<literal>pam-ussh</literal>) module.
+        description = lib.mdDoc ''
+          Enables Uber's USSH PAM (`pam-ussh`) module.
 
-          This is similar to <literal>pam-ssh-agent</literal>, except that
+          This is similar to `pam-ssh-agent`, except that
           the presence of a CA-signed SSH key with a valid principal is checked
           instead.
 
           Note that this module must both be enabled using this option and on a
-          per-PAM-service level as well (using <literal>usshAuth</literal>).
+          per-PAM-service level as well (using `usshAuth`).
 
-          More information can be found <link xlink:href="https://github.com/uber/pam-ussh">here</link>.
+          More information can be found [here](https://github.com/uber/pam-ussh).
         '';
       };
 
@@ -1067,16 +1067,16 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
-          Enables Yubico PAM (<literal>yubico-pam</literal>) module.
+        description = lib.mdDoc ''
+          Enables Yubico PAM (`yubico-pam`) module.
 
           If set, users listed in
-          <filename>~/.yubico/authorized_yubikeys</filename>
+          {file}`~/.yubico/authorized_yubikeys`
           are able to log in with the associated Yubikey tokens.
 
           The file must have only one line:
-          <literal>username:yubikey_token_id1:yubikey_token_id2</literal>
-          More information can be found <link xlink:href="https://developers.yubico.com/yubico-pam/">here</link>.
+          `username:yubikey_token_id1:yubikey_token_id2`
+          More information can be found [here](https://developers.yubico.com/yubico-pam/).
         '';
       };
       control = mkOption {
@@ -1111,7 +1111,7 @@ in
       mode = mkOption {
         default = "client";
         type = types.enum [ "client" "challenge-response" ];
-        description = ''
+        description = lib.mdDoc ''
           Mode of operation.
 
           Use "client" for online validation with a YubiKey validation service such as
@@ -1121,16 +1121,16 @@ in
           Challenge-Response configurations. See the man-page ykpamcfg(1) for further
           details on how to configure offline Challenge-Response validation.
 
-          More information can be found <link xlink:href="https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html">here</link>.
+          More information can be found [here](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html).
         '';
       };
       challengeResponsePath = mkOption {
         default = null;
         type = types.nullOr types.path;
-        description = ''
+        description = lib.mdDoc ''
           If not null, set the path used by yubico pam module where the challenge expected response is stored.
 
-          More information can be found <link xlink:href="https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html">here</link>.
+          More information can be found [here](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html).
         '';
       };
     };
diff --git a/nixos/modules/security/pam_mount.nix b/nixos/modules/security/pam_mount.nix
index ae314abd86c..11cc13a8cbe 100644
--- a/nixos/modules/security/pam_mount.nix
+++ b/nixos/modules/security/pam_mount.nix
@@ -31,9 +31,9 @@ in
       extraVolumes = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = ''
+        description = lib.mdDoc ''
           List of volume definitions for pam_mount.
-          For more information, visit <link xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html"/>.
+          For more information, visit <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>.
         '';
       };
 
@@ -63,20 +63,20 @@ in
         type = types.int;
         default = 0;
         example = 1;
-        description = ''
+        description = lib.mdDoc ''
           Sets the Debug-Level. 0 disables debugging, 1 enables pam_mount tracing,
           and 2 additionally enables tracing in mount.crypt. The default is 0.
-          For more information, visit <link xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html"/>.
+          For more information, visit <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>.
         '';
       };
 
       logoutWait = mkOption {
         type = types.int;
         default = 0;
-        description = ''
+        description = lib.mdDoc ''
           Amount of microseconds to wait until killing remaining processes after
           final logout.
-          For more information, visit <link xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html"/>.
+          For more information, visit <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>.
         '';
       };
 
diff --git a/nixos/modules/security/pam_usb.nix b/nixos/modules/security/pam_usb.nix
index 71e2af8f3a5..4275c26c6bd 100644
--- a/nixos/modules/security/pam_usb.nix
+++ b/nixos/modules/security/pam_usb.nix
@@ -17,9 +17,9 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Enable USB login for all login systems that support it.  For
-          more information, visit <link xlink:href="https://github.com/aluzzardi/pam_usb/wiki/Getting-Started#setting-up-devices-and-users"/>.
+          more information, visit <https://github.com/aluzzardi/pam_usb/wiki/Getting-Started#setting-up-devices-and-users>.
         '';
       };
 
diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix
index c1a69aedde4..faa99a31a6d 100644
--- a/nixos/modules/security/sudo.nix
+++ b/nixos/modules/security/sudo.nix
@@ -55,19 +55,19 @@ in
       type = types.bool;
       default = true;
       description =
-        ''
-          Whether users of the <literal>wheel</literal> group must
-          provide a password to run commands as super user via <command>sudo</command>.
+        lib.mdDoc ''
+          Whether users of the `wheel` group must
+          provide a password to run commands as super user via {command}`sudo`.
         '';
       };
 
     security.sudo.execWheelOnly = mkOption {
       type = types.bool;
       default = false;
-      description = ''
-        Only allow members of the <literal>wheel</literal> group to execute sudo by
+      description = lib.mdDoc ''
+        Only allow members of the `wheel` group to execute sudo by
         setting the executable's permissions accordingly.
-        This prevents users that are not members of <literal>wheel</literal> from
+        This prevents users that are not members of `wheel` from
         exploiting vulnerabilities in sudo such as CVE-2021-3156.
       '';
     };
@@ -139,12 +139,12 @@ in
           runAs = mkOption {
             type = with types; str;
             default = "ALL:ALL";
-            description = ''
+            description = lib.mdDoc ''
               Under which user/group the specified command is allowed to run.
 
-              A user can be specified using just the username: <literal>"foo"</literal>.
-              It is also possible to specify a user/group combination using <literal>"foo:bar"</literal>
-              or to only allow running as a specific group with <literal>":bar"</literal>.
+              A user can be specified using just the username: `"foo"`.
+              It is also possible to specify a user/group combination using `"foo:bar"`
+              or to only allow running as a specific group with `":bar"`.
             '';
           };
 
diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix
index 76d7f093f21..56958bf949d 100644
--- a/nixos/modules/services/backup/restic.nix
+++ b/nixos/modules/services/backup/restic.nix
@@ -227,7 +227,7 @@ in
           type = types.package;
           default = pkgs.restic;
           defaultText = literalExpression "pkgs.restic";
-          description = ''
+          description = lib.mdDoc ''
             Restic package to use.
           '';
         };
diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix
index 6e71eaa5b9a..cbfbc59bf5b 100644
--- a/nixos/modules/services/backup/syncoid.nix
+++ b/nixos/modules/services/backup/syncoid.nix
@@ -192,7 +192,7 @@ in
           target = mkOption {
             type = types.str;
             example = "user@server:pool/dataset";
-            description = ''
+            description = lib.mdDoc ''
               Target ZFS dataset. Can be either local
               («pool/dataset») or remote
               («user@server:pool/dataset»).
diff --git a/nixos/modules/services/backup/zrepl.nix b/nixos/modules/services/backup/zrepl.nix
index 7b31b0da036..ea858a8b77d 100644
--- a/nixos/modules/services/backup/zrepl.nix
+++ b/nixos/modules/services/backup/zrepl.nix
@@ -22,8 +22,8 @@ in
 
       settings = mkOption {
         default = { };
-        description = ''
-          Configuration for zrepl. See <link xlink:href="https://zrepl.github.io/configuration.html"/>
+        description = lib.mdDoc ''
+          Configuration for zrepl. See <https://zrepl.github.io/configuration.html>
           for more information.
         '';
         type = types.submodule {
diff --git a/nixos/modules/services/continuous-integration/github-runner.nix b/nixos/modules/services/continuous-integration/github-runner.nix
index 2c753b514c5..54003382368 100644
--- a/nixos/modules/services/continuous-integration/github-runner.nix
+++ b/nixos/modules/services/continuous-integration/github-runner.nix
@@ -18,11 +18,11 @@ in
     enable = mkOption {
       default = false;
       example = true;
-      description = ''
+      description = lib.mdDoc ''
         Whether to enable GitHub Actions runner.
 
         Note: GitHub recommends using self-hosted runners with private repositories only. Learn more here:
-        <link xlink:href="https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners">About self-hosted runners</link>.
+        [About self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners).
       '';
       type = lib.types.bool;
     };
diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix
index 03d3d2d16e3..9f076e2d7a2 100644
--- a/nixos/modules/services/continuous-integration/gitlab-runner.nix
+++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -113,15 +113,15 @@ in
     configFile = mkOption {
       type = types.nullOr types.path;
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Configuration file for gitlab-runner.
 
-        <option>configFile</option> takes precedence over <option>services</option>.
-        <option>checkInterval</option> and <option>concurrent</option> will be ignored too.
+        {option}`configFile` takes precedence over {option}`services`.
+        {option}`checkInterval` and {option}`concurrent` will be ignored too.
 
-        This option is deprecated, please use <option>services</option> instead.
-        You can use <option>registrationConfigFile</option> and
-        <option>registrationFlags</option>
+        This option is deprecated, please use {option}`services` instead.
+        You can use {option}`registrationConfigFile` and
+        {option}`registrationFlags`
         for settings not covered by this module.
       '';
     };
@@ -130,16 +130,16 @@ in
         freeformType = (pkgs.formats.json { }).type;
       };
       default = { };
-      description = ''
+      description = lib.mdDoc ''
         Global gitlab-runner configuration. See
-        <link xlink:href="https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section"/>
+        <https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section>
         for supported values.
       '';
     };
     gracefulTermination = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         Finish all remaining jobs before stopping.
         If not set gitlab-runner will stop immediatly without waiting
         for jobs to finish, which will lead to failed builds.
@@ -149,7 +149,7 @@ in
       type = types.str;
       default = "infinity";
       example = "5min 20s";
-      description = ''
+      description = lib.mdDoc ''
         Time to wait until a graceful shutdown is turned into a forceful one.
       '';
     };
@@ -158,17 +158,17 @@ in
       default = pkgs.gitlab-runner;
       defaultText = literalExpression "pkgs.gitlab-runner";
       example = literalExpression "pkgs.gitlab-runner_1_11";
-      description = "Gitlab Runner package to use.";
+      description = lib.mdDoc "Gitlab Runner package to use.";
     };
     extraPackages = mkOption {
       type = types.listOf types.package;
       default = [ ];
-      description = ''
+      description = lib.mdDoc ''
         Extra packages to add to PATH for the gitlab-runner process.
       '';
     };
     services = mkOption {
-      description = "GitLab Runner services.";
+      description = lib.mdDoc "GitLab Runner services.";
       default = { };
       example = literalExpression ''
         {
@@ -250,17 +250,17 @@ in
         options = {
           registrationConfigFile = mkOption {
             type = types.path;
-            description = ''
+            description = lib.mdDoc ''
               Absolute path to a file with environment variables
               used for gitlab-runner registration.
               A list of all supported environment variables can be found in
-              <literal>gitlab-runner register --help</literal>.
+              `gitlab-runner register --help`.
 
               Ones that you probably want to set is
 
-              <literal>CI_SERVER_URL=&lt;CI server URL&gt;</literal>
+              `CI_SERVER_URL=<CI server URL>`
 
-              <literal>REGISTRATION_TOKEN=&lt;registration secret&gt;</literal>
+              `REGISTRATION_TOKEN=<registration secret>`
 
               WARNING: make sure to use quoted absolute path,
               or it is going to be copied to Nix Store.
@@ -270,10 +270,10 @@ in
             type = types.listOf types.str;
             default = [ ];
             example = [ "--docker-helper-image my/gitlab-runner-helper" ];
-            description = ''
+            description = lib.mdDoc ''
               Extra command-line flags passed to
-              <literal>gitlab-runner register</literal>.
-              Execute <literal>gitlab-runner register --help</literal>
+              `gitlab-runner register`.
+              Execute `gitlab-runner register --help`
               for a list of supported flags.
             '';
           };
@@ -281,32 +281,32 @@ in
             type = types.attrsOf types.str;
             default = { };
             example = { NAME = "value"; };
-            description = ''
+            description = lib.mdDoc ''
               Custom environment variables injected to build environment.
-              For secrets you can use <option>registrationConfigFile</option>
-              with <literal>RUNNER_ENV</literal> variable set.
+              For secrets you can use {option}`registrationConfigFile`
+              with `RUNNER_ENV` variable set.
             '';
           };
           description = mkOption {
             type = types.nullOr types.str;
             default = null;
-            description = ''
+            description = lib.mdDoc ''
               Name/description of the runner.
             '';
           };
           executor = mkOption {
             type = types.str;
             default = "docker";
-            description = ''
+            description = lib.mdDoc ''
               Select executor, eg. shell, docker, etc.
-              See <link xlink:href="https://docs.gitlab.com/runner/executors/README.html">runner documentation</link> for more information.
+              See [runner documentation](https://docs.gitlab.com/runner/executors/README.html) for more information.
             '';
           };
           buildsDir = mkOption {
             type = types.nullOr types.path;
             default = null;
             example = "/var/lib/gitlab-runner/builds";
-            description = ''
+            description = lib.mdDoc ''
               Absolute path to a directory where builds will be stored
               in context of selected executor (Locally, Docker, SSH).
             '';
@@ -315,14 +315,14 @@ in
             type = types.nullOr types.str;
             default = null;
             example = "http://gitlab.example.local";
-            description = ''
+            description = lib.mdDoc ''
               Overwrite the URL for the GitLab instance. Used if the Runner can’t connect to GitLab on the URL GitLab exposes itself.
             '';
           };
           dockerImage = mkOption {
             type = types.nullOr types.str;
             default = null;
-            description = ''
+            description = lib.mdDoc ''
               Docker image to be used.
             '';
           };
@@ -330,7 +330,7 @@ in
             type = types.listOf types.str;
             default = [ ];
             example = [ "/var/run/docker.sock:/var/run/docker.sock" ];
-            description = ''
+            description = lib.mdDoc ''
               Bind-mount a volume and create it
               if it doesn't exist prior to mounting.
             '';
@@ -338,14 +338,14 @@ in
           dockerDisableCache = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               Disable all container caching.
             '';
           };
           dockerPrivileged = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               Give extended privileges to container.
             '';
           };
@@ -353,7 +353,7 @@ in
             type = types.listOf types.str;
             default = [ ];
             example = [ "other-host:127.0.0.1" ];
-            description = ''
+            description = lib.mdDoc ''
               Add a custom host-to-IP mapping.
             '';
           };
@@ -361,7 +361,7 @@ in
             type = types.listOf types.str;
             default = [ ];
             example = [ "ruby:*" "python:*" "php:*" "my.registry.tld:5000/*:*" ];
-            description = ''
+            description = lib.mdDoc ''
               Whitelist allowed images.
             '';
           };
@@ -369,21 +369,21 @@ in
             type = types.listOf types.str;
             default = [ ];
             example = [ "postgres:9" "redis:*" "mysql:*" ];
-            description = ''
+            description = lib.mdDoc ''
               Whitelist allowed services.
             '';
           };
           preCloneScript = mkOption {
             type = types.nullOr types.path;
             default = null;
-            description = ''
+            description = lib.mdDoc ''
               Runner-specific command script executed before code is pulled.
             '';
           };
           preBuildScript = mkOption {
             type = types.nullOr types.path;
             default = null;
-            description = ''
+            description = lib.mdDoc ''
               Runner-specific command script executed after code is pulled,
               just before build executes.
             '';
@@ -391,7 +391,7 @@ in
           postBuildScript = mkOption {
             type = types.nullOr types.path;
             default = null;
-            description = ''
+            description = lib.mdDoc ''
               Runner-specific command script executed after code is pulled
               and just after build executes.
             '';
@@ -399,22 +399,22 @@ in
           tagList = mkOption {
             type = types.listOf types.str;
             default = [ ];
-            description = ''
+            description = lib.mdDoc ''
               Tag list.
             '';
           };
           runUntagged = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               Register to run untagged builds; defaults to
-              <literal>true</literal> when <option>tagList</option> is empty.
+              `true` when {option}`tagList` is empty.
             '';
           };
           limit = mkOption {
             type = types.int;
             default = 0;
-            description = ''
+            description = lib.mdDoc ''
               Limit how many jobs can be handled concurrently by this service.
               0 (default) simply means don't limit.
             '';
@@ -422,14 +422,14 @@ in
           requestConcurrency = mkOption {
             type = types.int;
             default = 0;
-            description = ''
+            description = lib.mdDoc ''
               Limit number of concurrent requests for new jobs from GitLab.
             '';
           };
           maximumTimeout = mkOption {
             type = types.int;
             default = 0;
-            description = ''
+            description = lib.mdDoc ''
               What is the maximum timeout (in seconds) that will be set for
               job when using this Runner. 0 (default) simply means don't limit.
             '';
@@ -437,7 +437,7 @@ in
           protected = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               When set to true Runner will only run on pipelines
               triggered on protected branches.
             '';
@@ -445,9 +445,9 @@ in
           debugTraceDisabled = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               When set to true Runner will disable the possibility of
-              using the <literal>CI_DEBUG_TRACE</literal> feature.
+              using the `CI_DEBUG_TRACE` feature.
             '';
           };
         };
diff --git a/nixos/modules/services/databases/firebird.nix b/nixos/modules/services/databases/firebird.nix
index a26f1ff8258..4aaf4ca12aa 100644
--- a/nixos/modules/services/databases/firebird.nix
+++ b/nixos/modules/services/databases/firebird.nix
@@ -47,9 +47,9 @@ in
         defaultText = literalExpression "pkgs.firebird";
         type = types.package;
         example = literalExpression "pkgs.firebird_3";
-        description = ''
-          Which Firebird package to be installed: <literal>pkgs.firebird_3</literal>
-          For SuperServer use override: <literal>pkgs.firebird_3.override { superServer = true; };</literal>
+        description = lib.mdDoc ''
+          Which Firebird package to be installed: `pkgs.firebird_3`
+          For SuperServer use override: `pkgs.firebird_3.override { superServer = true; };`
         '';
       };
 
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix
index 1e6a6b844a3..1a096d2a88a 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -201,7 +201,7 @@ in
             ensurePermissions = mkOption {
               type = types.attrsOf types.str;
               default = {};
-              description = ''
+              description = lib.mdDoc ''
                 Permissions to ensure for the user, specified as attribute set.
                 The attribute names specify the database and tables to grant the permissions for,
                 separated by a dot. You may use wildcards here.
@@ -210,8 +210,8 @@ in
 
                 For more information on how to specify the target
                 and on which privileges exist, see the
-                <link xlink:href="https://mariadb.com/kb/en/library/grant/">GRANT syntax</link>.
-                The attributes are used as <literal>GRANT ''${attrName} ON ''${attrValue}</literal>.
+                [GRANT syntax](https://mariadb.com/kb/en/library/grant/).
+                The attributes are used as `GRANT ''${attrName} ON ''${attrValue}`.
               '';
               example = literalExpression ''
                 {
diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix
index ad659ccd82e..d1be4034dda 100644
--- a/nixos/modules/services/databases/neo4j.nix
+++ b/nixos/modules/services/databases/neo4j.nix
@@ -139,14 +139,14 @@ in {
     constrainLoadCsv = mkOption {
       type = types.bool;
       default = true;
-      description = ''
+      description = lib.mdDoc ''
         Sets the root directory for file URLs used with the Cypher
-        <literal>LOAD CSV</literal> clause to be that defined by
-        <option>directories.imports</option>. It restricts
+        `LOAD CSV` clause to be that defined by
+        {option}`directories.imports`. It restricts
         access to only those files within that directory and its
         subdirectories.
 
-        Setting this option to <literal>false</literal> introduces
+        Setting this option to `false` introduces
         possible security problems.
       '';
     };
@@ -154,14 +154,14 @@ in {
     defaultListenAddress = mkOption {
       type = types.str;
       default = "127.0.0.1";
-      description = ''
+      description = lib.mdDoc ''
         Default network interface to listen for incoming connections. To
         listen for connections on all interfaces, use "0.0.0.0".
 
         Specifies the default IP address and address part of connector
-        specific <option>listenAddress</option> options. To bind specific
+        specific {option}`listenAddress` options. To bind specific
         connectors to a specific network interfaces, specify the entire
-        <option>listenAddress</option> option for that connector.
+        {option}`listenAddress` option for that connector.
       '';
     };
 
@@ -225,18 +225,18 @@ in {
       sslPolicy = mkOption {
         type = types.str;
         default = "legacy";
-        description = ''
+        description = lib.mdDoc ''
           Neo4j SSL policy for BOLT traffic.
 
           The legacy policy is a special policy which is not defined in
           the policy configuration section, but rather derives from
-          <option>directories.certificates</option> and
-          associated files (by default: <filename>neo4j.key</filename> and
-          <filename>neo4j.cert</filename>). Its use will be deprecated.
+          {option}`directories.certificates` and
+          associated files (by default: {file}`neo4j.key` and
+          {file}`neo4j.cert`). Its use will be deprecated.
 
           Note: This connector must be configured to support/require
           SSL/TLS for the legacy policy to actually be utilized. See
-          <option>bolt.tlsLevel</option>.
+          {option}`bolt.tlsLevel`.
         '';
       };
 
@@ -254,19 +254,19 @@ in {
         type = types.path;
         default = "${cfg.directories.home}/certificates";
         defaultText = literalExpression ''"''${config.${opt.directories.home}}/certificates"'';
-        description = ''
+        description = lib.mdDoc ''
           Directory for storing certificates to be used by Neo4j for
           TLS connections.
 
           When setting this directory to something other than its default,
           ensure the directory's existence, and that read/write permissions are
-          given to the Neo4j daemon user <literal>neo4j</literal>.
+          given to the Neo4j daemon user `neo4j`.
 
           Note that changing this directory from its default will prevent
           the directory structure required for each SSL policy from being
           automatically generated. A policy's directory structure as defined by
-          its <option>baseDirectory</option>,<option>revokedDir</option> and
-          <option>trustedDir</option> must then be setup manually. The
+          its {option}`baseDirectory`,{option}`revokedDir` and
+          {option}`trustedDir` must then be setup manually. The
           existence of these directories is mandatory, as well as the presence
           of the certificate file and the private key. Ensure the correct
           permissions are set on these directories and files.
@@ -277,13 +277,13 @@ in {
         type = types.path;
         default = "${cfg.directories.home}/data";
         defaultText = literalExpression ''"''${config.${opt.directories.home}}/data"'';
-        description = ''
+        description = lib.mdDoc ''
           Path of the data directory. You must not configure more than one
           Neo4j installation to use the same data directory.
 
           When setting this directory to something other than its default,
           ensure the directory's existence, and that read/write permissions are
-          given to the Neo4j daemon user <literal>neo4j</literal>.
+          given to the Neo4j daemon user `neo4j`.
         '';
       };
 
@@ -302,15 +302,15 @@ in {
         type = types.path;
         default = "${cfg.directories.home}/import";
         defaultText = literalExpression ''"''${config.${opt.directories.home}}/import"'';
-        description = ''
+        description = lib.mdDoc ''
           The root directory for file URLs used with the Cypher
-          <literal>LOAD CSV</literal> clause. Only meaningful when
-          <option>constrainLoadCvs</option> is set to
-          <literal>true</literal>.
+          `LOAD CSV` clause. Only meaningful when
+          {option}`constrainLoadCvs` is set to
+          `true`.
 
           When setting this directory to something other than its default,
           ensure the directory's existence, and that read permission is
-          given to the Neo4j daemon user <literal>neo4j</literal>.
+          given to the Neo4j daemon user `neo4j`.
         '';
       };
 
@@ -318,14 +318,14 @@ in {
         type = types.path;
         default = "${cfg.directories.home}/plugins";
         defaultText = literalExpression ''"''${config.${opt.directories.home}}/plugins"'';
-        description = ''
+        description = lib.mdDoc ''
           Path of the database plugin directory. Compiled Java JAR files that
           contain database procedures will be loaded if they are placed in
           this directory.
 
           When setting this directory to something other than its default,
           ensure the directory's existence, and that read permission is
-          given to the Neo4j daemon user <literal>neo4j</literal>.
+          given to the Neo4j daemon user `neo4j`.
         '';
       };
     };
@@ -377,14 +377,14 @@ in {
       sslPolicy = mkOption {
         type = types.str;
         default = "legacy";
-        description = ''
+        description = lib.mdDoc ''
           Neo4j SSL policy for HTTPS traffic.
 
           The legacy policy is a special policy which is not defined in the
           policy configuration section, but rather derives from
-          <option>directories.certificates</option> and
-          associated files (by default: <filename>neo4j.key</filename> and
-          <filename>neo4j.cert</filename>). Its use will be deprecated.
+          {option}`directories.certificates` and
+          associated files (by default: {file}`neo4j.key` and
+          {file}`neo4j.cert`). Its use will be deprecated.
         '';
       };
     };
@@ -407,7 +407,7 @@ in {
           allowKeyGeneration = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               Allows the generation of a private key and associated self-signed
               certificate. Only performed when both objects cannot be found for
               this policy. It is recommended to turn this off again after keys
@@ -415,7 +415,7 @@ in {
 
               The public certificate is required to be duplicated to the
               directory holding trusted certificates as defined by the
-              <option>trustedDir</option> option.
+              {option}`trustedDir` option.
 
               Keys should in general be generated and distributed offline by a
               trusted certificate authority and not by utilizing this mode.
@@ -426,16 +426,16 @@ in {
             type = types.path;
             default = "${cfg.directories.certificates}/${name}";
             defaultText = literalExpression ''"''${config.${opt.directories.certificates}}/''${name}"'';
-            description = ''
+            description = lib.mdDoc ''
               The mandatory base directory for cryptographic objects of this
               policy. This path is only automatically generated when this
-              option as well as <option>directories.certificates</option> are
+              option as well as {option}`directories.certificates` are
               left at their default. Ensure read/write permissions are given
-              to the Neo4j daemon user <literal>neo4j</literal>.
+              to the Neo4j daemon user `neo4j`.
 
               It is also possible to override each individual
               configuration with absolute paths. See the
-              <option>privateKey</option> and <option>publicCertificate</option>
+              {option}`privateKey` and {option}`publicCertificate`
               policy options.
             '';
           };
@@ -470,15 +470,15 @@ in {
           publicCertificate = mkOption {
             type = types.str;
             default = "public.crt";
-            description = ''
+            description = lib.mdDoc ''
               The name of public X.509 certificate (chain) file in PEM format
-              for this policy to be found in the <option>baseDirectory</option>,
+              for this policy to be found in the {option}`baseDirectory`,
               or the absolute path to the certificate file. It is mandatory
               that a certificate can be found or generated.
 
               The public certificate is required to be duplicated to the
               directory holding trusted certificates as defined by the
-              <option>trustedDir</option> option.
+              {option}`trustedDir` option.
             '';
           };
 
@@ -522,18 +522,18 @@ in {
             type = types.path;
             default = "${config.baseDirectory}/trusted";
             defaultText = literalExpression ''"''${config.${options.baseDirectory}}/trusted"'';
-            description = ''
+            description = lib.mdDoc ''
               Path to directory of X.509 certificates in PEM format for
               trusted parties. Must be an absolute path. The existence of this
               directory is mandatory and will need to be created manually when:
               setting this option to something other than its default; setting
-              either this policy's <option>baseDirectory</option> or
-              <option>directories.certificates</option> to something other than
+              either this policy's {option}`baseDirectory` or
+              {option}`directories.certificates` to something other than
               their default. Ensure read/write permissions are given to the
-              Neo4j daemon user <literal>neo4j</literal>.
+              Neo4j daemon user `neo4j`.
 
               The public certificate as defined by
-              <option>publicCertificate</option> is required to be duplicated
+              {option}`publicCertificate` is required to be duplicated
               to this directory.
             '';
           };
diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix
index 94fc155000e..7a59de372f2 100644
--- a/nixos/modules/services/databases/openldap.nix
+++ b/nixos/modules/services/databases/openldap.nix
@@ -88,7 +88,7 @@ in {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = "Whether to enable the ldap server.";
+        description = lib.mdDoc "Whether to enable the ldap server.";
       };
 
       package = mkOption {
@@ -173,9 +173,9 @@ in {
       configDir = mkOption {
         type = types.nullOr types.path;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           Use this config directory instead of generating one from the
-          <literal>settings</literal> option. Overrides all NixOS settings.
+          `settings` option. Overrides all NixOS settings.
         '';
         example = "/var/lib/openldap/slapd.d";
       };
@@ -183,9 +183,9 @@ in {
       mutableConfig = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to allow writable on-line configuration. If
-          <literal>true</literal>, the NixOS settings will only be used to
+          `true`, the NixOS settings will only be used to
           initialize the OpenLDAP configuration if it does not exist, and are
           subsequently ignored.
         '';
diff --git a/nixos/modules/services/databases/pgmanage.nix b/nixos/modules/services/databases/pgmanage.nix
index 79c958b246c..9ce2265a4de 100644
--- a/nixos/modules/services/databases/pgmanage.nix
+++ b/nixos/modules/services/databases/pgmanage.nix
@@ -62,11 +62,11 @@ in {
         nuc-server  = "hostaddr=192.168.0.100 port=5432 dbname=postgres";
         mini-server = "hostaddr=127.0.0.1 port=5432 dbname=postgres sslmode=require";
       };
-      description = ''
+      description = lib.mdDoc ''
         pgmanage requires at least one PostgreSQL server be defined.
 
         Detailed information about PostgreSQL connection strings is available at:
-        <link xlink:href="http://www.postgresql.org/docs/current/static/libpq-connect.html"/>
+        <http://www.postgresql.org/docs/current/static/libpq-connect.html>
 
         Note that you should not specify your user name or password. That
         information will be entered on the login screen. If you specify a
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 8225a9aaba6..d0135647d6a 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -149,7 +149,7 @@ in
             ensurePermissions = mkOption {
               type = types.attrsOf types.str;
               default = {};
-              description = ''
+              description = lib.mdDoc ''
                 Permissions to ensure for the user, specified as an attribute set.
                 The attribute names specify the database and tables to grant the permissions for.
                 The attribute values specify the permissions to grant. You may specify one or
@@ -157,8 +157,8 @@ in
 
                 For more information on how to specify the target
                 and on which privileges exist, see the
-                <link xlink:href="https://www.postgresql.org/docs/current/sql-grant.html">GRANT syntax</link>.
-                The attributes are used as <literal>GRANT ''${attrValue} ON ''${attrName}</literal>.
+                [GRANT syntax](https://www.postgresql.org/docs/current/sql-grant.html).
+                The attributes are used as `GRANT ''${attrValue} ON ''${attrName}`.
               '';
               example = literalExpression ''
                 {
diff --git a/nixos/modules/services/databases/victoriametrics.nix b/nixos/modules/services/databases/victoriametrics.nix
index 4e002b3df7c..f87a5862f64 100644
--- a/nixos/modules/services/databases/victoriametrics.nix
+++ b/nixos/modules/services/databases/victoriametrics.nix
@@ -28,10 +28,10 @@ let cfg = config.services.victoriametrics; in
     extraOptions = mkOption {
       type = types.listOf types.str;
       default = [];
-      description = ''
+      description = lib.mdDoc ''
         Extra options to pass to VictoriaMetrics. See the README:
-        <link xlink:href="https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md"/>
-        or <command>victoriametrics -help</command> for more
+        <https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md>
+        or {command}`victoriametrics -help` for more
         information.
       '';
     };
diff --git a/nixos/modules/services/games/asf.nix b/nixos/modules/services/games/asf.nix
index 6939e15c207..b7892900376 100644
--- a/nixos/modules/services/games/asf.nix
+++ b/nixos/modules/services/games/asf.nix
@@ -136,8 +136,8 @@ in
           };
           settings = mkOption {
             type = types.attrs;
-            description = ''
-              Additional settings that are documented <link xlink:href="https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config">here</link>.
+            description = lib.mdDoc ''
+              Additional settings that are documented [here](https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Configuration#bot-config).
             '';
             default = { };
           };
diff --git a/nixos/modules/services/hardware/kanata.nix b/nixos/modules/services/hardware/kanata.nix
index f8250afa4a0..c7cd3c9d2eb 100644
--- a/nixos/modules/services/hardware/kanata.nix
+++ b/nixos/modules/services/hardware/kanata.nix
@@ -10,7 +10,7 @@ let
       device = mkOption {
         type = types.str;
         example = "/dev/input/by-id/usb-0000_0000-event-kbd";
-        description = "Path to the keyboard device.";
+        description = lib.mdDoc "Path to the keyboard device.";
       };
       config = mkOption {
         type = types.lines;
@@ -33,18 +33,18 @@ let
             ;; tap within 100ms for capslk, hold more than 100ms for lctl
             cap (tap-hold 100 100 caps lctl))
         '';
-        description = ''
+        description = lib.mdDoc ''
           Configuration other than defcfg.
-          See <link xlink:href="https://github.com/jtroo/kanata"/> for more information.
+          See <https://github.com/jtroo/kanata> for more information.
         '';
       };
       extraDefCfg = mkOption {
         type = types.lines;
         default = "";
         example = "danger-enable-cmd yes";
-        description = ''
+        description = lib.mdDoc ''
           Configuration of defcfg other than linux-dev.
-          See <link xlink:href="https://github.com/jtroo/kanata"/> for more information.
+          See <https://github.com/jtroo/kanata> for more information.
         '';
       };
     };
@@ -131,7 +131,7 @@ in
       default = pkgs.kanata;
       defaultText = lib.literalExpression "pkgs.kanata";
       example = lib.literalExpression "pkgs.kanata-with-cmd";
-      description = ''
+      description = lib.mdDoc ''
         kanata package to use.
         If you enable danger-enable-cmd, pkgs.kanata-with-cmd should be used.
       '';
@@ -139,7 +139,7 @@ in
     keyboards = mkOption {
       type = types.attrsOf (types.submodule keyboard);
       default = { };
-      description = "Keyboard configurations.";
+      description = lib.mdDoc "Keyboard configurations.";
     };
   };
 
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index f745e2f7f60..1723cb50848 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -209,11 +209,11 @@ in
       packages = mkOption {
         type = types.listOf types.path;
         default = [];
-        description = ''
-          List of packages containing <command>udev</command> rules.
+        description = lib.mdDoc ''
+          List of packages containing {command}`udev` rules.
           All files found in
-          <filename>«pkg»/etc/udev/rules.d</filename> and
-          <filename>«pkg»/lib/udev/rules.d</filename>
+          {file}`«pkg»/etc/udev/rules.d` and
+          {file}`«pkg»/lib/udev/rules.d`
           will be included.
         '';
         apply = map getBin;
@@ -281,15 +281,15 @@ in
     networking.usePredictableInterfaceNames = mkOption {
       default = true;
       type = types.bool;
-      description = ''
-        Whether to assign <link xlink:href="http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames">predictable names to network interfaces</link>.
+      description = lib.mdDoc ''
+        Whether to assign [predictable names to network interfaces](http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames).
         If enabled, interfaces
         are assigned names that contain topology information
-        (e.g. <literal>wlp3s0</literal>) and thus should be stable
+        (e.g. `wlp3s0`) and thus should be stable
         across reboots.  If disabled, names depend on the order in
         which interfaces are discovered by the kernel, which may
         change randomly across reboots; for instance, you may find
-        <literal>eth0</literal> and <literal>eth1</literal> flipping
+        `eth0` and `eth1` flipping
         unpredictably.
       '';
     };
diff --git a/nixos/modules/services/logging/filebeat.nix b/nixos/modules/services/logging/filebeat.nix
index 045cd1147ea..3dc9df372ac 100644
--- a/nixos/modules/services/logging/filebeat.nix
+++ b/nixos/modules/services/logging/filebeat.nix
@@ -31,20 +31,20 @@ in
       };
 
       inputs = mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Inputs specify how Filebeat locates and processes input data.
 
-          This is like <literal>services.filebeat.settings.filebeat.inputs</literal>,
+          This is like `services.filebeat.settings.filebeat.inputs`,
           but structured as an attribute set. This has the benefit
           that multiple NixOS modules can contribute settings to a
           single filebeat input.
 
           An input type can be specified multiple times by choosing a
-          different <literal>&lt;name></literal> for each, but setting
-          <xref linkend="opt-services.filebeat.inputs._name_.type"/>
+          different `<name>` for each, but setting
+          [](#opt-services.filebeat.inputs._name_.type)
           to the same value.
 
-          See <link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/configuration-filebeat-options.html"/>.
+          See <https://www.elastic.co/guide/en/beats/filebeat/current/configuration-filebeat-options.html>.
         '';
         default = {};
         type = types.attrsOf (types.submodule ({ name, ... }: {
@@ -77,24 +77,24 @@ in
       };
 
       modules = mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Filebeat modules provide a quick way to get started
           processing common log formats. They contain default
           configurations, Elasticsearch ingest pipeline definitions,
           and Kibana dashboards to help you implement and deploy a log
           monitoring solution.
 
-          This is like <literal>services.filebeat.settings.filebeat.modules</literal>,
+          This is like `services.filebeat.settings.filebeat.modules`,
           but structured as an attribute set. This has the benefit
           that multiple NixOS modules can contribute settings to a
           single filebeat module.
 
           A module can be specified multiple times by choosing a
-          different <literal>&lt;name></literal> for each, but setting
-          <xref linkend="opt-services.filebeat.modules._name_.module"/>
+          different `<name>` for each, but setting
+          [](#opt-services.filebeat.modules._name_.module)
           to the same value.
 
-          See <link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html"/>.
+          See <https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html>.
         '';
         default = {};
         type = types.attrsOf (types.submodule ({ name, ... }: {
diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix
index a6eb08ac5ea..53230cc51e5 100644
--- a/nixos/modules/services/logging/logrotate.nix
+++ b/nixos/modules/services/logging/logrotate.nix
@@ -276,9 +276,9 @@ in
         defaultText = ''
           A configuration file automatically generated by NixOS.
         '';
-        description = ''
+        description = lib.mdDoc ''
           Override the configuration file used by MySQL. By default,
-          NixOS generates one automatically from <xref linkend="opt-services.logrotate.settings"/>.
+          NixOS generates one automatically from [](#opt-services.logrotate.settings).
         '';
         example = literalExpression ''
           pkgs.writeText "logrotate.conf" '''
@@ -346,11 +346,11 @@ in
       extraConfig = mkOption {
         default = "";
         type = types.lines;
-        description = ''
+        description = lib.mdDoc ''
           Extra contents to append to the logrotate configuration file. Refer to
-          <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
+          <https://linux.die.net/man/8/logrotate> for details.
           This setting has been deprecated in favor of
-          <link linkend="opt-services.logrotate.settings">logrotate settings</link>.
+          [logrotate settings](#opt-services.logrotate.settings).
         '';
       };
     };
diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix
index c3eb61bd20d..c76d40a68c3 100644
--- a/nixos/modules/services/mail/mailman.nix
+++ b/nixos/modules/services/mail/mailman.nix
@@ -112,9 +112,9 @@ in {
         bindPasswordFile = mkOption {
           type = types.str;
           example = "/run/secrets/ldap-bind";
-          description = ''
+          description = lib.mdDoc ''
             Path to the file containing the bind password of the servie account
-            defined by <xref linkend="opt-services.mailman.ldap.bindDn"/>.
+            defined by [](#opt-services.mailman.ldap.bindDn).
           '';
         };
         superUserGroup = mkOption {
diff --git a/nixos/modules/services/mail/nullmailer.nix b/nixos/modules/services/mail/nullmailer.nix
index c37001e35bf..336c76c9850 100644
--- a/nixos/modules/services/mail/nullmailer.nix
+++ b/nixos/modules/services/mail/nullmailer.nix
@@ -38,11 +38,11 @@ with lib;
       remotesFile = mkOption {
         type = types.nullOr types.str;
         default = null;
-        description = ''
-          Path to the <literal>remotes</literal> control file. This file contains a
+        description = lib.mdDoc ''
+          Path to the `remotes` control file. This file contains a
           list of remote servers to which to send each message.
 
-          See <literal>man 8 nullmailer-send</literal> for syntax and available
+          See `man 8 nullmailer-send` for syntax and available
           options.
         '';
       };
@@ -153,17 +153,17 @@ with lib;
         remotes = mkOption {
           type = types.nullOr types.str;
           default = null;
-          description = ''
+          description = lib.mdDoc ''
             A list of remote servers to which to send each message. Each line
             contains a remote host name or address followed by an optional
             protocol string, separated by white space.
 
-            See <literal>man 8 nullmailer-send</literal> for syntax and available
+            See `man 8 nullmailer-send` for syntax and available
             options.
 
             WARNING: This is stored world-readable in the nix store. If you need
             to specify any secret credentials here, consider using the
-            <literal>remotesFile</literal> option instead.
+            `remotesFile` option instead.
           '';
         };
 
diff --git a/nixos/modules/services/mail/postfixadmin.nix b/nixos/modules/services/mail/postfixadmin.nix
index 27b5c60ec07..b86428770cb 100644
--- a/nixos/modules/services/mail/postfixadmin.nix
+++ b/nixos/modules/services/mail/postfixadmin.nix
@@ -13,12 +13,12 @@ in
     enable = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         Whether to enable postfixadmin.
 
         Also enables nginx virtual host management.
-        Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
-        See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
+        Further nginx configuration can be done by adapting `services.nginx.virtualHosts.<name>`.
+        See [](#opt-services.nginx.virtualHosts) for further information.
       '';
     };
 
diff --git a/nixos/modules/services/mail/public-inbox.nix b/nixos/modules/services/mail/public-inbox.nix
index 6f33283b548..a81dd1cdb37 100644
--- a/nixos/modules/services/mail/public-inbox.nix
+++ b/nixos/modules/services/mail/public-inbox.nix
@@ -23,10 +23,10 @@ let
     port = mkOption {
       type = with types; nullOr (either str port);
       default = defaultPort;
-      description = ''
+      description = lib.mdDoc ''
         Listening port.
         Beware that public-inbox uses well-known ports number to decide whether to enable TLS or not.
-        Set to null and use <literal>systemd.sockets.public-inbox-${proto}d.listenStreams</literal>
+        Set to null and use `systemd.sockets.public-inbox-${proto}d.listenStreams`
         if you need a more advanced listening.
       '';
     };
@@ -239,11 +239,11 @@ in
         type = with types; nullOr (either str port);
         default = 80;
         example = "/run/public-inbox-httpd.sock";
-        description = ''
+        description = lib.mdDoc ''
           Listening port or systemd's ListenStream= entry
           to be used as a reverse proxy, eg. in nginx:
-          <literal>locations."/inbox".proxyPass = "http://unix:''${config.services.public-inbox.http.port}:/inbox";</literal>
-          Set to null and use <literal>systemd.sockets.public-inbox-httpd.listenStreams</literal>
+          `locations."/inbox".proxyPass = "http://unix:''${config.services.public-inbox.http.port}:/inbox";`
+          Set to null and use `systemd.sockets.public-inbox-httpd.listenStreams`
           if you need a more advanced listening.
         '';
       };
diff --git a/nixos/modules/services/mail/roundcube.nix b/nixos/modules/services/mail/roundcube.nix
index 3b6c06d19e8..d8adf53e48a 100644
--- a/nixos/modules/services/mail/roundcube.nix
+++ b/nixos/modules/services/mail/roundcube.nix
@@ -14,12 +14,12 @@ in
     enable = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         Whether to enable roundcube.
 
         Also enables nginx virtual host management.
-        Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
-        See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
+        Further nginx configuration can be done by adapting `services.nginx.virtualHosts.<name>`.
+        See [](#opt-services.nginx.virtualHosts) for further information.
       '';
     };
 
@@ -99,11 +99,11 @@ in
     maxAttachmentSize = mkOption {
       type = types.int;
       default = 18;
-      description = ''
+      description = lib.mdDoc ''
         The maximum attachment size in MB.
 
         Note: Since roundcube only uses 70% of max upload values configured in php
-        30% is added automatically to <xref linkend="opt-services.roundcube.maxAttachmentSize"/>.
+        30% is added automatically to [](#opt-services.roundcube.maxAttachmentSize).
       '';
       apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.3)}M";
     };
diff --git a/nixos/modules/services/mail/sympa.nix b/nixos/modules/services/mail/sympa.nix
index 0a2a885a80f..0014701d583 100644
--- a/nixos/modules/services/mail/sympa.nix
+++ b/nixos/modules/services/mail/sympa.nix
@@ -86,9 +86,9 @@ in
       type = str;
       default = "en_US";
       example = "cs";
-      description = ''
+      description = lib.mdDoc ''
         Default Sympa language.
-        See <link xlink:href="https://github.com/sympa-community/sympa/tree/sympa-6.2/po/sympa"/>
+        See <https://github.com/sympa-community/sympa/tree/sympa-6.2/po/sympa>
         for available options.
       '';
     };
@@ -136,9 +136,9 @@ in
             example = {
               default_max_list_members = 3;
             };
-            description = ''
-              The <filename>robot.conf</filename> configuration file as key value set.
-              See <link xlink:href="https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html"/>
+            description = lib.mdDoc ''
+              The {file}`robot.conf` configuration file as key value set.
+              See <https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html>
               for list of configuration parameters.
             '';
           };
@@ -285,9 +285,9 @@ in
           viewlogs_page_size = 50;
         }
       '';
-      description = ''
-        The <filename>sympa.conf</filename> configuration file as key value set.
-        See <link xlink:href="https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html"/>
+      description = lib.mdDoc ''
+        The {file}`sympa.conf` configuration file as key value set.
+        See <https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html>
         for list of configuration parameters.
       '';
     };
diff --git a/nixos/modules/services/matrix/appservice-discord.nix b/nixos/modules/services/matrix/appservice-discord.nix
index 87a706ae95e..c72a2123a92 100644
--- a/nixos/modules/services/matrix/appservice-discord.nix
+++ b/nixos/modules/services/matrix/appservice-discord.nix
@@ -40,16 +40,16 @@ in {
             };
           }
         '';
-        description = ''
-          <filename>config.yaml</filename> configuration as a Nix attribute set.
+        description = lib.mdDoc ''
+          {file}`config.yaml` configuration as a Nix attribute set.
 
           Configuration options should match those described in
-          <link xlink:href="https://github.com/Half-Shot/matrix-appservice-discord/blob/master/config/config.sample.yaml">config.sample.yaml</link>.
+          [config.sample.yaml](https://github.com/Half-Shot/matrix-appservice-discord/blob/master/config/config.sample.yaml).
 
-          <option>config.bridge.domain</option> and <option>config.bridge.homeserverUrl</option>
+          {option}`config.bridge.domain` and {option}`config.bridge.homeserverUrl`
           should be set to match the public host name of the Matrix homeserver for webhooks and avatars to work.
 
-          Secret tokens should be specified using <option>environmentFile</option>
+          Secret tokens should be specified using {option}`environmentFile`
           instead of this world-readable attribute set.
         '';
       };
diff --git a/nixos/modules/services/matrix/mautrix-facebook.nix b/nixos/modules/services/matrix/mautrix-facebook.nix
index 384a4f4a706..dfdf6e25021 100644
--- a/nixos/modules/services/matrix/mautrix-facebook.nix
+++ b/nixos/modules/services/matrix/mautrix-facebook.nix
@@ -75,12 +75,12 @@ in {
             };
           }
         '';
-        description = ''
-          <filename>config.yaml</filename> configuration as a Nix attribute set.
+        description = lib.mdDoc ''
+          {file}`config.yaml` configuration as a Nix attribute set.
           Configuration options should match those described in
-          <link xlink:href="https://github.com/mautrix/facebook/blob/master/mautrix_facebook/example-config.yaml">example-config.yaml</link>.
+          [example-config.yaml](https://github.com/mautrix/facebook/blob/master/mautrix_facebook/example-config.yaml).
 
-          Secret tokens should be specified using <option>environmentFile</option>
+          Secret tokens should be specified using {option}`environmentFile`
           instead of this world-readable attribute set.
         '';
       };
diff --git a/nixos/modules/services/matrix/mautrix-telegram.nix b/nixos/modules/services/matrix/mautrix-telegram.nix
index 492ed1b24bc..196100a531a 100644
--- a/nixos/modules/services/matrix/mautrix-telegram.nix
+++ b/nixos/modules/services/matrix/mautrix-telegram.nix
@@ -78,12 +78,12 @@ in {
             };
           }
         '';
-        description = ''
-          <filename>config.yaml</filename> configuration as a Nix attribute set.
+        description = lib.mdDoc ''
+          {file}`config.yaml` configuration as a Nix attribute set.
           Configuration options should match those described in
-          <link xlink:href="https://github.com/tulir/mautrix-telegram/blob/master/example-config.yaml">example-config.yaml</link>.
+          [example-config.yaml](https://github.com/tulir/mautrix-telegram/blob/master/example-config.yaml).
 
-          Secret tokens should be specified using <option>environmentFile</option>
+          Secret tokens should be specified using {option}`environmentFile`
           instead of this world-readable attribute set.
         '';
       };
diff --git a/nixos/modules/services/misc/autorandr.nix b/nixos/modules/services/misc/autorandr.nix
index a77535cca49..036bb4f41be 100644
--- a/nixos/modules/services/misc/autorandr.nix
+++ b/nixos/modules/services/misc/autorandr.nix
@@ -27,9 +27,9 @@ let
     options = {
       fingerprint = mkOption {
         type = types.attrsOf types.str;
-        description = ''
+        description = lib.mdDoc ''
           Output name to EDID mapping.
-          Use <literal>autorandr --fingerprint</literal> to get current setup values.
+          Use `autorandr --fingerprint` to get current setup values.
         '';
         default = { };
       };
diff --git a/nixos/modules/services/misc/bees.nix b/nixos/modules/services/misc/bees.nix
index 2adc9f2a1fa..37f90c68222 100644
--- a/nixos/modules/services/misc/bees.nix
+++ b/nixos/modules/services/misc/bees.nix
@@ -11,7 +11,7 @@ let
   fsOptions = with types; {
     options.spec = mkOption {
       type = str;
-      description = ''
+      description = lib.mdDoc ''
         Description of how to identify the filesystem to be duplicated by this
         instance of bees. Note that deduplication crosses subvolumes; one must
         not configure multiple instances for subvolumes of the same filesystem
@@ -28,7 +28,7 @@ let
     options.hashTableSizeMB = mkOption {
       type = types.addCheck types.int (n: mod n 16 == 0);
       default = 1024; # 1GB; default from upstream beesd script
-      description = ''
+      description = lib.mdDoc ''
         Hash table size in MB; must be a multiple of 16.
 
         A larger ratio of index size to storage size means smaller blocks of
diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix
index d0c82d72602..3343e94778a 100644
--- a/nixos/modules/services/misc/etcd.nix
+++ b/nixos/modules/services/misc/etcd.nix
@@ -125,9 +125,9 @@ in {
     };
 
     extraConf = mkOption {
-      description = ''
+      description = lib.mdDoc ''
         Etcd extra configuration. See
-        <link xlink:href="https://github.com/coreos/etcd/blob/master/Documentation/op-guide/configuration.md#configuration-flags"/>
+        <https://github.com/coreos/etcd/blob/master/Documentation/op-guide/configuration.md#configuration-flags>
       '';
       type = types.attrsOf types.str;
       default = {};
diff --git a/nixos/modules/services/misc/klipper.nix b/nixos/modules/services/misc/klipper.nix
index 52913369bbc..b34ca6f8c5d 100644
--- a/nixos/modules/services/misc/klipper.nix
+++ b/nixos/modules/services/misc/klipper.nix
@@ -71,7 +71,7 @@ in
       };
 
       firmwares = mkOption {
-        description = "Firmwares klipper should manage";
+        description = lib.mdDoc "Firmwares klipper should manage";
         default = { };
         type = with types; attrsOf
           (submodule {
diff --git a/nixos/modules/services/misc/sssd.nix b/nixos/modules/services/misc/sssd.nix
index 3f6b96258f1..70afbe0433a 100644
--- a/nixos/modules/services/misc/sssd.nix
+++ b/nixos/modules/services/misc/sssd.nix
@@ -42,7 +42,7 @@ in {
       kcm = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to use SSS as a Kerberos Cache Manager (KCM).
           Kerberos will be configured to cache credentials in SSS.
         '';
diff --git a/nixos/modules/services/monitoring/cadvisor.nix b/nixos/modules/services/monitoring/cadvisor.nix
index 7374b1ece49..d5e44031016 100644
--- a/nixos/modules/services/monitoring/cadvisor.nix
+++ b/nixos/modules/services/monitoring/cadvisor.nix
@@ -66,16 +66,16 @@ in {
 
       storageDriverPasswordFile = mkOption {
         type = types.str;
-        description = ''
+        description = lib.mdDoc ''
           File that contains the cadvisor storage driver password.
 
-          <option>storageDriverPasswordFile</option> takes precedence over <option>storageDriverPassword</option>
+          {option}`storageDriverPasswordFile` takes precedence over {option}`storageDriverPassword`
 
-          Warning: when <option>storageDriverPassword</option> is non-empty this defaults to a file in the
-          world-readable Nix store that contains the value of <option>storageDriverPassword</option>.
+          Warning: when {option}`storageDriverPassword` is non-empty this defaults to a file in the
+          world-readable Nix store that contains the value of {option}`storageDriverPassword`.
 
           It's recommended to override this with a path not in the Nix store.
-          Tip: use <link xlink:href="https://nixos.org/nixops/manual/#idm140737318306400">nixops key management</link>
+          Tip: use [nixops key management](https://nixos.org/nixops/manual/#idm140737318306400)
         '';
       };
 
@@ -88,10 +88,10 @@ in {
       extraOptions = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = ''
+        description = lib.mdDoc ''
           Additional cadvisor options.
 
-          See <link xlink:href="https://github.com/google/cadvisor/blob/master/docs/runtime_options.md"/> for available options.
+          See <https://github.com/google/cadvisor/blob/master/docs/runtime_options.md> for available options.
         '';
       };
     };
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index 0905b4b57fb..8edb2ca0997 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -251,9 +251,9 @@ in {
 
       extraConfig = mkOption {
         default = {};
-        description = ''
+        description = lib.mdDoc ''
           Extra seyren configuration. See
-          <link xlink:href="https://github.com/scobal/seyren#config"/>
+          <https://github.com/scobal/seyren#config>
         '';
         type = types.attrsOf types.str;
         example = literalExpression ''
diff --git a/nixos/modules/services/monitoring/metricbeat.nix b/nixos/modules/services/monitoring/metricbeat.nix
index 0968d25c2ad..14066da1be8 100644
--- a/nixos/modules/services/monitoring/metricbeat.nix
+++ b/nixos/modules/services/monitoring/metricbeat.nix
@@ -32,17 +32,17 @@ in
       };
 
       modules = mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Metricbeat modules are responsible for reading metrics from the various sources.
 
-          This is like <literal>services.metricbeat.settings.metricbeat.modules</literal>,
+          This is like `services.metricbeat.settings.metricbeat.modules`,
           but structured as an attribute set. This has the benefit that multiple
           NixOS modules can contribute settings to a single metricbeat module.
 
-          A module can be specified multiple times by choosing a different <literal>&lt;name></literal>
-          for each, but setting <xref linkend="opt-services.metricbeat.modules._name_.module"/> to the same value.
+          A module can be specified multiple times by choosing a different `<name>`
+          for each, but setting [](#opt-services.metricbeat.modules._name_.module) to the same value.
 
-          See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>.
+          See <https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html>.
         '';
         default = {};
         type = types.attrsOf (types.submodule ({ name, ... }: {
diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix
index 3455d0d3d4a..9461bd3f35b 100644
--- a/nixos/modules/services/monitoring/munin.nix
+++ b/nixos/modules/services/monitoring/munin.nix
@@ -138,29 +138,29 @@ in
       enable = mkOption {
         default = false;
         type = types.bool;
-        description = ''
+        description = lib.mdDoc ''
           Enable Munin Node agent. Munin node listens on 0.0.0.0 and
           by default accepts connections only from 127.0.0.1 for security reasons.
 
-          See <link xlink:href="http://guide.munin-monitoring.org/en/latest/architecture/index.html"/>.
+          See <http://guide.munin-monitoring.org/en/latest/architecture/index.html>.
         '';
       };
 
       extraConfig = mkOption {
         default = "";
         type = types.lines;
-        description = ''
-          <filename>munin-node.conf</filename> extra configuration. See
-          <link xlink:href="http://guide.munin-monitoring.org/en/latest/reference/munin-node.conf.html"/>
+        description = lib.mdDoc ''
+          {file}`munin-node.conf` extra configuration. See
+          <http://guide.munin-monitoring.org/en/latest/reference/munin-node.conf.html>
         '';
       };
 
       extraPluginConfig = mkOption {
         default = "";
         type = types.lines;
-        description = ''
-          <filename>plugin-conf.d</filename> extra plugin configuration. See
-          <link xlink:href="http://guide.munin-monitoring.org/en/latest/plugin/use.html"/>
+        description = lib.mdDoc ''
+          {file}`plugin-conf.d` extra plugin configuration. See
+          <http://guide.munin-monitoring.org/en/latest/plugin/use.html>
         '';
         example = ''
           [fail2ban_*]
@@ -266,11 +266,11 @@ in
       extraGlobalConfig = mkOption {
         default = "";
         type = types.lines;
-        description = ''
-          <filename>munin.conf</filename> extra global configuration.
-          See <link xlink:href="http://guide.munin-monitoring.org/en/latest/reference/munin.conf.html"/>.
+        description = lib.mdDoc ''
+          {file}`munin.conf` extra global configuration.
+          See <http://guide.munin-monitoring.org/en/latest/reference/munin.conf.html>.
           Useful to setup notifications, see
-          <link xlink:href="http://guide.munin-monitoring.org/en/latest/tutorial/alert.html"/>
+          <http://guide.munin-monitoring.org/en/latest/tutorial/alert.html>
         '';
         example = ''
           contact.email.command mail -s "Munin notification for ''${var:host}" someone@example.com
@@ -280,10 +280,10 @@ in
       hosts = mkOption {
         default = "";
         type = types.lines;
-        description = ''
+        description = lib.mdDoc ''
           Definitions of hosts of nodes to collect data from. Needs at least one
           host for cron to succeed. See
-          <link xlink:href="http://guide.munin-monitoring.org/en/latest/reference/munin.conf.html"/>
+          <http://guide.munin-monitoring.org/en/latest/reference/munin.conf.html>
         '';
         example = literalExpression ''
           '''
diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index 661b38b4c5a..e20eaf3b144 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -114,13 +114,13 @@ in {
         example = literalExpression ''
           [ "/path/to/plugins.d" ]
         '';
-        description = ''
+        description = lib.mdDoc ''
           Extra paths to add to the netdata global "plugins directory"
           option.  Useful for when you want to include your own
           collection scripts.
 
           Details about writing a custom netdata plugin are available at:
-          <link xlink:href="https://docs.netdata.cloud/collectors/plugins.d/"/>
+          <https://docs.netdata.cloud/collectors/plugins.d/>
 
           Cannot be combined with configText.
         '';
diff --git a/nixos/modules/services/monitoring/parsedmarc.nix b/nixos/modules/services/monitoring/parsedmarc.nix
index 60ebbd6f752..b0858184b5f 100644
--- a/nixos/modules/services/monitoring/parsedmarc.nix
+++ b/nixos/modules/services/monitoring/parsedmarc.nix
@@ -29,11 +29,11 @@ in
         enable = lib.mkOption {
           type = lib.types.bool;
           default = false;
-          description = ''
+          description = lib.mdDoc ''
             Whether Postfix and Dovecot should be set up to receive
             mail locally. parsedmarc will be configured to watch the
             local inbox as the automatically created user specified in
-            <xref linkend="opt-services.parsedmarc.provision.localMail.recipientName" />
+            [](#opt-services.parsedmarc.provision.localMail.recipientName)
           '';
         };
 
@@ -68,13 +68,13 @@ in
       geoIp = lib.mkOption {
         type = lib.types.bool;
         default = true;
-        description = ''
-          Whether to enable and configure the <link linkend="opt-services.geoipupdate.enable">geoipupdate</link>
+        description = lib.mdDoc ''
+          Whether to enable and configure the [geoipupdate](#opt-services.geoipupdate.enable)
           service to automatically fetch GeoIP databases. Not crucial,
           but recommended for full functionality.
 
-          To finish the setup, you need to manually set the <xref linkend="opt-services.geoipupdate.settings.AccountID"/> and
-          <xref linkend="opt-services.geoipupdate.settings.LicenseKey"/>
+          To finish the setup, you need to manually set the [](#opt-services.geoipupdate.settings.AccountID) and
+          [](#opt-services.geoipupdate.settings.LicenseKey)
           options.
         '';
       };
@@ -95,11 +95,11 @@ in
             config.${opt.provision.elasticsearch} && config.${options.services.grafana.enable}
           '';
           apply = x: x && cfg.provision.elasticsearch;
-          description = ''
+          description = lib.mdDoc ''
             Whether the automatically provisioned Elasticsearch
             instance should be added as a grafana datasource. Has no
             effect unless
-            <xref linkend="opt-services.parsedmarc.provision.elasticsearch"/>
+            [](#opt-services.parsedmarc.provision.elasticsearch)
             is also enabled.
           '';
         };
@@ -206,12 +206,12 @@ in
             password = lib.mkOption {
               type = with lib.types; nullOr (either path (attrsOf path));
               default = null;
-              description = ''
+              description = lib.mdDoc ''
                 The IMAP server password.
 
                 Always handled as a secret whether the value is
-                wrapped in a <literal>{ _secret = ...; }</literal>
-                attrset or not (refer to <xref linkend="opt-services.parsedmarc.settings"/> for
+                wrapped in a `{ _secret = ...; }`
+                attrset or not (refer to [](#opt-services.parsedmarc.settings) for
                 details).
               '';
               apply = x: if isAttrs x || x == null then x else { _secret = x; };
@@ -270,12 +270,12 @@ in
             password = lib.mkOption {
               type = with lib.types; nullOr (either path (attrsOf path));
               default = null;
-              description = ''
+              description = lib.mdDoc ''
                 The SMTP server password.
 
                 Always handled as a secret whether the value is
-                wrapped in a <literal>{ _secret = ...; }</literal>
-                attrset or not (refer to <xref linkend="opt-services.parsedmarc.settings"/> for
+                wrapped in a `{ _secret = ...; }`
+                attrset or not (refer to [](#opt-services.parsedmarc.settings) for
                 details).
               '';
               apply = x: if isAttrs x || x == null then x else { _secret = x; };
@@ -322,13 +322,13 @@ in
             password = lib.mkOption {
               type = with lib.types; nullOr (either path (attrsOf path));
               default = null;
-              description = ''
+              description = lib.mdDoc ''
                 The password to use when connecting to Elasticsearch,
                 if required.
 
                 Always handled as a secret whether the value is
-                wrapped in a <literal>{ _secret = ...; }</literal>
-                attrset or not (refer to <xref linkend="opt-services.parsedmarc.settings"/> for
+                wrapped in a `{ _secret = ...; }`
+                attrset or not (refer to [](#opt-services.parsedmarc.settings) for
                 details).
               '';
               apply = x: if isAttrs x || x == null then x else { _secret = x; };
diff --git a/nixos/modules/services/networking/biboumi.nix b/nixos/modules/services/networking/biboumi.nix
index 7e603300883..24e0c0328fe 100644
--- a/nixos/modules/services/networking/biboumi.nix
+++ b/nixos/modules/services/networking/biboumi.nix
@@ -83,13 +83,13 @@ in
           };
           options.password = mkOption {
             type = with types; nullOr str;
-            description = ''
+            description = lib.mdDoc ''
               The password used to authenticate the XMPP component to your XMPP server.
               This password must be configured in the XMPP server,
               associated with the external component on
-              <link linkend="opt-services.biboumi.settings.hostname">hostname</link>.
+              [hostname](#opt-services.biboumi.settings.hostname).
 
-              Set it to null and use <link linkend="opt-services.biboumi.credentialsFile">credentialsFile</link>
+              Set it to null and use [credentialsFile](#opt-services.biboumi.credentialsFile)
               if you do not want this password to go into the Nix store.
             '';
           };
@@ -155,12 +155,12 @@ in
 
       credentialsFile = mkOption {
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
           Path to a configuration file to be merged with the settings.
           Beware not to surround "=" with spaces when setting biboumi's options in this file.
           Useful to merge a file which is better kept out of the Nix store
           because it contains sensible data like
-          <link linkend="opt-services.biboumi.settings.password">password</link>.
+          [password](#opt-services.biboumi.settings.password).
         '';
         default = "/dev/null";
         example = "/run/keys/biboumi.cfg";
diff --git a/nixos/modules/services/networking/bird-lg.nix b/nixos/modules/services/networking/bird-lg.nix
index 9f06bfcdc51..1440deb62b4 100644
--- a/nixos/modules/services/networking/bird-lg.nix
+++ b/nixos/modules/services/networking/bird-lg.nix
@@ -136,8 +136,8 @@ in
         extraArgs = mkOption {
           type = types.lines;
           default = "";
-          description = ''
-            Extra parameters documented <link xlink:href="https://github.com/xddxdd/bird-lg-go#frontend">here</link>.
+          description = lib.mdDoc ''
+            Extra parameters documented [here](https://github.com/xddxdd/bird-lg-go#frontend).
           '';
         };
       };
@@ -183,8 +183,8 @@ in
         extraArgs = mkOption {
           type = types.lines;
           default = "";
-          description = ''
-            Extra parameters documented <link xlink:href="https://github.com/xddxdd/bird-lg-go#proxy">here</link>.
+          description = lib.mdDoc ''
+            Extra parameters documented [here](https://github.com/xddxdd/bird-lg-go#proxy).
           '';
         };
       };
diff --git a/nixos/modules/services/networking/bird.nix b/nixos/modules/services/networking/bird.nix
index 4a738daf958..7708aaa476f 100644
--- a/nixos/modules/services/networking/bird.nix
+++ b/nixos/modules/services/networking/bird.nix
@@ -13,18 +13,18 @@ in
       enable = mkEnableOption "BIRD Internet Routing Daemon";
       config = mkOption {
         type = types.lines;
-        description = ''
+        description = lib.mdDoc ''
           BIRD Internet Routing Daemon configuration file.
-          <link xlink:href="http://bird.network.cz/"/>
+          <http://bird.network.cz/>
         '';
       };
       checkConfig = mkOption {
         type = types.bool;
         default = true;
-        description = ''
+        description = lib.mdDoc ''
           Whether the config should be checked at build time.
           When the config can't be checked during build time, for example when it includes
-          other files, either disable this option or use <literal>preCheckConfig</literal> to create
+          other files, either disable this option or use `preCheckConfig` to create
           the included files before checking.
         '';
       };
@@ -34,9 +34,9 @@ in
         example = ''
           echo "cost 100;" > include.conf
         '';
-        description = ''
+        description = lib.mdDoc ''
           Commands to execute before the config file check. The file to be checked will be
-          available as <literal>bird2.conf</literal> in the current directory.
+          available as `bird2.conf` in the current directory.
 
           Files created with this option will not be available at service runtime, only during
           build time checking.
diff --git a/nixos/modules/services/networking/coredns.nix b/nixos/modules/services/networking/coredns.nix
index 966957f1a0f..deaba69e99f 100644
--- a/nixos/modules/services/networking/coredns.nix
+++ b/nixos/modules/services/networking/coredns.nix
@@ -17,9 +17,9 @@ in {
         }
       '';
       type = types.lines;
-      description = ''
+      description = lib.mdDoc ''
         Verbatim Corefile to use.
-        See <link xlink:href="https://coredns.io/manual/toc/#configuration"/> for details.
+        See <https://coredns.io/manual/toc/#configuration> for details.
       '';
     };
 
diff --git a/nixos/modules/services/networking/ghostunnel.nix b/nixos/modules/services/networking/ghostunnel.nix
index ce5d386edc3..79cf80e57be 100644
--- a/nixos/modules/services/networking/ghostunnel.nix
+++ b/nixos/modules/services/networking/ghostunnel.nix
@@ -49,28 +49,28 @@ let
         };
 
         cert = mkOption {
-          description = ''
+          description = lib.mdDoc ''
             Path to certificate (PEM with certificate chain).
 
-            Not required if <literal>keystore</literal> is set.
+            Not required if `keystore` is set.
           '';
           type = types.nullOr types.str;
           default = null;
         };
 
         key = mkOption {
-          description = ''
+          description = lib.mdDoc ''
             Path to certificate private key (PEM with private key).
 
-            Not required if <literal>keystore</literal> is set.
+            Not required if `keystore` is set.
           '';
           type = types.nullOr types.str;
           default = null;
         };
 
         cacert = mkOption {
-          description = ''
-            Path to CA bundle file (PEM/X509). Uses system trust store if <literal>null</literal>.
+          description = lib.mdDoc ''
+            Path to CA bundle file (PEM/X509). Uses system trust store if `null`.
           '';
           type = types.nullOr types.str;
         };
@@ -124,7 +124,7 @@ let
         };
 
         extraArguments = mkOption {
-          description = "Extra arguments to pass to <literal>ghostunnel server</literal>";
+          description = lib.mdDoc "Extra arguments to pass to `ghostunnel server`";
           type = types.separatedString " ";
           default = "";
         };
diff --git a/nixos/modules/services/networking/hans.nix b/nixos/modules/services/networking/hans.nix
index bff39a5ab2a..ffb2ee841c6 100644
--- a/nixos/modules/services/networking/hans.nix
+++ b/nixos/modules/services/networking/hans.nix
@@ -19,11 +19,11 @@ in
     services.hans = {
       clients = mkOption {
         default = {};
-        description = ''
+        description = lib.mdDoc ''
           Each attribute of this option defines a systemd service that
           runs hans. Many or none may be defined.
           The name of each service is
-          <literal>hans-«name»</literal>
+          `hans-«name»`
           where «name» is the name of the
           corresponding attribute name.
         '';
diff --git a/nixos/modules/services/networking/iodine.nix b/nixos/modules/services/networking/iodine.nix
index 9749c728513..ea2fa3ac4be 100644
--- a/nixos/modules/services/networking/iodine.nix
+++ b/nixos/modules/services/networking/iodine.nix
@@ -28,11 +28,11 @@ in
     services.iodine = {
       clients = mkOption {
         default = {};
-        description = ''
+        description = lib.mdDoc ''
           Each attribute of this option defines a systemd service that
           runs iodine. Many or none may be defined.
           The name of each service is
-          <literal>iodine-«name»</literal>
+          `iodine-«name»`
           where «name» is the name of the
           corresponding attribute name.
         '';
diff --git a/nixos/modules/services/networking/kea.nix b/nixos/modules/services/networking/kea.nix
index d9d6e3f42ce..d674a97391c 100644
--- a/nixos/modules/services/networking/kea.nix
+++ b/nixos/modules/services/networking/kea.nix
@@ -54,11 +54,11 @@ in
           configFile = mkOption {
             type = nullOr path;
             default = null;
-            description = ''
-              Kea Control Agent configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/agent.html"/>.
+            description = lib.mdDoc ''
+              Kea Control Agent configuration as a path, see <https://kea.readthedocs.io/en/kea-${package.version}/arm/agent.html>.
 
-              Takes preference over <link linkend="opt-services.kea.ctrl-agent.settings">settings</link>.
-              Most users should prefer using <link linkend="opt-services.kea.ctrl-agent.settings">settings</link> instead.
+              Takes preference over [settings](#opt-services.kea.ctrl-agent.settings).
+              Most users should prefer using [settings](#opt-services.kea.ctrl-agent.settings) instead.
             '';
           };
 
@@ -93,11 +93,11 @@ in
           configFile = mkOption {
             type = nullOr path;
             default = null;
-            description = ''
-              Kea DHCP4 configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp4-srv.html"/>.
+            description = lib.mdDoc ''
+              Kea DHCP4 configuration as a path, see <https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp4-srv.html>.
 
-              Takes preference over <link linkend="opt-services.kea.dhcp4.settings">settings</link>.
-              Most users should prefer using <link linkend="opt-services.kea.dhcp4.settings">settings</link> instead.
+              Takes preference over [settings](#opt-services.kea.dhcp4.settings).
+              Most users should prefer using [settings](#opt-services.kea.dhcp4.settings) instead.
             '';
           };
 
@@ -153,11 +153,11 @@ in
           configFile = mkOption {
             type = nullOr path;
             default = null;
-            description = ''
-              Kea DHCP6 configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp6-srv.html"/>.
+            description = lib.mdDoc ''
+              Kea DHCP6 configuration as a path, see <https://kea.readthedocs.io/en/kea-${package.version}/arm/dhcp6-srv.html>.
 
-              Takes preference over <link linkend="opt-services.kea.dhcp6.settings">settings</link>.
-              Most users should prefer using <link linkend="opt-services.kea.dhcp6.settings">settings</link> instead.
+              Takes preference over [settings](#opt-services.kea.dhcp6.settings).
+              Most users should prefer using [settings](#opt-services.kea.dhcp6.settings) instead.
             '';
           };
 
@@ -214,11 +214,11 @@ in
           configFile = mkOption {
             type = nullOr path;
             default = null;
-            description = ''
-              Kea DHCP-DDNS configuration as a path, see <link xlink:href="https://kea.readthedocs.io/en/kea-${package.version}/arm/ddns.html"/>.
+            description = lib.mdDoc ''
+              Kea DHCP-DDNS configuration as a path, see <https://kea.readthedocs.io/en/kea-${package.version}/arm/ddns.html>.
 
-              Takes preference over <link linkend="opt-services.kea.dhcp-ddns.settings">settings</link>.
-              Most users should prefer using <link linkend="opt-services.kea.dhcp-ddns.settings">settings</link> instead.
+              Takes preference over [settings](#opt-services.kea.dhcp-ddns.settings).
+              Most users should prefer using [settings](#opt-services.kea.dhcp-ddns.settings) instead.
             '';
           };
 
diff --git a/nixos/modules/services/networking/ncdns.nix b/nixos/modules/services/networking/ncdns.nix
index 3527b9e1857..958231963c6 100644
--- a/nixos/modules/services/networking/ncdns.nix
+++ b/nixos/modules/services/networking/ncdns.nix
@@ -176,10 +176,10 @@ in
             certstore.nssdbdir = "../../home/alice/.pki/nssdb";
           }
         '';
-        description = ''
+        description = lib.mdDoc ''
           ncdns settings. Use this option to configure ncds
           settings not exposed in a NixOS option or to bypass one.
-          See the example ncdns.conf file at <link xlink:href="https://github.com/namecoin/ncdns/blob/master/_doc/ncdns.conf.example"/>
+          See the example ncdns.conf file at <https://github.com/namecoin/ncdns/blob/master/_doc/ncdns.conf.example>
           for the available options.
         '';
       };
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 563892cb365..e77fa97d240 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -387,12 +387,12 @@ in {
       enableStrongSwan = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Enable the StrongSwan plugin.
 
           If you enable this option the
-          <literal>networkmanager_strongswan</literal> plugin will be added to
-          the <option>networking.networkmanager.plugins</option> option
+          `networkmanager_strongswan` plugin will be added to
+          the {option}`networking.networkmanager.plugins` option
           so you don't need to to that yourself.
         '';
       };
diff --git a/nixos/modules/services/networking/nntp-proxy.nix b/nixos/modules/services/networking/nntp-proxy.nix
index 1a776aae617..4dd2922e83f 100644
--- a/nixos/modules/services/networking/nntp-proxy.nix
+++ b/nixos/modules/services/networking/nntp-proxy.nix
@@ -167,9 +167,9 @@ in
             passwordHash = mkOption {
               type = types.str;
               example = "$6$GtzE7FrpE$wwuVgFYU.TZH4Rz.Snjxk9XGua89IeVwPQ/fEUD8eujr40q5Y021yhn0aNcsQ2Ifw.BLclyzvzgegopgKcneL0";
-              description = ''
+              description = lib.mdDoc ''
                 SHA-512 password hash (can be generated by
-                <literal>mkpasswd -m sha-512 &lt;password&gt;</literal>)
+                `mkpasswd -m sha-512 <password>`)
               '';
             };
 
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index a372d3b207c..cf2afcacc52 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -392,8 +392,8 @@ let
       requestXFR = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = ''
-          Format: <literal>[AXFR|UDP] &lt;ip-address&gt; &lt;key-name | NOKEY&gt;</literal>
+        description = lib.mdDoc ''
+          Format: `[AXFR|UDP] <ip-address> <key-name | NOKEY>`
         '';
       };
 
diff --git a/nixos/modules/services/networking/ntp/ntpd.nix b/nixos/modules/services/networking/ntp/ntpd.nix
index 490d1619f11..a9dae2c8667 100644
--- a/nixos/modules/services/networking/ntp/ntpd.nix
+++ b/nixos/modules/services/networking/ntp/ntpd.nix
@@ -40,17 +40,17 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to synchronise your machine's time using ntpd, as a peer in
           the NTP network.
 
-          Disables <literal>systemd.timesyncd</literal> if enabled.
+          Disables `systemd.timesyncd` if enabled.
         '';
       };
 
       restrictDefault = mkOption {
         type = types.listOf types.str;
-        description = ''
+        description = lib.mdDoc ''
           The restriction flags to be set by default.
 
           The default flags prevent external hosts from using ntpd as a DDoS
@@ -63,7 +63,7 @@ in
 
       restrictSource = mkOption {
         type = types.listOf types.str;
-        description = ''
+        description = lib.mdDoc ''
           The restriction flags to be set on source.
 
           The default flags allow peers to be added by ntpd from configured
diff --git a/nixos/modules/services/networking/openconnect.nix b/nixos/modules/services/networking/openconnect.nix
index c7294145975..469f0a3bc3b 100644
--- a/nixos/modules/services/networking/openconnect.nix
+++ b/nixos/modules/services/networking/openconnect.nix
@@ -38,10 +38,10 @@ let
       # set an authentication cookie, because they have to be requested
       # for every new connection and would only work once.
       passwordFile = mkOption {
-        description = ''
+        description = lib.mdDoc ''
           File containing the password to authenticate with. This
-          is passed to <literal>openconnect</literal> via the
-          <literal>--passwd-on-stdin</literal> option.
+          is passed to `openconnect` via the
+          `--passwd-on-stdin` option.
         '';
         default = null;
         example = "/var/lib/secrets/openconnect-passwd";
@@ -63,13 +63,13 @@ let
       };
 
       extraOptions = mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Extra config to be appended to the interface config. It should
           contain long-format options as would be accepted on the command
-          line by <literal>openconnect</literal>
+          line by `openconnect`
           (see https://www.infradead.org/openconnect/manual.html).
-          Non-key-value options like <literal>deflate</literal> can be used by
-          declaring them as booleans, i. e. <literal>deflate = true;</literal>.
+          Non-key-value options like `deflate` can be used by
+          declaring them as booleans, i. e. `deflate = true;`.
         '';
         default = { };
         example = {
diff --git a/nixos/modules/services/networking/openvpn.nix b/nixos/modules/services/networking/openvpn.nix
index ce0f0f90fc9..492a0936fdb 100644
--- a/nixos/modules/services/networking/openvpn.nix
+++ b/nixos/modules/services/networking/openvpn.nix
@@ -115,11 +115,11 @@ in
         }
       '';
 
-      description = ''
+      description = lib.mdDoc ''
         Each attribute of this option defines a systemd service that
         runs an OpenVPN instance.  These can be OpenVPN servers or
         clients.  The name of each systemd service is
-        <literal>openvpn-«name».service</literal>,
+        `openvpn-«name».service`,
         where «name» is the corresponding
         attribute name.
       '';
diff --git a/nixos/modules/services/networking/pleroma.nix b/nixos/modules/services/networking/pleroma.nix
index 03868c8cc76..de9d0821c63 100644
--- a/nixos/modules/services/networking/pleroma.nix
+++ b/nixos/modules/services/networking/pleroma.nix
@@ -34,7 +34,7 @@ in {
 
       configs = mkOption {
         type = with types; listOf str;
-        description = ''
+        description = lib.mdDoc ''
           Pleroma public configuration.
 
           This list gets appended from left to
@@ -42,9 +42,9 @@ in {
           configuration imperatively, meaning you can override a
           setting by appending a new str to this NixOS option list.
 
-          <emphasis>DO NOT STORE ANY PLEROMA SECRET
-          HERE</emphasis>, use
-          <link linkend="opt-services.pleroma.secretConfigFile">services.pleroma.secretConfigFile</link>
+          *DO NOT STORE ANY PLEROMA SECRET
+          HERE*, use
+          [services.pleroma.secretConfigFile](#opt-services.pleroma.secretConfigFile)
           instead.
 
           This setting is going to be stored in a file part of
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index cbc4e303b64..6da83eb7de1 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -257,12 +257,12 @@ in
       authorizedKeysFiles = mkOption {
         type = types.listOf types.str;
         default = [];
-        description = ''
+        description = lib.mdDoc ''
           Specify the rules for which files to read on the host.
 
           This is an advanced option. If you're looking to configure user
-          keys, you can generally use <xref linkend="opt-users.users._name_.openssh.authorizedKeys.keys"/>
-          or <xref linkend="opt-users.users._name_.openssh.authorizedKeys.keyFiles"/>.
+          keys, you can generally use [](#opt-users.users._name_.openssh.authorizedKeys.keys)
+          or [](#opt-users.users._name_.openssh.authorizedKeys.keyFiles).
 
           These are paths relative to the host root file system or home
           directories and they are subject to certain token expansion rules.
@@ -298,13 +298,13 @@ in
           "curve25519-sha256@libssh.org"
           "diffie-hellman-group-exchange-sha256"
         ];
-        description = ''
+        description = lib.mdDoc ''
           Allowed key exchange algorithms
 
           Uses the lower bound recommended in both
-          <link xlink:href="https://stribika.github.io/2015/01/04/secure-secure-shell.html"/>
+          <https://stribika.github.io/2015/01/04/secure-secure-shell.html>
           and
-          <link xlink:href="https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67"/>
+          <https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67>
         '';
       };
 
@@ -318,13 +318,13 @@ in
           "aes192-ctr"
           "aes128-ctr"
         ];
-        description = ''
+        description = lib.mdDoc ''
           Allowed ciphers
 
           Defaults to recommended settings from both
-          <link xlink:href="https://stribika.github.io/2015/01/04/secure-secure-shell.html"/>
+          <https://stribika.github.io/2015/01/04/secure-secure-shell.html>
           and
-          <link xlink:href="https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67"/>
+          <https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67>
         '';
       };
 
@@ -338,13 +338,13 @@ in
           "hmac-sha2-256"
           "umac-128@openssh.com"
         ];
-        description = ''
+        description = lib.mdDoc ''
           Allowed MACs
 
           Defaults to recommended settings from both
-          <link xlink:href="https://stribika.github.io/2015/01/04/secure-secure-shell.html"/>
+          <https://stribika.github.io/2015/01/04/secure-secure-shell.html>
           and
-          <link xlink:href="https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67"/>
+          <https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67>
         '';
       };
 
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix
index 994a0cf9ec1..9017c53f4e5 100644
--- a/nixos/modules/services/networking/wireguard.nix
+++ b/nixos/modules/services/networking/wireguard.nix
@@ -118,11 +118,11 @@ let
         default = null;
         type = with types; nullOr str;
         example = "container";
-        description = ''The pre-existing network namespace in which the
+        description = lib.mdDoc ''The pre-existing network namespace in which the
         WireGuard interface is created, and which retains the socket even if the
-        interface is moved via <option>interfaceNamespace</option>. When
-        <literal>null</literal>, the interface is created in the init namespace.
-        See <link xlink:href="https://www.wireguard.com/netns/">documentation</link>.
+        interface is moved via {option}`interfaceNamespace`. When
+        `null`, the interface is created in the init namespace.
+        See [documentation](https://www.wireguard.com/netns/).
         '';
       };
 
@@ -130,11 +130,11 @@ let
         default = null;
         type = with types; nullOr str;
         example = "init";
-        description = ''The pre-existing network namespace the WireGuard
-        interface is moved to. The special value <literal>init</literal> means
-        the init namespace. When <literal>null</literal>, the interface is not
+        description = lib.mdDoc ''The pre-existing network namespace the WireGuard
+        interface is moved to. The special value `init` means
+        the init namespace. When `null`, the interface is not
         moved.
-        See <link xlink:href="https://www.wireguard.com/netns/">documentation</link>.
+        See [documentation](https://www.wireguard.com/netns/).
         '';
       };
     };
diff --git a/nixos/modules/services/networking/yggdrasil.nix b/nixos/modules/services/networking/yggdrasil.nix
index e99f31b0eaa..266149cf221 100644
--- a/nixos/modules/services/networking/yggdrasil.nix
+++ b/nixos/modules/services/networking/yggdrasil.nix
@@ -64,21 +64,21 @@ in {
         type = types.nullOr types.str;
         default = null;
         example = "wheel";
-        description = "Group to grant access to the Yggdrasil control socket. If <literal>null</literal>, only root can access the socket.";
+        description = lib.mdDoc "Group to grant access to the Yggdrasil control socket. If `null`, only root can access the socket.";
       };
 
       openMulticastPort = mkOption {
         type = bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to open the UDP port used for multicast peer
           discovery. The NixOS firewall blocks link-local
           communication, so in order to make local peering work you
-          will also need to set <literal>LinkLocalTCPPort</literal> in your
-          yggdrasil configuration (<option>config</option> or
-          <option>configFile</option>) to a port number other than 0,
+          will also need to set `LinkLocalTCPPort` in your
+          yggdrasil configuration ({option}`config` or
+          {option}`configFile`) to a port number other than 0,
           and then add that port to
-          <option>networking.firewall.allowedTCPPorts</option>.
+          {option}`networking.firewall.allowedTCPPorts`.
         '';
       };
 
diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix
index 4be3a90b649..29c499e33ab 100644
--- a/nixos/modules/services/security/privacyidea.nix
+++ b/nixos/modules/services/security/privacyidea.nix
@@ -215,9 +215,9 @@ in
         environmentFile = mkOption {
           default = null;
           type = types.nullOr types.str;
-          description = ''
+          description = lib.mdDoc ''
             Environment file containing secrets to be substituted into
-            <xref linkend="opt-services.privacyidea.ldap-proxy.settings"/>.
+            [](#opt-services.privacyidea.ldap-proxy.settings).
           '';
         };
       };
diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix
index 0516d207707..84f577c3853 100644
--- a/nixos/modules/services/security/tor.nix
+++ b/nixos/modules/services/security/tor.nix
@@ -476,11 +476,11 @@ in
                   };
                   clientNames = mkOption {
                     type = with types; nonEmptyListOf (strMatching "[A-Za-z0-9+-_]+");
-                    description = ''
+                    description = lib.mdDoc ''
                       Only clients that are listed here are authorized to access the hidden service.
-                      Generated authorization data can be found in <filename>${stateDir}/onion/$name/hostname</filename>.
+                      Generated authorization data can be found in {file}`${stateDir}/onion/$name/hostname`.
                       Clients need to put this authorization data in their configuration file using
-                      <xref linkend="opt-services.tor.settings.HidServAuth"/>.
+                      [](#opt-services.tor.settings.HidServAuth).
                     '';
                   };
                 };
diff --git a/nixos/modules/services/security/vault.nix b/nixos/modules/services/security/vault.nix
index e4777910b6d..ef982963029 100644
--- a/nixos/modules/services/security/vault.nix
+++ b/nixos/modules/services/security/vault.nix
@@ -116,13 +116,13 @@ in
       storageConfig = mkOption {
         type = types.nullOr types.lines;
         default = null;
-        description = ''
+        description = lib.mdDoc ''
           HCL configuration to insert in the storageBackend section.
 
           Confidential values should not be specified here because this option's
           value is written to the Nix store, which is publicly readable.
           Provide credentials and such in a separate file using
-          <xref linkend="opt-services.vault.extraSettingsPaths"/>.
+          [](#opt-services.vault.extraSettingsPaths).
         '';
       };
 
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index 65b40c56a3b..def04d944f0 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -38,17 +38,17 @@ in
       packages = mkOption {
         type = types.listOf types.path;
         default = [ ];
-        description = ''
+        description = lib.mdDoc ''
           Packages whose D-Bus configuration files should be included in
           the configuration of the D-Bus system-wide or session-wide
           message bus.  Specifically, files in the following directories
           will be included into their respective DBus configuration paths:
-          <filename>«pkg»/etc/dbus-1/system.d</filename>
-          <filename>«pkg»/share/dbus-1/system.d</filename>
-          <filename>«pkg»/share/dbus-1/system-services</filename>
-          <filename>«pkg»/etc/dbus-1/session.d</filename>
-          <filename>«pkg»/share/dbus-1/session.d</filename>
-          <filename>«pkg»/share/dbus-1/services</filename>
+          {file}`«pkg»/etc/dbus-1/system.d`
+          {file}`«pkg»/share/dbus-1/system.d`
+          {file}`«pkg»/share/dbus-1/system-services`
+          {file}`«pkg»/etc/dbus-1/session.d`
+          {file}`«pkg»/share/dbus-1/session.d`
+          {file}`«pkg»/share/dbus-1/services`
         '';
       };
 
diff --git a/nixos/modules/services/system/earlyoom.nix b/nixos/modules/services/system/earlyoom.nix
index 3e361fce00f..b2e2d21002c 100644
--- a/nixos/modules/services/system/earlyoom.nix
+++ b/nixos/modules/services/system/earlyoom.nix
@@ -32,32 +32,32 @@ in
     freeMemKillThreshold = mkOption {
       type = types.nullOr (types.ints.between 1 100);
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Minimum available memory (in percent) before sending SIGKILL.
-        If unset, this defaults to half of <option>freeMemThreshold</option>.
+        If unset, this defaults to half of {option}`freeMemThreshold`.
 
-        See the description of <xref linkend="opt-services.earlyoom.freeMemThreshold"/>.
+        See the description of [](#opt-services.earlyoom.freeMemThreshold).
       '';
     };
 
     freeSwapThreshold = mkOption {
       type = types.ints.between 1 100;
       default = 10;
-      description = ''
+      description = lib.mdDoc ''
         Minimum free swap space (in percent) before sending SIGTERM.
 
-        See the description of <xref linkend="opt-services.earlyoom.freeMemThreshold"/>.
+        See the description of [](#opt-services.earlyoom.freeMemThreshold).
       '';
     };
 
     freeSwapKillThreshold = mkOption {
       type = types.nullOr (types.ints.between 1 100);
       default = null;
-      description = ''
+      description = lib.mdDoc ''
         Minimum free swap space (in percent) before sending SIGKILL.
-        If unset, this defaults to half of <option>freeSwapThreshold</option>.
+        If unset, this defaults to half of {option}`freeSwapThreshold`.
 
-        See the description of <xref linkend="opt-services.earlyoom.freeMemThreshold"/>.
+        See the description of [](#opt-services.earlyoom.freeMemThreshold).
       '';
     };
 
diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix
index 1641f1ad184..6a038dc0a32 100644
--- a/nixos/modules/services/torrent/transmission.nix
+++ b/nixos/modules/services/torrent/transmission.nix
@@ -55,13 +55,13 @@ in
             type = types.path;
             default = "${cfg.home}/${incompleteDir}";
             defaultText = literalExpression ''"''${config.${opt.home}}/${incompleteDir}"'';
-            description = ''
+            description = lib.mdDoc ''
               When enabled with
               services.transmission.home
-              <xref linkend="opt-services.transmission.settings.incomplete-dir-enabled"/>,
+              [](#opt-services.transmission.settings.incomplete-dir-enabled),
               new torrents will download the files to this directory.
               When complete, the files will be moved to download-dir
-              <xref linkend="opt-services.transmission.settings.download-dir"/>.
+              [](#opt-services.transmission.settings.download-dir).
             '';
           };
           options.incomplete-dir-enabled = mkOption {
@@ -82,17 +82,17 @@ in
           options.peer-port-random-high = mkOption {
             type = types.port;
             default = 65535;
-            description = ''
+            description = lib.mdDoc ''
               The maximum peer port to listen to for incoming connections
-              when <xref linkend="opt-services.transmission.settings.peer-port-random-on-start"/> is enabled.
+              when [](#opt-services.transmission.settings.peer-port-random-on-start) is enabled.
             '';
           };
           options.peer-port-random-low = mkOption {
             type = types.port;
             default = 65535;
-            description = ''
+            description = lib.mdDoc ''
               The minimal peer port to listen to for incoming connections
-              when <xref linkend="opt-services.transmission.settings.peer-port-random-on-start"/> is enabled.
+              when [](#opt-services.transmission.settings.peer-port-random-on-start) is enabled.
             '';
           };
           options.peer-port-random-on-start = mkOption {
@@ -117,9 +117,9 @@ in
           options.script-torrent-done-enabled = mkOption {
             type = types.bool;
             default = false;
-            description = ''
+            description = lib.mdDoc ''
               Whether to run
-              <xref linkend="opt-services.transmission.settings.script-torrent-done-filename"/>
+              [](#opt-services.transmission.settings.script-torrent-done-filename)
               at torrent completion.
             '';
           };
@@ -156,15 +156,15 @@ in
           options.watch-dir-enabled = mkOption {
             type = types.bool;
             default = false;
-            description = ''Whether to enable the
-              <xref linkend="opt-services.transmission.settings.watch-dir"/>.
+            description = lib.mdDoc ''Whether to enable the
+              [](#opt-services.transmission.settings.watch-dir).
             '';
           };
           options.trash-original-torrent-files = mkOption {
             type = types.bool;
             default = false;
-            description = ''Whether to delete torrents added from the
-              <xref linkend="opt-services.transmission.settings.watch-dir"/>.
+            description = lib.mdDoc ''Whether to delete torrents added from the
+              [](#opt-services.transmission.settings.watch-dir).
             '';
           };
         };
@@ -174,26 +174,26 @@ in
         type = with types; nullOr str;
         default = null;
         example = "770";
-        description = ''
-          If not <literal>null</literal>, is used as the permissions
-          set by <literal>systemd.activationScripts.transmission-daemon</literal>
-          on the directories <xref linkend="opt-services.transmission.settings.download-dir"/>,
-          <xref linkend="opt-services.transmission.settings.incomplete-dir"/>.
-          and <xref linkend="opt-services.transmission.settings.watch-dir"/>.
+        description = lib.mdDoc ''
+          If not `null`, is used as the permissions
+          set by `systemd.activationScripts.transmission-daemon`
+          on the directories [](#opt-services.transmission.settings.download-dir),
+          [](#opt-services.transmission.settings.incomplete-dir).
+          and [](#opt-services.transmission.settings.watch-dir).
           Note that you may also want to change
-          <xref linkend="opt-services.transmission.settings.umask"/>.
+          [](#opt-services.transmission.settings.umask).
         '';
       };
 
       home = mkOption {
         type = types.path;
         default = "/var/lib/transmission";
-        description = ''
-          The directory where Transmission will create <literal>${settingsDir}</literal>.
-          as well as <literal>${downloadsDir}/</literal> unless
-          <xref linkend="opt-services.transmission.settings.download-dir"/> is changed,
-          and <literal>${incompleteDir}/</literal> unless
-          <xref linkend="opt-services.transmission.settings.incomplete-dir"/> is changed.
+        description = lib.mdDoc ''
+          The directory where Transmission will create `${settingsDir}`.
+          as well as `${downloadsDir}/` unless
+          [](#opt-services.transmission.settings.download-dir) is changed,
+          and `${incompleteDir}/` unless
+          [](#opt-services.transmission.settings.incomplete-dir) is changed.
         '';
       };
 
@@ -211,10 +211,10 @@ in
 
       credentialsFile = mkOption {
         type = types.path;
-        description = ''
+        description = lib.mdDoc ''
           Path to a JSON file to be merged with the settings.
           Useful to merge a file which is better kept out of the Nix store
-          to set secret config parameters like <literal>rpc-password</literal>.
+          to set secret config parameters like `rpc-password`.
         '';
         default = "/dev/null";
         example = "/var/lib/secrets/transmission/settings.json";
diff --git a/nixos/modules/services/web-apps/dokuwiki.nix b/nixos/modules/services/web-apps/dokuwiki.nix
index 49865b962d1..a148dec8199 100644
--- a/nixos/modules/services/web-apps/dokuwiki.nix
+++ b/nixos/modules/services/web-apps/dokuwiki.nix
@@ -260,14 +260,14 @@ in
       webserver = mkOption {
         type = types.enum [ "nginx" "caddy" ];
         default = "nginx";
-        description = ''
+        description = lib.mdDoc ''
           Whether to use nginx or caddy for virtual host management.
 
-          Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
-          See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
+          Further nginx configuration can be done by adapting `services.nginx.virtualHosts.<name>`.
+          See [](#opt-services.nginx.virtualHosts) for further information.
 
-          Further apache2 configuration can be done by adapting <literal>services.httpd.virtualHosts.&lt;name&gt;</literal>.
-          See <xref linkend="opt-services.httpd.virtualHosts"/> for further information.
+          Further apache2 configuration can be done by adapting `services.httpd.virtualHosts.<name>`.
+          See [](#opt-services.httpd.virtualHosts) for further information.
         '';
       };
 
diff --git a/nixos/modules/services/web-apps/hedgedoc.nix b/nixos/modules/services/web-apps/hedgedoc.nix
index 4e1a2125984..6f579b365cf 100644
--- a/nixos/modules/services/web-apps/hedgedoc.nix
+++ b/nixos/modules/services/web-apps/hedgedoc.nix
@@ -150,9 +150,9 @@ in
             addDefaults = true;
           }
         '';
-        description = ''
+        description = lib.mdDoc ''
           Specify the Content Security Policy which is passed to Helmet.
-          For configuration details see <link xlink:href="https://helmetjs.github.io/docs/csp/"/>.
+          For configuration details see <https://helmetjs.github.io/docs/csp/>.
         '';
       };
       protocolUseSSL = mkOption {
diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix
index 110df53effd..c1091bc09a0 100644
--- a/nixos/modules/services/web-apps/keycloak.nix
+++ b/nixos/modules/services/web-apps/keycloak.nix
@@ -210,13 +210,13 @@ in
         name = mkOption {
           type = str;
           default = "keycloak";
-          description = ''
+          description = lib.mdDoc ''
             Database name to use when connecting to an external or
             manually provisioned database; has no effect when a local
             database is automatically provisioned.
 
-            To use this with a local database, set <xref linkend="opt-services.keycloak.database.createLocally"/> to
-            <literal>false</literal> and create the database and user
+            To use this with a local database, set [](#opt-services.keycloak.database.createLocally) to
+            `false` and create the database and user
             manually.
           '';
         };
@@ -224,13 +224,13 @@ in
         username = mkOption {
           type = str;
           default = "keycloak";
-          description = ''
+          description = lib.mdDoc ''
             Username to use when connecting to an external or manually
             provisioned database; has no effect when a local database is
             automatically provisioned.
 
-            To use this with a local database, set <xref linkend="opt-services.keycloak.database.createLocally"/> to
-            <literal>false</literal> and create the database and user
+            To use this with a local database, set [](#opt-services.keycloak.database.createLocally) to
+            `false` and create the database and user
             manually.
           '';
         };
@@ -415,21 +415,21 @@ in
           }
         '';
 
-        description = ''
+        description = lib.mdDoc ''
           Configuration options corresponding to parameters set in
-          <filename>conf/keycloak.conf</filename>.
+          {file}`conf/keycloak.conf`.
 
-          Most available options are documented at <link xlink:href="https://www.keycloak.org/server/all-config"/>.
+          Most available options are documented at <https://www.keycloak.org/server/all-config>.
 
           Options containing secret data should be set to an attribute
-          set containing the attribute <literal>_secret</literal> - a
+          set containing the attribute `_secret` - a
           string pointing to a file containing the value the option
           should be set to. See the example to get a better picture of
           this: in the resulting
-          <filename>conf/keycloak.conf</filename> file, the
-          <literal>https-key-store-password</literal> key will be set
+          {file}`conf/keycloak.conf` file, the
+          `https-key-store-password` key will be set
           to the contents of the
-          <filename>/run/keys/store_password</filename> file.
+          {file}`/run/keys/store_password` file.
         '';
       };
     };
diff --git a/nixos/modules/services/web-apps/mastodon.nix b/nixos/modules/services/web-apps/mastodon.nix
index 00c30d73bb6..d0594ff7419 100644
--- a/nixos/modules/services/web-apps/mastodon.nix
+++ b/nixos/modules/services/web-apps/mastodon.nix
@@ -197,14 +197,14 @@ in {
       };
 
       vapidPublicKeyFile = lib.mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Path to file containing the public key used for Web Push
           Voluntary Application Server Identification.  A new keypair can
           be generated by running:
 
-          <literal>nix build -f '&lt;nixpkgs&gt;' mastodon; cd result; bin/rake webpush:generate_keys</literal>
+          `nix build -f '<nixpkgs>' mastodon; cd result; bin/rake webpush:generate_keys`
 
-          If <option>mastodon.vapidPrivateKeyFile</option>does not
+          If {option}`mastodon.vapidPrivateKeyFile`does not
           exist, it and this file will be created with a new keypair.
         '';
         default = "/var/lib/mastodon/secrets/vapid-public-key";
@@ -218,11 +218,11 @@ in {
       };
 
       secretKeyBaseFile = lib.mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Path to file containing the secret key base.
           A new secret key base can be generated by running:
 
-          <literal>nix build -f '&lt;nixpkgs&gt;' mastodon; cd result; bin/rake secret</literal>
+          `nix build -f '<nixpkgs>' mastodon; cd result; bin/rake secret`
 
           If this file does not exist, it will be created with a new secret key base.
         '';
@@ -231,11 +231,11 @@ in {
       };
 
       otpSecretFile = lib.mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Path to file containing the OTP secret.
           A new OTP secret can be generated by running:
 
-          <literal>nix build -f '&lt;nixpkgs&gt;' mastodon; cd result; bin/rake secret</literal>
+          `nix build -f '<nixpkgs>' mastodon; cd result; bin/rake secret`
 
           If this file does not exist, it will be created with a new OTP secret.
         '';
@@ -244,12 +244,12 @@ in {
       };
 
       vapidPrivateKeyFile = lib.mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Path to file containing the private key used for Web Push
           Voluntary Application Server Identification.  A new keypair can
           be generated by running:
 
-          <literal>nix build -f '&lt;nixpkgs&gt;' mastodon; cd result; bin/rake webpush:generate_keys</literal>
+          `nix build -f '<nixpkgs>' mastodon; cd result; bin/rake webpush:generate_keys`
 
           If this file does not exist, it will be created with a new
           private key.
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index a121401f758..feee7494a71 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -93,8 +93,8 @@ in {
       type = types.str;
       default = config.services.nextcloud.home;
       defaultText = literalExpression "config.services.nextcloud.home";
-      description = ''
-        Data storage path of nextcloud.  Will be <xref linkend="opt-services.nextcloud.home"/> by default.
+      description = lib.mdDoc ''
+        Data storage path of nextcloud.  Will be [](#opt-services.nextcloud.home) by default.
         This folder will be populated with a config.php and data folder which contains the state of the instance (excl the database).";
       '';
       example = "/mnt/nextcloud-file";
@@ -102,10 +102,10 @@ in {
     extraApps = mkOption {
       type = types.attrsOf types.package;
       default = { };
-      description = ''
+      description = lib.mdDoc ''
         Extra apps to install. Should be an attrSet of appid to packages generated by fetchNextcloudApp.
         The appid must be identical to the "id" value in the apps appinfo/info.xml.
-        Using this will disable the appstore to prevent Nextcloud from updating these apps (see <xref linkend="opt-services.nextcloud.appstoreEnable"/>).
+        Using this will disable the appstore to prevent Nextcloud from updating these apps (see [](#opt-services.nextcloud.appstoreEnable)).
       '';
       example = literalExpression ''
         {
@@ -127,8 +127,8 @@ in {
     extraAppsEnable = mkOption {
       type = types.bool;
       default = true;
-      description = ''
-        Automatically enable the apps in <xref linkend="opt-services.nextcloud.extraApps"/> every time nextcloud starts.
+      description = lib.mdDoc ''
+        Automatically enable the apps in [](#opt-services.nextcloud.extraApps) every time nextcloud starts.
         If set to false, apps need to be enabled in the Nextcloud user interface or with nextcloud-occ app:enable.
       '';
     };
@@ -136,10 +136,10 @@ in {
       type = types.nullOr types.bool;
       default = null;
       example = true;
-      description = ''
+      description = lib.mdDoc ''
         Allow the installation of apps and app updates from the store.
-        Enabled by default unless there are packages in <xref linkend="opt-services.nextcloud.extraApps"/>.
-        Set to true to force enable the store even if <xref linkend="opt-services.nextcloud.extraApps"/> is used.
+        Enabled by default unless there are packages in [](#opt-services.nextcloud.extraApps).
+        Set to true to force enable the store even if [](#opt-services.nextcloud.extraApps) is used.
         Set to false to disable the installation of apps from the global appstore. App management is always enabled regardless of this setting.
       '';
     };
@@ -585,9 +585,9 @@ in {
       hstsMaxAge = mkOption {
         type = types.ints.positive;
         default = 15552000;
-        description = ''
-          Value for the <literal>max-age</literal> directive of the HTTP
-          <literal>Strict-Transport-Security</literal> header.
+        description = lib.mdDoc ''
+          Value for the `max-age` directive of the HTTP
+          `Strict-Transport-Security` header.
 
           See section 6.1.1 of IETF RFC 6797 for detailed information on this
           directive and header.
diff --git a/nixos/modules/services/web-apps/node-red.nix b/nixos/modules/services/web-apps/node-red.nix
index 3e6e38c50db..e5b0998d3c4 100644
--- a/nixos/modules/services/web-apps/node-red.nix
+++ b/nixos/modules/services/web-apps/node-red.nix
@@ -47,9 +47,9 @@ in
       type = types.path;
       default = "${cfg.package}/lib/node_modules/node-red/settings.js";
       defaultText = literalExpression ''"''${package}/lib/node_modules/node-red/settings.js"'';
-      description = ''
+      description = lib.mdDoc ''
         Path to the JavaScript configuration file.
-        See <link xlink:href="https://github.com/node-red/node-red/blob/master/packages/node_modules/node-red/settings.js"/>
+        See <https://github.com/node-red/node-red/blob/master/packages/node_modules/node-red/settings.js>
         for a configuration example.
       '';
     };
diff --git a/nixos/modules/services/web-apps/trilium.nix b/nixos/modules/services/web-apps/trilium.nix
index 75464b21fd4..bb1061cf278 100644
--- a/nixos/modules/services/web-apps/trilium.nix
+++ b/nixos/modules/services/web-apps/trilium.nix
@@ -53,7 +53,7 @@ in
     noAuthentication = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         If set to true, no password is required to access the web frontend.
       '';
     };
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index fcc2976cd2c..5c39de0dde7 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -170,7 +170,7 @@ in
     supportDDC = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         Support setting monitor brightness via DDC.
 
         This is not needed for controlling brightness of the internal monitor
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix
index 00a47e7814f..f4195c4c2dc 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix
@@ -55,12 +55,12 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to enable lightdm-mini-greeter as the lightdm greeter.
 
           Note that this greeter starts only the default X session.
           You can configure the default X session using
-          <xref linkend="opt-services.xserver.displayManager.defaultSession"/>.
+          [](#opt-services.xserver.displayManager.defaultSession).
         '';
       };
 
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
index e8f799e2729..8d6bfa98a7e 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
@@ -17,12 +17,12 @@ in
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
+        description = lib.mdDoc ''
           Whether to enable lightdm-tiny-greeter as the lightdm greeter.
 
           Note that this greeter starts only the default X session.
           You can configure the default X session using
-          <xref linkend="opt-services.xserver.displayManager.defaultSession"/>.
+          [](#opt-services.xserver.displayManager.defaultSession).
         '';
       };
 
diff --git a/nixos/modules/services/x11/window-managers/fvwm2.nix b/nixos/modules/services/x11/window-managers/fvwm2.nix
index 909b3a475a9..b5ef36f58d5 100644
--- a/nixos/modules/services/x11/window-managers/fvwm2.nix
+++ b/nixos/modules/services/x11/window-managers/fvwm2.nix
@@ -24,7 +24,7 @@ in
       gestures = mkOption {
         default = false;
         type = types.bool;
-        description = "Whether or not to enable libstroke for gesture support";
+        description = lib.mdDoc "Whether or not to enable libstroke for gesture support";
       };
     };
   };
diff --git a/nixos/modules/system/boot/initrd-network.nix b/nixos/modules/system/boot/initrd-network.nix
index eff125971d0..a1017c3e242 100644
--- a/nixos/modules/system/boot/initrd-network.nix
+++ b/nixos/modules/system/boot/initrd-network.nix
@@ -50,17 +50,17 @@ in
     boot.initrd.network.enable = mkOption {
       type = types.bool;
       default = false;
-      description = ''
+      description = lib.mdDoc ''
         Add network connectivity support to initrd. The network may be
-        configured using the <literal>ip</literal> kernel parameter,
-        as described in <link xlink:href="https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt">the kernel documentation</link>.
+        configured using the `ip` kernel parameter,
+        as described in [the kernel documentation](https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt).
         Otherwise, if
-        <option>networking.useDHCP</option> is enabled, an IP address
+        {option}`networking.useDHCP` is enabled, an IP address
         is acquired using DHCP.
 
         You should add the module(s) required for your network card to
         boot.initrd.availableKernelModules.
-        <literal>lspci -v | grep -iA8 'network\|ethernet'</literal>
+        `lspci -v | grep -iA8 'network\|ethernet'`
         will tell you which.
       '';
     };
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 3b468f00aba..bffa7010d2f 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -548,11 +548,11 @@ in
     boot.initrd.luks.devices = mkOption {
       default = { };
       example = { luksroot.device = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08"; };
-      description = ''
+      description = lib.mdDoc ''
         The encrypted disk that should be opened before the root
         filesystem is mounted. Both LVM-over-LUKS and LUKS-over-LVM
         setups are supported. The unencrypted devices can be accessed as
-        <filename>/dev/mapper/«name»</filename>.
+        {file}`/dev/mapper/«name»`.
       '';
 
       type = with types; attrsOf (submodule (
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 1849dcfe1e1..efd6fabd2f3 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -1904,11 +1904,11 @@ in
       };
 
       extraArgs = mkOption {
-        description = ''
+        description = lib.mdDoc ''
           Extra command-line arguments to pass to systemd-networkd-wait-online.
-          These also affect per-interface <literal>systemd-network-wait-online@</literal> services.
+          These also affect per-interface `systemd-network-wait-online@` services.
 
-          See <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.service.html"><citerefentry><refentrytitle>systemd-networkd-wait-online.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></link> for all available options.
+          See [{manpage}`systemd-networkd-wait-online.service(8)`](https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.service.html) for all available options.
         '';
         type = with types; listOf str;
         default = [];
diff --git a/nixos/modules/system/boot/systemd/logind.nix b/nixos/modules/system/boot/systemd/logind.nix
index bd05c07e26f..59801603213 100644
--- a/nixos/modules/system/boot/systemd/logind.nix
+++ b/nixos/modules/system/boot/systemd/logind.nix
@@ -26,14 +26,14 @@ in
     services.logind.killUserProcesses = mkOption {
       default = false;
       type = types.bool;
-      description = ''
+      description = lib.mdDoc ''
         Specifies whether the processes of a user should be killed
         when the user logs out.  If true, the scope unit corresponding
         to the session and all processes inside that scope will be
         terminated.  If false, the scope is "abandoned" (see
-        <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.scope.html#">systemd.scope(5)</link>), and processes are not killed.
+        [systemd.scope(5)](https://www.freedesktop.org/software/systemd/man/systemd.scope.html#)), and processes are not killed.
 
-        See <link xlink:href="https://www.freedesktop.org/software/systemd/man/logind.conf.html#KillUserProcesses=">logind.conf(5)</link>
+        See [logind.conf(5)](https://www.freedesktop.org/software/systemd/man/logind.conf.html#KillUserProcesses=)
         for more details.
       '';
     };
diff --git a/nixos/modules/system/boot/systemd/tmpfiles.nix b/nixos/modules/system/boot/systemd/tmpfiles.nix
index 0d5adf596e1..e990e953b05 100644
--- a/nixos/modules/system/boot/systemd/tmpfiles.nix
+++ b/nixos/modules/system/boot/systemd/tmpfiles.nix
@@ -25,16 +25,16 @@ in
       default = [];
       example = literalExpression "[ pkgs.lvm2 ]";
       apply = map getLib;
-      description = ''
-        List of packages containing <command>systemd-tmpfiles</command> rules.
+      description = lib.mdDoc ''
+        List of packages containing {command}`systemd-tmpfiles` rules.
 
         All files ending in .conf found in
-        <filename>«pkg»/lib/tmpfiles.d</filename>
+        {file}`«pkg»/lib/tmpfiles.d`
         will be included.
         If this folder does not exist or does not contain any files an error will be returned instead.
 
-        If a <filename>lib</filename> output is available, rules are searched there and only there.
-        If there is no <filename>lib</filename> output it will fall back to <filename>out</filename>
+        If a {file}`lib` output is available, rules are searched there and only there.
+        If there is no {file}`lib` output it will fall back to {file}`out`
         and if that does not exist either, the default output will be used.
       '';
     };
diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix
index 46a30c53ea8..ca269016783 100644
--- a/nixos/modules/tasks/auto-upgrade.nix
+++ b/nixos/modules/tasks/auto-upgrade.nix
@@ -25,10 +25,10 @@ in {
         type = types.enum ["switch" "boot"];
         default = "switch";
         example = "boot";
-        description = ''
+        description = lib.mdDoc ''
           Whether to run
-          <literal>nixos-rebuild switch --upgrade</literal> or run
-          <literal>nixos-rebuild boot --upgrade</literal>
+          `nixos-rebuild switch --upgrade` or run
+          `nixos-rebuild boot --upgrade`
         '';
       };
 
diff --git a/nixos/modules/tasks/scsi-link-power-management.nix b/nixos/modules/tasks/scsi-link-power-management.nix
index 549c35fc5b8..a5395657e99 100644
--- a/nixos/modules/tasks/scsi-link-power-management.nix
+++ b/nixos/modules/tasks/scsi-link-power-management.nix
@@ -25,7 +25,7 @@ in
     powerManagement.scsiLinkPolicy = mkOption {
       default = null;
       type = types.nullOr (types.enum allowedValues);
-      description = ''
+      description = lib.mdDoc ''
         SCSI link power management policy. The kernel default is
         "max_performance".
 
diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix
index 1699b0bcea4..6b8c21336c6 100644
--- a/nixos/modules/virtualisation/nixos-containers.nix
+++ b/nixos/modules/virtualisation/nixos-containers.nix
@@ -579,11 +579,11 @@ in
             privateNetwork = mkOption {
               type = types.bool;
               default = false;
-              description = ''
+              description = lib.mdDoc ''
                 Whether to give the container its own private virtual
                 Ethernet interface.  The interface is called
-                <literal>eth0</literal>, and is hooked up to the interface
-                <literal>ve-«container-name»</literal>
+                `eth0`, and is hooked up to the interface
+                `ve-«container-name»`
                 on the host.  If this option is not set, then the
                 container shares the network interfaces of the host,
                 and can bind to any port on any interface.
@@ -728,12 +728,12 @@ in
               };
           }
         '';
-      description = ''
+      description = lib.mdDoc ''
         A set of NixOS system configurations to be run as lightweight
         containers.  Each container appears as a service
-        <literal>container-«name»</literal>
+        `container-«name»`
         on the host system, allowing it to be started and stopped via
-        <command>systemctl</command>.
+        {command}`systemctl`.
       '';
     };