209 lines
7.9 KiB
Nix
Executable file
209 lines
7.9 KiB
Nix
Executable file
{
|
|
description = "Immich - Self-hosted photo and video backup solution (Docker Compose deployment)";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
};
|
|
|
|
outputs = { self, nixpkgs, flake-utils }:
|
|
let
|
|
# NixOS module to integrate Immich with the system
|
|
nixosModule = { config, lib, pkgs, ... }:
|
|
with lib;
|
|
let
|
|
cfg = config.services.immich-docker;
|
|
in
|
|
{
|
|
options.services.immich-docker = {
|
|
enable = mkEnableOption "Immich photo management server (Docker Compose deployment)";
|
|
|
|
domain = mkOption {
|
|
type = types.str;
|
|
default = "immich.local";
|
|
description = "Domain name for Immich web interface";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 2283;
|
|
description = "Port for Immich web interface";
|
|
};
|
|
|
|
dataDir = mkOption {
|
|
type = types.path;
|
|
default = "/mnt/userdata/immich";
|
|
description = "Directory for Immich data";
|
|
};
|
|
|
|
dbPassword = mkOption {
|
|
type = types.str;
|
|
default = "immich";
|
|
description = "PostgreSQL database password";
|
|
};
|
|
|
|
typesenseApiKey = mkOption {
|
|
type = types.str;
|
|
default = "immich-typesense-secret-key-change-this";
|
|
description = "Typesense search API key";
|
|
};
|
|
|
|
enableWatchtower = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Enable automatic container updates via Watchtower";
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
# Check for conflicts with the built-in Immich module
|
|
assertions = [
|
|
{
|
|
assertion = !(config.services.immich.enable or false);
|
|
message = "services.immich-docker conflicts with services.immich. Please disable the default Nixpkgs Immich module by setting services.immich.enable = false.";
|
|
}
|
|
];
|
|
|
|
# Ensure Docker is available
|
|
virtualisation.docker.enable = mkDefault true;
|
|
|
|
# Install docker-compose
|
|
environment.systemPackages = with pkgs; [
|
|
docker-compose
|
|
];
|
|
|
|
# Create required directories
|
|
systemd.tmpfiles.rules = [
|
|
"d /etc/compose/immich 0755 root root -"
|
|
"d ${cfg.dataDir}/upload 0755 root root -"
|
|
"d ${cfg.dataDir}/library 0755 root root -"
|
|
"d ${cfg.dataDir}/postgres 0755 root root -"
|
|
"d ${cfg.dataDir}/typesense 0755 root root -"
|
|
];
|
|
|
|
# Generate docker-compose configuration
|
|
environment.etc."compose/immich/docker-compose.yml".text = ''
|
|
version: "3.8"
|
|
|
|
services:
|
|
immich_server:
|
|
image: ghcr.io/immich-app/immich-server:v1.122.2
|
|
container_name: immich_server
|
|
ports:
|
|
- "${toString cfg.port}:3000"
|
|
environment:
|
|
- DB_HOSTNAME=immich_postgres
|
|
- DB_USERNAME=immich
|
|
- DB_PASSWORD=${cfg.dbPassword}
|
|
- DB_DATABASE_NAME=immich
|
|
- REDIS_HOSTNAME=immich_redis
|
|
- TYPESENSE_HOST=immich_typesense
|
|
- IMMICH_WEB_URL=http://localhost:${toString cfg.port}
|
|
- DISABLE_REVERSE_GEOCODING=false
|
|
volumes:
|
|
- ${cfg.dataDir}/upload:/usr/src/app/upload
|
|
- ${cfg.dataDir}/library:/usr/src/app/library
|
|
- /etc/localtime:/etc/localtime:ro
|
|
depends_on:
|
|
- immich_postgres
|
|
- immich_redis
|
|
- immich_typesense
|
|
restart: unless-stopped
|
|
${if cfg.enableWatchtower then ''labels:
|
|
com.centurylinklabs.watchtower.enable: "true"'' else ""}
|
|
|
|
immich_microservices:
|
|
image: ghcr.io/immich-app/immich-server:v1.122.2
|
|
container_name: immich_microservices
|
|
command: ["start-microservices.sh"]
|
|
environment:
|
|
- DB_HOSTNAME=immich_postgres
|
|
- DB_USERNAME=immich
|
|
- DB_PASSWORD=${cfg.dbPassword}
|
|
- DB_DATABASE_NAME=immich
|
|
- REDIS_HOSTNAME=immich_redis
|
|
- TYPESENSE_HOST=immich_typesense
|
|
- DISABLE_REVERSE_GEOCODING=false
|
|
volumes:
|
|
- ${cfg.dataDir}/upload:/usr/src/app/upload
|
|
- ${cfg.dataDir}/library:/usr/src/app/library
|
|
- /etc/localtime:/etc/localtime:ro
|
|
depends_on:
|
|
- immich_postgres
|
|
- immich_redis
|
|
- immich_typesense
|
|
restart: unless-stopped
|
|
${if cfg.enableWatchtower then ''labels:
|
|
com.centurylinklabs.watchtower.enable: "true"'' else ""}
|
|
|
|
immich_postgres:
|
|
image: tensorchord/pgvecto-rs:pg14-v0.2.0
|
|
container_name: immich_postgres
|
|
environment:
|
|
- POSTGRES_USER=immich
|
|
- POSTGRES_PASSWORD=${cfg.dbPassword}
|
|
- POSTGRES_DB=immich
|
|
volumes:
|
|
- ${cfg.dataDir}/postgres:/var/lib/postgresql/data
|
|
restart: unless-stopped
|
|
${if cfg.enableWatchtower then ''labels:
|
|
com.centurylinklabs.watchtower.enable: "true"'' else ""}
|
|
|
|
immich_redis:
|
|
image: redis:7-alpine
|
|
container_name: immich_redis
|
|
restart: unless-stopped
|
|
${if cfg.enableWatchtower then ''labels:
|
|
com.centurylinklabs.watchtower.enable: "true"'' else ""}
|
|
|
|
immich_typesense:
|
|
image: typesense/typesense:0.24.0
|
|
container_name: immich_typesense
|
|
environment:
|
|
- TYPESENSE_API_KEY=${cfg.typesenseApiKey}
|
|
- TYPESENSE_DATA_DIR=/data
|
|
volumes:
|
|
- ${cfg.dataDir}/typesense:/data
|
|
restart: unless-stopped
|
|
${if cfg.enableWatchtower then ''labels:
|
|
com.centurylinklabs.watchtower.enable: "true"'' else ""}
|
|
|
|
networks:
|
|
default:
|
|
name: immich_network
|
|
'';
|
|
|
|
# Systemd service to manage Immich docker-compose stack
|
|
systemd.services.docker-compose-immich = {
|
|
description = "Immich Docker Compose Stack";
|
|
after = [ "docker.service" "network-online.target" ];
|
|
wants = [ "network-online.target" ];
|
|
requiredBy = [ "multi-user.target" ];
|
|
path = [ pkgs.docker-compose pkgs.docker ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = "yes";
|
|
WorkingDirectory = "/etc/compose/immich";
|
|
ExecStart = "${pkgs.docker-compose}/bin/docker-compose up -d";
|
|
ExecStop = "${pkgs.docker-compose}/bin/docker-compose down";
|
|
};
|
|
};
|
|
|
|
# Network firewall configuration (optional, enable if using firewall)
|
|
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
|
};
|
|
};
|
|
in
|
|
{
|
|
# Provide NixOS module
|
|
nixosModules.immich-docker = nixosModule;
|
|
|
|
# Provide the module as the default package
|
|
packages = flake-utils.lib.eachDefaultSystem (system:
|
|
{
|
|
immich-docker-module = nixosModule;
|
|
default = nixosModule;
|
|
}
|
|
);
|
|
};
|
|
}
|