python312Packages.yoda: 2.0.1 -> 2.0.2
[NixPkgs.git] / nixos / modules / services / misc / rmfakecloud.nix
blobb1f81c10b9a46f13e2eeb601db2ee4d46416ab79
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.services.rmfakecloud;
9   serviceDataDir = "/var/lib/rmfakecloud";
13   options = {
14     services.rmfakecloud = {
15       enable = lib.mkEnableOption "rmfakecloud remarkable self-hosted cloud";
17       package = lib.mkPackageOption pkgs "rmfakecloud" { };
19       storageUrl = lib.mkOption {
20         type = lib.types.str;
21         example = "https://local.appspot.com";
22         description = ''
23           URL used by the tablet to access the rmfakecloud service.
24         '';
25       };
27       port = lib.mkOption {
28         type = lib.types.port;
29         default = 3000;
30         description = ''
31           Listening port number.
32         '';
33       };
35       logLevel = lib.mkOption {
36         type = lib.types.enum [
37           "info"
38           "debug"
39           "warn"
40           "error"
41         ];
42         default = "info";
43         description = ''
44           Logging level.
45         '';
46       };
48       extraSettings = lib.mkOption {
49         type = with lib.types; attrsOf str;
50         default = { };
51         example = {
52           DATADIR = "/custom/path/for/rmfakecloud/data";
53         };
54         description = ''
55           Extra settings in the form of a set of key-value pairs.
56           For tokens and secrets, use `environmentFile` instead.
58           Available settings are listed on
59           https://ddvk.github.io/rmfakecloud/install/configuration/.
60         '';
61       };
63       environmentFile = lib.mkOption {
64         type = with lib.types; nullOr path;
65         default = null;
66         example = "/etc/secrets/rmfakecloud.env";
67         description = ''
68           Path to an environment file loaded for the rmfakecloud service.
70           This can be used to securely store tokens and secrets outside of the
71           world-readable Nix store. Since this file is read by systemd, it may
72           have permission 0400 and be owned by root.
73         '';
74       };
75     };
76   };
78   config = lib.mkIf cfg.enable {
79     systemd.services.rmfakecloud = {
80       description = "rmfakecloud remarkable self-hosted cloud";
82       environment = {
83         STORAGE_URL = cfg.storageUrl;
84         PORT = toString cfg.port;
85         LOGLEVEL = cfg.logLevel;
86       } // cfg.extraSettings;
88       preStart = ''
89         # Generate the secret key used to sign client session tokens.
90         # Replacing it invalidates the previously established sessions.
91         if [ -z "$JWT_SECRET_KEY" ] && [ ! -f jwt_secret_key ]; then
92           (umask 077; touch jwt_secret_key)
93           cat /dev/urandom | tr -cd '[:alnum:]' | head -c 48 >> jwt_secret_key
94         fi
95       '';
97       script = ''
98         if [ -z "$JWT_SECRET_KEY" ]; then
99           export JWT_SECRET_KEY="$(cat jwt_secret_key)"
100         fi
102         ${cfg.package}/bin/rmfakecloud
103       '';
105       wantedBy = [ "multi-user.target" ];
106       wants = [ "network-online.target" ];
107       after = [ "network-online.target" ];
109       serviceConfig = {
110         Type = "simple";
111         Restart = "always";
113         EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
115         AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
117         DynamicUser = true;
118         PrivateDevices = true;
119         ProtectHome = true;
120         ProtectKernelTunables = true;
121         ProtectKernelModules = true;
122         ProtectControlGroups = true;
123         CapabilityBoundingSet = [ "" ];
124         DevicePolicy = "closed";
125         LockPersonality = true;
126         MemoryDenyWriteExecute = true;
127         ProtectClock = true;
128         ProtectHostname = true;
129         ProtectKernelLogs = true;
130         ProtectProc = "invisible";
131         ProcSubset = "pid";
132         RemoveIPC = true;
133         RestrictAddressFamilies = [
134           "AF_INET"
135           "AF_INET6"
136         ];
137         RestrictNamespaces = true;
138         RestrictRealtime = true;
139         RestrictSUIDSGID = true;
140         SystemCallArchitectures = "native";
141         WorkingDirectory = serviceDataDir;
142         StateDirectory = baseNameOf serviceDataDir;
143         UMask = "0027";
144       };
145     };
146   };
148   meta.maintainers = with lib.maintainers; [ pacien ];