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