756 lines
26 KiB
Nix
756 lines
26 KiB
Nix
{
|
|
description = "Nextcloud";
|
|
|
|
inputs.nixpkgs.url = "nixpkgs/nixos-unstable";
|
|
|
|
outputs = inputs: {
|
|
nixosModules.default =
|
|
{
|
|
config,
|
|
lib,
|
|
options,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
inherit (lib)
|
|
concatStringsSep
|
|
hasAttrByPath
|
|
mkEnableOption
|
|
mkIf
|
|
mkMerge
|
|
mkOption
|
|
optional
|
|
optionalAttrs
|
|
setAttrByPath
|
|
types
|
|
unique
|
|
;
|
|
|
|
cfg = config.custom.nextcloud;
|
|
|
|
nextcloudUrl = "https://${cfg.hostName}";
|
|
whiteboardUrl =
|
|
if cfg.addons.whiteboard.externalUrl != null then
|
|
cfg.addons.whiteboard.externalUrl
|
|
else
|
|
"https://${cfg.addons.whiteboard.hostName}";
|
|
euroofficeUrl =
|
|
if cfg.addons.eurooffice.externalUrl != null then
|
|
cfg.addons.eurooffice.externalUrl
|
|
else
|
|
"https://${cfg.addons.eurooffice.hostName}";
|
|
|
|
appSet = cfg.package.packages.apps;
|
|
packagedAppNames = unique (
|
|
cfg.addons.apps
|
|
++ optional cfg.useAuthentikSSO "user_oidc"
|
|
++ optional cfg.addons.whiteboard.enable "whiteboard"
|
|
);
|
|
packagedApps = lib.genAttrs packagedAppNames (
|
|
name:
|
|
if builtins.hasAttr name appSet then
|
|
builtins.getAttr name appSet
|
|
else
|
|
throw "custom.nextcloud: Nextcloud app '${name}' is not packaged for ${
|
|
cfg.package.name or "the selected Nextcloud package"
|
|
}"
|
|
);
|
|
|
|
euroofficeApp = pkgs.fetchNextcloudApp {
|
|
url = cfg.addons.eurooffice.app.url;
|
|
hash = cfg.addons.eurooffice.app.hash;
|
|
license = cfg.addons.eurooffice.app.license;
|
|
};
|
|
|
|
allExtraApps =
|
|
packagedApps
|
|
// optionalAttrs cfg.addons.eurooffice.enable {
|
|
eurooffice = euroofficeApp;
|
|
}
|
|
// cfg.addons.extraApps;
|
|
|
|
nginxTls = {
|
|
forceSSL = cfg.nginx.forceSSL;
|
|
enableACME = cfg.nginx.enableACME;
|
|
useACMEHost = cfg.nginx.useACMEHost;
|
|
};
|
|
|
|
publicProxyTarget =
|
|
if cfg.anubis.enable then
|
|
"http://${cfg.bindAddress}:${toString cfg.anubis.port}"
|
|
else
|
|
"http://${cfg.bindAddress}:${toString cfg.rawPort}";
|
|
|
|
authentikDiscoveryUrl =
|
|
if cfg.authentik.discoveryUrl != null then
|
|
cfg.authentik.discoveryUrl
|
|
else
|
|
"https://${cfg.authentik.hostName}/application/o/${cfg.authentik.applicationSlug}/.well-known/openid-configuration";
|
|
|
|
authentikBlueprint = ''
|
|
version: 1
|
|
metadata:
|
|
name: Nextcloud
|
|
labels:
|
|
blueprints.goauthentik.io/instantiate: "true"
|
|
|
|
entries:
|
|
- model: authentik_core.group
|
|
identifiers:
|
|
name: ${cfg.authentik.groupName}
|
|
attrs:
|
|
is_superuser: false
|
|
|
|
- model: authentik_providers_oauth2.oauth2provider
|
|
identifiers:
|
|
name: ${cfg.authentik.providerName}
|
|
attrs:
|
|
name: ${cfg.authentik.providerName}
|
|
client_type: confidential
|
|
client_id: ${cfg.authentik.clientId}
|
|
client_secret: !Env ${cfg.authentik.blueprint.secretEnvName}
|
|
grant_types:
|
|
- authorization_code
|
|
- refresh_token
|
|
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
|
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
|
redirect_uris:
|
|
- matching_mode: strict
|
|
url: ${nextcloudUrl}/apps/user_oidc/code
|
|
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
|
property_mappings:
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
|
|
|
|
- model: authentik_core.application
|
|
identifiers:
|
|
slug: ${cfg.authentik.applicationSlug}
|
|
attrs:
|
|
name: Nextcloud
|
|
slug: ${cfg.authentik.applicationSlug}
|
|
provider: !Find [authentik_providers_oauth2.oauth2provider, [name, ${cfg.authentik.providerName}]]
|
|
|
|
- model: authentik_policies.policybinding
|
|
identifiers:
|
|
target: !Find [authentik_core.application, [slug, ${cfg.authentik.applicationSlug}]]
|
|
group: !Find [authentik_core.group, [name, ${cfg.authentik.groupName}]]
|
|
order: 0
|
|
attrs:
|
|
enabled: true
|
|
'';
|
|
|
|
whiteboardModuleAvailable = hasAttrByPath [ "services" "nextcloud-whiteboard-server" ] options;
|
|
anubisModuleAvailable = hasAttrByPath [ "services" "anubis" "instances" ] options;
|
|
authentikTargetAvailable = hasAttrByPath cfg.authentik.blueprint.targetOption options;
|
|
|
|
whiteboardStart = pkgs.writeShellScript "nextcloud-whiteboard-with-secret" ''
|
|
set -euo pipefail
|
|
export JWT_SECRET_KEY="$(<"$CREDENTIALS_DIRECTORY/jwt")"
|
|
exec ${lib.getExe pkgs.nextcloud-whiteboard-server}
|
|
'';
|
|
|
|
configScript = pkgs.writeShellScript "nextcloud-stack-config" ''
|
|
set -euo pipefail
|
|
|
|
OCC=${lib.escapeShellArg "${config.services.nextcloud.occ}/bin/nextcloud-occ"}
|
|
|
|
"$OCC" config:app:set files default_quota --value ${lib.escapeShellArg cfg.defaultQuota}
|
|
|
|
${lib.optionalString cfg.addons.whiteboard.enable ''
|
|
jwt_secret="$(<"$CREDENTIALS_DIRECTORY/jwt")"
|
|
"$OCC" config:app:set whiteboard collabBackendUrl --value=${lib.escapeShellArg "${whiteboardUrl}/"}
|
|
"$OCC" config:app:set whiteboard jwt_secret_key --value="$jwt_secret"
|
|
''}
|
|
|
|
${lib.optionalString cfg.addons.eurooffice.enable ''
|
|
jwt_secret="$(<"$CREDENTIALS_DIRECTORY/jwt")"
|
|
"$OCC" config:app:set eurooffice StorageUrl --value=${lib.escapeShellArg "${nextcloudUrl}/"}
|
|
"$OCC" config:app:set eurooffice DocumentServerUrl --value=${lib.escapeShellArg "${euroofficeUrl}/"}
|
|
"$OCC" config:app:set eurooffice jwt_secret --value="$jwt_secret"
|
|
"$OCC" config:app:set eurooffice jwt_header --value=${lib.escapeShellArg cfg.addons.eurooffice.jwtHeader}
|
|
"$OCC" config:app:set eurooffice editFormats --value=${lib.escapeShellArg cfg.addons.eurooffice.editFormats}
|
|
''}
|
|
|
|
${lib.optionalString cfg.useAuthentikSSO ''
|
|
oidc_secret="$(<"$CREDENTIALS_DIRECTORY/oidc")"
|
|
"$OCC" user_oidc:provider ${lib.escapeShellArg cfg.authentik.providerName} \
|
|
--clientid=${lib.escapeShellArg cfg.authentik.clientId} \
|
|
--clientsecret="$oidc_secret" \
|
|
--discoveryuri=${lib.escapeShellArg authentikDiscoveryUrl} \
|
|
--unique-uid=${if cfg.authentik.uniqueUid then "1" else "0"}
|
|
''}
|
|
|
|
${concatStringsSep "\n" cfg.addons.occCommands}
|
|
'';
|
|
in
|
|
{
|
|
options.custom.nextcloud = {
|
|
enable = mkEnableOption "Nextcloud";
|
|
|
|
hostName = mkOption {
|
|
type = types.str;
|
|
description = "Public Nextcloud hostname.";
|
|
example = "cloud.example.com";
|
|
};
|
|
|
|
bindAddress = mkOption {
|
|
type = types.str;
|
|
default = "127.0.0.1";
|
|
description = "Loopback address used by internal services.";
|
|
};
|
|
|
|
rawPort = mkOption {
|
|
type = types.port;
|
|
default = 5003;
|
|
description = "Port for the raw Nextcloud nginx vhost.";
|
|
};
|
|
|
|
package = mkOption {
|
|
type = types.package;
|
|
default = pkgs.nextcloud34;
|
|
defaultText = lib.literalExpression "pkgs.nextcloud34";
|
|
description = "Nextcloud package.";
|
|
};
|
|
|
|
adminUser = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "admin";
|
|
description = "Initial admin username. Set to null to disable initial admin creation on Nextcloud 32+.";
|
|
};
|
|
|
|
maxUploadSize = mkOption {
|
|
type = types.str;
|
|
default = "1G";
|
|
};
|
|
|
|
defaultQuota = mkOption {
|
|
type = types.str;
|
|
default = "10 GB";
|
|
};
|
|
|
|
appstoreEnable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = types.attrs;
|
|
default = { };
|
|
description = "Extra services.nextcloud.settings values.";
|
|
};
|
|
|
|
useAuthentikSSO = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Configure the user_oidc app for Authentik.";
|
|
};
|
|
|
|
secrets = {
|
|
adminPasswordFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "Runtime file containing the initial Nextcloud admin password.";
|
|
};
|
|
|
|
jwtFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "Runtime file containing the shared JWT secret for addons.";
|
|
};
|
|
|
|
oidcClientSecretFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "Runtime file containing the Authentik OIDC client secret.";
|
|
};
|
|
|
|
nextcloud = mkOption {
|
|
type = types.attrsOf types.str;
|
|
default = { };
|
|
description = "Extra secret config.php entries passed to services.nextcloud.secrets.";
|
|
};
|
|
};
|
|
|
|
database = {
|
|
type = mkOption {
|
|
type = types.enum [
|
|
"mysql"
|
|
"pgsql"
|
|
"sqlite"
|
|
];
|
|
default = "mysql";
|
|
};
|
|
|
|
createLocally = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
|
|
name = mkOption {
|
|
type = types.str;
|
|
default = "nextcloud";
|
|
};
|
|
|
|
user = mkOption {
|
|
type = types.str;
|
|
default = "nextcloud";
|
|
};
|
|
|
|
host = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "Database host. Leave null when createLocally is true.";
|
|
};
|
|
|
|
passwordFile = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
};
|
|
|
|
nginx = {
|
|
forceSSL = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
|
|
enableACME = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
|
|
useACMEHost = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "example.com";
|
|
};
|
|
|
|
extraPublicConfig = mkOption {
|
|
type = types.lines;
|
|
default = "";
|
|
};
|
|
};
|
|
|
|
anubis = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 7003;
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = types.attrs;
|
|
default = { };
|
|
};
|
|
};
|
|
|
|
authentik = {
|
|
hostName = mkOption {
|
|
type = types.str;
|
|
default = "auth.example.com";
|
|
};
|
|
|
|
discoveryUrl = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
|
|
clientId = mkOption {
|
|
type = types.str;
|
|
default = "nextcloud";
|
|
};
|
|
|
|
providerName = mkOption {
|
|
type = types.str;
|
|
default = "Authentik";
|
|
};
|
|
|
|
applicationSlug = mkOption {
|
|
type = types.str;
|
|
default = "nextcloud";
|
|
};
|
|
|
|
groupName = mkOption {
|
|
type = types.str;
|
|
default = "nextcloud-users";
|
|
};
|
|
|
|
uniqueUid = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
|
|
hideLoginForm = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
|
|
blueprint = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Generate an Authentik blueprint under /etc/nextcloud.";
|
|
};
|
|
|
|
autoAttach = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Also attach the blueprint to targetOption when that option exists.";
|
|
};
|
|
|
|
targetOption = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [
|
|
"methanium"
|
|
"authentik"
|
|
"blueprints"
|
|
"nextcloud"
|
|
];
|
|
};
|
|
|
|
secretEnvName = mkOption {
|
|
type = types.str;
|
|
default = "NEXTCLOUD_OIDC_SECRET";
|
|
};
|
|
};
|
|
};
|
|
|
|
addons = {
|
|
apps = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [
|
|
"mail"
|
|
"deck"
|
|
];
|
|
description = "App names from the selected Nextcloud package app set.";
|
|
};
|
|
|
|
extraApps = mkOption {
|
|
type = types.attrsOf types.package;
|
|
default = { };
|
|
description = "Additional app packages merged into services.nextcloud.extraApps.";
|
|
};
|
|
|
|
occCommands = mkOption {
|
|
type = types.listOf types.lines;
|
|
default = [ ];
|
|
description = "Extra idempotent shell commands run after nextcloud-setup.";
|
|
};
|
|
|
|
whiteboard = {
|
|
enable = mkEnableOption "Nextcloud Whiteboard";
|
|
|
|
hostName = mkOption {
|
|
type = types.str;
|
|
default = "whiteboard.example.com";
|
|
};
|
|
|
|
externalUrl = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "External Whiteboard URL. Defaults to https://hostName.";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 5004;
|
|
};
|
|
|
|
nginx.enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
|
|
disableRecording = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Apply the custom DISABLE_RECORDING patch from the original configuration.";
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = types.attrsOf types.str;
|
|
default = { };
|
|
};
|
|
};
|
|
|
|
eurooffice = {
|
|
enable = mkEnableOption "EuroOffice document server integration";
|
|
|
|
hostName = mkOption {
|
|
type = types.str;
|
|
default = "office.example.com";
|
|
};
|
|
|
|
externalUrl = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = "External EuroOffice URL. Defaults to https://hostName.";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 5005;
|
|
};
|
|
|
|
nginx.enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
};
|
|
|
|
image = mkOption {
|
|
type = types.str;
|
|
default = "ghcr.io/euro-office/documentserver:latest";
|
|
};
|
|
|
|
jwtHeader = mkOption {
|
|
type = types.str;
|
|
default = "Authorization";
|
|
};
|
|
|
|
editFormats = mkOption {
|
|
type = types.str;
|
|
default = ''{"docm":true,"docx":true,"dotm":true,"dotx":true,"xlsm":true,"xlsx":true,"pptm":true,"pptx":true,"pdf":true}'';
|
|
};
|
|
|
|
environment = mkOption {
|
|
type = types.attrsOf types.str;
|
|
default = { };
|
|
};
|
|
|
|
app = {
|
|
url = mkOption {
|
|
type = types.str;
|
|
default = "https://github.com/nextcloud-releases/eurooffice/releases/download/v11.0.1/eurooffice-v11.0.1.tar.gz";
|
|
};
|
|
|
|
hash = mkOption {
|
|
type = types.str;
|
|
default = "sha256-HXpvyCNhlxAvrxSEu6/5u0mpg7TrTsaS2gii9mf74ns=";
|
|
};
|
|
|
|
license = mkOption {
|
|
type = types.str;
|
|
default = "asl20";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable (mkMerge [
|
|
{
|
|
assertions = [
|
|
{
|
|
assertion = cfg.adminUser == null || cfg.secrets.adminPasswordFile != null;
|
|
message = "custom.nextcloud.secrets.adminPasswordFile is required when adminUser is not null.";
|
|
}
|
|
{
|
|
assertion =
|
|
!(cfg.addons.whiteboard.enable || cfg.addons.eurooffice.enable) || cfg.secrets.jwtFile != null;
|
|
message = "custom.nextcloud.secrets.jwtFile is required by Whiteboard and EuroOffice.";
|
|
}
|
|
{
|
|
assertion = !cfg.useAuthentikSSO || cfg.secrets.oidcClientSecretFile != null;
|
|
message = "custom.nextcloud.secrets.oidcClientSecretFile is required when useAuthentikSSO is true.";
|
|
}
|
|
{
|
|
assertion = !cfg.addons.whiteboard.enable || whiteboardModuleAvailable;
|
|
message = "The selected nixpkgs does not provide services.nextcloud-whiteboard-server.";
|
|
}
|
|
{
|
|
assertion = !cfg.anubis.enable || anubisModuleAvailable;
|
|
message = "The selected nixpkgs does not provide services.anubis.instances.";
|
|
}
|
|
{
|
|
assertion = !cfg.authentik.blueprint.enable || cfg.useAuthentikSSO;
|
|
message = "authentik.blueprint.enable requires useAuthentikSSO = true.";
|
|
}
|
|
];
|
|
|
|
services.nextcloud = {
|
|
enable = true;
|
|
package = cfg.package;
|
|
hostName = "raw-" + cfg.hostName;
|
|
appstoreEnable = cfg.appstoreEnable;
|
|
maxUploadSize = cfg.maxUploadSize;
|
|
configureRedis = true;
|
|
|
|
database.createLocally = cfg.database.createLocally;
|
|
|
|
config = {
|
|
adminuser = cfg.adminUser;
|
|
adminpassFile = cfg.secrets.adminPasswordFile;
|
|
dbtype = cfg.database.type;
|
|
dbname = cfg.database.name;
|
|
dbuser = cfg.database.user;
|
|
}
|
|
// optionalAttrs (cfg.database.host != null) {
|
|
dbhost = cfg.database.host;
|
|
}
|
|
// optionalAttrs (cfg.database.passwordFile != null) {
|
|
dbpassFile = cfg.database.passwordFile;
|
|
};
|
|
|
|
https = true;
|
|
|
|
settings = mkMerge [
|
|
{
|
|
trusted_domains = [ cfg.hostName ];
|
|
trusted_proxies = unique [
|
|
cfg.bindAddress
|
|
"127.0.0.1"
|
|
"::1"
|
|
];
|
|
overwritehost = cfg.hostName;
|
|
overwriteprotocol = "https";
|
|
}
|
|
(mkIf cfg.useAuthentikSSO {
|
|
hide_login_form = cfg.authentik.hideLoginForm;
|
|
})
|
|
cfg.settings
|
|
];
|
|
|
|
secrets = cfg.secrets.nextcloud;
|
|
extraAppsEnable = true;
|
|
extraApps = allExtraApps;
|
|
};
|
|
|
|
services.nginx.virtualHosts.${"raw-" + cfg.hostName}.listen = lib.mkForce [
|
|
{
|
|
addr = cfg.bindAddress;
|
|
port = cfg.rawPort;
|
|
}
|
|
];
|
|
|
|
services.nginx.virtualHosts.${cfg.hostName} = nginxTls // {
|
|
extraConfig = cfg.nginx.extraPublicConfig;
|
|
locations."/" = {
|
|
proxyPass = publicProxyTarget;
|
|
proxyWebsockets = true;
|
|
};
|
|
};
|
|
|
|
systemd.services.nextcloud-stack-config = {
|
|
description = "Declarative Nextcloud stack configuration";
|
|
after = [ "nextcloud-setup.service" ];
|
|
requires = [ "nextcloud-setup.service" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
restartTriggers = [ configScript ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
User = "nextcloud";
|
|
LoadCredential =
|
|
optional (cfg.secrets.jwtFile != null) "jwt:${cfg.secrets.jwtFile}"
|
|
++ optional (cfg.secrets.oidcClientSecretFile != null) "oidc:${cfg.secrets.oidcClientSecretFile}"
|
|
++ optional (cfg.database.passwordFile != null) "dbpass:${cfg.database.passwordFile}"
|
|
++ lib.mapAttrsToList (name: path: "${name}:${path}") cfg.secrets.nextcloud;
|
|
ExecStart = configScript;
|
|
};
|
|
};
|
|
}
|
|
|
|
(mkIf (cfg.anubis.enable && anubisModuleAvailable) {
|
|
services.anubis.instances.nextcloud.settings = {
|
|
BIND = "${cfg.bindAddress}:${toString cfg.anubis.port}";
|
|
TARGET = "http://${cfg.bindAddress}:${toString cfg.rawPort}";
|
|
}
|
|
// cfg.anubis.settings;
|
|
})
|
|
|
|
(mkIf (cfg.addons.whiteboard.enable && whiteboardModuleAvailable) {
|
|
services.nextcloud-whiteboard-server = {
|
|
enable = true;
|
|
secrets = [ ];
|
|
settings = {
|
|
NEXTCLOUD_URL = nextcloudUrl;
|
|
HOST = cfg.bindAddress;
|
|
PORT = toString cfg.addons.whiteboard.port;
|
|
}
|
|
// cfg.addons.whiteboard.settings;
|
|
};
|
|
|
|
systemd.services.nextcloud-whiteboard-server.serviceConfig = {
|
|
LoadCredential = optional (cfg.secrets.jwtFile != null) "jwt:${cfg.secrets.jwtFile}";
|
|
ExecStart = lib.mkForce whiteboardStart;
|
|
};
|
|
})
|
|
|
|
(mkIf (cfg.addons.whiteboard.enable && cfg.addons.whiteboard.nginx.enable) {
|
|
services.nginx.virtualHosts.${cfg.addons.whiteboard.hostName} = nginxTls // {
|
|
locations."/" = {
|
|
proxyPass = "http://${cfg.bindAddress}:${toString cfg.addons.whiteboard.port}";
|
|
proxyWebsockets = true;
|
|
};
|
|
};
|
|
})
|
|
|
|
(mkIf (cfg.addons.whiteboard.enable && cfg.addons.whiteboard.disableRecording) {
|
|
nixpkgs.overlays = [
|
|
(final: prev: {
|
|
nextcloud-whiteboard-server = prev.nextcloud-whiteboard-server.overrideAttrs (old: {
|
|
postPatch = (old.postPatch or "") + ''
|
|
substituteInPlace websocket_server/SocketManager.js \
|
|
--replace-fail $'const support = await checkPuppeteerAvailability({ force: false })\n\t\t\tsocket.emit(\'recording-availability\', {\n\t\t\t\tavailable: support.available,\n\t\t\t\treason: support.reason || null,\n\t\t\t})' $'if (process.env.DISABLE_RECORDING === "1") {\n\t\t\t\tsocket.emit(\'recording-availability\', {\n\t\t\t\t\tavailable: false,\n\t\t\t\t\treason: null,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst support = await checkPuppeteerAvailability({ force: false })\n\t\t\tsocket.emit(\'recording-availability\', {\n\t\t\t\tavailable: support.available,\n\t\t\t\treason: support.reason || null,\n\t\t\t})'
|
|
'';
|
|
});
|
|
})
|
|
];
|
|
|
|
services.nextcloud-whiteboard-server.settings.DISABLE_RECORDING = "1";
|
|
})
|
|
|
|
(mkIf cfg.addons.eurooffice.enable {
|
|
virtualisation.oci-containers.containers.nextcloud-eurooffice = {
|
|
serviceName = "nextcloud-eurooffice";
|
|
image = cfg.addons.eurooffice.image;
|
|
ports = [ "${cfg.bindAddress}:${toString cfg.addons.eurooffice.port}:80" ];
|
|
environmentFiles = [ "/run/nextcloud-eurooffice/eurooffice.env" ];
|
|
environment = {
|
|
JWT_ENABLED = "true";
|
|
JWT_HEADER = cfg.addons.eurooffice.jwtHeader;
|
|
ALLOW_PRIVATE_IP_ADDRESS = "true";
|
|
}
|
|
// cfg.addons.eurooffice.environment;
|
|
};
|
|
|
|
systemd.services.nextcloud-eurooffice = {
|
|
serviceConfig = {
|
|
LoadCredential = optional (cfg.secrets.jwtFile != null) "jwt:${cfg.secrets.jwtFile}";
|
|
RuntimeDirectory = "nextcloud-eurooffice";
|
|
RuntimeDirectoryMode = "0700";
|
|
};
|
|
preStart = ''
|
|
set -euo pipefail
|
|
jwt_secret="$(<"$CREDENTIALS_DIRECTORY/jwt")"
|
|
umask 077
|
|
printf 'JWT_SECRET=%s\n' "$jwt_secret" > /run/nextcloud-eurooffice/eurooffice.env
|
|
'';
|
|
};
|
|
})
|
|
|
|
(mkIf (cfg.addons.eurooffice.enable && cfg.addons.eurooffice.nginx.enable) {
|
|
services.nginx.virtualHosts.${cfg.addons.eurooffice.hostName} = nginxTls // {
|
|
locations."/" = {
|
|
proxyPass = "http://${cfg.bindAddress}:${toString cfg.addons.eurooffice.port}";
|
|
proxyWebsockets = true;
|
|
};
|
|
};
|
|
})
|
|
|
|
(mkIf cfg.authentik.blueprint.enable {
|
|
environment.etc."nextcloud/authentik-blueprint.yaml".text = authentikBlueprint;
|
|
})
|
|
|
|
(mkIf (
|
|
cfg.authentik.blueprint.enable && cfg.authentik.blueprint.autoAttach && authentikTargetAvailable
|
|
) (setAttrByPath cfg.authentik.blueprint.targetOption authentikBlueprint))
|
|
]);
|
|
};
|
|
};
|
|
}
|