@@ -136,6 +136,7 @@ in
|
||||
"outline"
|
||||
"shlink"
|
||||
"comentario"
|
||||
"immich"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
@@ -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; })
|
||||
|
@@ -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"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@@ -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
|
Reference in New Issue
Block a user