at master 7.7 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 inherit (lib) types; 10 cfg = config.services.opencloud; 11 12 defaultUser = "opencloud"; 13 defaultGroup = defaultUser; 14 15 settingsFormat = pkgs.formats.yaml { }; 16in 17{ 18 options = { 19 services.opencloud = { 20 enable = lib.mkEnableOption "OpenCloud"; 21 22 package = lib.mkPackageOption pkgs "opencloud" { }; 23 webPackage = lib.mkPackageOption pkgs [ "opencloud" "web" ] { }; 24 idpWebPackage = lib.mkPackageOption pkgs [ "opencloud" "idp-web" ] { }; 25 26 user = lib.mkOption { 27 type = types.str; 28 default = defaultUser; 29 example = "mycloud"; 30 description = '' 31 The user to run OpenCloud as. 32 By default, a user named `${defaultUser}` will be created whose home 33 directory is [](#opt-services.opencloud.stateDir). 34 ''; 35 }; 36 37 group = lib.mkOption { 38 type = types.str; 39 default = defaultGroup; 40 example = "mycloud"; 41 description = '' 42 The group to run OpenCloud under. 43 By default, a group named `${defaultGroup}` will be created. 44 ''; 45 }; 46 47 address = lib.mkOption { 48 type = types.str; 49 default = "127.0.0.1"; 50 description = "Web server bind address."; 51 }; 52 53 port = lib.mkOption { 54 type = types.port; 55 default = 9200; 56 description = "Web server port."; 57 }; 58 59 url = lib.mkOption { 60 type = types.str; 61 default = "https://localhost:9200"; 62 example = "https://cloud.example.com"; 63 description = "Web interface root public URL, including scheme and port (if non-default)."; 64 }; 65 66 stateDir = lib.mkOption { 67 default = "/var/lib/opencloud"; 68 type = types.str; 69 description = "OpenCloud data directory."; 70 }; 71 72 settings = lib.mkOption { 73 type = lib.types.attrsOf settingsFormat.type; 74 default = { }; 75 description = '' 76 Additional YAML configuration for OpenCloud services. 77 78 Every item in this attrset will be mapped to a .yaml file in /etc/opencloud. 79 80 The possible config options are currently not well documented, see source code: 81 https://github.com/opencloud-eu/opencloud/blob/main/pkg/config/config.go 82 ''; 83 84 example = { 85 proxy = { 86 auto_provision_accounts = true; 87 oidc.rewrite_well_known = true; 88 role_assignment = { 89 driver = "oidc"; 90 oidc_role_mapper.role_claim = "opencloud_roles"; 91 }; 92 }; 93 web.web.config.oidc.scope = "openid profile email opencloud_roles"; 94 }; 95 }; 96 97 environmentFile = lib.mkOption { 98 type = types.nullOr types.path; 99 default = null; 100 example = "/run/keys/opencloud.env"; 101 description = '' 102 An environment file as defined in {manpage}`systemd.exec(5)`. 103 104 Use this to inject secrets, e.g. database or auth credentials out of band. 105 106 Configuration provided here will override `settings` and `environment`. 107 ''; 108 }; 109 110 environment = lib.mkOption { 111 type = types.attrsOf types.str; 112 default = { 113 OC_INSECURE = "true"; 114 }; 115 description = '' 116 Extra environment variables to set for the service. 117 118 Use this to set configuration that may affect multiple microservices. 119 120 Set `OC_INSECURE = "false"` if you want OpenCloud to terminate TLS. 121 122 Configuration provided here will override `settings`. 123 ''; 124 example = { 125 OC_INSECURE = "false"; 126 OC_LOG_LEVEL = "error"; 127 }; 128 }; 129 }; 130 }; 131 132 config = lib.mkIf cfg.enable { 133 users.users.${defaultUser} = lib.mkIf (cfg.user == defaultUser) { 134 group = cfg.group; 135 home = cfg.stateDir; 136 isSystemUser = true; 137 createHome = true; 138 description = "OpenCloud daemon user"; 139 }; 140 141 users.groups = lib.mkIf (cfg.group == defaultGroup) { ${defaultGroup} = { }; }; 142 143 systemd = { 144 services = 145 let 146 environment = { 147 PROXY_HTTP_ADDR = "${cfg.address}:${toString cfg.port}"; 148 OC_URL = cfg.url; 149 OC_BASE_DATA_PATH = cfg.stateDir; 150 WEB_ASSET_CORE_PATH = "${cfg.webPackage}"; 151 IDP_ASSET_PATH = "${cfg.idpWebPackage}/assets"; 152 OC_CONFIG_DIR = "/etc/opencloud"; 153 } 154 // cfg.environment; 155 commonServiceConfig = { 156 EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile; 157 MemoryDenyWriteExecute = true; 158 NoNewPrivileges = true; 159 PrivateTmp = true; 160 PrivateDevices = true; 161 ProtectSystem = "strict"; 162 ProtectHome = true; 163 ProtectControlGroups = true; 164 ProtectKernelModules = true; 165 ProtectKernelTunables = true; 166 ProtectKernelLogs = true; 167 RestrictAddressFamilies = [ 168 "AF_UNIX" 169 "AF_INET" 170 "AF_INET6" 171 ]; 172 RestrictNamespaces = true; 173 RestrictRealtime = true; 174 RestrictSUIDSGID = true; 175 LockPersonality = true; 176 SystemCallArchitectures = "native"; 177 }; 178 in 179 { 180 opencloud-init-config = lib.mkIf (cfg.settings.opencloud or { } == { }) { 181 description = "Provision initial OpenCloud config"; 182 before = [ "opencloud.service" ]; 183 wantedBy = [ "multi-user.target" ]; 184 185 inherit environment; 186 187 serviceConfig = { 188 Type = "oneshot"; 189 ReadWritePaths = [ "/etc/opencloud" ]; 190 } 191 // commonServiceConfig; 192 193 path = [ cfg.package ]; 194 script = '' 195 set -x 196 config="''${OC_CONFIG_DIR}/opencloud.yaml" 197 if [ ! -e "$config" ]; then 198 echo "Provisioning initial OpenCloud config..." 199 opencloud init --insecure "''${OC_INSECURE:false}" --config-path "''${OC_CONFIG_DIR}" 200 chown ${cfg.user}:${cfg.group} "$config" 201 fi 202 ''; 203 }; 204 205 opencloud = { 206 description = "OpenCloud - a secure and private way to store, access, and share your files"; 207 after = [ "network.target" ]; 208 wantedBy = [ "multi-user.target" ]; 209 210 inherit environment; 211 212 serviceConfig = { 213 Type = "simple"; 214 ExecStart = "${lib.getExe cfg.package} server"; 215 WorkingDirectory = cfg.stateDir; 216 User = cfg.user; 217 Group = cfg.group; 218 Restart = "always"; 219 ReadWritePaths = [ cfg.stateDir ]; 220 } 221 // commonServiceConfig; 222 223 restartTriggers = lib.mapAttrsToList ( 224 name: _: config.environment.etc."opencloud/${name}.yaml".source 225 ) cfg.settings; 226 }; 227 }; 228 }; 229 230 systemd.tmpfiles.settings."10-opencloud" = { 231 ${cfg.stateDir}.d = { 232 inherit (cfg) user group; 233 mode = "0750"; 234 }; 235 "${cfg.stateDir}/idm".d = { 236 inherit (cfg) user group; 237 mode = "0750"; 238 }; 239 }; 240 241 environment.etc = 242 (lib.mapAttrs' (name: value: { 243 name = "opencloud/${name}.yaml"; 244 value.source = settingsFormat.generate "${name}.yaml" value; 245 }) cfg.settings) 246 // { 247 # ensure /etc/opencloud gets created, so we can provision the config 248 "opencloud/.keep".text = ""; 249 }; 250 }; 251 252 meta = { 253 doc = ./opencloud.md; 254 maintainers = with lib.maintainers; [ 255 christoph-heiss 256 k900 257 ]; 258 }; 259}