From 492b643d8b6644f7011133e9a6f43fa52d0ec81b Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Tue, 30 Sep 2025 10:13:59 +0100 Subject: [PATCH] Add immich Signed-off-by: Nikolaos Karaolidis --- README.md | 1 - flake.lock | 8 +- hosts/jupiter/hardware/default.nix | 5 +- .../console/podman/authelia/default.nix | 1 + .../storm/configs/console/podman/default.nix | 1 + .../configs/console/podman/immich/default.nix | 215 ++++++++++++++++++ .../console/podman/immich/post-start.sh | 22 ++ overlays/default.nix | 3 + packages/default.nix | 3 + .../immich-machine-learning/default.nix | 41 ++++ .../immich-machine-learning/entrypoint.sh | 19 ++ packages/docker/immich/default.nix | 42 ++++ packages/docker/immich/entrypoint.sh | 16 ++ .../docker/postgresql-vectorchord/default.nix | 100 ++++++++ .../docker/postgresql-vectorchord/init.sh | 3 + packages/docker/postgresql/entrypoint.sh | 9 +- scripts/cache.sh | 19 -- submodules/secrets | 2 +- 18 files changed, 479 insertions(+), 31 deletions(-) create mode 100644 hosts/jupiter/users/storm/configs/console/podman/immich/default.nix create mode 100644 hosts/jupiter/users/storm/configs/console/podman/immich/post-start.sh create mode 100644 packages/docker/immich-machine-learning/default.nix create mode 100644 packages/docker/immich-machine-learning/entrypoint.sh create mode 100644 packages/docker/immich/default.nix create mode 100644 packages/docker/immich/entrypoint.sh create mode 100644 packages/docker/postgresql-vectorchord/default.nix create mode 100644 packages/docker/postgresql-vectorchord/init.sh delete mode 100755 scripts/cache.sh diff --git a/README.md b/README.md index 94fe8e1..029e969 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ NixOS dotfiles and configuration for various hosts and users. - [`remove-host.sh`](./scripts/remove-host.sh): Remove references to a host. - [`update-keys.sh`](./scripts/update-keys.sh): Update the encryption keys in all relevant files using `sops.yaml` configurations. - [`update.sh`](./scripts/update.sh): Update flake and all packages. - - [`cache.sh`](./scripts/cache.sh): Build all `nixosConfiguration`s and push them to `attic`. Any `options.nix` files create custom option definitions when present. diff --git a/flake.lock b/flake.lock index 8021347..93a03c0 100644 --- a/flake.lock +++ b/flake.lock @@ -511,11 +511,11 @@ "secrets": { "flake": false, "locked": { - "lastModified": 1758576944, - "narHash": "sha256-P6fvi2mjyJEUg19BTZ6eb+fRM8V6s2xY1SWQ8gb49U0=", + "lastModified": 1759165833, + "narHash": "sha256-EYAVKr7gGY7MDmgPIYsW3yk96q51UT1vtzlupR8paKg=", "ref": "refs/heads/main", - "rev": "a9d956a20fc4534fcc7d3da7f0994c499c4ea405", - "revCount": 47, + "rev": "a5c1c552628492281e05e99458f1ca3ec272b448", + "revCount": 48, "type": "git", "url": "ssh://git@karaolidis.com/karaolidis/nix-secrets.git" }, diff --git a/hosts/jupiter/hardware/default.nix b/hosts/jupiter/hardware/default.nix index ea8448c..2aa493d 100644 --- a/hosts/jupiter/hardware/default.nix +++ b/hosts/jupiter/hardware/default.nix @@ -92,10 +92,7 @@ ]; }; - nixpkgs.config = { - cudaSupport = true; - rocmSupport = true; - }; + nixpkgs.config.cudaSupport = true; services = { xserver.videoDrivers = [ "nvidia" ]; diff --git a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix index f205ece..21772f5 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix @@ -136,6 +136,7 @@ in "outline" "shlink" "comentario" + "immich" ]; }; } diff --git a/hosts/jupiter/users/storm/configs/console/podman/default.nix b/hosts/jupiter/users/storm/configs/console/podman/default.nix index c30c810..09d4304 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/default.nix @@ -16,6 +16,7 @@ in (import ./comentario { inherit user home; }) (import ./gitea { inherit user home; }) (import ./grafana { inherit user home; }) + (import ./immich { inherit user home; }) (import ./littlelink { inherit user home; }) (import ./lore { inherit user home; }) (import ./media { inherit user home; }) diff --git a/hosts/jupiter/users/storm/configs/console/podman/immich/default.nix b/hosts/jupiter/users/storm/configs/console/podman/immich/default.nix new file mode 100644 index 0000000..a4ce757 --- /dev/null +++ b/hosts/jupiter/users/storm/configs/console/podman/immich/default.nix @@ -0,0 +1,215 @@ +{ user, home }: +{ + config, + inputs, + pkgs, + lib, + ... +}: +let + hmConfig = config.home-manager.users.${user}; + inherit (hmConfig.virtualisation.quadlet) volumes containers networks; + autheliaClientId = "kwrm5k1Bgwqd4BCXiWp0feL6adpthOn0GGgQ9iIVW7IH1UIj7bA2HVj9Jv42hUheoYoE8wWJpQi8woPomrSJIauTmsBMMFTTrI6r"; +in +{ + home-manager.users.${user} = { + sops = { + secrets = { + "immich/smtp".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; + "immich/postgresql".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; + "immich/admin".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; + "immich/authelia/password".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; + "immich/authelia/digest".sopsFile = "${inputs.secrets}/hosts/jupiter/secrets.yaml"; + }; + + templates = { + immich-postgresql-env.content = '' + POSTGRES_PASSWORD=${hmConfig.sops.placeholder."immich/postgresql"} + ''; + + immich-env.content = '' + DB_PASSWORD=${hmConfig.sops.placeholder."immich/postgresql"} + IMMICH_ADMIN_PASSWORD=${hmConfig.sops.placeholder."immich/admin"} + ''; + + immich.content = builtins.readFile ( + (pkgs.formats.json { }).generate "config.json" { + ffmpeg = { + accel = "nvenc"; + accelDecode = true; + }; + + oauth = { + enabled = true; + buttonText = "Login with Authelia"; + clientId = autheliaClientId; + clientSecret = hmConfig.sops.placeholder."immich/authelia/password"; + issuerUrl = "https://id.karaolidis.com/.well-known/openid-configuration"; + scope = lib.strings.concatStringsSep " " [ + "openid" + "profile" + "email" + ]; + }; + + passwordLogin.enabled = true; + + newVersionCheck.enabled = false; + + library.watch.enabled = true; + + server.externalDomain = "https://photos.karaolidis.com"; + + notifications.smtp = { + enabled = true; + from = "jupiter@karaolidis.com"; + transport = { + host = "smtp.protonmail.ch"; + port = 587; + username = "jupiter@karaolidis.com"; + password = hmConfig.sops.placeholder."immich/smtp"; + }; + }; + } + ); + + authelia-immich.content = builtins.readFile ( + (pkgs.formats.yaml { }).generate "immich.yaml" { + identity_providers.oidc = { + authorization_policies.immich = { + default_policy = "deny"; + rules = [ + { + policy = "one_factor"; + subject = "group:immich"; + } + ]; + }; + + clients = [ + { + client_id = autheliaClientId; + client_name = "immich"; + client_secret = hmConfig.sops.placeholder."immich/authelia/digest"; + redirect_uris = [ + "https://photos.karaolidis.com/auth/login" + "https://photos.karaolidis.com/user-settings" + "app.immich:///oauth-callback" + ]; + authorization_policy = "immich"; + scopes = [ + "openid" + "profile" + "email" + ]; + token_endpoint_auth_method = "client_secret_post"; + pre_configured_consent_duration = "1 year"; + } + ]; + }; + } + ); + }; + }; + + systemd.user.tmpfiles.rules = [ + "d /mnt/storage/private/storm/containers/storage/volumes/immich/_data 700 storm storm" + ]; + + virtualisation.quadlet = { + networks.immich = { }; + + volumes = { + immich-redis = { }; + immich-postgresql = { }; + immich-machine-learning-cache = { }; + }; + + containers = { + immich = { + containerConfig = { + image = "docker-archive:${pkgs.dockerImages.immich}"; + volumes = + let + postStart = pkgs.writeTextFile { + name = "post-start.sh"; + executable = true; + text = builtins.readFile ./post-start.sh; + }; + in + [ + "${hmConfig.sops.templates.immich.path}:/etc/immich/config.json:ro" + "${postStart}:/etc/immich/post-start.sh:ro" + "/mnt/storage/private/storm/containers/storage/volumes/immich/_data:/var/lib/immich" + ]; + networks = [ + networks.immich.ref + networks.traefik.ref + ]; + labels = [ + "traefik.enable=true" + "traefik.http.routers.immich.rule=Host(`photos.karaolidis.com`)" + ]; + environments = { + DB_HOSTNAME = "immich-postgresql"; + DB_USERNAME = "immich"; + DB_DATABASE_NAME = "immich"; + REDIS_HOSTNAME = "immich-redis"; + IMMICH_ADMIN_EMAIL = "jupiter@karaolidis.com"; + IMMICH_ADMIN_NAME = "Admin"; + }; + environmentFiles = [ hmConfig.sops.templates.immich-env.path ]; + podmanArgs = [ "--cdi-spec-dir=/run/cdi" ]; + devices = [ "nvidia.com/gpu=all" ]; + }; + + unitConfig = { + After = [ + "${containers.immich-postgresql._serviceName}.service" + "${containers.immich-redis._serviceName}.service" + "sops-nix.service" + ]; + Requires = [ + "${containers.immich-postgresql._serviceName}.service" + "${containers.immich-redis._serviceName}.service" + ]; + }; + }; + + immich-machine-learning.containerConfig = { + image = "docker-archive:${pkgs.dockerImages.immich-machine-learning}"; + volumes = [ "${volumes.immich-machine-learning-cache.ref}:/tmp/immich-machine-learning" ]; + networks = [ networks.immich.ref ]; + podmanArgs = [ "--cdi-spec-dir=/run/cdi" ]; + devices = [ "nvidia.com/gpu=all" ]; + }; + + immich-postgresql = { + containerConfig = { + image = "docker-archive:${pkgs.dockerImages.postgresql-vectorchord}"; + networks = [ networks.immich.ref ]; + volumes = [ "${volumes.immich-postgresql.ref}:/var/lib/postgresql/data" ]; + environments = { + POSTGRES_DB = "immich"; + POSTGRES_USER = "immich"; + }; + environmentFiles = [ hmConfig.sops.templates.immich-postgresql-env.path ]; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + + immich-redis.containerConfig = { + image = "docker-archive:${pkgs.dockerImages.redis}"; + networks = [ networks.immich.ref ]; + volumes = [ "${volumes.immich-redis.ref}:/var/lib/redis" ]; + exec = [ "--save 60 1" ]; + }; + + authelia.containerConfig.volumes = [ + "${hmConfig.sops.templates.authelia-immich.path}:/etc/authelia/conf.d/immich.yaml:ro" + ]; + }; + }; + }; +} diff --git a/hosts/jupiter/users/storm/configs/console/podman/immich/post-start.sh b/hosts/jupiter/users/storm/configs/console/podman/immich/post-start.sh new file mode 100644 index 0000000..39b2f4f --- /dev/null +++ b/hosts/jupiter/users/storm/configs/console/podman/immich/post-start.sh @@ -0,0 +1,22 @@ +# shellcheck shell=sh + +IMMICH_HOST="${IMMICH_HOST:-http://localhost:2283}" +IMMICH_ADMIN_NAME="${IMMICH_ADMIN_NAME:-Admin}" + +until response="$(curl -sf "$IMMICH_HOST/api/server/config")"; do + echo "Waiting for Immich to be ready..." + sleep 1 +done + +is_initialized="$(echo "$response" | jq -r '.isInitialized')" + +if [ "$is_initialized" = "false" ]; then + curl -sf "$IMMICH_HOST/api/auth/admin-sign-up" \ + -X POST \ + -H 'Content-Type: application/json' \ + --data-raw '{ + "email":"'"$IMMICH_ADMIN_EMAIL"'", + "password":"'"$IMMICH_ADMIN_PASSWORD"'", + "name":"'"$IMMICH_ADMIN_NAME"'" + }' +fi diff --git a/overlays/default.nix b/overlays/default.nix index e29f102..bf7843b 100644 --- a/overlays/default.nix +++ b/overlays/default.nix @@ -24,6 +24,8 @@ final: prev: grafana-image-renderer = final.docker-image-grafana-image-renderer; grafana-to-ntfy = final.docker-image-grafana-to-ntfy; grafana = final.docker-image-grafana; + immich = final.docker-image-immich; + immich-machine-learning = final.docker-image-immich-machine-learning; jellyseerr = final.docker-image-jellyseerr; littlelink-server = final.docker-image-littlelink-server; mariadb = final.docker-image-mariadb; @@ -36,6 +38,7 @@ final: prev: outline = final.docker-image-outline; plex = final.docker-image-plex; postgresql = final.docker-image-postgresql; + postgresql-vectorchord = final.docker-image-postgresql-vectorchord; prometheus = final.docker-image-prometheus; prometheus-fail2ban-exporter = final.docker-image-prometheus-fail2ban-exporter; prometheus-node-exporter = final.docker-image-prometheus-node-exporter; diff --git a/packages/default.nix b/packages/default.nix index 7185b54..674f6a6 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -17,6 +17,8 @@ docker-image-grafana-image-renderer = import ./docker/grafana-image-renderer { inherit pkgs; }; docker-image-grafana-to-ntfy = import ./docker/grafana-to-ntfy { inherit pkgs; }; docker-image-grafana = import ./docker/grafana { inherit pkgs; }; + docker-image-immich = import ./docker/immich { inherit pkgs; }; + docker-image-immich-machine-learning = import ./docker/immich-machine-learning { inherit pkgs; }; docker-image-jellyseerr = import ./docker/jellyseerr { inherit pkgs; }; docker-image-littlelink-server = import ./docker/littlelink-server { inherit pkgs; }; docker-image-mariadb = import ./docker/mariadb { inherit pkgs; }; @@ -29,6 +31,7 @@ docker-image-outline = import ./docker/outline { inherit pkgs; }; docker-image-plex = import ./docker/plex { inherit pkgs; }; docker-image-postgresql = import ./docker/postgresql { inherit pkgs; }; + docker-image-postgresql-vectorchord = import ./docker/postgresql-vectorchord { inherit pkgs; }; docker-image-prometheus = import ./docker/prometheus { inherit pkgs; }; docker-image-prometheus-fail2ban-exporter = import ./docker/prometheus-fail2ban-exporter { inherit pkgs; diff --git a/packages/docker/immich-machine-learning/default.nix b/packages/docker/immich-machine-learning/default.nix new file mode 100644 index 0000000..e0a30dc --- /dev/null +++ b/packages/docker/immich-machine-learning/default.nix @@ -0,0 +1,41 @@ +{ pkgs, ... }: +let + entrypoint = pkgs.writeTextFile { + name = "entrypoint"; + executable = true; + destination = "/bin/entrypoint"; + text = builtins.readFile ./entrypoint.sh; + }; +in +pkgs.dockerTools.buildImage { + name = "immich-machine-learning"; + fromImage = pkgs.docker-image-base; + + copyToRoot = pkgs.buildEnv { + name = "root"; + paths = with pkgs; [ + entrypoint + immich-machine-learning + ]; + pathsToLink = [ + "/bin" + "/lib" + "/share" + "/nix-support" + ]; + }; + + config = { + Entrypoint = [ "entrypoint" ]; + Volumes = { + "/tmp/immich-machine-learning" = { }; + }; + Env = [ + "IMMICH_LOG_LEVEL=warn" + "MACHINE_LEARNING_CACHE_FOLDER=/tmp/immich-machine-learning" + ]; + ExposedPorts = { + "3003/tcp" = { }; + }; + }; +} diff --git a/packages/docker/immich-machine-learning/entrypoint.sh b/packages/docker/immich-machine-learning/entrypoint.sh new file mode 100644 index 0000000..d6519cd --- /dev/null +++ b/packages/docker/immich-machine-learning/entrypoint.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env sh + +set -o errexit +set -o nounset + +LOG_PIPE="$(mktemp -u)" +mkfifo "$LOG_PIPE" + +( + while IFS= read -r line; do + if echo "$line" | grep -qEi "\[(WARN|ERROR)\]"; then + echo "$line" >&2 + else + echo "$line" + fi + done < "$LOG_PIPE" +) & + +exec machine-learning "$@" > "$LOG_PIPE" 2>&1 diff --git a/packages/docker/immich/default.nix b/packages/docker/immich/default.nix new file mode 100644 index 0000000..5bc424e --- /dev/null +++ b/packages/docker/immich/default.nix @@ -0,0 +1,42 @@ +{ pkgs, ... }: +let + entrypoint = pkgs.writeTextFile { + name = "entrypoint"; + executable = true; + destination = "/bin/entrypoint"; + text = builtins.readFile ./entrypoint.sh; + }; +in +pkgs.dockerTools.buildImage { + name = "immich"; + fromImage = pkgs.docker-image-base; + + copyToRoot = pkgs.buildEnv { + name = "root"; + paths = with pkgs; [ + entrypoint + immich + curl + jq + ]; + pathsToLink = [ + "/bin" + "/lib" + ]; + }; + + config = { + Entrypoint = [ "entrypoint" ]; + Volumes = { + "/var/lib/immich" = { }; + }; + WorkingDir = "/var/lib/immich"; + Env = [ + "IMMICH_CONFIG_FILE=/etc/immich/config.json" + "IMMICH_MEDIA_LOCATION=/var/lib/immich" + ]; + ExposedPorts = { + "2283/tcp" = { }; + }; + }; +} diff --git a/packages/docker/immich/entrypoint.sh b/packages/docker/immich/entrypoint.sh new file mode 100644 index 0000000..b093b57 --- /dev/null +++ b/packages/docker/immich/entrypoint.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +set -o errexit +set -o nounset + +server "$@" & +PID="$!" + +if [ -f /etc/immich/post-start.sh ]; then + # shellcheck disable=SC1091 + . /etc/immich/post-start.sh +fi + +trap 'kill -KILL "$PID"' INT TERM +wait "$PID" +exit $? diff --git a/packages/docker/postgresql-vectorchord/default.nix b/packages/docker/postgresql-vectorchord/default.nix new file mode 100644 index 0000000..15f55f5 --- /dev/null +++ b/packages/docker/postgresql-vectorchord/default.nix @@ -0,0 +1,100 @@ +{ pkgs, ... }: +let + postgresql = pkgs.postgresql.overrideAttrs (oldAttrs: { + patches = oldAttrs.patches or [ ] ++ [ ../postgresql/allow-root.patch ]; + }); + + # https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/sql/postgresql/generic.nix + postgresqlVectorchord = + let + installedExtensions = with postgresql.pkgs; [ + pgvector + vectorchord + ]; + + finalPackage = pkgs.buildEnv { + name = "${postgresql.pname}-vectorchord"; + + paths = installedExtensions ++ [ + postgresql + postgresql.man + ]; + + pathsToLink = [ + "/" + "/bin" + "/share/postgresql/extension" + "/share/postgresql/timezonesets" + "/share/postgresql/tsearch_data" + ]; + + nativeBuildInputs = with pkgs; [ makeBinaryWrapper ]; + + postBuild = + let + args = pkgs.lib.concatMap (ext: ext.wrapperArgs or [ ]) installedExtensions; + in + '' + wrapProgram "$out/bin/postgres" ${pkgs.lib.concatStringsSep " " args} + ''; + + passthru = { + inherit installedExtensions; + inherit (postgresql) pkgs psqlSchema version; + + pg_config = postgresql.pg_config.override { + outputs = { + out = finalPackage; + man = finalPackage; + }; + }; + }; + }; + in + finalPackage; + + entrypoint = pkgs.writeTextFile { + name = "entrypoint"; + executable = true; + destination = "/bin/entrypoint"; + text = builtins.readFile ../postgresql/entrypoint.sh; + }; + + init = pkgs.writeTextDir "/etc/postgresql/init.sh" (builtins.readFile ./init.sh); +in +pkgs.dockerTools.buildImage { + name = "postgresql-vectorchord"; + fromImage = pkgs.docker-image-base; + + copyToRoot = pkgs.buildEnv { + name = "root"; + paths = [ + entrypoint + postgresqlVectorchord + init + ]; + pathsToLink = [ + "/bin" + "/lib" + "/share" + ]; + }; + + runAsRoot = '' + mkdir -p /etc/postgresql /run/postgresql + cp ${postgresql}/share/postgresql/postgresql.conf.sample /etc/postgresql/postgresql.conf + ${pkgs.gnused}/bin/sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /etc/postgresql/postgresql.conf + ${pkgs.gnused}/bin/sed -ri "s/^#shared_preload_libraries = '''/shared_preload_libraries = 'vchord'/" /etc/postgresql/postgresql.conf + ''; + + config = { + Entrypoint = [ "entrypoint" ]; + ExposedPorts = { + "5432/tcp" = { }; + }; + WorkingDir = "/var/lib/postgresql"; + Volumes = { + "/var/lib/postgresql/data" = { }; + }; + }; +} diff --git a/packages/docker/postgresql-vectorchord/init.sh b/packages/docker/postgresql-vectorchord/init.sh new file mode 100644 index 0000000..0bc743e --- /dev/null +++ b/packages/docker/postgresql-vectorchord/init.sh @@ -0,0 +1,3 @@ +# shellcheck shell=sh + +psql --username="$POSTGRES_USER" -d postgres -c "CREATE EXTENSION IF NOT EXISTS vchord CASCADE;" diff --git a/packages/docker/postgresql/entrypoint.sh b/packages/docker/postgresql/entrypoint.sh index 8db37e9..0aa9570 100644 --- a/packages/docker/postgresql/entrypoint.sh +++ b/packages/docker/postgresql/entrypoint.sh @@ -31,13 +31,18 @@ if [ ! -s "$PGDATA/PG_VERSION" ]; then POSTGRES_HOST_AUTH_METHOD="${POSTGRES_HOST_AUTH_METHOD:=$auth_method}" printf "\nhost all all all %s\n" "$POSTGRES_HOST_AUTH_METHOD" >> "$PGDATA/pg_hba.conf" - pg_ctl -w start + pg_ctl -w start -o "-c config_file=/etc/postgresql/postgresql.conf" if ! psql --username="$POSTGRES_USER" -d postgres -tc "SELECT 1 FROM pg_database WHERE datname = '$POSTGRES_DB'" | grep -q 1; then psql --username="$POSTGRES_USER" -d postgres -c "CREATE DATABASE \"$POSTGRES_DB\";" fi - pg_ctl -m fast -w stop + if [ -f /etc/postgresql/init.sh ]; then + # shellcheck disable=SC1091 + . /etc/postgresql/init.sh + fi + + pg_ctl -m fast -w stop -o "-c config_file=/etc/postgresql/postgresql.conf" fi exec postgres -c config_file="/etc/postgresql/postgresql.conf" "$@" > "$LOG_PIPE" 2>&1 diff --git a/scripts/cache.sh b/scripts/cache.sh deleted file mode 100755 index ed94ac2..0000000 --- a/scripts/cache.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -flake_json=$(nix flake show --json) - -build_and_push() { - local expr="$1" - nix build "$expr" --no-link --print-out-paths | while IFS= read -r path; do - attic push main "$path" - done -} - -jq -r '.nixosConfigurations | keys[]' <<<"$flake_json" | while IFS= read -r cfg; do - expr=".#nixosConfigurations.\"$cfg\".config.system.build.toplevel" - build_and_push "$expr" -done diff --git a/submodules/secrets b/submodules/secrets index a9d956a..a5c1c55 160000 --- a/submodules/secrets +++ b/submodules/secrets @@ -1 +1 @@ -Subproject commit a9d956a20fc4534fcc7d3da7f0994c499c4ea405 +Subproject commit a5c1c552628492281e05e99458f1ca3ec272b448