at 25.11-pre 4.1 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.rmfakecloud; 9 serviceDataDir = "/var/lib/rmfakecloud"; 10 11in 12{ 13 options = { 14 services.rmfakecloud = { 15 enable = lib.mkEnableOption "rmfakecloud remarkable self-hosted cloud"; 16 17 package = lib.mkPackageOption pkgs "rmfakecloud" { }; 18 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 }; 26 27 port = lib.mkOption { 28 type = lib.types.port; 29 default = 3000; 30 description = '' 31 Listening port number. 32 ''; 33 }; 34 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 }; 47 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. 57 58 Available settings are listed on 59 https://ddvk.github.io/rmfakecloud/install/configuration/. 60 ''; 61 }; 62 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. 69 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 }; 77 78 config = lib.mkIf cfg.enable { 79 systemd.services.rmfakecloud = { 80 description = "rmfakecloud remarkable self-hosted cloud"; 81 82 environment = { 83 STORAGE_URL = cfg.storageUrl; 84 PORT = toString cfg.port; 85 LOGLEVEL = cfg.logLevel; 86 } // cfg.extraSettings; 87 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 ''; 96 97 script = '' 98 if [ -z "$JWT_SECRET_KEY" ]; then 99 export JWT_SECRET_KEY="$(cat jwt_secret_key)" 100 fi 101 102 ${cfg.package}/bin/rmfakecloud 103 ''; 104 105 wantedBy = [ "multi-user.target" ]; 106 wants = [ "network-online.target" ]; 107 after = [ "network-online.target" ]; 108 109 serviceConfig = { 110 Type = "simple"; 111 Restart = "always"; 112 113 EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; 114 115 AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; 116 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 }; 147 148 meta.maintainers = with lib.maintainers; [ euxane ]; 149}