From 1cf6d264e4c8a527e5b67bb529b8981abcfbfc92 Mon Sep 17 00:00:00 2001 From: ibizaman Date: Sun, 21 Jan 2024 23:38:57 -0800 Subject: [PATCH] add declarative sso integration for nextcloud --- modules/blocks/authelia.nix | 99 +++++--- modules/blocks/postgresql.nix | 3 - modules/services/home-assistant.nix | 25 ++ modules/services/nextcloud-server.nix | 233 +++++++++++++++++- .../services/nextcloud-server/docs/default.md | 195 ++++++++++++--- test/modules/postgresql.nix | 6 +- test/vm/nextcloud.nix | 1 + 7 files changed, 465 insertions(+), 97 deletions(-) diff --git a/modules/blocks/authelia.nix b/modules/blocks/authelia.nix index 5375aa4..89259d6 100644 --- a/modules/blocks/authelia.nix +++ b/modules/blocks/authelia.nix @@ -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 `.` 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/.*" diff --git a/modules/blocks/postgresql.nix b/modules/blocks/postgresql.nix index 391e8a2..cff5999 100644 --- a/modules/blocks/postgresql.nix +++ b/modules/blocks/postgresql.nix @@ -50,9 +50,6 @@ in let commonConfig = { services.postgresql.settings = { - idle_in_transaction_session_timeout = "30s"; - idle_session_timeout = "30s"; - track_io_timing = "true"; }; }; diff --git a/modules/services/home-assistant.nix b/modules/services/home-assistant.nix index eb5bb3b..6f16d5d 100644 --- a/modules/services/home-assistant.nix +++ b/modules/services/home-assistant.nix @@ -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"; + }; + }; }; }; diff --git a/modules/services/nextcloud-server.nix b/modules/services/nextcloud-server.nix index a8ce8fd..ac4dc63 100644 --- a/modules/services/nextcloud-server.nix +++ b/modules/services/nextcloud-server.nix @@ -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. + + ``` + .[:] + ``` + ''; example = "nextcloud"; }; domain = lib.mkOption { - description = "Domain to serve Nextcloud under."; + description = '' + Domain under which Nextcloud is served. + + ``` + .[:] + ``` + ''; 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. + + ``` + .[:] + ``` + ''; + 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 < "${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"; + } + ]; + }) ]; } diff --git a/modules/services/nextcloud-server/docs/default.md b/modules/services/nextcloud-server/docs/default.md index 5ffcb37..cf0c122 100644 --- a/modules/services/nextcloud-server/docs/default.md +++ b/modules/services/nextcloud-server/docs/default.md @@ -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 = ; + jwtSecretFile = ; }; ``` @@ -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 = ; 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 = ; + ldapAdminPasswordFile = ; + sessionSecretFile = ; + storageEncryptionKeyFile = ; + identityProvidersOIDCHMACSecretFile = ; + identityProvidersOIDCIssuerPrivateKeyFile = ; + }; +}; +``` + +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 = ; + secretFileForAuthelia = ; +}; +``` + +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 diff --git a/test/modules/postgresql.nix b/test/modules/postgresql.nix index 863fa75..961616d 100644 --- a/test/modules/postgresql.nix +++ b/test/modules/postgresql.nix @@ -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 { diff --git a/test/vm/nextcloud.nix b/test/vm/nextcloud.nix index 4df22e5..72477ec 100644 --- a/test/vm/nextcloud.nix +++ b/test/vm/nextcloud.nix @@ -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