at master 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 } 87 // cfg.extraSettings; 88 89 preStart = '' 90 # Generate the secret key used to sign client session tokens. 91 # Replacing it invalidates the previously established sessions. 92 if [ -z "$JWT_SECRET_KEY" ] && [ ! -f jwt_secret_key ]; then 93 (umask 077; touch jwt_secret_key) 94 cat /dev/urandom | tr -cd '[:alnum:]' | head -c 48 >> jwt_secret_key 95 fi 96 ''; 97 98 script = '' 99 if [ -z "$JWT_SECRET_KEY" ]; then 100 export JWT_SECRET_KEY="$(cat jwt_secret_key)" 101 fi 102 103 ${cfg.package}/bin/rmfakecloud 104 ''; 105 106 wantedBy = [ "multi-user.target" ]; 107 wants = [ "network-online.target" ]; 108 after = [ "network-online.target" ]; 109 110 serviceConfig = { 111 Type = "simple"; 112 Restart = "always"; 113 114 EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; 115 116 AmbientCapabilities = lib.mkIf (cfg.port < 1024) [ "CAP_NET_BIND_SERVICE" ]; 117 118 DynamicUser = true; 119 PrivateDevices = true; 120 ProtectHome = true; 121 ProtectKernelTunables = true; 122 ProtectKernelModules = true; 123 ProtectControlGroups = true; 124 CapabilityBoundingSet = [ "" ]; 125 DevicePolicy = "closed"; 126 LockPersonality = true; 127 MemoryDenyWriteExecute = true; 128 ProtectClock = true; 129 ProtectHostname = true; 130 ProtectKernelLogs = true; 131 ProtectProc = "invisible"; 132 ProcSubset = "pid"; 133 RemoveIPC = true; 134 RestrictAddressFamilies = [ 135 "AF_INET" 136 "AF_INET6" 137 ]; 138 RestrictNamespaces = true; 139 RestrictRealtime = true; 140 RestrictSUIDSGID = true; 141 SystemCallArchitectures = "native"; 142 WorkingDirectory = serviceDataDir; 143 StateDirectory = baseNameOf serviceDataDir; 144 UMask = "0027"; 145 }; 146 }; 147 }; 148 149 meta.maintainers = with lib.maintainers; [ euxane ]; 150}