Compare commits

..

2 Commits

Author SHA1 Message Date
Lennart J. Kurzweg (Nx2)
245fdbb60f Merge branch 'master' of ssh://ssh.nx2.site:50022/nx2/dotfiles 2026-05-03 00:00:08 +02:00
Lennart J. Kurzweg (Nx2)
6ab13007de nextcloud 2026-05-03 00:00:07 +02:00
8 changed files with 159 additions and 38 deletions

View File

@@ -58,6 +58,7 @@
./system-modules/nx2site/audiobookshelf.nix
# ./system-modules/nx2site/baikal.nix
./system-modules/nx2site/nextcloud.nix
./system-modules/nx2site/nxcaldav.nix
./system-modules/nx2site/copyparty.nix
./system-modules/nx2site/gitea.nix

View File

@@ -37,16 +37,25 @@ nx2site:
password: ENC[AES256_GCM,data:wnXEAWH/aiCbB0FUnAZ73kfhFeNuuvo=,iv:4uVb7f9JBRDjX060fKGc3MwA1wBJuf6QKU6rom+0aIE=,tag:NHikKehpTfeWKT72OXRqdw==,type:str]
paperless.pw: ENC[AES256_GCM,data:IW63GmHCVCIebWg917VNyLjQMQ6LIg8rwg==,iv:7/kSSlWFUV0vaaMfagBM/0IxeMhZ16mYN2ZlKmKFU3Y=,tag:S0cmsYkZP6v6NbhFRiv3Sg==,type:str]
nextcloud:
admin-pass: ENC[AES256_GCM,data:u6k70HwxBKAom8kvUihNjwbYsOikOt4sG1U=,iv:K0XPh1NfaGhFJ0ZVOWqnihZee6uuWxr0Vu8aR0ykr30=,tag:YyxgoVUxk4YxFnDmXkBXpw==,type:str]
db-pass: ENC[AES256_GCM,data:HHY1XolLvLngYQHkfFEYTEmcIR7BSpwQ,iv:hFeuULgGVq+QxzIO0dcBaSlTFP1E7B6tv7BM0EUcTQA=,tag:ZsZyKMSeRLCEB3mZUiBa6w==,type:str]
admin_pass: ENC[AES256_GCM,data:o+ESwFMa9KDBB2gkbWynw4mXUdJV3lSiNg==,iv:fKJAeXOlsJ+ndDYpEbUGKRrojQiv4dqfUJ54CFmDjgw=,tag:eNIEZ7UxWTsD0Zxhs98rLg==,type:str]
db_pass: ENC[AES256_GCM,data:dZoJWk2QQZkTvJpCAH2ag/o1erCX1/M=,iv:40SdyZ3yt8PSdW+2UeEyUYUesqlyYsGLChFOtsP97pI=,tag:zFdh8H5YYUN7pQEe4sjfnw==,type:str]
lennart_pass: ENC[AES256_GCM,data:nQdwsLQua0WTeuwDz0dA2GlXrf6eM7w=,iv:y4RdJOnepMV6BsL811eVJzAj+FdOhox3TR5Za2gs550=,tag:/JJJVajEn17OeP7GqAGy2w==,type:str]
daniel_pass: ENC[AES256_GCM,data:VRrN9+gB2CKneyYZGFnKGDNrlIc7,iv:q0iEdhjUMxq+3PyBgTe8gi7kdx+K29xlU4GH3Glcjlg=,tag:4WnY1LeGyKAFcScgOehrUw==,type:str]
diane_pass: ENC[AES256_GCM,data:7CapmSg7taPaYi5Pbl+dAaTzGqUpgQ==,iv:W76pALNzIQ524BrewO7219O3Ltc5I+H/2Nh8s8yz8YM=,tag:NW8hdSG3ld393QOKB28a1A==,type:str]
georg_pass: ENC[AES256_GCM,data:YdBk2H9VUjDupJVrgv6CZj0fBrM=,iv:lD+DCnLXIoSpbMG0tDmUBg1Gvb2Hw57bX4P7cbHPquE=,tag:0GM/9/D7XbdlI6tSlo1xfA==,type:str]
tessa_pass: ENC[AES256_GCM,data:SinnyQZdRSRT4T8lI0jip1FT8mQfvg==,iv:rUEQGytDe23Xucv7UrvPTseGz32vCh6K+ve9vSi4urI=,tag:sMIp1YqDxiPoGsUylyaLqg==,type:str]
copyparty:
user-password:
nx2: ENC[AES256_GCM,data:55yxXcN1eKvfpjWySw54r2dMlSg9,iv:w9rGUSUkumysj4ti6XqUm+sL0wwU6sgObfCefwfS5Mo=,tag:2TEDwHqU4RzOZ9+oiffGlg==,type:str]
dovecot: ENC[AES256_GCM,data:2pCvTWe4UZmyQNxPZpyfeII8+gezmXkNub0q5tMCzg==,iv:MTN1OU9jEtbl841YBcAGNptwu3kbyBeyIQwUme3/IOM=,tag:qYUsre28bhEDHxN1OLLBIQ==,type:str]
maddy:
nxcaldav_password: ENC[AES256_GCM,data:cpq6OJDPw2moea1LBfisVNIW9qmJeqc=,iv:h2EN4ButO+nIhx8oIATbtRFYrp6bj05vSQ2vJeqDp94=,tag:WEuC3bJ5pGp1VWfZrL7XUg==,type:str]
nextcloud_password: ENC[AES256_GCM,data:dIPqnmOYStsHpra2lZ0+9YA02vLphQ==,iv:qasttDr1EfNtATSXyV9jafemx/v1C173Cxf/x+ZW0MA=,tag:mgWEqKMT5VuKa7eT5kDFNA==,type:str]
nextcloud_password_bcrypt: ENC[AES256_GCM,data:peK83T6fHjy4LIM28pKa4cJzJ/+RzjwbT2VX1uRey6G52cjS0voItAtrElP8lIcVB9DO7bKd5psTQd7PKlU=,iv:ZoLa4slUlJaRepimftj/PPQZp4Ns1nLgPiW0eh9fg7s=,tag:scBrK6h453lVzir4UpZ4Hw==,type:str]
lennart_password: ENC[AES256_GCM,data:a2lTi3j24EowghFITkKd+6UMB/E=,iv:gja6miTo3bTg86nWNeaGwpMgNccX5+HJINI2tgHJBrg=,tag:ScEKrHAb3yeqg3ynLpHFkA==,type:str]
daniel_password: ENC[AES256_GCM,data:AdA+cN++Z1rAm8CbuP60k2/Gu2bJ,iv:yGMbo4s6oUkh5aWJDSiCTeey/tkjKkAbzYRDjMzEnYk=,tag:XjL01czFJ5AHqieVshlMPA==,type:str]
diane_password: ENC[AES256_GCM,data:Lu2mWItrAN0YIInhWLsGPjwFNhks0g==,iv:5KInpqxklKyP78qlMjF40Lt582Fv9RauTT7TmeXan/A=,tag:ZrubtryuYMaA4ewfZeq/xQ==,type:str]
georg_password: ENC[AES256_GCM,data:g7taZiePiPJCJ6Hw9K3bKmXv+eE=,iv:7awlDxneKL9PM3RJKnbt/P6kuum2iX13N8xbLcJHWcI=,tag:Kk8It+J3NZZ0X1XwFm8YGA==,type:str]
tessa_password: ENC[AES256_GCM,data:jUvzfWUj4f0n0HsGopbwF5VhMhuIkw==,iv:r9IxQJNRhU+WhB9vFMLKhcud+Xw7T5iuTsliu9XwVSw=,tag:cz5TsII1tmQw0GsNtrDdQw==,type:str]
nxcaldav:
lennart_password: ENC[AES256_GCM,data:77nhdaJ32JnYY5xwAEQ4RinKFMo=,iv:xFXTxaIqazsLOTv+6rpNJf6+mrkG84hEFRCiT7CnZt4=,tag:DWb59tiXN+EFOJxbDdhoBw==,type:str]
daniel_password: ENC[AES256_GCM,data:BIvizxlUP/bOI/KluXKvXMjKHR3O,iv:GCcuhrCbEky1uzjLxcMEZ2kIrZQXpoAv2OhfOm+HMtk=,tag:iaesITsIsI3E7qrKDDzU+Q==,type:str]
@@ -130,8 +139,8 @@ sops:
MkZGai9DZ3ZzT0I2MmMwRzVkcFhXdlEKLbM/9kCpiXLW8Me4MDq+JFifG7FhwPZS
5t4zNtuLttY3NUwT9KK4g4P+Yl10oNsjcCbGNYTxlIARFEU+X6zwUQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-04-22T15:43:57Z"
mac: ENC[AES256_GCM,data:fgOVEf1z1vKNAyDO/dYpprwFoR4Z/DJkEW02O6mOcmGLa+ipCOjasrC9k8es6CXMqq6HRqSgKO7VLXeVUpKc+99PWEGuhgYzjfQ6sxUFwj6+YLJrkNoiDf6YIid/yY0+H/XirlYiybyg2bCZdN153T556uWR2Mke1C+UkSdmVq4=,iv:BEl/oijLXI7qyjq/H4rL5aQqtd3PmfimHMFS/dF0sxI=,tag:iGWE/CpcS56bFI7cgN86Hg==,type:str]
lastmodified: "2026-05-02T11:46:05Z"
mac: ENC[AES256_GCM,data:6YVu+C4K70yV+rOEMWhMs6/HnjvDMu5JrR2rX1N74XDeTO5XRwYuz6CM5Mo0X6mvq0Ixg9UUaJgpr8azsGOcZSm6pkZOZ5Pa3IFFP8ntNJfI7WPr3mbflu0AI8RY7FAMYhjyhMOs1u790OEZaRNYA0KcPm6qMuuLkj03/MkHmQw=,iv:B81lYn++TqYL1R9lyAi2MU+JD6cwWGQoHKuTMPryGJs=,tag:nOPEj2Ce+ozgN1mZaDeb4g==,type:str]
pgp:
- created_at: "2025-10-06T11:16:18Z"
enc: |-

View File

@@ -91,12 +91,12 @@ def main():
print(f"*.${hyper.domain}: {update_record(record_id="${record_id.sub}", record_name="*.${hyper.domain}", ip=my_ip, type="A", proxied=True, pw=pw).status_code}")
print(f"ssh.${hyper.domain}: {update_record(record_id="${record_id.ssh}", record_name="ssh.${hyper.domain}", ip=my_ip, type="A", proxied=False, pw=pw).status_code}")
print(f"dev.${hyper.domain}: {update_record(record_id="${record_id.dev}", record_name="dev.${hyper.domain}", ip=my_ip, type="A", proxied=False, pw=pw).status_code}")
print(f"mail.${hyper.domain}: {update_record(record_id="${record_id.dev}", record_name="mail.${hyper.domain}", ip=my_ip, type="A", proxied=False, pw=pw).status_code}")
print(f"mail.${hyper.domain}: {update_record(record_id="${record_id.mail}", record_name="mail.${hyper.domain}", ip=my_ip, type="A", proxied=False, pw=pw).status_code}")
print(f"${hyper.domain}: {update_record(record_id="${record_id.base6}", record_name="${hyper.domain}", ip=my_ip6, type="AAAA", proxied=True, pw=pw).status_code}")
print(f"*.${hyper.domain}: {update_record(record_id="${record_id.sub6}", record_name="*.${hyper.domain}", ip=my_ip6, type="AAAA", proxied=True, pw=pw).status_code}")
print(f"ssh.${hyper.domain}: {update_record(record_id="${record_id.ssh6}", record_name="ssh.${hyper.domain}", ip=my_ip6, type="AAAA", proxied=False, pw=pw).status_code}")
print(f"mail.${hyper.domain}: {update_record(record_id="${record_id.ssh6}", record_name="mail.${hyper.domain}", ip=my_ip6, type="AAAA", proxied=False, pw=pw).status_code}")
print(f"mail.${hyper.domain}: {update_record(record_id="${record_id.mail6}", record_name="mail.${hyper.domain}", ip=my_ip6, type="AAAA", proxied=False, pw=pw).status_code}")
if __name__ == "__main__":
main()

View File

@@ -1,8 +1,12 @@
{ config, pkgs, ... }@all: with all; {
sops.secrets = {
"nx2site/maddy/nxcaldav_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
"nx2site/maddy/nextcloud_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
"nx2site/maddy/lennart_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
"nx2site/maddy/daniel_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
"nx2site/maddy/diane_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
"nx2site/maddy/georg_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
"nx2site/maddy/tessa_password" = { owner = "maddy"; group = "maddy"; mode = "600"; };
};
users.users."maddy" = {
extraGroups = [ "acme" "nginx" ];
@@ -15,13 +19,21 @@
hostname = "mail.${hyper.domain}";
ensureAccounts = [
"nxcaldav@${hyper.domain}"
"nextcloud@${hyper.domain}"
"lennart@${hyper.domain}"
"daniel@${hyper.domain}"
"diane@${hyper.domain}"
"georg@${hyper.domain}"
"tessa@${hyper.domain}"
];
ensureCredentials = {
"nxcaldav@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/nxcaldav_password".path;
"nextcloud@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/nextcloud_password".path;
"lennart@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/lennart_password".path;
"daniel@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/daniel_password".path;
"diane@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/diane_password".path;
"georg@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/georg_password".path;
"tessa@${hyper.domain}".passwordFile = config.sops.secrets."nx2site/maddy/tessa_password".path;
};
openFirewall = true;
@@ -34,12 +46,28 @@
};
# Enable TLS listeners. Configuring this via the module is not yet
# implemented, see https://github.com/NixOS/nixpkgs/pull/153372
config = builtins.replaceStrings [
config = (builtins.replaceStrings [
"imap tcp://0.0.0.0:143"
"submission tcp://0.0.0.0:587"
] [
"imap tls://0.0.0.0:993 tcp://0.0.0.0:143"
"submission tls://0.0.0.0:465 tcp://0.0.0.0:587"
] options.services.maddy.config.default;
] options.services.maddy.config.default) + ''
smtp tcp://127.0.0.1:2525 {
tls off
# 1. Allow local delivery (e.g., app sending to admin@nx2.site)
destination postmaster $(local_domains) {
deliver_to &local_routing
}
# 2. Allow remote delivery (e.g., app sending to gmail.com)
default_destination {
modify {
# Ensure outgoing mail is signed even if sent via 2525
dkim $(primary_domain) $(local_domains) default
}
deliver_to &remote_queue
}
}
'';
};
}

View File

@@ -1,27 +1,98 @@
{ pkgs, ...}@all: with all;
{
sops.secrets = {
"nx2site/nextcloud/admin-pass" = { owner = "nextcloud"; };
"nx2site/nextcloud/db-pass" = { owner = "nextcloud"; };
# "nx2site/nextcloud/users-pass/nx2" = { owner = "nextcloud"; };
{ config, pkgs, ... }@all: with all; let
user = "nextcloud";
in {
sops.secrets = let ss = { owner = user; group = user; mode = "777"; }; in {
"nx2site/nextcloud/admin_pass" = ss;
"nx2site/nextcloud/db_pass" = ss;
"nx2site/nextcloud/lennart_pass" = ss;
"nx2site/nextcloud/daniel_pass" = ss;
"nx2site/nextcloud/diane_pass" = ss;
"nx2site/nextcloud/georg_pass" = ss;
"nx2site/nextcloud/tessa_pass" = ss;
};
services = {
nextcloud = {
enable = true;
package = pkgs.nextcloud;
hostName = "nc.${hyper.domain}";
https = true;
configureRedis = true;
config = {
adminpassFile = config.sops.secrets."nx2site/nextcloud/admin-pass".path;
adminuser = "nx2";
dbtype = "pgsql";
# dbhost = config.services.postgresql.settings.port; # using usix socket
dbname = "nextcloud";
dbpassFile = config.sops.secrets."nx2site/nextcloud/db-pass".path;
};
users.users."${user}" = {
isSystemUser = true;
isNormalUser = false;
group = user;
};
# users.groups."${user}" = {};
users.groups.nextcloud.members = [ "nextcloud" config.services.nginx.user ];
services.nextcloud = {
enable = true;
hostName = "n.${hyper.domain}";
# Need to manually increment with every major upgrade.
package = pkgs.nextcloud33;
# Let NixOS install and configure the database automatically.
# database.createLocally = false;
# Let NixOS install and configure Redis caching automatically.
configureRedis = true;
# Increase the maximum file upload size.
maxUploadSize = "16G";
https = true;
# autoUpdateApps.enable = true;
appstoreEnable = false;
extraAppsEnable = true;
extraApps = with config.services.nextcloud.package.packages.apps; {
inherit calendar contacts notes tasks;
};
settings = {
overwriteProtocol = "https";
default_phone_region = "DE";
"mail_smtpmode" = "smtp";
"mail_smtphost" = "127.0.0.1";
"mail_smtpport" = 2525;
"mail_from_address" = "nextcloud";
"mail_domain" = hyper.domain;
"mail_smtpsecure" = ""; # = STARTTLS
# "mail_smtpauth" = true;
# "mail_smtpauthtype" = "LOGIN";
# "mail_smtpname" = "nextcloud@${hyper.domain}";
};
secrets."mail_smtppassword" = config.sops.secrets."nx2site/maddy/nextcloud_password".path;
# secrets.settings."mail_smtppassword" = config.sops.secrets."nx2site/maddy/nextcloud_password".path;
config = {
adminpassFile = config.sops.secrets."nx2site/nextcloud/admin_pass".path;
dbtype = "pgsql";
adminuser = "nextcloud";
# dbhost = "localhost:5432";
dbhost = "/run/postgresql";
dbname = "nextcloud";
dbuser = "nextcloud";
dbpassFile = config.sops.secrets."nx2site/nextcloud/db_pass".path;
};
phpOptions = {
"memory_limit" = pkgs.lib.mkForce "2G";
"opcache.interned_strings_buffer" = "16";
};
};
systemd.services.nextcloud-ensure-users = let
users = pkgs.lib.mergeAttrsList (pkgs.lib.map (name: {
"${name}" = {
email = "${name}@nx2.site";
passwordFile = config.sops.secrets."nx2site/nextcloud/${name}_pass".path;
};
}) [ "lennart" "daniel" "diane" "georg" "tessa" ]);
in {
enable = true;
script = let occ = "${config.services.nextcloud.occ}/bin/nextcloud-occ"; in /* bash */ ''
${pkgs.lib.optionalString (users != {}) ''
${pkgs.lib.concatStringsSep "\n" (pkgs.lib.mapAttrsToList (name: cfg: ''
if ${occ} user:info "${name}" | grep "user not found"; then
export OC_PASS="$(cat ${pkgs.lib.escapeShellArg cfg.passwordFile})"
${occ} user:add --password-from-env "${name}"
fi
${pkgs.lib.optionalString (cfg.email != null) ''
${occ} user:setting "${name}" settings email "${cfg.email}"
''}
'') users)}
''}
'';
wantedBy = [ "multi-user.target" ];
after = [ "nextcloud-setup.service" ];
};
services.phpfpm.pools.nextcloud.settings = pkgs.lib.mkIf config.services.nextcloud.enable {
"listen.owner" = config.services.nginx.user;
"listen.group" = config.services.nginx.group;
};
}

View File

@@ -112,6 +112,10 @@
User = user;
Group = user;
ExecStart = ''${nxc}/bin/nxcaldav -c ${cfg}'';
Restart = "on-failure";
RestartSec = 5;
StartLimitBurst = 5;
StartLimitIntervalSec = 60;
};
};
}

View File

@@ -173,6 +173,14 @@
listen = dl;
locations = { "/" = { proxyPass = "http://127.0.0.1:14243"; }; };
});
"n.${hyper.domain}" = {
listen = dl;
forceSSL = true;
enableACME = true;
# rest is done by the nextcloud module
};
# "nc.${hyper.domain}" = vh // {
# # directly to nc
# };
@@ -240,7 +248,7 @@
};
};
};
"~^(.*).${hyper.domain}$" = {
"~^(?!n\.)(.*)\.${hyper.domain}$" = {
listen = dl;
root = "/var/nginx/webroot";
locations."~.*".return = "502";

View File

@@ -27,8 +27,8 @@
"gitea"
"vaultwarden"
"paperless"
"nextcloud"
"nxcaldav"
"nextcloud"
];
settings = {
port = 5432; # default
@@ -47,10 +47,6 @@
name = "vaultwarden";
ensureDBOwnership = true;
}
{
name = "nextcloud";
ensureDBOwnership = true;
}
{
name = "paperless";
ensureDBOwnership = true;
@@ -59,6 +55,10 @@
name = "nxcaldav";
ensureDBOwnership = true;
}
{
name = "nextcloud";
ensureDBOwnership = true;
}
];
};
postgresqlBackup = {