From 7f12cb9bdc471bf74abb2b65c5354e710bbbe069 Mon Sep 17 00:00:00 2001 From: Tigor Hutasuhut Date: Thu, 13 Jun 2024 23:14:37 +0700 Subject: [PATCH] homeserver: added nextcloud --- options/services.nix | 1 + profiles/homeserver.nix | 1 + secrets/nextcloud.yaml | 22 ++++ system/services/default.nix | 1 + system/services/nextcloud-extras.nix | 175 +++++++++++++++++++++++++++ system/services/nextcloud.nix | 42 +++++++ 6 files changed, 242 insertions(+) create mode 100644 secrets/nextcloud.yaml create mode 100644 system/services/nextcloud-extras.nix create mode 100644 system/services/nextcloud.nix diff --git a/options/services.nix b/options/services.nix index 1a331a7..7a14828 100644 --- a/options/services.nix +++ b/options/services.nix @@ -9,5 +9,6 @@ in forgejo.enable = mkEnableOption "forgejo"; kavita.enable = mkEnableOption "kavita"; samba.enable = mkEnableOption "samba"; + nextcloud.enable = mkEnableOption "nextcloud"; }; } diff --git a/profiles/homeserver.nix b/profiles/homeserver.nix index b5c184e..eb6a956 100644 --- a/profiles/homeserver.nix +++ b/profiles/homeserver.nix @@ -33,6 +33,7 @@ forgejo.enable = true; kavita.enable = true; samba.enable = true; + nextcloud.enable = true; }; }; } diff --git a/secrets/nextcloud.yaml b/secrets/nextcloud.yaml new file mode 100644 index 0000000..aaf73a1 --- /dev/null +++ b/secrets/nextcloud.yaml @@ -0,0 +1,22 @@ +nextcloud: + homeserver: ENC[AES256_GCM,data:ZX0LfvXQ1h1LInuvRajKpyhAP8AbyGbTs40=,iv:gpADsYG655zUdDC+j0idtVdMCmwjWSFhSJ2Us0BgBkM=,tag:JPHrZ0YZSEI+AqUm6Bb48Q==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1kruum2varzua7w5n6n52vhwyek2arc685rhcwt0u7k2jf5mecsjslkl9ll + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPeWIrNllOYlhnd3FYZGls + TUdDaSs0RHhVMHBxRFJwSWFxS0N5WVUxYXhNCmRTdnNMQy9TMDd1MUxLYSt0OEs5 + VTg4TnpqVUdEY1Ywa280NktQYnVVUDgKLS0tIExtUjZXdTViMklLYVFqOHBkQnBV + bDN6M1ZEK3ZsdW5ydHNIc282TVo4YVkKeOgUwUJanhOn034l2B6Xp0UxogGP0/US + Bl+Mt+MYolkkNo3CT6w1bmsDXEDOb1Za8lmsMM1OH13bVpSQ/ygVzQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-06-13T16:14:14Z" + mac: ENC[AES256_GCM,data:QbHr/M2lcH0RFMHA5w+cdft803ZeDLgD7k45/gtM+09PmmQG4UMoHns4PoSxBtHUQkjNtHo53jet+sduC5fuO4Rek8xNsgmoIk7Zd46UU8I4QLxGcXLLWyOvddvR2LH5JpQCXbfHULJBynZskBtTntPg2h9F13PuTehOM0lHykM=,iv:su2ZOOK2v8x9vLgCcGTUJTSREMcxCAQXvhC/FKMk4nU=,tag:t5G+vnMw2KgiWYpSqQN1Cw==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/system/services/default.nix b/system/services/default.nix index a728034..ce6cefa 100644 --- a/system/services/default.nix +++ b/system/services/default.nix @@ -5,5 +5,6 @@ ./cockpit.nix ./forgejo.nix ./samba.nix + ./nextcloud.nix ]; } diff --git a/system/services/nextcloud-extras.nix b/system/services/nextcloud-extras.nix new file mode 100644 index 0000000..9b67aaa --- /dev/null +++ b/system/services/nextcloud-extras.nix @@ -0,0 +1,175 @@ +# Directly ripped from https://github.com/onny/nixos-nextcloud-testumgebung/blob/main/nextcloud-extras.nix + +{ config +, lib +, ... +}: +let + + inherit + (lib) + optionalString + escapeShellArg + types + concatStringsSep + mapAttrsToList + mkIf + mkOption + mkDefault + mkForce + ; + + cfg = config.services.nextcloud; + fpm = config.services.phpfpm.pools.nextcloud; + webserver = config.services.${cfg.webserver}; + +in +{ + + options = { + services.nextcloud = { + + ensureUsers = mkOption { + default = { }; + description = lib.mdDoc '' + List of user accounts which get automatically created if they don't + exist yet. This option does not delete accounts which are not listed + anymore. + ''; + example = { + user1 = { + passwordFile = /secrets/user1-localhost; + email = "user1@localhost"; + }; + user2 = { + passwordFile = /secrets/user2-localhost; + email = "user2@localhost"; + }; + }; + type = types.attrsOf (types.submodule { + options = { + passwordFile = mkOption { + type = types.path; + example = "/path/to/file"; + default = null; + description = lib.mdDoc '' + Specifies the path to a file containing the + clear text password for the user. + ''; + }; + email = mkOption { + type = types.str; + example = "user1@localhost"; + default = null; + }; + }; + }); + }; + + webserver = mkOption { + type = types.enum [ "nginx" "caddy" ]; + default = "nginx"; + description = '' + Whether to use nginx or caddy for virtual host management. + Further nginx configuration can be done by adapting services.nginx.virtualHosts.<name>. + See for further information. + ''; + }; + + }; + }; + + config = mkIf cfg.enable { + + systemd.services.nextcloud-ensure-users = { + enable = true; + script = '' + ${optionalString (cfg.ensureUsers != {}) '' + ${concatStringsSep "\n" (mapAttrsToList (name: cfg: '' + if ${config.services.nextcloud.occ}/bin/nextcloud-occ user:info "${name}" | grep "user not found"; then + export OC_PASS="$(cat ${escapeShellArg cfg.passwordFile})" + ${config.services.nextcloud.occ}/bin/nextcloud-occ user:add --password-from-env "${name}" + fi + if ! ${config.services.nextcloud.occ}/bin/nextcloud-occ user:info "${name}" | grep "user not found"; then + ${optionalString (cfg.email != null) '' + ${config.services.nextcloud.occ}/bin/nextcloud-occ user:setting "${name}" settings email "${cfg.email}" + ''} + fi + '') cfg.ensureUsers)} + ''} + ''; + wantedBy = [ "multi-user.target" ]; + after = [ "nextcloud-setup.service" ]; + }; + + services.phpfpm.pools.nextcloud.settings = { + "listen.owner" = webserver.user; + "listen.group" = webserver.group; + }; + + users.groups.nextcloud.members = [ "nextcloud" webserver.user ]; + + services.nginx = lib.mkIf (cfg.webserver == "caddy") { + enable = mkForce false; + }; + + services.caddy = lib.mkIf (cfg.webserver == "caddy") { + enable = mkDefault true; + virtualHosts."${if cfg.https then "https" else "http"}://${cfg.hostName}" = { + extraConfig = '' + encode zstd gzip + + root * ${config.services.nginx.virtualHosts.${cfg.hostName}.root} + + redir /.well-known/carddav /remote.php/dav 301 + redir /.well-known/caldav /remote.php/dav 301 + redir /.well-known/* /index.php{uri} 301 + redir /remote/* /remote.php{uri} 301 + + header { + Strict-Transport-Security max-age=31536000 + Permissions-Policy interest-cohort=() + X-Content-Type-Options nosniff + X-Frame-Options SAMEORIGIN + Referrer-Policy no-referrer + X-XSS-Protection "1; mode=block" + X-Permitted-Cross-Domain-Policies none + X-Robots-Tag "noindex, nofollow" + -X-Powered-By + } + + php_fastcgi unix/${fpm.socket} { + root ${config.services.nginx.virtualHosts.${cfg.hostName}.root} + env front_controller_active true + env modHeadersAvailable true + } + + @forbidden { + path /build/* /tests/* /config/* /lib/* /3rdparty/* /templates/* /data/* + path /.* /autotest* /occ* /issue* /indie* /db_* /console* + not path /.well-known/* + } + error @forbidden 404 + + @immutable { + path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite + query v=* + } + header @immutable Cache-Control "max-age=15778463, immutable" + + @static { + path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite + not query v=* + } + header @static Cache-Control "max-age=15778463" + + @woff2 path *.woff2 + header @woff2 Cache-Control "max-age=604800" + + file_server + ''; + }; + }; + + }; +} diff --git a/system/services/nextcloud.nix b/system/services/nextcloud.nix new file mode 100644 index 0000000..a4979d3 --- /dev/null +++ b/system/services/nextcloud.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.profile.services.nextcloud; +in +{ + imports = [ ./nextcloud-extras.nix ]; + config = lib.mkIf cfg.enable { + users.groups.nextcloud.members = [ config.profile.user.name ]; + sops.secrets = + let + opts = { + owner = "nextcloud"; + sopsFile = ../../secrets/nextcloud.yaml; + }; + in + { + "nextcloud/homeserver" = opts; + }; + + # Do not set services.nextcloud.home. Issues with sandboxing nature of NixOS. + # Instead uses bind mount and fstab to mount seeked directory to /var/lib/nextcloud. + fileSystems."/nas/nextcloud" = { + device = "/var/lib/nextcloud"; + fsType = "none"; + options = [ "bind" ]; + }; + services.nextcloud = + let + secrets = config.sops.secrets; + in + { + enable = true; + https = true; + webserver = "caddy"; + hostName = "nextcloud.tigor.web.id"; # The nextcloud-extras will ensure Caddy to take care of this. + config = { + adminuser = "homeserver"; + adminpassFile = secrets."nextcloud/homeserver".path; + }; + }; + }; +}