🏡 my personal home lab
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

simplify kitchenowl

+62 -85
+6 -2
modules/home-assistant.nix
··· 65 65 }; 66 66 }; 67 67 68 - sops.secrets.zigbee2mqtt-mosquitto-password = { }; 69 - sops.secrets.zigbee2mqtt-mosquitto-password-hashed = { }; 68 + sops.secrets.zigbee2mqtt-mosquitto-password = { 69 + owner = "zigbee2mqtt"; 70 + }; 71 + sops.secrets.zigbee2mqtt-mosquitto-password-hashed = { 72 + owner = "mosquitto"; 73 + }; 70 74 71 75 networking.firewall.allowedTCPPorts = [ 72 76 8123
+2 -2
modules/immich.nix
··· 29 29 services.postgresqlBackup = { 30 30 enable = true; 31 31 databases = [ "immich" ]; 32 - location = "/mnt/nas/backup/immich/db"; 32 + location = "/mnt/nas/backup/postgresql"; 33 33 startAt = "daily"; 34 34 }; 35 35 ··· 48 48 "/run/current-system/sw/bin/bash" 49 49 "-c" 50 50 '' 51 - dir=/mnt/nas/backup/immich/db 51 + dir=/mnt/nas/backup/postgresql 52 52 # keep first of each month 53 53 for f in "$dir"/immich.sql.gz.*; do 54 54 [ -f "$f" ] || continue
+52 -78
modules/kitchenowl.nix
··· 1 - { config, ... }: 1 + { config, lib, ... }: 2 2 { 3 3 virtualisation.oci-containers = { 4 4 backend = "podman"; ··· 6 6 kitchenowl-web = { 7 7 image = "tombursch/kitchenowl-web:latest"; 8 8 dependsOn = [ "kitchenowl" ]; 9 + ports = [ "9080:80" ]; 9 10 environment = { 10 - BACK_URL = "localhost:5000"; 11 + BACK_URL = "kitchenowl:5000"; 11 12 }; 12 - extraOptions = [ "--pod=kitchenowl-pod" ]; 13 13 }; 14 14 15 15 kitchenowl = { 16 16 image = "tombursch/kitchenowl-backend:latest"; 17 17 environmentFiles = [ config.sops.templates."kitchenowl.env".path ]; 18 - volumes = [ "/var/lib/kitchenowl:/data" ]; 19 - dependsOn = [ "kitchenowl-db" ]; 20 - extraOptions = [ "--pod=kitchenowl-pod" ]; 21 - }; 22 - 23 - kitchenowl-db = { 24 - image = "postgres:18"; 25 - environmentFiles = [ config.sops.templates."kitchenowl-db.env".path ]; 26 - volumes = [ "/var/lib/kitchenowl-db:/var/lib/postgresql" ]; 27 - extraOptions = [ "--pod=kitchenowl-pod" ]; 18 + volumes = [ 19 + "/var/lib/kitchenowl:/data" 20 + "/run/postgresql:/run/postgresql" 21 + ]; 28 22 }; 29 23 }; 30 24 }; 31 25 32 - systemd.services.kitchenowl-pod = { 33 - serviceConfig = { 34 - Type = "oneshot"; 35 - RemainAfterExit = true; 36 - ExecStart = "${config.virtualisation.podman.package}/bin/podman pod create --name kitchenowl-pod -p 9080:80"; 37 - ExecStop = "${config.virtualisation.podman.package}/bin/podman pod rm -f kitchenowl-pod"; 38 - }; 39 - wantedBy = [ "multi-user.target" ]; 26 + services.postgresql = { 27 + enable = true; 28 + ensureDatabases = [ "kitchenowl" ]; 29 + ensureUsers = [ 30 + { 31 + name = "kitchenowl"; 32 + ensureDBOwnership = true; 33 + } 34 + ]; 35 + authentication = lib.mkAfter '' 36 + local kitchenowl kitchenowl trust 37 + ''; 40 38 }; 41 39 42 - systemd.services.podman-kitchenowl-web = { 43 - after = [ "kitchenowl-pod.service" ]; 44 - requires = [ "kitchenowl-pod.service" ]; 45 - }; 46 - systemd.services.podman-kitchenowl = { 47 - after = [ "kitchenowl-pod.service" ]; 48 - requires = [ "kitchenowl-pod.service" ]; 49 - }; 50 - systemd.services.podman-kitchenowl-db = { 51 - after = [ "kitchenowl-pod.service" ]; 52 - requires = [ "kitchenowl-pod.service" ]; 40 + services.postgresqlBackup = { 41 + enable = true; 42 + databases = [ "kitchenowl" ]; 43 + location = "/mnt/nas/backup/postgresql"; 44 + startAt = "daily"; 53 45 }; 54 46 55 - sops.templates."kitchenowl.env".content = '' 56 - JWT_SECRET_KEY=${config.sops.placeholder.kitchenowl-jwt-secret} 57 - DB_DRIVER=postgresql 58 - DB_HOST=localhost 59 - DB_PORT=5432 60 - DB_NAME=kitchenowl 61 - DB_USER=kitchenowl 62 - DB_PASSWORD=${config.sops.placeholder.kitchenowl-db-password} 63 - FRONT_URL=https://kitchen.goo.garden 64 - OIDC_ISSUER=https://id.goo.garden 65 - OIDC_CLIENT_ID=${config.sops.placeholder.kitchenowl-oidc-client-id} 66 - OIDC_CLIENT_SECRET=${config.sops.placeholder.kitchenowl-oidc-client-secret} 67 - OPEN_REGISTRATION=false 68 - ''; 69 - sops.templates."kitchenowl-db.env".content = '' 70 - POSTGRES_DB=kitchenowl 71 - POSTGRES_USER=kitchenowl 72 - POSTGRES_PASSWORD=${config.sops.placeholder.kitchenowl-db-password} 73 - ''; 74 - 75 - sops.secrets.kitchenowl-jwt-secret = { }; 76 - sops.secrets.kitchenowl-db-password = { }; 77 - sops.secrets.kitchenowl-oidc-client-id = { }; 78 - sops.secrets.kitchenowl-oidc-client-secret = { }; 79 - 80 - systemd.services.kitchenowl-db-backup = { 81 - description = "Backup KitchenOwl PostgreSQL database"; 47 + systemd.services.kitchenowl-db-backup-rotate = { 48 + description = "Rotate KitchenOwl DB backups"; 82 49 after = [ 83 - "podman-kitchenowl-db.service" 50 + "postgresqlBackup-kitchenowl.service" 84 51 "mnt-nas.mount" 85 52 ]; 86 53 requires = [ "mnt-nas.mount" ]; 54 + wantedBy = [ "postgresqlBackup-kitchenowl.service" ]; 87 55 serviceConfig = { 88 56 Type = "oneshot"; 89 57 ExecStart = toString [ 90 58 "/run/current-system/sw/bin/bash" 91 59 "-c" 92 60 '' 93 - dir=/mnt/nas/backup/kitchenowl/db 94 - mkdir -p "$dir" 95 - f="$dir/kitchenowl-$(date +%F).dump" 96 - ${config.virtualisation.podman.package}/bin/podman exec kitchenowl-db pg_dump -Fc -U kitchenowl kitchenowl > "$f.tmp" && mv "$f.tmp" "$f" 97 - # rotate: keep 14 daily, first of month for 90 days 98 - for old in "$dir"/kitchenowl-*.dump; do 99 - [ -f "$old" ] || continue 100 - age=$(( ($(date +%s) - $(date -r "$old" +%s)) / 86400 )) 101 - day=$(date -r "$old" +%d) 61 + dir=/mnt/nas/backup/postgresql 62 + for f in "$dir"/kitchenowl.sql.gz.*; do 63 + [ -f "$f" ] || continue 64 + age=$(( ($(date +%s) - $(date -r "$f" +%s)) / 86400 )) 65 + day=$(date -r "$f" +%d) 102 66 if [ "$age" -gt 14 ] && [ "$day" != "01" ]; then 103 - rm -f "$old" 67 + rm -f "$f" 104 68 elif [ "$age" -gt 90 ]; then 105 - rm -f "$old" 69 + rm -f "$f" 106 70 fi 107 71 done 108 72 '' ··· 110 74 }; 111 75 }; 112 76 113 - systemd.timers.kitchenowl-db-backup = { 114 - wantedBy = [ "timers.target" ]; 115 - timerConfig = { 116 - OnCalendar = "daily"; 117 - Persistent = true; 118 - }; 119 - }; 77 + sops.templates."kitchenowl.env".content = '' 78 + JWT_SECRET_KEY=${config.sops.placeholder.kitchenowl-jwt-secret} 79 + DB_DRIVER=postgresql 80 + DB_HOST=/run/postgresql 81 + DB_NAME=kitchenowl 82 + DB_USER=kitchenowl 83 + FRONT_URL=https://kitchen.goo.garden 84 + OIDC_ISSUER=https://id.goo.garden 85 + OIDC_CLIENT_ID=${config.sops.placeholder.kitchenowl-oidc-client-id} 86 + OIDC_CLIENT_SECRET=${config.sops.placeholder.kitchenowl-oidc-client-secret} 87 + OPEN_REGISTRATION=false 88 + ''; 89 + 90 + sops.secrets.kitchenowl-jwt-secret = { }; 91 + 92 + sops.secrets.kitchenowl-oidc-client-id = { }; 93 + sops.secrets.kitchenowl-oidc-client-secret = { }; 120 94 121 95 networking.firewall.allowedTCPPorts = [ 9080 ]; 122 96 }
+2 -3
secrets/secrets.yaml
··· 7 7 restic-password: ENC[AES256_GCM,data:JnJpfpHbVVrnwmOcTQAr1JG+l/6IBC5Jpahw0tlK/VKORL2EQzQEYNLURxPbfwReKrUpsZf3x7B9,iv:iidvEALfAQEGwrHlHL4pXP4ICkhM49v1a3vP480RJ+k=,tag:LZOwGksaXS2ok9pZtO+XuA==,type:str] 8 8 pocket-id-encryption-key: ENC[AES256_GCM,data:GotMtKCXugB+qNvMPRoLHLNFfb60+ngX+ykfInbK1QmRv8SME1+gEjFb08XzodzuydlAKqdR/0svIZPw88YA4g==,iv:7ub4AxT6Dnrr/aE5Wvuyp5hWk8D+zNUMG+P6bYLWGVM=,tag:SlKYIB59TX4lEedgUWBHFw==,type:str] 9 9 kitchenowl-jwt-secret: ENC[AES256_GCM,data:legJFjeCURS2aiVBm5rY9Yz4/9cje22zMn6nRbLfliHSI3Bj2viVvsSCvOnvR+VxCcoJYwPhJPmaMGlCf5LV6g==,iv:vbygH1lPayQeoyemFNLqxJy6N24VvxC4qzj0UKceF9Q=,tag:QPO0/0G9xfpLUg6rjtiEKQ==,type:str] 10 - kitchenowl-db-password: ENC[AES256_GCM,data:dLbd7ikyUqudXHpdohzwoSGdR4XwrDJpiV5Zxvfvm+kyDgLyoNFeIR2riMxAwSXgoOwNxpsNe9Zhtm6sdsVwTg==,iv:KlVfJwJDGxqzCq3e+208vhtTxA736s6mbweF9Dbjzq8=,tag:AvDPlFZk+7UpeuIL0RAhEA==,type:str] 11 10 kitchenowl-oidc-client-id: ENC[AES256_GCM,data:ifQHYZP6Z3H1SQkQ8XRaZ//GuWf6Jn98+q3nXs7QXGu8QywO,iv:1jfTO846YR57WwCGhVEoxHQZr2W92Z7pWDYPceHDMYo=,tag:BOf81pF/tWDE2Z7/tTHV0g==,type:str] 12 11 kitchenowl-oidc-client-secret: ENC[AES256_GCM,data:rAaxP7OZoQ/soElu10BYnI7L1Fze3AwXkZE1geZ87jE=,iv:nZpHxJZPRndNpAJVrB6YsKPS1SgovfcFIZ9XtP+8dEY=,tag:N6ew5wyFhZChIf5yBV/bVQ==,type:str] 13 12 immich-db-password: ENC[AES256_GCM,data:fnhbOlPlidS0mPV/ehJbauutyDgzycTseHNfR33/MUQl6bE8bZ8aWRpRbqHtUy1UfxjJfoeJF5C+IcJTGYXRdA==,iv:faUyWBEy73G5GOrtI+NUODLzyV10ISOIZ+JJLGPv8zA=,tag:jqhVAo+JYYuFdqi7Zpn89A==,type:str] ··· 63 62 ajA5bDZCY1BnblVYRGQ1QTE2S2I4M2cKSIGmFBP6sqiiM+cvTMQuZHit9fN5Vffk 64 63 1pWz8xSen/tqoywqipRf3LqzFb2K7Bx15vwazHbm6LJJa+ZQaruVMg== 65 64 -----END AGE ENCRYPTED FILE----- 66 - lastmodified: "2026-03-24T16:07:14Z" 67 - mac: ENC[AES256_GCM,data:Vi4nG2qoP+BxCmdPYfE2UhieRuks/HtJcjZW8RxpKHdR+2TGcd6wMSWBvWcbA6eEgnckpYdU9Si/SDncfLl5VTx2k6EcoM5cbke9V5rz8+C4tNBOB0b8aOa8YRcF5U8oLAqhA/Xg54ltdHqjlo5JFZgbN7+XLeQvMNJm3CD8zmA=,iv:2i1bh/93Bw+CuSFsic5IxdqcHmF/HEmrj+KcAgkilns=,tag:MbmWiHrZbSj3g39WoCTwKQ==,type:str] 65 + lastmodified: "2026-03-24T22:16:27Z" 66 + mac: ENC[AES256_GCM,data:nDb+jCMETbVmW5BWRuxGYRqbcci8pmFf6MKfFnAfA623vlEqTPH4zj7M/E5dHv6vruvk9UBQdUG2IPokhRIBGya+JrHJVLrcwN57gs2PqUcV4I2B9vLcXdDeyhzjciw53KryZXmyD0+jc5DJnbp7IMr7X7dv1d2KjHx/nSMpdoc=,iv:IJw2IDxkGv2WEFNcQtpNnP0m6hubkwXopvV8USx8q9E=,tag:5uxXxmL4BXsrGFU0esa/tg==,type:str] 68 67 unencrypted_suffix: _unencrypted 69 68 version: 3.12.2