summaryrefslogtreecommitdiffstats
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/hardware/all-firmware.nix12
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix6
-rw-r--r--nixos/modules/installer/netboot/netboot.nix6
-rw-r--r--nixos/modules/installer/tools/nix-fallback-paths.nix10
-rw-r--r--nixos/modules/misc/ids.nix1
-rw-r--r--nixos/modules/misc/version.nix5
-rw-r--r--nixos/modules/module-list.nix4
-rw-r--r--nixos/modules/services/cluster/kubernetes/addons/dns.nix54
-rw-r--r--nixos/modules/services/cluster/kubernetes/pki.nix2
-rw-r--r--nixos/modules/services/hardware/sane.nix27
-rw-r--r--nixos/modules/services/misc/gitea.nix11
-rw-r--r--nixos/modules/services/misc/libreddit.nix66
-rw-r--r--nixos/modules/services/misc/mx-puppet-discord.nix120
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix34
-rw-r--r--nixos/modules/services/network-filesystems/litestream/default.nix100
-rw-r--r--nixos/modules/services/network-filesystems/litestream/litestream.xml65
-rw-r--r--nixos/modules/services/networking/bird.nix4
-rw-r--r--nixos/modules/services/networking/firewall.nix4
-rw-r--r--nixos/modules/services/networking/kea.nix16
-rw-r--r--nixos/modules/services/networking/networkmanager.nix13
-rw-r--r--nixos/modules/services/networking/nftables.nix1
-rw-r--r--nixos/modules/services/networking/syncthing.nix634
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix3
-rw-r--r--nixos/modules/services/system/uptimed.nix10
-rw-r--r--nixos/modules/services/web-apps/node-red.nix148
-rw-r--r--nixos/modules/services/web-apps/tt-rss.nix127
-rwxr-xr-xnixos/modules/services/x11/display-managers/set-session.py3
-rw-r--r--nixos/modules/system/boot/systemd.nix3
-rw-r--r--nixos/modules/system/etc/etc.nix64
-rw-r--r--nixos/modules/system/etc/make-etc.sh45
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix8
33 files changed, 1146 insertions, 463 deletions
diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix
index 3e88a4c20adc..524dae57010b 100644
--- a/nixos/modules/hardware/all-firmware.nix
+++ b/nixos/modules/hardware/all-firmware.nix
@@ -35,6 +35,14 @@ in {
'';
};
+ hardware.wirelessRegulatoryDatabase = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Load the wireless regulatory database at boot.
+ '';
+ };
+
};
@@ -58,6 +66,7 @@ in {
++ optionals (versionOlder config.boot.kernelPackages.kernel.version "4.13") [
rtl8723bs-firmware
];
+ hardware.wirelessRegulatoryDatabase = true;
})
(mkIf cfg.enableAllFirmware {
assertions = [{
@@ -75,5 +84,8 @@ in {
b43FirmwareCutter
] ++ optional (pkgs.stdenv.hostPlatform.isi686 || pkgs.stdenv.hostPlatform.isx86_64) facetimehd-firmware;
})
+ (mkIf cfg.wirelessRegulatoryDatabase {
+ hardware.firmware = [ pkgs.wireless-regdb ];
+ })
];
}
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index d94af0b5bf74..f03845132476 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -654,7 +654,11 @@ in
];
fileSystems."/" =
- { fsType = "tmpfs";
+ # This module is often over-layed onto an existing host config
+ # that defines `/`. We use mkOverride 60 to override standard
+ # values, but at the same time leave room for mkForce values
+ # targeted at the image build.
+ { fsType = mkOverride 60 "tmpfs";
options = [ "mode=0755" ];
};
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index 238ab6d0617b..f7543fdf4a23 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -30,7 +30,11 @@ with lib;
else [ pkgs.grub2 pkgs.syslinux ]);
fileSystems."/" =
- { fsType = "tmpfs";
+ # This module is often over-layed onto an existing host config
+ # that defines `/`. We use mkOverride 60 to override standard
+ # values, but at the same time leave room for mkForce values
+ # targeted at the image build.
+ { fsType = mkOverride 60 "tmpfs";
options = [ "mode=0755" ];
};
diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix
index e3576074a5b7..15c76287e34e 100644
--- a/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,7 +1,7 @@
{
- x86_64-linux = "/nix/store/qsgz2hhn6mzlzp53a7pwf9z2pq3l5z6h-nix-2.3.14";
- i686-linux = "/nix/store/1yw40bj04lykisw2jilq06lir3k9ga4a-nix-2.3.14";
- aarch64-linux = "/nix/store/32yzwmynmjxfrkb6y6l55liaqdrgkj4a-nix-2.3.14";
- x86_64-darwin = "/nix/store/06j0vi2d13w4l0p3jsigq7lk4x6gkycj-nix-2.3.14";
- aarch64-darwin = "/nix/store/77wi7vpbrghw5rgws25w30bwb8yggnk9-nix-2.3.14";
+ x86_64-linux = "/nix/store/jhbxh1jwjc3hjhzs9y2hifdn0rmnfwaj-nix-2.3.15";
+ i686-linux = "/nix/store/9pspwnkdrgzma1l4xlv7arhwa56y16di-nix-2.3.15";
+ aarch64-linux = "/nix/store/72aqi5g7f4fhgvgafbcqwcpqjgnczj48-nix-2.3.15";
+ x86_64-darwin = "/nix/store/6p6qwp73dgfkqhynmxrzbx1lcfgfpqal-nix-2.3.15";
+ aarch64-darwin = "/nix/store/dmq2vksdhssgfl822shd0ky3x5x0klh4-nix-2.3.15";
}
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 858c7ee53dbb..a7a31ba85768 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -187,6 +187,7 @@ in
#seeks = 148; # removed 2020-06-21
prosody = 149;
i2pd = 150;
+ systemd-coredump = 151;
systemd-network = 152;
systemd-resolve = 153;
systemd-timesync = 154;
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index a6fffb76f6e8..8f246a9278b7 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -103,9 +103,10 @@ in
''
NAME=NixOS
ID=nixos
- VERSION="${cfg.version} (${cfg.codeName})"
+ VERSION="${cfg.release} (${cfg.codeName})"
VERSION_CODENAME=${toLower cfg.codeName}
- VERSION_ID="${cfg.version}"
+ VERSION_ID="${cfg.release}"
+ BUILD_ID="${cfg.version}"
PRETTY_NAME="NixOS ${cfg.release} (${cfg.codeName})"
LOGO="nix-snowflake"
HOME_URL="https://nixos.org/"
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 899b05cf190e..1a6d8599e7e8 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -520,6 +520,7 @@
./services/misc/logkeys.nix
./services/misc/leaps.nix
./services/misc/lidarr.nix
+ ./services/misc/libreddit.nix
./services/misc/lifecycled.nix
./services/misc/mame.nix
./services/misc/matrix-appservice-discord.nix
@@ -530,6 +531,7 @@
./services/misc/mediatomb.nix
./services/misc/metabase.nix
./services/misc/mwlib.nix
+ ./services/misc/mx-puppet-discord.nix
./services/misc/n8n.nix
./services/misc/nix-daemon.nix
./services/misc/nix-gc.nix
@@ -634,6 +636,7 @@
./services/network-filesystems/glusterfs.nix
./services/network-filesystems/kbfs.nix
./services/network-filesystems/ipfs.nix
+ ./services/network-filesystems/litestream/default.nix
./services/network-filesystems/netatalk.nix
./services/network-filesystems/nfsd.nix
./services/network-filesystems/openafs/client.nix
@@ -961,6 +964,7 @@
./services/web-apps/moodle.nix
./services/web-apps/nextcloud.nix
./services/web-apps/nexus.nix
+ ./services/web-apps/node-red.nix
./services/web-apps/plantuml-server.nix
./services/web-apps/plausible.nix
./services/web-apps/pgpkeyserver-lite.nix
diff --git a/nixos/modules/services/cluster/kubernetes/addons/dns.nix b/nixos/modules/services/cluster/kubernetes/addons/dns.nix
index 24d86628b211..8f937a13231b 100644
--- a/nixos/modules/services/cluster/kubernetes/addons/dns.nix
+++ b/nixos/modules/services/cluster/kubernetes/addons/dns.nix
@@ -60,6 +60,45 @@ in {
sha256 = "02r440xcdsgi137k5lmmvp0z5w5fmk8g9mysq5pnysq1wl8sj6mw";
};
};
+
+ corefile = mkOption {
+ description = ''
+ Custom coredns corefile configuration.
+
+ See: <link xlink:href="https://coredns.io/manual/toc/#configuration"/>.
+ '';
+ type = types.str;
+ default = ''
+ .:${toString ports.dns} {
+ errors
+ health :${toString ports.health}
+ kubernetes ${cfg.clusterDomain} in-addr.arpa ip6.arpa {
+ pods insecure
+ fallthrough in-addr.arpa ip6.arpa
+ }
+ prometheus :${toString ports.metrics}
+ forward . /etc/resolv.conf
+ cache 30
+ loop
+ reload
+ loadbalance
+ }'';
+ defaultText = ''
+ .:${toString ports.dns} {
+ errors
+ health :${toString ports.health}
+ kubernetes ''${config.services.kubernetes.addons.dns.clusterDomain} in-addr.arpa ip6.arpa {
+ pods insecure
+ fallthrough in-addr.arpa ip6.arpa
+ }
+ prometheus :${toString ports.metrics}
+ forward . /etc/resolv.conf
+ cache 30
+ loop
+ reload
+ loadbalance
+ }'';
+ };
};
config = mkIf cfg.enable {
@@ -151,20 +190,7 @@ in {
namespace = "kube-system";
};
data = {
- Corefile = ".:${toString ports.dns} {
- errors
- health :${toString ports.health}
- kubernetes ${cfg.clusterDomain} in-addr.arpa ip6.arpa {
- pods insecure
- fallthrough in-addr.arpa ip6.arpa
- }
- prometheus :${toString ports.metrics}
- forward . /etc/resolv.conf
- cache 30
- loop
- reload
- loadbalance
- }";
+ Corefile = cfg.corefile;
};
};
diff --git a/nixos/modules/services/cluster/kubernetes/pki.nix b/nixos/modules/services/cluster/kubernetes/pki.nix
index d9311d3e3a04..faf951d81574 100644
--- a/nixos/modules/services/cluster/kubernetes/pki.nix
+++ b/nixos/modules/services/cluster/kubernetes/pki.nix
@@ -189,7 +189,7 @@ in
# manually paste it in place. Just symlink.
# otherwise, create the target file, ready for users to insert the token
- mkdir -p $(dirname ${certmgrAPITokenPath})
+ mkdir -p "$(dirname "${certmgrAPITokenPath}")"
if [ -f "${cfsslAPITokenPath}" ]; then
ln -fs "${cfsslAPITokenPath}" "${certmgrAPITokenPath}"
else
diff --git a/nixos/modules/services/hardware/sane.nix b/nixos/modules/services/hardware/sane.nix
index 8c1bde7b4158..ccf726bd182b 100644
--- a/nixos/modules/services/hardware/sane.nix
+++ b/nixos/modules/services/hardware/sane.nix
@@ -4,7 +4,10 @@ with lib;
let
- pkg = pkgs.sane-backends;
+ pkg = pkgs.sane-backends.override {
+ scanSnapDriversUnfree = config.hardware.sane.drivers.scanSnap.enable;
+ scanSnapDriversPackage = config.hardware.sane.drivers.scanSnap.package;
+ };
sanedConf = pkgs.writeTextFile {
name = "saned.conf";
@@ -98,6 +101,28 @@ in
'';
};
+ hardware.sane.drivers.scanSnap.enable = mkOption {
+ type = types.bool;
+ default = false;
+ example = true;
+ description = ''
+ Whether to enable drivers for the Fujitsu ScanSnap scanners.
+
+ The driver files are unfree and extracted from the Windows driver image.
+ '';
+ };
+
+ hardware.sane.drivers.scanSnap.package = mkOption {
+ type = types.package;
+ default = pkgs.sane-drivers.epjitsu;
+ description = ''
+ Epjitsu driver package to use. Useful if you want to extract the driver files yourself.
+
+ The process is described in the <literal>/etc/sane.d/epjitsu.conf</literal> file in
+ the <literal>sane-backends</literal> package.
+ '';
+ };
+
services.saned.enable = mkOption {
type = types.bool;
default = false;
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index b6c1ca3e61a9..2f8e595cad00 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -523,19 +523,12 @@ in
''}
# update all hooks' binary paths
- HOOKS=$(find ${cfg.repositoryRoot} -mindepth 4 -maxdepth 6 -type f -wholename "*git/hooks/*")
- if [ "$HOOKS" ]
- then
- sed -ri 's,/nix/store/[a-z0-9.-]+/bin/gitea,${gitea}/bin/gitea,g' $HOOKS
- sed -ri 's,/nix/store/[a-z0-9.-]+/bin/env,${pkgs.coreutils}/bin/env,g' $HOOKS
- sed -ri 's,/nix/store/[a-z0-9.-]+/bin/bash,${pkgs.bash}/bin/bash,g' $HOOKS
- sed -ri 's,/nix/store/[a-z0-9.-]+/bin/perl,${pkgs.perl}/bin/perl,g' $HOOKS
- fi
+ ${gitea}/bin/gitea admin regenerate hooks
# update command option in authorized_keys
if [ -r ${cfg.stateDir}/.ssh/authorized_keys ]
then
- sed -ri 's,/nix/store/[a-z0-9.-]+/bin/gitea,${gitea}/bin/gitea,g' ${cfg.stateDir}/.ssh/authorized_keys
+ ${gitea}/bin/gitea admin regenerate keys
fi
'';
diff --git a/nixos/modules/services/misc/libreddit.nix b/nixos/modules/services/misc/libreddit.nix
new file mode 100644
index 000000000000..77b34a856204
--- /dev/null
+++ b/nixos/modules/services/misc/libreddit.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+ let
+ cfg = config.services.libreddit;
+
+ args = concatStringsSep " " ([
+ "--port ${toString cfg.port}"
+ "--address ${cfg.address}"
+ ] ++ optional cfg.redirect "--redirect-https");
+
+in
+{
+ options = {
+ services.libreddit = {
+ enable = mkEnableOption "Private front-end for Reddit";
+
+ address = mkOption {
+ default = "0.0.0.0";
+ example = "127.0.0.1";
+ type = types.str;
+ description = "The address to listen on";
+ };
+
+ port = mkOption {
+ default = 8080;
+ example = 8000;
+ type = types.port;
+ description = "The port to listen on";
+ };
+
+ redirect = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the redirecting to HTTPS";
+ };
+
+ openFirewall = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Open ports in the firewall for the libreddit web interface";
+ };
+
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.libreddit = {
+ description = "Private front-end for Reddit";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+ serviceConfig = {
+ DynamicUser = true;
+ ExecStart = "${pkgs.libreddit}/bin/libreddit ${args}";
+ AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
+ Restart = "on-failure";
+ RestartSec = "2s";
+ };
+ };
+
+ networking.firewall = mkIf cfg.openFirewall {
+ allowedTCPPorts = [ cfg.port ];
+ };
+ };
+}
diff --git a/nixos/modules/services/misc/mx-puppet-discord.nix b/nixos/modules/services/misc/mx-puppet-discord.nix
new file mode 100644
index 000000000000..11116f7c3489
--- /dev/null
+++ b/nixos/modules/services/misc/mx-puppet-discord.nix
@@ -0,0 +1,120 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+ dataDir = "/var/lib/mx-puppet-discord";
+ registrationFile = "${dataDir}/discord-registration.yaml";
+ cfg = config.services.mx-puppet-discord;
+ settingsFormat = pkgs.formats.json {};
+ settingsFile = settingsFormat.generate "mx-puppet-discord-config.json" cfg.settings;
+
+in {
+ options = {
+ services.mx-puppet-discord = {
+ enable = mkEnableOption ''
+ mx-puppet-discord is a discord puppeting bridge for matrix.
+ It handles bridging private and group DMs, as well as Guilds (servers)
+ '';
+
+ settings = mkOption rec {
+ apply = recursiveUpdate default;
+ inherit (settingsFormat) type;
+ default = {
+ bridge.port = 8434;
+ presence = {
+ enabled = true;
+ interval = 500;
+ };
+ provisioning.whitelist = [ ];
+ relay.whitelist = [ ];
+
+ # variables are preceded by a colon.
+ namePatterns = {
+ user = ":name";
+ userOverride = ":displayname";
+ room = ":name";
+ group = ":name";
+ };
+
+ #defaults to sqlite but can be configured to use postgresql with
+ #connstring
+ database.filename = "${dataDir}/mx-puppet-discord/database.db";
+ logging = {
+ console = "info";
+ lineDateFormat = "MMM-D HH:mm:ss.SSS";
+ };
+ };
+ example = literalExample ''
+ {
+ bridge = {
+ bindAddress = "localhost";
+ domain = "example.com";
+ homeserverUrl = "https://example.com";
+ };
+
+ provisioning.whitelist = [ "@admin:example.com" ];
+ relay.whitelist = [ "@.*:example.com" ];
+ }
+ '';
+ description = ''
+ <filename>config.yaml</filename> configuration as a Nix attribute set.
+ Configuration options should match those described in
+ <link xlink:href="https://github.com/matrix-discord/mx-puppet-discord/blob/master/sample.config.yaml">
+ sample.config.yaml</link>.
+ '';
+ };
+ serviceDependencies = mkOption {
+ type = with types; listOf str;
+ default = optional config.services.matrix-synapse.enable "matrix-synapse.service";
+ description = ''
+ List of Systemd services to require and wait for when starting the application service.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.mx-puppet-discord = {
+ description = ''
+ mx-puppet-discord is a discord puppeting bridge for matrix.
+ It handles bridging private and group DMs, as well as Guilds (servers).
+ '';
+
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "network-online.target" ] ++ cfg.serviceDependencies;
+ after = [ "network-online.target" ] ++ cfg.serviceDependencies;
+
+ preStart = ''
+ # generate the appservice's registration file if absent
+ if [ ! -f '${registrationFile}' ]; then
+ ${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -r -c ${settingsFile} \
+ -f ${registrationFile}
+ fi
+ '';
+
+ serviceConfig = {
+ Type = "simple";
+ Restart = "always";
+
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+
+ DynamicUser = true;
+ PrivateTmp = true;
+ WorkingDirectory = pkgs.mx-puppet-discord;
+ StateDirectory = baseNameOf dataDir;
+ UMask = 0027;
+
+ ExecStart = ''
+ ${pkgs.mx-puppet-discord}/bin/mx-puppet-discord -c ${settingsFile}
+ '';
+ };
+ };
+ };
+
+ meta.maintainers = with maintainers; [ govanify ];
+}
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 133e96da0ec8..70b27b7d3d09 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -458,7 +458,7 @@ in
description = "The flake reference to which <option>from></option> is to be rewritten.";
};
flake = mkOption {
- type = types.unspecified;
+ type = types.nullOr types.attrs;
default = null;
example = literalExample "nixpkgs";
description = ''
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix
index d648de6a4148..9182c2f2ed87 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -33,6 +33,7 @@ let
"domain"
"dovecot"
"fritzbox"
+ "influxdb"
"json"
"jitsi"
"kea"
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix
new file mode 100644
index 000000000000..ba45173e946a
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/exporters/influxdb.nix
@@ -0,0 +1,34 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.influxdb;
+in
+{
+ port = 9122;
+ extraOpts = {
+ sampleExpiry = mkOption {
+ type = types.str;
+ default = "5m";
+ example = "10m";
+ description = "How long a sample is valid for";
+ };
+ udpBindAddress = mkOption {
+ type = types.str;
+ default = ":9122";
+ example = "192.0.2.1:9122";
+ description = "Address on which to listen for udp packets";
+ };
+ };
+ serviceOpts = {
+ serviceConfig = {
+ RuntimeDirectory = "prometheus-influxdb-exporter";
+ ExecStart = ''
+ ${pkgs.prometheus-influxdb-exporter}/bin/influxdb_exporter \
+ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
+ --influxdb.sample-expiry ${cfg.sampleExpiry} ${concatStringsSep " " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixos/modules/services/network-filesystems/litestream/default.nix b/nixos/modules/services/network-filesystems/litestream/default.nix
new file mode 100644
index 000000000000..f1806c5af0a9
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/litestream/default.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.litestream;
+ settingsFormat = pkgs.formats.yaml {};
+in
+{
+ options.services.litestream = {
+ enable = mkEnableOption "litestream";
+
+ package = mkOption {
+ description = "Package to use.";
+ default = pkgs.litestream;
+ defaultText = "pkgs.litestream";
+ type = types.package;
+ };
+
+ settings = mkOption {
+ description = ''
+ See the <link xlink:href="https://litestream.io/reference/config/">documentation</link>.
+ '';
+ type = settingsFormat.type;
+ example = {
+ dbs = [
+ {
+ path = "/var/lib/db1";
+ replicas = [
+ {
+ url = "s3://mybkt.litestream.io/db1";
+ }
+ ];
+ }
+ ];
+ };
+ };
+
+ environmentFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/run/secrets/litestream";
+ description = ''
+ Environment file as defined in <citerefentry>
+ <refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>.
+
+ Secrets may be passed to the service without adding them to the
+ world-readable Nix store, by specifying placeholder variables as
+ the option value in Nix and setting these variables accordingly in the
+ environment file.
+
+ By default, Litestream will perform environment variable expansion
+ within the config file before reading it. Any references to ''$VAR or
+ ''${VAR} formatted variables will be replaced with their environment
+ variable values. If no value is set then it will be replaced with an
+ empty string.
+
+ <programlisting>
+ # Content of the environment file
+ LITESTREAM_ACCESS_KEY_ID=AKIAxxxxxxxxxxxxxxxx
+ LITESTREAM_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxx
+ </programlisting>
+
+ Note that this file needs to be available on the host on which
+ this exporter is running.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [ cfg.package ];
+ environment.etc = {
+ "litestream.yml" = {
+ source = settingsFormat.generate "litestream-config.yaml" cfg.settings;
+ };
+ };
+
+ systemd.services.litestream = {
+ description = "Litestream";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "networking.target" ];
+ serviceConfig = {
+ EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
+ ExecStart = "${cfg.package}/bin/litestream replicate";
+ Restart = "always";
+ User = "litestream";
+ Group = "litestream";
+ };
+ };
+
+ users.users.litestream = {
+ description = "Litestream user";
+ group = "litestream";
+ isSystemUser = true;
+ };
+ users.groups.litestream = {};
+ };
+ meta.doc = ./litestream.xml;
+}
diff --git a/nixos/modules/services/network-filesystems/litestream/litestream.xml b/nixos/modules/services/network-filesystems/litestream/litestream.xml
new file mode 100644
index 000000000000..598f9be8cf63
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/litestream/litestream.xml
@@ -0,0 +1,65 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="module-services-litestream">
+ <title>Litestream</title>
+ <para>
+ <link xlink:href="https://litestream.io/">Litestream</link> is a standalone streaming
+ replication tool for SQLite.
+ </para>
+
+ <section xml:id="module-services-litestream-configuration">
+ <title>Configuration</title>
+
+ <para>
+ Litestream service is managed by a dedicated user named <literal>litestream</literal>
+ which needs permission to the database file. Here's an example config which gives
+ required permissions to access <link linkend="opt-services.grafana.database.path">
+ grafana database</link>:
+<programlisting>
+{ pkgs, ... }:
+{
+ users.users.litestream.extraGroups = [ "grafana" ];
+
+ systemd.services.grafana.serviceConfig.ExecStartPost = "+" + pkgs.writeShellScript "grant-grafana-permissions" ''
+ timeout=10
+
+ while [ ! -f /var/lib/grafana/data/grafana.db ];
+ do
+ if [ "$timeout" == 0 ]; then
+ echo "ERROR: Timeout while waiting for /var/lib/grafana/data/grafana.db."
+ exit 1
+ fi
+
+ sleep 1
+
+ ((timeout--))
+ done
+
+ find /var/lib/grafana -type d -exec chmod -v 775 {} \;