Personal-use NixOS configuration
1{
2 hosts ? [ ],
3}:
4
5{
6 config,
7 flakeLib,
8 ...
9}:
10
11let
12 videoDevice = "/dev/dri/renderD128";
13in
14{
15 imports = [
16 ../databases/postgresql.nix
17 ../databases/redis.nix
18 ];
19
20 services.immich = {
21 enable = true;
22
23 host = "127.0.0.1";
24
25 accelerationDevices = [ videoDevice ];
26
27 database = {
28 enableVectors = false;
29 enableVectorChord = true;
30 };
31
32 settings = {
33 trash.days = 31;
34
35 image = {
36 thumbnail = {
37 size = 240;
38 quality = 50;
39 };
40
41 preview = {
42 format = "webp";
43 size = 1080;
44 quality = 75;
45 };
46 };
47
48 ffmpeg = {
49 acceptedContainers = [ "webm" ];
50 acceptedVideoCodecs = [
51 "hevc"
52 "vp9"
53 "av1"
54 ];
55 acceptedAudioCodecs = [ "libopus" ];
56
57 targetVideoCodec = "hevc";
58 targetAudioCodec = "libopus";
59
60 crf = 31;
61 twoPass = true;
62
63 preferredHwDevice = videoDevice;
64 accelDecode = true;
65 };
66
67 machineLearning = {
68 # Assumes the machine is powerful, while balancing speed
69 # "ViT-B-32__laion2b-s34b-b79k" uses a third of the memory and is ~twice as fast, but is ~10% less accurate
70 clip.modelName = "ViT-B-16-SigLIP2__webli";
71
72 facialRecognition = {
73 # Largest model, generally very accurate
74 modelName = "antelopev2";
75
76 minScore = 0.5;
77 minFaces = 5;
78 };
79 };
80
81 # Assumes we're keeping copies elsewhere (zfs snapshots)
82 backup.database.enabled = false;
83 };
84 };
85
86 users.users.immich.extraGroups = [
87 "render"
88 "video"
89 ];
90
91 # Caddy reverse proxy configuration
92 services.caddy.virtualHosts = flakeLib.mkProxies hosts ''
93 reverse_proxy :${toString config.services.immich.port}
94 '';
95}