Skip to content

Commit b504cc1

Browse files
K900christoph-heiss
andcommitted
nixos/opencloud: init module
Co-authored-by: Christoph Heiss <[email protected]>
1 parent 3c20fdf commit b504cc1

File tree

7 files changed

+426
-0
lines changed

7 files changed

+426
-0
lines changed

nixos/doc/manual/redirects.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@
5050
"module-services-crab-hole-upstream-options": [
5151
"index.html#module-services-crab-hole-upstream-options"
5252
],
53+
"module-services-opencloud": [
54+
"index.html#module-services-opencloud"
55+
],
56+
"module-services-opencloud-basic-usage": [
57+
"index.html#module-services-opencloud-basic-usage"
58+
],
5359
"module-services-strfry": [
5460
"index.html#module-services-strfry"
5561
],

nixos/doc/manual/release-notes/rl-2505.section.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ Alongside many enhancements to NixOS modules and general system improvements, th
200200

201201
- [`g3proxy`](https://github.com/bytedance/g3), an open source enterprise forward proxy from ByteDance, similar to Squid or tinyproxy. Available as [services.g3proxy](#opt-services.g3proxy.enable).
202202

203+
- [OpenCloud](https://opencloud.eu/), an open-source, modern file-sync and sharing platform. It is a fork of oCIS, a ground-up rewrite of the well-known PHP-based NextCloud server. Available as [services.opencloud](#opt-services.opencloud.enable).
204+
203205
- [echoip](https://github.com/mpolden/echoip), a simple service for looking up your IP address. Available as [services.echoip](#opt-services.echoip.enable).
204206

205207
- [whoami](https://github.com/traefik/whoami), a tiny Go server that prints OS information and HTTP request to output. Available as [services.whoami](#opt-services.whoami.enable).

nixos/modules/module-list.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,7 @@
16101610
./services/web-apps/oncall.nix
16111611
./services/web-apps/onlyoffice.nix
16121612
./services/web-apps/open-web-calendar.nix
1613+
./services/web-apps/opencloud.nix
16131614
./services/web-apps/openvscode-server.nix
16141615
./services/web-apps/openwebrx.nix
16151616
./services/web-apps/outline.nix
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# OpenCloud {#module-services-opencloud}
2+
3+
[OpenCloud](https://opencloud.eu/en) is an open-source, modern file-sync and
4+
sharing platform. It is a fork of oCIS, a ground-up rewrite of the well-known
5+
PHP-based NextCloud server.
6+
7+
The service can be configured using a combination of [](#opt-services.opencloud.settings),
8+
[](#opt-services.opencloud.environment) and [](#opt-services.opencloud.environmentFile).
9+
10+
## Basic usage {#module-services-opencloud-basic-usage}
11+
12+
OpenCloud is configured using a combination of YAML and environment
13+
variables. The full documentation can be found at
14+
[OpenCloud Admin Docs](https://docs.opencloud.eu/docs/admin/intro).
15+
16+
The general flow of configuring OpenCloud is:
17+
- configure services with `services.opencloud.settings.<service>` when possible
18+
- configure global settings that affect multiple services via `services.opencloud.environment`
19+
- allow NixOS to provision a default `opencloud.yaml` for you, containing default credentials
20+
for communication between the microservices
21+
- provide additional secrets via `environmentFile`, provisioned out of band
22+
23+
Please note that current NixOS module for OpenCloud is configured to run in
24+
`fullstack` mode, which starts all the services for OpenCloud in a single
25+
instance, in so called supervised mode. This will start multiple OpenCloud
26+
services and listen on multiple other ports.
27+
28+
Current known services and their ports are as below:
29+
30+
| Service | Group | Port |
31+
|--------------------|---------|-------|
32+
| gateway | api | 9142 |
33+
| sharing | api | 9150 |
34+
| app-registry | api | 9242 |
35+
| ocdav | web | 45023 |
36+
| auth-machine | api | 9166 |
37+
| storage-system | api | 9215 |
38+
| webdav | web | 9115 |
39+
| webfinger | web | 46871 |
40+
| storage-system | web | 9216 |
41+
| web | web | 9100 |
42+
| eventhistory | api | 33177 |
43+
| ocs | web | 9110 |
44+
| storage-publiclink | api | 9178 |
45+
| settings | web | 9190 |
46+
| ocm | api | 9282 |
47+
| settings | api | 9191 |
48+
| ocm | web | 9280 |
49+
| app-provider | api | 9164 |
50+
| storage-users | api | 9157 |
51+
| auth-service | api | 9199 |
52+
| thumbnails | web | 9186 |
53+
| thumbnails | api | 9185 |
54+
| storage-shares | api | 9154 |
55+
| sse | sse | 46833 |
56+
| userlog | userlog | 45363 |
57+
| search | api | 9220 |
58+
| proxy | web | 9200 |
59+
| idp | web | 9130 |
60+
| frontend | web | 9140 |
61+
| groups | api | 9160 |
62+
| graph | graph | 9120 |
63+
| users | api | 9144 |
64+
| auth-basic | api | 9146 |
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
{
2+
config,
3+
lib,
4+
pkgs,
5+
...
6+
}:
7+
8+
let
9+
inherit (lib) types;
10+
cfg = config.services.opencloud;
11+
12+
defaultUser = "opencloud";
13+
defaultGroup = defaultUser;
14+
15+
settingsFormat = pkgs.formats.yaml { };
16+
in
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+
85+
environmentFile = lib.mkOption {
86+
type = types.nullOr types.path;
87+
default = null;
88+
example = "/run/keys/opencloud.env";
89+
description = ''
90+
An environment file as defined in {manpage}`systemd.exec(5)`.
91+
92+
Use this to inject secrets, e.g. database or auth credentials out of band.
93+
94+
Configuration provided here will override `settings` and `environment`.
95+
'';
96+
};
97+
98+
environment = lib.mkOption {
99+
type = types.attrsOf types.str;
100+
default = {
101+
OC_INSECURE = "true";
102+
};
103+
description = ''
104+
Extra environment variables to set for the service.
105+
106+
Use this to set configuration that may affect multiple microservices.
107+
108+
Configuration provided here will override `settings`.
109+
'';
110+
example = {
111+
OC_INSECURE = "false";
112+
OC_LOG_LEVEL = "error";
113+
};
114+
};
115+
};
116+
};
117+
118+
config = lib.mkIf cfg.enable {
119+
users.users.${defaultUser} = lib.mkIf (cfg.user == defaultUser) {
120+
group = cfg.group;
121+
home = cfg.stateDir;
122+
isSystemUser = true;
123+
createHome = true;
124+
description = "OpenCloud daemon user";
125+
};
126+
127+
users.groups = lib.mkIf (cfg.group == defaultGroup) { ${defaultGroup} = { }; };
128+
129+
systemd = {
130+
services =
131+
let
132+
environment = {
133+
PROXY_HTTP_ADDR = "${cfg.address}:${toString cfg.port}";
134+
OC_URL = cfg.url;
135+
OC_BASE_DATA_PATH = cfg.stateDir;
136+
WEB_ASSET_CORE_PATH = "${cfg.webPackage}";
137+
IDP_ASSET_PATH = "${cfg.idpWebPackage}/assets";
138+
OC_CONFIG_DIR = "/etc/opencloud";
139+
} // cfg.environment;
140+
commonServiceConfig = {
141+
EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile;
142+
MemoryDenyWriteExecute = true;
143+
NoNewPrivileges = true;
144+
PrivateTmp = true;
145+
PrivateDevices = true;
146+
ProtectSystem = "strict";
147+
ProtectHome = true;
148+
ProtectControlGroups = true;
149+
ProtectKernelModules = true;
150+
ProtectKernelTunables = true;
151+
ProtectKernelLogs = true;
152+
RestrictAddressFamilies = [
153+
"AF_UNIX"
154+
"AF_INET"
155+
"AF_INET6"
156+
];
157+
RestrictNamespaces = true;
158+
RestrictRealtime = true;
159+
RestrictSUIDSGID = true;
160+
LockPersonality = true;
161+
SystemCallArchitectures = "native";
162+
};
163+
in
164+
{
165+
opencloud-init-config = lib.mkIf (cfg.settings.opencloud or { } == { }) {
166+
description = "Provision initial OpenCloud config";
167+
before = [ "opencloud.service" ];
168+
wantedBy = [ "multi-user.target" ];
169+
170+
inherit environment;
171+
172+
serviceConfig = {
173+
Type = "oneshot";
174+
ReadWritePaths = [ "/etc/opencloud" ];
175+
} // commonServiceConfig;
176+
177+
path = [ cfg.package ];
178+
script = ''
179+
set -x
180+
config="''${OC_CONFIG_DIR}/opencloud.yaml"
181+
if [ ! -e "$config" ]; then
182+
echo "Provisioning initial OpenCloud config..."
183+
opencloud init --insecure "''${OC_INSECURE:false}" --config-path "''${OC_CONFIG_DIR}"
184+
chown ${cfg.user}:${cfg.group} "$config"
185+
fi
186+
'';
187+
};
188+
189+
opencloud = {
190+
description = "OpenCloud - a secure and private way to store, access, and share your files";
191+
after = [ "network.target" ];
192+
wantedBy = [ "multi-user.target" ];
193+
194+
inherit environment;
195+
196+
serviceConfig = {
197+
Type = "simple";
198+
ExecStart = "${lib.getExe cfg.package} server";
199+
WorkingDirectory = cfg.stateDir;
200+
User = cfg.user;
201+
Group = cfg.group;
202+
Restart = "always";
203+
ReadWritePaths = [ cfg.stateDir ];
204+
} // commonServiceConfig;
205+
206+
restartTriggers = lib.mapAttrsToList (
207+
name: _: config.environment.etc."opencloud/${name}.yaml".source
208+
) cfg.settings;
209+
};
210+
};
211+
};
212+
213+
systemd.tmpfiles.settings."10-opencloud" = {
214+
${cfg.stateDir}.d = {
215+
inherit (cfg) user group;
216+
mode = "0750";
217+
};
218+
"${cfg.stateDir}/idm".d = {
219+
inherit (cfg) user group;
220+
mode = "0750";
221+
};
222+
};
223+
224+
environment.etc =
225+
(lib.mapAttrs' (name: value: {
226+
name = "opencloud/${name}.yaml";
227+
value.source = settingsFormat.generate "${name}.yaml" value;
228+
}) cfg.settings)
229+
// {
230+
# ensure /etc/opencloud gets created, so we can provision the config
231+
"opencloud/.keep".text = "";
232+
};
233+
};
234+
235+
meta = {
236+
doc = ./opencloud.md;
237+
maintainers = with lib.maintainers; [
238+
christoph-heiss
239+
k900
240+
];
241+
};
242+
}

nixos/tests/all-tests.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,7 @@ in
975975
ombi = handleTest ./ombi.nix { };
976976
openarena = handleTest ./openarena.nix { };
977977
openbao = runTest ./openbao.nix;
978+
opencloud = runTest ./opencloud.nix;
978979
openldap = handleTest ./openldap.nix { };
979980
opensearch = discoverTests (import ./opensearch.nix);
980981
openresty-lua = handleTest ./openresty-lua.nix { };

0 commit comments

Comments
 (0)