From b354dc202add41beac0a626c8ec04b9841d32c58 Mon Sep 17 00:00:00 2001 From: mjallen18 Date: Wed, 8 Apr 2026 16:07:48 -0500 Subject: [PATCH] nas --- modules/nixos/services/nextcloud/default.nix | 67 ++++++++++++++++++-- secrets/nas-secrets.yaml | 9 ++- systems/x86_64-linux/jallen-nas/sops.nix | 8 +++ 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/modules/nixos/services/nextcloud/default.nix b/modules/nixos/services/nextcloud/default.nix index 474a547..05bf435 100755 --- a/modules/nixos/services/nextcloud/default.nix +++ b/modules/nixos/services/nextcloud/default.nix @@ -160,20 +160,75 @@ let ) null config.systemd.tmpfiles.rules; overrideStorePath = if overrideLine != null then lib.last (lib.splitString " " overrideLine) else null; + + # Bootstrap config.php written when the file is absent/empty. + # Satisfies Nextcloud's Config.php writeData() guard (needs 'version') + # and the setup script's `-s` check (needs non-empty file). + # passwordsalt/secret/instanceid are intentionally left empty here — + # they must be populated manually or via SOPS before first use. + bootstrapConfig = pkgs.writeText "nextcloud-bootstrap-config.php" ( + " true,\n" + + " 'version' => '${config.services.nextcloud.package.version}',\n" + + " 'datadirectory' => '${cfg.dataDir}/nextcloud/data',\n" + + " 'dbtype' => 'pgsql',\n" + + " 'dbname' => 'nextcloud',\n" + + " 'dbhost' => '/run/postgresql',\n" + + " 'dbuser' => 'nextcloud',\n" + + " 'dbpassword' => " + + "''" + + ",\n" + + " 'instanceid' => " + + "''" + + ",\n" + + " 'passwordsalt' => " + + "''" + + ",\n" + + " 'secret' => " + + "''" + + ",\n" + + "];\n" + ); in lib.mkIf (overrideStorePath != null) { - # systemd-tmpfiles refuses to create the override.config.php symlink because - # /media/nas/main is owned by nix-apps (not root/nextcloud), triggering an - # "unsafe path transition" error. Work around this by creating the symlink - # directly as root (the '+' prefix) before the setup script's ownership check. - # The target store path is resolved at Nix eval time so it is always current. + # systemd-tmpfiles refuses to create paths under /media/nas/main because + # of an "unsafe path transition" (owned by nix-apps, not root/nextcloud). + # Work around by creating the required dirs/symlinks as root ('+' prefix) + # before the setup script's ownership check runs. ExecStartPre = [ ( "+" + pkgs.writeShellScript "nextcloud-fix-override-config" '' - dest="${cfg.dataDir}/nextcloud/config/override.config.php" + ncdir="${cfg.dataDir}/nextcloud" + + # Ensure required directories exist with correct ownership + for dir in "$ncdir" "$ncdir/config" "$ncdir/data" "$ncdir/store-apps"; do + if [ ! -d "$dir" ]; then + ${pkgs.coreutils}/bin/mkdir -p "$dir" + fi + ${pkgs.coreutils}/bin/chown nextcloud:nextcloud "$dir" + ${pkgs.coreutils}/bin/chmod 0750 "$dir" + done + + # override.config.php symlink (updated each generation) + dest="$ncdir/config/override.config.php" echo "Creating symlink: $dest -> ${overrideStorePath}" ${pkgs.coreutils}/bin/ln -sf "${overrideStorePath}" "$dest" + + # If config.php is absent or empty, copy in a bootstrap stub. + # Nextcloud's Config.php writeData() guard requires 'version' in the + # merged cache, and the setup script's -s check requires a non-empty + # file. The real runtime settings come from override.config.php via + # array_replace_recursive; this stub just satisfies those two guards. + cfgfile="$ncdir/config/config.php" + if [ ! -s "$cfgfile" ]; then + echo "Writing bootstrap config.php" + ${pkgs.coreutils}/bin/cp ${bootstrapConfig} "$cfgfile" + ${pkgs.coreutils}/bin/chown nextcloud:nextcloud "$cfgfile" + ${pkgs.coreutils}/bin/chmod 0640 "$cfgfile" + fi '' ) ]; diff --git a/secrets/nas-secrets.yaml b/secrets/nas-secrets.yaml index 407f95d..9e300fa 100755 --- a/secrets/nas-secrets.yaml +++ b/secrets/nas-secrets.yaml @@ -23,7 +23,10 @@ jallen-nas: redis_nextcloud: ENC[AES256_GCM,data:mllmOV98zpqLPhI=,iv:Vl52jKAfzy+aCqpGYUQ80Ye3sGDAR/3ULSStEjAi1hg=,tag:DwUT2cdQ/BA1TwdnXoElXA==,type:str] nextcloud: dbpassword: ENC[AES256_GCM,data:kvBa4tUglGHuLH0=,iv:IUWHIH6vx6QlXaKNyq2l0lZGZvudskCW9+jCZ2oENVs=,tag:2UC565EXzGxb2N4XO43ydw==,type:str] - adminpassword: ENC[AES256_GCM,data:UJ4LBpif5TIOJqY=,iv:28UgOD1LIoHOVBPTQ3MpofjdkBwY3ghLK2vIbTwZQaA=,tag:F/77ApazlfppzQG6UdTQdQ==,type:str] + adminpassword: ENC[AES256_GCM,data:3Fa9ryPgmWKH9A8=,iv:/iji/991Ijb4r0VLA4QlQBbt18evzGUtoJbQEo+hHqM=,tag:RKyS79eM0Pp4aFt6Z7RmWw==,type:str] + instanceid: ENC[AES256_GCM,data:3wNXF951lMRkpxBdpfA=,iv:97sxghu9Yp8lxOUQti4lR1UPXnBP1gpMJwIV5bw4TKc=,tag:ZoI4FHyQA+71bOM9J0vzLw==,type:str] + passwordsalt: ENC[AES256_GCM,data:mg7arfQVC7WnO3/g7cXxf4t9fW+5cev1AbhmuN+QJu3aCuQJCD56,iv:AtM9sbmOLKns3EEErIe+VKzjS/8sCLeKr804G51gAzU=,tag:cf/jRMSKXUC4L4gc4bgs0A==,type:str] + secret: ENC[AES256_GCM,data:5oDcVaF1fYLy/XhwkXrM/vwA2+94sTK9Xjg4se23sxvgupGnzlAoEw6WCDJGZHnb1PqGLSiNDFBgHsMR,iv:8U5aVb9gv12lMB/GMezPkNgwOX/ylBMFQAqvyr59Cig=,tag:MWzDd/SDl0OUp1m0lsNNAw==,type:str] smtp_settings: ENC[AES256_GCM,data:8KyWmx+e/DouS8OucMrd2AMFE9w1b4WKHr8RuJ8kMqSlL7MP5GLwW4WZhPCJto6kTzAsy4WPFb23oG6UbQg9DK7b2CiUoC5S5mcDxX3lnzX7clyrosDvIHqVlwjamtgfCuNJWcT+RB6a91T84HEDTnKMTsiJvLxpSEHehzL3ItndV9p4+JTs5tZFX+dOZgqVIMN9syQqFsSpI6fk8LNJh90rXXg4jkh7+EFjmBk3QoSOuI1z4JiRpiauVP23VwTtTqiL1Aw8NpDhX1bU0RL+DAWQIZd8o9k/oedziCfKuea73yq4Z8uDaZJ3BW5m1Z1QA44Yu08qvKzBiAAnEb3bQ83ltWI2mfygupjm3tfIVfQoMB8scivaN+5Nlkx3u8f9SAzxyuvqYxZx8TDsyWGEG6p2frHxX72qxu/xb+DYrXBpyDkVA6ng,iv:CqS+/0kL4JmPXRc05Zr2+CFksP1RhOvzIr732z6A1bw=,tag:ux0ja/g1Y40c21hslYnorA==,type:str] gitea: mail-key: ENC[AES256_GCM,data:kfurnrj8eNKGw+KZcijs4jhJgQ==,iv:mFNVcxVyOj5Se/SyLOcKh5ja/QJmL8wfejzSGOzq6yo=,tag:XBU3urrqarICO7niqBRNbA==,type:str] @@ -245,8 +248,8 @@ sops: L0gwQm5takNjMkVGNzVlSStJYlUwWDAKP8QA3rRUHYbyyhPC/k0Eq2EIKfjyc7Co 7BkHH3msC6h9g42BB5iIYe6KQ+UGxMQBFvp+qSB27jaIfajN5MP0BA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-03-30T01:56:41Z" - mac: ENC[AES256_GCM,data:U7xBMz0kJd2fF81rCRD0x4g573lEUnn2Q8e6V/0zgwzoaC39VyZ3RBAUVBS+5d4GSTjrU82sucSNYBZphOGODdgnmL7jSBwaKxg4co9fjuABFmn5WFKJgsw07F48/F2DraftSlRoq1YYkzOhiravgVyWU6aC7o5av+nFVhhfcrM=,iv:bnGpEY6mjPrmeJ+bQdZkXQPTzkBxmIy+5B8/dtJDLmM=,tag:OqvH+y5vjQryzyMUof4isA==,type:str] + lastmodified: "2026-04-08T20:48:03Z" + mac: ENC[AES256_GCM,data:iwAX9cd47lppnht7Tvu5lHxuMLrZ9GMAQpcAyZC+GkFV6P+Kkda1lxphuMKkntEeSkEbjG1Ca29bkhKQ1M7HxPnmV2ORIYqHz15ZQXcGnKyW5cj2mSn9skPlTjMY8VzN8LHhHWWba54EzG6b6fsKuYhtnZZiQWnXS4bZQeRxPB4=,iv:QaNu/kEXCkuSQ+METVL5pag1JrYLZoPeUyl4dnlzTew=,tag:7G7a6vTORnb+PFT8VdB9cg==,type:str] pgp: - created_at: "2026-02-06T15:34:30Z" enc: |- diff --git a/systems/x86_64-linux/jallen-nas/sops.nix b/systems/x86_64-linux/jallen-nas/sops.nix index 0b39ab1..85e6910 100755 --- a/systems/x86_64-linux/jallen-nas/sops.nix +++ b/systems/x86_64-linux/jallen-nas/sops.nix @@ -123,6 +123,14 @@ in # nextcloud # ------------------------------ + # instanceid / passwordsalt / secret are written into config.php at + # install time. Store them here so the bootstrap stub in the nextcloud + # module can restore config.php if it ever gets zeroed again. + # Add to nas-secrets.yaml via: sops secrets/nas-secrets.yaml + # jallen-nas/nextcloud/instanceid: + # jallen-nas/nextcloud/passwordsalt: + # jallen-nas/nextcloud/secret: + "jallen-nas/nextcloud/dbpassword" = sopsSettings // { mode = "0650"; restartUnits = [ "nextcloud.service" ];