grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / backup / restic-rest-server.nix
blob333609444da2afe04ce157fdc8f91104b787611f
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.restic.server;
4 in
6   meta.maintainers = [ lib.maintainers.bachp ];
8   options.services.restic.server = {
9     enable = lib.mkEnableOption "Restic REST Server";
11     listenAddress = lib.mkOption {
12       default = "8000";
13       example = "127.0.0.1:8080";
14       type = lib.types.str;
15       description = "Listen on a specific IP address and port or unix socket.";
16     };
18     dataDir = lib.mkOption {
19       default = "/var/lib/restic";
20       type = lib.types.path;
21       description = "The directory for storing the restic repository.";
22     };
24     appendOnly = lib.mkOption {
25       default = false;
26       type = lib.types.bool;
27       description = ''
28         Enable append only mode.
29         This mode allows creation of new backups but prevents deletion and modification of existing backups.
30         This can be useful when backing up systems that have a potential of being hacked.
31       '';
32     };
34     privateRepos = lib.mkOption {
35       default = false;
36       type = lib.types.bool;
37       description = ''
38         Enable private repos.
39         Grants access only when a subdirectory with the same name as the user is specified in the repository URL.
40       '';
41     };
43     prometheus = lib.mkOption {
44       default = false;
45       type = lib.types.bool;
46       description = "Enable Prometheus metrics at /metrics.";
47     };
49     extraFlags = lib.mkOption {
50       type = lib.types.listOf lib.types.str;
51       default = [];
52       description = ''
53         Extra commandline options to pass to Restic REST server.
54       '';
55     };
57     package = lib.mkPackageOption pkgs "restic-rest-server" { };
58   };
60   config = lib.mkIf cfg.enable {
61     assertions = [{
62       assertion = lib.substring 0 1 cfg.listenAddress != ":";
63       message = "The restic-rest-server now uses systemd socket activation, which expects only the Port number: services.restic.server.listenAddress = \"${lib.substring 1 6 cfg.listenAddress}\";";
64     }];
66     systemd.services.restic-rest-server = {
67       description = "Restic REST Server";
68       after = [ "network.target" "restic-rest-server.socket" ];
69       requires = [ "restic-rest-server.socket" ];
70       wantedBy = [ "multi-user.target" ];
71       serviceConfig = {
72         ExecStart = ''
73           ${cfg.package}/bin/rest-server \
74           --path ${cfg.dataDir} \
75           ${lib.optionalString cfg.appendOnly "--append-only"} \
76           ${lib.optionalString cfg.privateRepos "--private-repos"} \
77           ${lib.optionalString cfg.prometheus "--prometheus"} \
78           ${lib.escapeShellArgs cfg.extraFlags} \
79         '';
80         Type = "simple";
81         User = "restic";
82         Group = "restic";
84         # Security hardening
85         CapabilityBoundingSet = "";
86         LockPersonality = true;
87         MemoryDenyWriteExecute = true;
88         NoNewPrivileges = true;
89         PrivateNetwork = true;
90         PrivateTmp = true;
91         PrivateUsers = true;
92         ProtectClock = true;
93         ProtectHome = true;
94         ProtectHostname = true;
95         ProtectKernelLogs = true;
96         ProtectProc = "invisible";
97         ProtectSystem = "strict";
98         ProtectKernelTunables = true;
99         ProtectKernelModules = true;
100         ProtectControlGroups = true;
101         PrivateDevices = true;
102         ReadWritePaths = [ cfg.dataDir ];
103         RemoveIPC = true;
104         RestrictAddressFamilies = "none";
105         RestrictNamespaces = true;
106         RestrictRealtime = true;
107         RestrictSUIDSGID = true;
108         SystemCallArchitectures = "native";
109         SystemCallFilter = "@system-service";
110         UMask = 027;
111       };
112     };
114     systemd.sockets.restic-rest-server = {
115       listenStreams = [ cfg.listenAddress ];
116       wantedBy = [ "sockets.target" ];
117     };
119     systemd.tmpfiles.rules = lib.mkIf cfg.privateRepos [
120         "f ${cfg.dataDir}/.htpasswd 0700 restic restic -"
121     ];
123     users.users.restic = {
124       group = "restic";
125       home = cfg.dataDir;
126       createHome = true;
127       uid = config.ids.uids.restic;
128     };
130     users.groups.restic.gid = config.ids.uids.restic;
131   };