aboutsummaryrefslogtreecommitdiff
path: root/modules/hosts/server/nextcloud
diff options
context:
space:
mode:
authorLeander Scherer <leander@schererleander.de>2026-01-08 02:48:11 +0100
committerLeander Scherer <leander@schererleander.de>2026-01-08 19:08:12 +0100
commit6174f3650cf42aaf008012e828d5a1f8e2ce037f (patch)
tree9bbbd99680cd5adb56596a14734d4896bc6af733 /modules/hosts/server/nextcloud
parentc582c4d0675aada46fa196b7af1941ed753d055f (diff)
refactor(modules): separate nixos/home-manager modules, use standard option conventions
Diffstat (limited to 'modules/hosts/server/nextcloud')
-rw-r--r--modules/hosts/server/nextcloud/default.nix156
1 files changed, 156 insertions, 0 deletions
diff --git a/modules/hosts/server/nextcloud/default.nix b/modules/hosts/server/nextcloud/default.nix
new file mode 100644
index 0000000..a527de2
--- /dev/null
+++ b/modules/hosts/server/nextcloud/default.nix
@@ -0,0 +1,156 @@
+{
+ pkgs,
+ config,
+ username,
+ options,
+ lib,
+ ...
+}:
+let
+ cfg = config.nx.server.nextcloud;
+ inherit (lib) mkOption types mkIf;
+in
+{
+ options.nx.server.nextcloud = {
+ enable = mkOption {
+ description = "Setup nextcloud server";
+ type = types.bool;
+ default = false;
+ };
+ adminUser = mkOption {
+ description = "Admin user";
+ type = types.str;
+ default = "schererleander";
+ };
+ adminPassFile = mkOption {
+ description = "Admin user key file";
+ type = types.str;
+ default = "/etc/nextcloud-admin-pass";
+ };
+ hostName = mkOption {
+ description = "Nextcloud hostname";
+ type = types.str;
+ default = "cloud.schererleander.de";
+ };
+ backup = mkOption {
+ description = "enable borgbase backups";
+ type = types.bool;
+ default = true;
+ };
+ jail = mkOption {
+ description = "setup fail2ban jail";
+ type = types.bool;
+ default = config.nx.server.fail2ban.enable;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.nextcloud = {
+ enable = true;
+ package = pkgs.nextcloud32;
+ hostName = cfg.hostName;
+ https = true;
+ database.createLocally = true;
+ maxUploadSize = "16G";
+ config = {
+ dbtype = "mysql";
+ adminuser = cfg.adminUser;
+ adminpassFile = cfg.adminPassFile;
+ };
+ settings = {
+ maintenance_window_start = 2; # 02:00
+ default_phone_region = "de";
+ overwriteProtocol = "https";
+ trusted_domains = [ cfg.hostName ];
+ logtimezone = config.nx.server.timeZone;
+ log_type = "file";
+ };
+ phpOptions."opcache.interned_strings_buffer" = "64";
+ };
+
+ services.nginx.virtualHosts = mkIf ((config.nx.server.nginx or { }).enable or false) {
+ "${cfg.hostName}" = {
+ forceSSL = true;
+ sslCertificate = config.nx.server.nginx.sslCertificate;
+ sslCertificateKey = config.nx.server.nginx.sslCertificateKey;
+ };
+ };
+
+ services.borgbackup.jobs.nextcloud = mkIf cfg.backup {
+ paths = [
+ "/var/lib/nextcloud"
+ "/var/lib/backup/nextcloud/db"
+ ];
+ repo = "h8xn8qvo@h8xn8qvo.repo.borgbase.com:repo";
+ encryption.mode = "none";
+ environment = {
+ BORG_RSH = "ssh -i /home/${username}/.ssh/borgbase-nextcloud -o StrictHostKeyChecking=accept-new";
+ TMPDIR = "/var/tmp";
+ };
+ compression = "auto,lzma";
+ startAt = "daily";
+ readWritePaths = [
+ "/var/lib/backup"
+ "/var/lib/nextcloud"
+ ];
+ preHook = ''
+ set -euo pipefail
+ INSTALL="${pkgs.coreutils}/bin/install"
+ FIND="${pkgs.findutils}/bin/find"
+ MYSQLDUMP="${pkgs.mariadb.client}/bin/mysql-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 = mkIf cfg.jail {
+ 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;
+ bantime = 86400;
+ findtime = 43200;
+ };
+ };
+ };
+ };
+
+ environment.etc = mkIf cfg.jail {
+ # 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)?"
+ ''
+ );
+ };
+ };
+}