add declarative sso integration for nextcloud
This commit is contained in:
parent
8a5f4e3bf2
commit
1cf6d264e4
7 changed files with 465 additions and 97 deletions
|
@ -6,6 +6,7 @@ let
|
|||
contracts = pkgs.callPackage ../contracts {};
|
||||
|
||||
fqdn = "${cfg.subdomain}.${cfg.domain}";
|
||||
fqdnWithPort = if isNull cfg.port then fqdn else "${fqdn}:${toString cfg.port}";
|
||||
|
||||
autheliaCfg = config.services.authelia.instances.${fqdn};
|
||||
|
||||
|
@ -36,6 +37,12 @@ in
|
|||
example = "mydomain.com";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
description = "If given, adds a port to the `<subdomain>.<domain>` endpoint.";
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = null;
|
||||
};
|
||||
|
||||
ssl = lib.mkOption {
|
||||
description = "Path to SSL files";
|
||||
type = lib.types.nullOr contracts.ssl.certs;
|
||||
|
@ -86,7 +93,11 @@ in
|
|||
};
|
||||
identityProvidersOIDCIssuerPrivateKeyFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "File containing the identity provider OIDC issuer private key.";
|
||||
description = ''
|
||||
File containing the identity provider OIDC issuer private key.
|
||||
|
||||
Generate one with `nix run nixpkgs#openssl -- genrsa -out keypair.pem 2048`
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -99,39 +110,47 @@ in
|
|||
};
|
||||
|
||||
smtp = lib.mkOption {
|
||||
description = "SMTP options.";
|
||||
default = null;
|
||||
type = lib.types.nullOr (lib.types.submodule {
|
||||
options = {
|
||||
from_address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "SMTP address from which the emails originate.";
|
||||
example = "authelia@mydomain.com";
|
||||
description = ''
|
||||
If a string is given, writes notifications to the given path.Otherwise, send notifications
|
||||
by smtp.
|
||||
|
||||
https://www.authelia.com/configuration/notifications/introduction/
|
||||
'';
|
||||
default = "/tmp/authelia-notifications";
|
||||
type = lib.types.oneOf [
|
||||
lib.types.str
|
||||
(lib.types.nullOr (lib.types.submodule {
|
||||
options = {
|
||||
from_address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "SMTP address from which the emails originate.";
|
||||
example = "authelia@mydomain.com";
|
||||
};
|
||||
from_name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "SMTP name from which the emails originate.";
|
||||
default = "Authelia";
|
||||
};
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "SMTP host to send the emails to.";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = "SMTP port to send the emails to.";
|
||||
default = 25;
|
||||
};
|
||||
username = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Username to connect to the SMTP host.";
|
||||
};
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "File containing the password to connect to the SMTP host.";
|
||||
};
|
||||
};
|
||||
from_name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "SMTP name from which the emails originate.";
|
||||
default = "Authelia";
|
||||
};
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "SMTP host to send the emails to.";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = "SMTP port to send the emails to.";
|
||||
default = 25;
|
||||
};
|
||||
username = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Username to connect to the SMTP host.";
|
||||
};
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "File containing the password to connect to the SMTP host.";
|
||||
};
|
||||
};
|
||||
});
|
||||
}))
|
||||
];
|
||||
};
|
||||
|
||||
rules = lib.mkOption {
|
||||
|
@ -175,7 +194,7 @@ in
|
|||
AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE = toString cfg.secrets.identityProvidersOIDCHMACSecretFile;
|
||||
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE = toString cfg.secrets.identityProvidersOIDCIssuerPrivateKeyFile;
|
||||
|
||||
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = lib.mkIf (!(isNull cfg.smtp)) (toString cfg.smtp.passwordFile);
|
||||
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = lib.mkIf (!(builtins.isString cfg.smtp)) (toString cfg.smtp.passwordFile);
|
||||
};
|
||||
settings = {
|
||||
server.host = "127.0.0.1";
|
||||
|
@ -207,7 +226,7 @@ in
|
|||
};
|
||||
totp = {
|
||||
disable = "false";
|
||||
issuer = fqdn;
|
||||
issuer = fqdnWithPort;
|
||||
algorithm = "sha1";
|
||||
digits = "6";
|
||||
period = "30";
|
||||
|
@ -217,7 +236,7 @@ in
|
|||
# Inspired from https://www.authelia.com/configuration/session/introduction/ and https://www.authelia.com/configuration/session/redis
|
||||
session = {
|
||||
name = "authelia_session";
|
||||
domain = cfg.domain;
|
||||
domain = if isNull cfg.port then cfg.domain else "${cfg.domain}:${toString cfg.port}";
|
||||
same_site = "lax";
|
||||
expiration = "1h";
|
||||
inactivity = "5m";
|
||||
|
@ -238,10 +257,10 @@ in
|
|||
};
|
||||
};
|
||||
notifier = {
|
||||
filesystem = lib.mkIf (isNull cfg.smtp) {
|
||||
filename = "/tmp/authelia-notifications";
|
||||
filesystem = lib.mkIf (builtins.isString cfg.smtp) {
|
||||
filename = cfg.smtp;
|
||||
};
|
||||
smtp = lib.mkIf (!(isNull cfg.smtp)) {
|
||||
smtp = lib.mkIf (!(builtins.isString cfg.smtp)) {
|
||||
host = cfg.smtp.host;
|
||||
port = cfg.smtp.port;
|
||||
username = cfg.smtp.username;
|
||||
|
@ -260,7 +279,7 @@ in
|
|||
];
|
||||
rules = [
|
||||
{
|
||||
domain = fqdn;
|
||||
domain = fqdnWithPort;
|
||||
policy = "bypass";
|
||||
resources = [
|
||||
"^/api/.*"
|
||||
|
|
|
@ -50,9 +50,6 @@ in
|
|||
let
|
||||
commonConfig = {
|
||||
services.postgresql.settings = {
|
||||
idle_in_transaction_session_timeout = "30s";
|
||||
idle_session_timeout = "30s";
|
||||
track_io_timing = "true";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -197,6 +197,31 @@ in
|
|||
shell_command = {
|
||||
delete_backups = "find ${config.services.home-assistant.configDir}/backups -type f -delete";
|
||||
};
|
||||
|
||||
conversation.intents = {
|
||||
TellJoke = [
|
||||
"Tell [me] (a joke|something funny|a dad joke)"
|
||||
"Raconte [moi] (une blague)"
|
||||
];
|
||||
};
|
||||
sensor = [
|
||||
{
|
||||
name = "random_joke";
|
||||
platform = "rest";
|
||||
json_attributes = ["joke" "id" "status"];
|
||||
value_template = "{{ value_json.joke }}";
|
||||
resource = "https://icanhazdadjoke.com/";
|
||||
scan_interval = "3600";
|
||||
headers.Accept = "application/json";
|
||||
}
|
||||
];
|
||||
intent_script.TellJoke = {
|
||||
speech.text = ''{{ state_attr("sensor.random_joke", "joke") }}'';
|
||||
action = {
|
||||
service = "homeassistant.update_entity";
|
||||
entity_id = "sensor.random_joke";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ let
|
|||
cfg = config.shb.nextcloud;
|
||||
|
||||
fqdn = "${cfg.subdomain}.${cfg.domain}";
|
||||
fqdnWithPort = if isNull cfg.port then fqdn else "${fqdn}:${toString cfg.port}";
|
||||
protocol = if !(isNull cfg.ssl) then "https" else "http";
|
||||
|
||||
ssoFqdnWithPort = if isNull cfg.apps.sso.port then cfg.apps.sso.endpoint else "${cfg.apps.sso.endpoint}:${toString cfg.apps.sso.port}";
|
||||
|
||||
contracts = pkgs.callPackage ../contracts {};
|
||||
|
||||
|
@ -19,16 +23,40 @@ in
|
|||
|
||||
subdomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Subdomain under which Nextcloud will be served.";
|
||||
description = ''
|
||||
Subdomain under which Nextcloud will be served.
|
||||
|
||||
```
|
||||
<subdomain>.<domain>[:<port>]
|
||||
```
|
||||
'';
|
||||
example = "nextcloud";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
description = "Domain to serve Nextcloud under.";
|
||||
description = ''
|
||||
Domain under which Nextcloud is served.
|
||||
|
||||
```
|
||||
<subdomain>.<domain>[:<port>]
|
||||
```
|
||||
'';
|
||||
type = lib.types.str;
|
||||
example = "domain.com";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
description = ''
|
||||
Port under which Nextcloud will be served. If null is given, then the port is omitted.
|
||||
|
||||
```
|
||||
<subdomain>.<domain>[:<port>]
|
||||
```
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = null;
|
||||
};
|
||||
|
||||
ssl = lib.mkOption {
|
||||
description = "Path to SSL files";
|
||||
type = lib.types.nullOr contracts.ssl.certs;
|
||||
|
@ -168,7 +196,11 @@ in
|
|||
|
||||
jwtSecretFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "File containing the JWT secret. This option is required.";
|
||||
description = ''
|
||||
File containing the JWT secret. This option is required.
|
||||
|
||||
Must be readable by the nextcloud system user.
|
||||
'';
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
|
@ -216,7 +248,7 @@ in
|
|||
enable = lib.mkEnableOption "LDAP app.";
|
||||
|
||||
host = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Host serving the LDAP server.
|
||||
'';
|
||||
|
@ -224,7 +256,7 @@ in
|
|||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
type = lib.types.port;
|
||||
description = ''
|
||||
Port of the service serving the LDAP server.
|
||||
'';
|
||||
|
@ -245,7 +277,11 @@ in
|
|||
|
||||
adminPasswordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "File containing the admin password of the LDAP server.";
|
||||
description = ''
|
||||
File containing the admin password of the LDAP server.
|
||||
|
||||
Must be readable by the nextcloud system user.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
|
@ -257,6 +293,81 @@ in
|
|||
};
|
||||
});
|
||||
};
|
||||
|
||||
sso = lib.mkOption {
|
||||
description = ''
|
||||
SSO Integration App. [Manual](https://docs.nextcloud.com/server/latest/admin_manual/configuration_user/oidc_auth.html)
|
||||
|
||||
Enabling this app will create a new LDAP configuration or update one that exists with
|
||||
the given host.
|
||||
'';
|
||||
default = {};
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "SSO app.";
|
||||
|
||||
endpoint = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "OIDC endpoint for SSO.";
|
||||
example = "https://authelia.example.com";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
description = "If given, adds a port to the endpoint.";
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = null;
|
||||
};
|
||||
|
||||
provider = lib.mkOption {
|
||||
type = lib.types.enum [ "Authelia" ];
|
||||
description = "OIDC provider name, used for display.";
|
||||
default = "Authelia";
|
||||
};
|
||||
|
||||
clientID = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Client ID for the OIDC endpoint.";
|
||||
default = "nextcloud";
|
||||
};
|
||||
|
||||
authorization_policy = lib.mkOption {
|
||||
type = lib.types.enum [ "one_factor" "two_factor" ];
|
||||
description = "Require one factor (password) or two factor (device) authentication.";
|
||||
default = "one_factor";
|
||||
};
|
||||
|
||||
secretFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
File containing the secret for the OIDC endpoint.
|
||||
|
||||
Must be readable by the nextcloud system user.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
secretFileForAuthelia = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
File containing the secret for the OIDC endpoint, must be readable by the Authelia user.
|
||||
|
||||
Must be readable by the authelia system user.
|
||||
'';
|
||||
default = "";
|
||||
};
|
||||
|
||||
fallbackDefaultAuth = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Fallback to normal Nextcloud auth if something goes wrong with the SSO app.
|
||||
Usually, you want to enable this to transfer existing users to LDAP and then you
|
||||
can disabled it.
|
||||
'';
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -387,7 +498,7 @@ in
|
|||
protocol = if !(isNull cfg.ssl) then "https" else "http";
|
||||
in {
|
||||
"overwrite.cli.url" = "${protocol}://${fqdn}";
|
||||
"overwritehost" = if (isNull cfg.externalFqdn) then fqdn else cfg.externalFqdn;
|
||||
"overwritehost" = fqdnWithPort;
|
||||
# 'trusted_domains' needed otherwise we get this issue https://help.nextcloud.com/t/the-polling-url-does-not-start-with-https-despite-the-login-url-started-with-https/137576/2
|
||||
# TODO: could instead set extraTrustedDomains
|
||||
"trusted_domains" = [ fqdn ];
|
||||
|
@ -450,8 +561,8 @@ in
|
|||
# [1]: https://help.nextcloud.com/t/download-aborts-after-time-or-large-file/25044/6
|
||||
# [2]: https://stackoverflow.com/a/50891625/1013628
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
|
@ -470,7 +581,7 @@ in
|
|||
};
|
||||
systemd.services.phpfpm-nextcloud.preStart = ''
|
||||
mkdir -p /var/log/xdebug; chown -R nextcloud: /var/log/xdebug
|
||||
'';
|
||||
'';
|
||||
|
||||
systemd.services.nextcloud-cron.path = [
|
||||
pkgs.perl
|
||||
|
@ -514,8 +625,8 @@ in
|
|||
|
||||
locations."/" = {
|
||||
extraConfig = ''
|
||||
allow ${cfg.apps.onlyoffice.localNetworkIPRange};
|
||||
'';
|
||||
allow ${cfg.apps.onlyoffice.localNetworkIPRange};
|
||||
'';
|
||||
};
|
||||
};
|
||||
})
|
||||
|
@ -620,5 +731,103 @@ in
|
|||
'1'
|
||||
'';
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.apps.sso.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.apps.sso.enable -> cfg.apps.ldap.enable;
|
||||
message = "SSO app requires LDAP app to work correctly.";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.nextcloud-setup.script =
|
||||
''
|
||||
${occ} app:install oidc_login || :
|
||||
${occ} app:enable oidc_login
|
||||
'';
|
||||
|
||||
systemd.services.nextcloud-setup.preStart =
|
||||
''
|
||||
mkdir -p ${cfg.dataDir}/config
|
||||
cat <<EOF > "${cfg.dataDir}/config/secretFile"
|
||||
{
|
||||
"oidc_login_client_secret": "$(cat ${cfg.apps.sso.secretFile})"
|
||||
}
|
||||
EOF
|
||||
'';
|
||||
|
||||
services.nextcloud = {
|
||||
secretFile = "${cfg.dataDir}/config/secretFile";
|
||||
|
||||
# See all options at https://github.com/pulsejet/nextcloud-oidc-login
|
||||
extraOptions = {
|
||||
allow_user_to_change_display_name = false;
|
||||
lost_password_link = "disabled";
|
||||
oidc_login_provider_url = ssoFqdnWithPort;
|
||||
oidc_login_client_id = cfg.apps.sso.clientID;
|
||||
|
||||
# Automatically redirect the login page to the provider.
|
||||
oidc_login_auto_redirect = !cfg.apps.sso.fallbackDefaultAuth;
|
||||
# Authelia at least does not support this.
|
||||
oidc_login_end_session_redirect = false;
|
||||
# Redirect to this page after logging out the user
|
||||
oidc_login_logout_url = ssoFqdnWithPort;
|
||||
oidc_login_button_text = "Log in with ${cfg.apps.sso.provider}";
|
||||
oidc_login_hide_password_form = false;
|
||||
oidc_login_use_id_token = true;
|
||||
oidc_login_attributes = {
|
||||
id = "preferred_username";
|
||||
name = "name";
|
||||
mail = "email";
|
||||
groups = "groups";
|
||||
};
|
||||
oidc_login_default_group = "oidc";
|
||||
oidc_login_use_external_storage = false;
|
||||
oidc_login_scope = "openid profile email groups";
|
||||
oidc_login_proxy_ldap = false;
|
||||
# Enable creation of users new to Nextcloud from OIDC login. A user may be known to the
|
||||
# IdP but not (yet) known to Nextcloud. This setting controls what to do in this case.
|
||||
# * 'true' (default): if the user authenticates to the IdP but is not known to Nextcloud,
|
||||
# then they will be returned to the login screen and not allowed entry;
|
||||
# * 'false': if the user authenticates but is not yet known to Nextcloud, then the user
|
||||
# will be automatically created; note that with this setting, you will be allowing (or
|
||||
# relying on) a third-party (the IdP) to create new users
|
||||
oidc_login_disable_registration = false;
|
||||
oidc_login_redir_fallback = cfg.apps.sso.fallbackDefaultAuth;
|
||||
# oidc_login_alt_login_page = "assets/login.php";
|
||||
oidc_login_tls_verify = true;
|
||||
# If you get your groups from the oidc_login_attributes, you might want to create them if
|
||||
# they are not already existing, Default is `false`.
|
||||
oidc_create_groups = true;
|
||||
# Enable use of WebDAV via OIDC bearer token.
|
||||
oidc_login_webdav_enabled = true;
|
||||
oidc_login_password_authentication = false;
|
||||
oidc_login_public_key_caching_time = 86400;
|
||||
oidc_login_min_time_between_jwks_requests = 10;
|
||||
oidc_login_well_known_caching_time = 86400;
|
||||
# If true, nextcloud will download user avatars on login. This may lead to security issues
|
||||
# as the server does not control which URLs will be requested. Use with care.
|
||||
oidc_login_update_avatar = false;
|
||||
};
|
||||
};
|
||||
|
||||
shb.authelia.oidcClients = lib.mkIf (cfg.apps.sso.provider == "Authelia") [
|
||||
{
|
||||
id = cfg.apps.sso.clientID;
|
||||
description = "Nextcloud";
|
||||
secretFile = cfg.apps.sso.secretFileForAuthelia;
|
||||
public = "false";
|
||||
authorization_policy = cfg.apps.sso.authorization_policy;
|
||||
redirect_uris = [ "${protocol}://${fqdnWithPort}/apps/oidc_login/oidc" ];
|
||||
scopes = [
|
||||
"openid"
|
||||
"profile"
|
||||
"email"
|
||||
"groups"
|
||||
];
|
||||
userinfo_signing_algorithm = "none";
|
||||
}
|
||||
];
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ This NixOS module is a service that sets up a [Nextcloud Server](https://nextclo
|
|||
- Declarative [Apps](#services-nextcloud-server-options-shb.nextcloud.apps) Configuration - no need
|
||||
to configure those with the UI.
|
||||
- [LDAP](#services-nextcloud-server-usage-ldap) app: enables app and sets up integration with an existing LDAP server.
|
||||
- [OIDC](#services-nextcloud-server-usage-oidc) app: enables app and sets up integration with an existing OIDC server.
|
||||
- [Preview Generator](#services-nextcloud-server-usage-previewgenerator) app: enables app and sets
|
||||
up required cron job.
|
||||
- [Only Office](#services-nextcloud-server-usage-onlyoffice) app: enables app and sets up Only
|
||||
|
@ -35,9 +36,36 @@ This NixOS module is a service that sets up a [Nextcloud Server](https://nextclo
|
|||
|
||||
## Usage {#services-nextcloud-server-usage}
|
||||
|
||||
### Basic Configuration {#services-nextcloud-server-usage-basic}
|
||||
### Secrets {#services-nextcloud-server-secrets}
|
||||
|
||||
This section corresponds to the `basic` target host defined in the [flake.nix](./flake.nix) file.
|
||||
All the secrets should be readable by the nextcloud user.
|
||||
|
||||
Secret should not be stored in the nix store. If you're using
|
||||
[sops-nix](https://github.com/Mic92/sops-nix) and assuming your secrets file is located at
|
||||
`./secrets.yaml`, you can define a secret with:
|
||||
|
||||
```nix
|
||||
sops.secrets."nextcloud/adminpass" = {
|
||||
sopsFile = ./secrets.yaml;
|
||||
mode = "0400";
|
||||
owner = "nextcloud";
|
||||
group = "nextcloud";
|
||||
restartUnits = [ "phpfpm-nextcloud.service" ];
|
||||
};
|
||||
```
|
||||
|
||||
Then you can use that secret:
|
||||
|
||||
```nix
|
||||
shb.nextcloud.adminPassFile = config.sops.secrets."nextcloud/adminpass".path;
|
||||
```
|
||||
|
||||
### Nextcloud through HTTP {#services-nextcloud-server-usage-basic}
|
||||
|
||||
:::: {.note}
|
||||
This section corresponds to the `basic` section of the [Nextcloud
|
||||
demo](demo-nextcloud-server.html#demo-nextcloud-deploy-basic).
|
||||
::::
|
||||
|
||||
This will set up a Nextcloud service that runs on the NixOS target machine, reachable at
|
||||
`http://nextcloud.example.com`. If the `shb.ssl` block is [enabled](block-ssl.html#usage), the
|
||||
|
@ -53,27 +81,19 @@ shb.nextcloud = {
|
|||
};
|
||||
```
|
||||
|
||||
The secret should not be stored in the nix store. If you're using
|
||||
[sops-nix](https://github.com/Mic92/sops-nix) and assuming your secrets file is located at
|
||||
`./secrets.yaml`, you can set the `adminPassFile` option with:
|
||||
|
||||
```nix
|
||||
shb.nextcloud.adminPassFile = config.sops.secrets."nextcloud/adminpass".path;
|
||||
|
||||
sops.secrets."nextcloud/adminpass" = {
|
||||
sopsFile = ./secrets.yaml;
|
||||
mode = "0400";
|
||||
owner = "nextcloud";
|
||||
group = "nextcloud";
|
||||
restartUnits = [ "phpfpm-nextcloud.service" ];
|
||||
};
|
||||
```
|
||||
After deploying, the Nextcloud server will be reachable at `http://nextcloud.example.com`.
|
||||
|
||||
### With LDAP Support {#services-nextcloud-server-usage-ldap}
|
||||
|
||||
This section corresponds to the `ldap` target host defined in the [flake.nix](./flake.nix) file. The same information from the [basic](#services-nextcloud-server-usage-basic) section applies, so please read that first.
|
||||
:::: {.note}
|
||||
This section corresponds to the `ldap` section of the [Nextcloud
|
||||
demo](demo-nextcloud-server.html#demo-nextcloud-deploy-ldap).
|
||||
::::
|
||||
|
||||
This target host uses the LDAP block provided by Self Host Blocks to setup a
|
||||
We will build upon the [Basic Configuration](#services-nextcloud-server-usage-basic) section, so
|
||||
please read that first.
|
||||
|
||||
We will use the LDAP block provided by Self Host Blocks to setup a
|
||||
[LLDAP](https://github.com/lldap/lldap) service.
|
||||
|
||||
```nix
|
||||
|
@ -84,24 +104,8 @@ shb.ldap = {
|
|||
ldapPort = 3890;
|
||||
webUIListenPort = 17170;
|
||||
dcdomain = "dc=example,dc=com";
|
||||
ldapUserPasswordFile = config.sops.secrets."lldap/user_password".path;
|
||||
jwtSecretFile = config.sops.secrets."lldap/jwt_secret".path;
|
||||
};
|
||||
|
||||
sops.secrets."lldap/user_password" = {
|
||||
sopsFile = ./secrets.yaml;
|
||||
mode = "0440";
|
||||
owner = "lldap";
|
||||
group = "lldap";
|
||||
restartUnits = [ "lldap.service" ];
|
||||
};
|
||||
|
||||
sops.secrets."lldap/jwt_secret" = {
|
||||
sopsFile = ./secrets.yaml;
|
||||
mode = "0440";
|
||||
owner = "lldap";
|
||||
group = "lldap";
|
||||
restartUnits = [ "lldap.service" ];
|
||||
ldapUserPasswordFile = <path/to/ldapUserPasswordSecret>;
|
||||
jwtSecretFile = <path/to/ldapJwtSecret>;
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -115,12 +119,110 @@ shb.nextcloud.apps.ldap
|
|||
port = config.shb.ldap.ldapPort;
|
||||
dcdomain = config.shb.ldap.dcdomain;
|
||||
adminName = "admin";
|
||||
adminPasswordFile = config.sops.secrets."nextcloud/ldap_admin_password".path;
|
||||
adminPasswordFile = <path/to/ldapUserPasswordSecret>;
|
||||
userGroup = "nextcloud_user";
|
||||
};
|
||||
```
|
||||
|
||||
It's nice to be able to reference a options that were defined in the ldap block.
|
||||
The `shb.nextcloud.apps.ldap.adminPasswordFile` must be the same as the
|
||||
`shb.ldap.ldapUserPasswordFile`. The other secret can be randomly generated with `nix run
|
||||
nixpkgs#openssl -- rand -hex 64`.
|
||||
|
||||
And that's it. Now, go to the LDAP server at `http://ldap.example.com`, create the `nextcloud_user`
|
||||
group, create a user and add it to the group. When that's done, go back to the Nextcloud server at
|
||||
`http://nextcloud.example.com` and login with that user.
|
||||
|
||||
Note that we cannot create an admin user from the LDAP server, so you need to create a normal user
|
||||
like above, login with it once so it is known to Nextcloud, then logout, login with the admin
|
||||
Nextcloud user and promote that new user to admin level.
|
||||
|
||||
### With OIDC Support {#services-nextcloud-server-usage-oidc}
|
||||
|
||||
:::: {.note}
|
||||
This section corresponds to the `sso` section of the [Nextcloud
|
||||
demo](demo-nextcloud-server.html#demo-nextcloud-deploy-sso).
|
||||
::::
|
||||
|
||||
We will build upon the [Basic Configuration](#services-nextcloud-server-usage-basic) and [With LDAP
|
||||
Support](#services-nextcloud-server-usage-ldap) sections, so please read those first and setup the
|
||||
LDAP app as described above.
|
||||
|
||||
Here though, we must setup SSL certificates because the SSO provider only works with the https
|
||||
protocol. This is actually quite easy thanks to the [SSL block](blocks-ssl.html). For example, with
|
||||
self-signed certificates:
|
||||
|
||||
```nix
|
||||
shb.certs = {
|
||||
cas.selfsigned.myca = {
|
||||
name = "My CA";
|
||||
};
|
||||
certs.selfsigned = {
|
||||
nextcloud = {
|
||||
ca = config.shb.certs.cas.selfsigned.myca;
|
||||
domain = "nextcloud.example.com";
|
||||
};
|
||||
auth = {
|
||||
ca = config.shb.certs.cas.selfsigned.myca;
|
||||
domain = "auth.example.com";
|
||||
};
|
||||
ldap = {
|
||||
ca = config.shb.certs.cas.selfsigned.myca;
|
||||
domain = "ldap.example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
We need to setup the SSO provider, here Authelia thanks to the corresponding SHB block:
|
||||
|
||||
```nix
|
||||
shb.authelia = {
|
||||
enable = true;
|
||||
domain = "example.com";
|
||||
subdomain = "auth";
|
||||
ssl = config.shb.certs.certs.selfsigned.auth;
|
||||
|
||||
ldapEndpoint = "ldap://127.0.0.1:${builtins.toString config.shb.ldap.ldapPort}";
|
||||
dcdomain = config.shb.ldap.dcdomain;
|
||||
|
||||
secrets = {
|
||||
jwtSecretFile = <path/to/autheliaJwtSecret>;
|
||||
ldapAdminPasswordFile = <path/to/ldapUserPasswordSecret>;
|
||||
sessionSecretFile = <path/to/autheliaSessionSecret>;
|
||||
storageEncryptionKeyFile = <path/to/autheliaStorageEncryptionKeySecret>;
|
||||
identityProvidersOIDCHMACSecretFile = <path/to/providersOIDCHMACSecret>;
|
||||
identityProvidersOIDCIssuerPrivateKeyFile = <path/to/providersOIDCIssuerSecret>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
The `shb.authelia.secrets.ldapAdminPasswordFile` must be the same as the
|
||||
`shb.ldap.ldapUserPasswordFile` defined in the previous section. The secrets can be randomly
|
||||
generated with `nix run nixpkgs#openssl -- rand -hex 64`.
|
||||
|
||||
Now, on the Nextcloud side, you need to add the following options:
|
||||
|
||||
```nix
|
||||
shb.nextcloud.ssl = config.shb.certs.certs.selfsigned.nextcloud;
|
||||
|
||||
shb.nextcloud.apps.sso = {
|
||||
enable = true;
|
||||
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
|
||||
clientID = "nextcloud";
|
||||
fallbackDefaultAuth = false;
|
||||
|
||||
secretFile = <path/to/oidcNextcloudSharedSecret>;
|
||||
secretFileForAuthelia = <path/to/oidcNextcloudSharedSecret>;
|
||||
};
|
||||
```
|
||||
|
||||
Passing the `ssl` option will auto-configure nginx to force SSL connections with the given
|
||||
certificate.
|
||||
|
||||
The `shb.nextcloud.apps.sso.secretFile` and `shb.nextcloud.apps.sso.secretFileForAuthelia` options
|
||||
must have the same content. The former is a file that must be owned by the `nextcloud` user while
|
||||
the latter must be owned by the `authelia` user. I want to avoid needing to define the same secret
|
||||
twice with a future secrets SHB block.
|
||||
|
||||
### Tweak PHPFpm Config {#services-nextcloud-server-usage-phpfpm}
|
||||
|
||||
|
@ -139,6 +241,8 @@ shb.nextcloud.phpFpmPoolSettings = {
|
|||
|
||||
### Tweak PostgreSQL Settings {#services-nextcloud-server-usage-postgres}
|
||||
|
||||
These settings will impact all databases.
|
||||
|
||||
```nix
|
||||
shb.nextcloud.postgresSettings = {
|
||||
max_connections = "100";
|
||||
|
@ -227,6 +331,19 @@ without LDAP integration on a VM with minimal manual steps.
|
|||
|
||||
On the command line, the `occ` tool is called `nextcloud-occ`.
|
||||
|
||||
## Debug {#services-nextcloud-server-debug}
|
||||
|
||||
In case of an issue, check the logs for any systemd service mentioned in this section.
|
||||
|
||||
On startup, the oneshot systemd service `nextcloud-setup.service` starts. After it finishes, the
|
||||
`phpfpm-nextcloud.service` starts to serve Nextcloud. The `nginx.service` is used as the reverse
|
||||
proxy. `postgresql.service` run the database.
|
||||
|
||||
Nextcloud' configuration is found at `${shb.nextcloud.dataDir}/config/config.php`. Nginx'
|
||||
configuration can be found with `systemctl cat nginx | grep -om 1 -e "[^ ]\+conf"`.
|
||||
|
||||
Enable verbose logging by setting the `shb.nextcloud.debug` boolean to `true`.
|
||||
|
||||
## Options Reference {#services-nextcloud-server-options}
|
||||
|
||||
```{=include=} options
|
||||
|
|
|
@ -24,9 +24,9 @@ let
|
|||
};
|
||||
|
||||
commonSettings = {
|
||||
idle_in_transaction_session_timeout = "30s";
|
||||
idle_session_timeout = "30s";
|
||||
track_io_timing = "true";
|
||||
# idle_in_transaction_session_timeout = "30s";
|
||||
# idle_session_timeout = "30s";
|
||||
# track_io_timing = "true";
|
||||
};
|
||||
in
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ in
|
|||
options = {
|
||||
shb.ssl.enable = lib.mkEnableOption "ssl";
|
||||
shb.backup = lib.mkOption { type = lib.types.anything; };
|
||||
shb.authelia = lib.mkOption { type = lib.types.anything; };
|
||||
};
|
||||
}
|
||||
# ../../modules/blocks/authelia.nix
|
||||
|
|
Loading…
Reference in a new issue