aboutsummaryrefslogtreecommitdiff
path: root/modules/services/nextcloud.nix
diff options
context:
space:
mode:
authorschererleander <leander@schererleander.de>2026-02-05 12:03:07 +0100
committerschererleander <leander@schererleander.de>2026-02-05 15:19:41 +0100
commit3b13d9a2a367db84d48940460532c17a374bb488 (patch)
tree599110a39c4baecf3991fe9a58d0103a43c38896 /modules/services/nextcloud.nix
parent46aa4842b98d9215baca00060c233f386a0c2188 (diff)
feat(modules): use dendritic pattern
Diffstat (limited to 'modules/services/nextcloud.nix')
-rw-r--r--modules/services/nextcloud.nix131
1 files changed, 131 insertions, 0 deletions
diff --git a/modules/services/nextcloud.nix b/modules/services/nextcloud.nix
new file mode 100644
index 0000000..1c6e656
--- /dev/null
+++ b/modules/services/nextcloud.nix
@@ -0,0 +1,131 @@
+{
+ flake.modules.nixos.nextcloud =
+ {
+ config,
+ lib,
+ pkgs,
+ ...
+ }:
+ {
+ services.nextcloud = {
+ enable = true;
+ package = pkgs.nextcloud32;
+ hostName = "cloud.schererleander.de";
+ https = true;
+ database.createLocally = true;
+ maxUploadSize = "16G";
+ config = {
+ dbtype = "mysql";
+ adminuser = "schererleander";
+ adminpassFile = config.sops.secrets."nextcloud-admin-pass".path;
+ };
+ secrets = {
+ secret = config.sops.secrets."nextcloud-secret".path;
+ };
+ settings = {
+ maintenance_window_start = 2; # 02:00
+ default_phone_region = "de";
+ overwriteProtocol = "https";
+ trusted_domains = [ "cloud.schererleander.de" ];
+ logtimezone = config.time.timeZone;
+ log_type = "file";
+ # Disable mail functionality for single-user instance
+ mail_smtpmode = "null";
+ };
+ phpOptions."opcache.interned_strings_buffer" = "64";
+ };
+
+ services.nginx.virtualHosts = {
+ "cloud.schererleander.de" = {
+ forceSSL = true;
+ sslCertificate = config.sops.secrets."cert_fullchain".path;
+ sslCertificateKey = config.sops.secrets."cert_private".path;
+ };
+ };
+
+ services.borgbackup.jobs.nextcloud = {
+ paths = [
+ "/var/lib/nextcloud"
+ "/var/lib/backup/nextcloud/db"
+ ];
+ repo = "$BORG_REPO";
+ encryption.mode = "none";
+ user = "root";
+ group = "root";
+ environment = {
+ BORG_RSH = "ssh -i ${
+ config.sops.secrets."borgbase_ssh_key".path
+ } -o StrictHostKeyChecking=accept-new";
+ TMPDIR = "/var/tmp";
+ };
+ compression = "auto,lzma";
+ startAt = "daily";
+ readWritePaths = [
+ "/var/lib/backup"
+ "/var/lib/nextcloud"
+ ];
+ preHook = ''
+ set -euo pipefail
+
+ export BORG_REPO="$(cat ${config.sops.secrets."borg_repo".path})"
+
+ INSTALL="${pkgs.coreutils}/bin/install"
+ FIND="${pkgs.findutils}/bin/find"
+ MYSQLDUMP="${pkgs.mariadb.client}/bin/mariadb-dump"
+ GZIP="${pkgs.gzip}/bin/gzip"
+ OCC="${lib.getExe config.services.nextcloud.occ}"
+
+ # This command requires write access to /var/lib/backup.
+ $INSTALL -d -m 0750 -o root -g root /var/lib/backup/nextcloud/db
+
+ trap "$OCC maintenance:mode --off >/dev/null 2>&1 || true" EXIT
+
+ $OCC maintenance:mode --on
+
+ # Make a consistent database dump without locking the site.
+ $MYSQLDUMP --single-transaction --quick --lock-tables=false --databases nextcloud \
+ | $GZIP -c > /var/lib/backup/nextcloud/db/nextcloud-$(date +%F-%H%M%S).sql.gz
+
+ # Delete local dump files older than 14 days.
+ $FIND /var/lib/backup/nextcloud/db -type f -name "*.sql.gz" -mtime +14 -delete || true
+ '';
+ postHook = ''
+ set -euo pipefail
+ ${lib.getExe config.services.nextcloud.occ} maintenance:mode --off || true
+ '';
+ };
+
+ services.fail2ban = {
+ enable = true;
+ bantime = lib.mkDefault "1h";
+ jails = {
+ nextcloud = {
+ enabled = true;
+ settings = {
+ backend = "systemd";
+ journalmatch = "SYSLOG_IDENTIFIER=Nextcloud";
+ # END modification to work with syslog instead of logile
+ port = 443;
+ protocol = "tcp";
+ filter = "nextcloud";
+ maxretry = 3;
+ findtime = 43200;
+ };
+ };
+ };
+ };
+
+ environment.etc = {
+ # Adapted failregex for syslogs
+ "fail2ban/filter.d/nextcloud.local".text = pkgs.lib.mkDefault (
+ pkgs.lib.mkAfter ''
+ [Definition]
+ _groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
+ failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
+ ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
+ datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"
+ ''
+ );
+ };
+ };
+}