diff --git a/fmt.nix b/fmt.nix index b04cc45..5405df8 100644 --- a/fmt.nix +++ b/fmt.nix @@ -17,6 +17,8 @@ global.excludes = [ "sops/*" "vars/*" + "*/sops/*" + "*/vars/*" "*/.gitignore" "LICENSE" diff --git a/inventories/default.nix b/inventories/default.nix index 0ab58b6..d0280e9 100644 --- a/inventories/default.nix +++ b/inventories/default.nix @@ -9,7 +9,6 @@ clan = { modules = { pocket-id = ../modules/clan/pocket-id; - nextcloud = ../modules/clan/nextcloud; stirling-pdf = ../modules/clan/stirling-pdf; actual-budget = ../modules/clan/actual-budget; victoria-metrics = ../modules/clan/victoria-metrics; diff --git a/machines/b4l/services/nextcloud.nix b/machines/b4l/services/nextcloud.nix new file mode 100644 index 0000000..bb2d3f3 --- /dev/null +++ b/machines/b4l/services/nextcloud.nix @@ -0,0 +1,35 @@ +{ config, pkgs, ... }: +let + ncDomain = "${config.clan.core.vars.generators.nextcloud.files.subdomain.value}.${config.networking.fqdn}"; +in +{ + clan.core.vars.generators.nextcloud = { + files.subdomain.secret = false; + + prompts = { + subdomain = { + persist = true; + type = "line"; + description = "Sub-domain for Nextcloud app. Default:(cloud)"; + }; + }; + + script = ''cat $prompts/subdomain | echo -n "cloud" > $out/subdomain''; + }; + + services.nextcloud = { + hostName = ncDomain; + package = pkgs.nextcloud31; + + settings = { + + overwriteprotocol = "https"; + trusted_domains = [ ]; + trusted_proxies = [ ]; + }; + }; + services.nginx.virtualHosts."${ncDomain}" = { + useACMEHost = "${config.networking.fqdn}"; + forceSSL = true; + }; +} diff --git a/modules/clan/nextcloud/default.nix b/modules/clan/nextcloud/default.nix index 5d823ab..4f0ba63 100644 --- a/modules/clan/nextcloud/default.nix +++ b/modules/clan/nextcloud/default.nix @@ -1,3 +1,4 @@ +{ ... }: { _class = "clan.service"; manifest.name = "nextcloud"; @@ -5,79 +6,45 @@ manifest.categories = [ "System" ]; roles.default = { - interface = - { lib, pkgs, ... }: - { - options = { - domain = lib.mkOption { - type = lib.types.str; - default = "cloud"; - description = "Sub domain for Nextcloud to run."; - }; - package = lib.mkOption { - type = lib.types.package; - description = "Which package to use for the Nextcloud instance."; - }; - }; - }; - perInstance = + perInstance.nixosModule = { - settings, + config, + pkgs, + lib, ... }: { - nixosModule = - { - config, - pkgs, - ... - }: - let - domain = "${settings.domain}.${config.networking.fqdn}"; - nextcloudUser = "nextcloud"; - in - { - clan.core.vars.generators.nextcloud = { - files = { - adminpassFile = { - owner = nextcloudUser; - group = nextcloudUser; - secret = true; - }; - }; - script = '' - xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminpassFile - ''; - runtimeInputs = [ - pkgs.xkcdpass - ]; - }; - services.nextcloud = { - enable = true; - hostName = domain; - package = pkgs.nextcloud31; - database.createLocally = true; - config = { - dbtype = "pgsql"; - dbhost = "/run/postgresql"; - dbuser = nextcloudUser; - dbname = nextcloudUser; - adminuser = "admin"; - adminpassFile = config.clan.core.vars.generators.nextcloud.files.adminpassFile.path; - }; - - settings = { - overwriteprotocol = "https"; - trusted_domains = [ ]; - trusted_proxies = [ ]; - }; - }; - services.nginx.virtualHosts."${domain}" = { - useACMEHost = "${config.networking.fqdn}"; - forceSSL = true; + clan.core.vars.generators.nextcloud = { + files = { + adminpassFile = { + owner = "nextcloud"; + group = "nextcloud"; + secret = true; }; }; + script = '' + xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminpassFile + ''; + runtimeInputs = [ + pkgs.xkcdpass + ]; + }; + + services.nextcloud = { + enable = lib.mkDefault true; + hostName = lib.mkDefault "localhost"; + database.createLocally = lib.mkDefault true; + config = { + dbtype = lib.mkDefault "pgsql"; + dbhost = lib.mkDefault "/run/postgresql"; + dbuser = lib.mkDefault "nextcloud"; + dbname = lib.mkDefault "nextcloud"; + adminuser = lib.mkDefault "admin"; + adminpassFile = lib.mkDefault config.clan.core.vars.generators.nextcloud.files.adminpassFile.path; + }; + + }; }; }; } diff --git a/modules/clan/nextcloud/flake-module.nix b/modules/clan/nextcloud/flake-module.nix new file mode 100644 index 0000000..e715faa --- /dev/null +++ b/modules/clan/nextcloud/flake-module.nix @@ -0,0 +1,19 @@ +{ lib, ... }: +let + module = lib.modules.importApply ./default.nix { }; +in +{ + clan.modules = { + nextcloud = module; + }; + + perSystem = + { ... }: + { + clan.nixosTests.nextcloud = { + imports = [ ./tests/vm/default.nix ]; + + clan.modules."@clan/nextcloud" = module; + }; + }; +} diff --git a/modules/clan/nextcloud/tests/vm/default.nix b/modules/clan/nextcloud/tests/vm/default.nix new file mode 100644 index 0000000..327b5f0 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/default.nix @@ -0,0 +1,36 @@ +{ + ... +}: +{ + name = "service-nextcloud"; + + clan = { + directory = ./.; + inventory = { + machines.server = { }; + + instances = { + nextcloud-test = { + module.name = "@clan/nextcloud"; + module.input = "self"; + roles.default.machines."server" = { }; + }; + }; + }; + }; + + nodes = { + server = { + services.nextcloud = { }; + }; + }; + + testScript = '' + start_all() + + server.wait_for_unit("phpfpm-nextcloud.service") + + # Check that garage is running + server.succeed("systemctl status phpfpm-nextcloud.service") + ''; +} diff --git a/modules/clan/nextcloud/tests/vm/sops/machines/server/key.json b/modules/clan/nextcloud/tests/vm/sops/machines/server/key.json new file mode 100755 index 0000000..6397675 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/sops/machines/server/key.json @@ -0,0 +1,6 @@ +[ + { + "publickey": "age15md5wyqzn4jwc7pgyjkjhcd6nfuct9gxgrl7x5qxdzgvrh32ruvqmk3wfq", + "type": "age" + } +] \ No newline at end of file diff --git a/modules/clan/nextcloud/tests/vm/sops/secrets/server-age.key/secret b/modules/clan/nextcloud/tests/vm/sops/secrets/server-age.key/secret new file mode 100644 index 0000000..c3eb045 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/sops/secrets/server-age.key/secret @@ -0,0 +1,15 @@ +{ + "data": "ENC[AES256_GCM,data:LtzjjbqrzdiFqw5sEI6nYAjLuWJOqiEcO9T8POnjDHK0l55RAxLLzlc1w2DTRPd46vAFy04IYgPiwwQJj8WuYdgjymXTyVqGvNA=,iv:q/L8DpR9E/NNIW2cNFft/e65xGHK9HN19W8ISd6lgdA=,tag:7XFi8VgfG40I0wSHqasXSQ==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxMGF5Q3V5T29ub09XL0Mx\nUVBlSUc2TnRkaGxoQW5uMzUzd04xOWFYRkNBClZ3eVU3dEovWDVZSkR0bnRRY3Bn\nOFNQWDFRckFxVlpvTVRsa01ad0NkRDAKLS0tIGd2UDV3cWZTTkF6V3p4Y3ZKOXdo\nY1doTFoyT2dSaG93b0lGb01YaExDTXMKe4wjgOysbF+NKlnmQgard1N6Xhazex7y\nCuvGnbcy2TLxDNhjdgjoOxUV1xQWnwoYOF1QDbL7l2k59iE3lzUG8Q==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-07-29T03:24:54Z", + "mac": "ENC[AES256_GCM,data:s6W/U0FekNcDdKk9/L54Q0V/XZhrDQwP/moNFbxbucD0sAXzEYMWbWTDNCz6/NVtqr3A++Vk65LFr8bgWuh4uxekXrLDN0Pyb7AJpDkp7IlE6ijT3cQk+OVpcpTt+FgFt3JZLyrmOL/H638sg4c0bptN+Fj8LrNXFdauWCDBlkA=,iv:oiEPi/zvH0m312ezyT0SnUavlX47pduzyz8NIwuCaNs=,tag:e6KkwWAJSZbiliKm4VT6yw==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/modules/clan/nextcloud/tests/vm/sops/secrets/server-age.key/users/admin b/modules/clan/nextcloud/tests/vm/sops/secrets/server-age.key/users/admin new file mode 120000 index 0000000..9e21a99 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/sops/secrets/server-age.key/users/admin @@ -0,0 +1 @@ +../../../users/admin \ No newline at end of file diff --git a/modules/clan/nextcloud/tests/vm/sops/users/admin/key.json b/modules/clan/nextcloud/tests/vm/sops/users/admin/key.json new file mode 100644 index 0000000..e408aa9 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/sops/users/admin/key.json @@ -0,0 +1,4 @@ +{ + "publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "type": "age" +} diff --git a/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/machines/server b/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/machines/server new file mode 120000 index 0000000..2bd819e --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/machines/server @@ -0,0 +1 @@ +../../../../../../sops/machines/server \ No newline at end of file diff --git a/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/secret b/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/secret new file mode 100644 index 0000000..de65119 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/secret @@ -0,0 +1,19 @@ +{ + "data": "ENC[AES256_GCM,data:NVuUW3KNwUUs/Cwswvi4kDo8GZM453y/TRlHWut3OA==,iv:7rSqlQxgJCRecmpNrmGZeT03f1eOuO+W8O2QBkoKdXc=,tag:F9WkMVBV8zh4L86sBA4LVQ==,type:str]", + "sops": { + "age": [ + { + "recipient": "age15md5wyqzn4jwc7pgyjkjhcd6nfuct9gxgrl7x5qxdzgvrh32ruvqmk3wfq", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBic1hPNFdyYzE5UndKNEtj\neDdJc2RuN0Y5WTB2d1h0ZFVJRUpnTnA3TW5JCklqUzFucVNKU3JLeG5JVG1KR05q\ncVg2OFBRNW1RZ0pwWnc2eFlmYzEzZ2MKLS0tIEJod0QvMHBZVlpxMldGdTRmRTNB\nQmVOQ2U2bDd0WTQvRFJnZ2NybFJoTFEKiimfshCLluicTeVyLbFQDm+8JMXBx/n0\n9NwAb4mJwQ8B0qlFsdiXZU4pP02aw7f/NH4hX6BvBBw+SP42plkmfw==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFV3FmNlJHeEhKT3NUVG9K\nNXNGdDlsVmtnWng5dGlIaVNRdXlaWVdNdmhrCi9KLzZYVWxpanlLUzJKVDlRSHlM\nRFFtditYZ1lXY3pFeUNXTk9OVitSd3MKLS0tIERVWHFNZitETlRuNEpDS1FxVS9C\nMk5UNlBjTkNRTFc5T0J1TTlZZm1ZOG8KWwGkEKK8nEWib4Va9lrVFnHU0m0zPjFE\n/3eMObt62ngwrmbAq0bNe2gFiC/OhLDf5BixldSgSeu9AenRz3Mdjg==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-07-29T03:24:55Z", + "mac": "ENC[AES256_GCM,data:B3LUWx3g6P5R006NrsFMZNc466qFadfnlXS5hitToZrNEf9VN3NlINwi2liYf9JjgSXXVV6IybVoW7LYDFRNRrG2QXfvWEfozVr/JtjvufcmuyM96PbzURUfOKndau1GbJagUO4MH3l3AEvkZnSRR3nIKWGYZDiJTNo8yRIK7nw=,iv:IXdWo8y9jPYgII5HRJ6sRxb3WOcKdifDsZoU4tusDuQ=,tag:xdqph+Y2nMYNDD3hbxCcXA==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/users/admin b/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/users/admin new file mode 120000 index 0000000..ca714e1 --- /dev/null +++ b/modules/clan/nextcloud/tests/vm/vars/per-machine/server/nextcloud/adminpassFile/users/admin @@ -0,0 +1 @@ +../../../../../../sops/users/admin \ No newline at end of file diff --git a/shell.nix b/shell.nix index f25e3ba..1fe4b94 100644 --- a/shell.nix +++ b/shell.nix @@ -8,7 +8,10 @@ { devshells.default = { devshell = { - packages = [ inputs.clan-core.packages.${system}.clan-cli ]; + packages = [ + inputs.clan-core.packages.${system}.clan-cli + inputs.clan-core.packages.${system}.generate-test-vars + ]; }; }; }; diff --git a/vars/per-machine/b4l/nextcloud/subdomain/value b/vars/per-machine/b4l/nextcloud/subdomain/value new file mode 100644 index 0000000..ac2564f --- /dev/null +++ b/vars/per-machine/b4l/nextcloud/subdomain/value @@ -0,0 +1 @@ +cloud \ No newline at end of file