my over complex system configurations dotfiles.isabelroses.com/
nixos nix flake dotfiles linux
10
fork

Configure Feed

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

nixos/services: photoprism -> immich

isabel b85cf1d5 72bcdedb

+290 -60
+1 -1
modules/nixos/services/default.nix
··· 8 8 ./blahaj.nix 9 9 ./cloudflared.nix 10 10 ./forgejo.nix 11 + ./immich.nix 11 12 ./kanidm.nix 12 13 # ./buildbot.nix 13 14 ./lego.nix ··· 17 18 ./nixpkgs-prs-bot.nix 18 19 ./ntfy.nix 19 20 ./pds 20 - ./photoprism.nix 21 21 ./piper.nix 22 22 ./port-collector.nix 23 23 ./postgresql.nix
+261
modules/nixos/services/immich.nix
··· 1 + { 2 + lib, 3 + self, 4 + config, 5 + ... 6 + }: 7 + let 8 + cfg = config.garden.services.immich; 9 + rdomain = config.networking.domain; 10 + 11 + inherit (lib) mkIf; 12 + inherit (self.lib) mkServiceOption mkSystemSecret; 13 + in 14 + { 15 + options.garden.services.immich = mkServiceOption "immich" { 16 + port = 3007; 17 + domain = "photos.${rdomain}"; 18 + }; 19 + 20 + config = mkIf cfg.enable { 21 + garden.services.postgresql.enable = true; 22 + 23 + sops.secrets.immich-clientid = mkSystemSecret { 24 + file = "immich"; 25 + key = "clientid"; 26 + }; 27 + 28 + users.users.immich.extraGroups = [ 29 + "video" 30 + "render" 31 + ]; 32 + 33 + services = { 34 + immich = { 35 + enable = true; 36 + inherit (cfg) port host; 37 + 38 + # give it acess to all hardware devices 39 + accelerationDevices = null; 40 + 41 + # where to store our media 42 + mediaLocation = "/srv/storage/immich"; 43 + 44 + settings = { 45 + backup = { 46 + database = { 47 + enabled = false; # we use borg for this 48 + cronExpression = "0 02 * * *"; 49 + keepLastAmount = 14; 50 + }; 51 + }; 52 + ffmpeg = { 53 + accel = "disabled"; 54 + accelDecode = false; 55 + acceptedAudioCodecs = [ 56 + "aac" 57 + "mp3" 58 + "libopus" 59 + ]; 60 + acceptedContainers = [ 61 + "mov" 62 + "ogg" 63 + "webm" 64 + ]; 65 + acceptedVideoCodecs = [ 66 + "h264" 67 + ]; 68 + bframes = -1; 69 + cqMode = "auto"; 70 + crf = 23; 71 + gopSize = 0; 72 + maxBitrate = "0"; 73 + preferredHwDevice = "auto"; 74 + preset = "ultrafast"; 75 + refs = 0; 76 + targetAudioCodec = "aac"; 77 + targetResolution = "720"; 78 + targetVideoCodec = "h264"; 79 + temporalAQ = false; 80 + threads = 0; 81 + tonemap = "hable"; 82 + transcode = "required"; 83 + twoPass = false; 84 + }; 85 + image = { 86 + colorspace = "p3"; 87 + extractEmbedded = false; 88 + fullsize = { 89 + enabled = false; 90 + format = "jpeg"; 91 + quality = 80; 92 + }; 93 + preview = { 94 + format = "jpeg"; 95 + quality = 80; 96 + size = 1440; 97 + }; 98 + thumbnail = { 99 + format = "webp"; 100 + quality = 80; 101 + size = 250; 102 + }; 103 + }; 104 + 105 + job = { 106 + backgroundTask.concurrency = 5; 107 + faceDetection.concurrency = 2; 108 + library.concurrency = 5; 109 + metadataExtraction.concurrency = 5; 110 + migration.concurrency = 5; 111 + notifications.concurrency = 5; 112 + ocr.concurrency = 1; 113 + search.concurrency = 5; 114 + sidecar.concurrency = 5; 115 + smartSearch.concurrency = 2; 116 + thumbnailGeneration.concurrency = 3; 117 + videoConversion.concurrency = 1; 118 + }; 119 + 120 + library = { 121 + scan = { 122 + cronExpression = "0 0 * * *"; 123 + enabled = true; 124 + }; 125 + watch.enabled = false; 126 + }; 127 + 128 + logging = { 129 + enabled = true; 130 + level = "log"; 131 + }; 132 + 133 + machineLearning = { 134 + enabled = true; 135 + 136 + availabilityChecks = { 137 + enabled = true; 138 + interval = 30000; 139 + timeout = 2000; 140 + }; 141 + 142 + clip = { 143 + enabled = true; 144 + modelName = "ViT-B-32__openai"; 145 + }; 146 + 147 + duplicateDetection = { 148 + enabled = true; 149 + maxDistance = 0.01; 150 + }; 151 + 152 + facialRecognition = { 153 + enabled = true; 154 + maxDistance = 0.5; 155 + minFaces = 3; 156 + minScore = 0.65; 157 + modelName = "buffalo_l"; 158 + }; 159 + 160 + ocr = { 161 + enabled = true; 162 + maxResolution = 736; 163 + minDetectionScore = 0.5; 164 + minRecognitionScore = 0.8; 165 + modelName = "PP-OCRv5_mobile"; 166 + }; 167 + 168 + urls = [ "http://127.0.0.1:3003" ]; 169 + }; 170 + 171 + map = { 172 + enabled = true; 173 + darkStyle = "https://tiles.immich.cloud/v1/style/dark.json"; 174 + lightStyle = "https://tiles.immich.cloud/v1/style/light.json"; 175 + }; 176 + 177 + metadata.faces.import = false; 178 + newVersionCheck.enabled = false; 179 + 180 + nightlyTasks = { 181 + clusterNewFaces = true; 182 + databaseCleanup = true; 183 + generateMemories = true; 184 + missingThumbnails = true; 185 + startTime = "00:00"; 186 + syncQuotaUsage = true; 187 + }; 188 + 189 + notifications.smtp = { 190 + enabled = false; 191 + from = ""; 192 + replyTo = ""; 193 + transport = { 194 + host = ""; 195 + ignoreCert = false; 196 + password = ""; 197 + port = 587; 198 + secure = false; 199 + username = ""; 200 + }; 201 + }; 202 + 203 + oauth = { 204 + enabled = true; 205 + autoLaunch = false; 206 + autoRegister = true; 207 + buttonText = "Login with kanidm"; 208 + clientId = "immich"; 209 + clientSecret._secret = config.sops.secrets.immich-clientid.path; 210 + defaultStorageQuota = null; 211 + issuerUrl = "https://${config.garden.services.kanidm.domain}/oauth2/openid/immich"; 212 + mobileOverrideEnabled = true; 213 + mobileRedirectUri = "https://${cfg.domain}/api/oauth/mobile-redirect"; 214 + profileSigningAlgorithm = "none"; 215 + roleClaim = "immich.access"; 216 + scope = "openid email profile"; 217 + signingAlgorithm = "ES256"; 218 + storageLabelClaim = "preferred_username"; 219 + storageQuotaClaim = "immich_quota"; 220 + timeout = 30000; 221 + tokenEndpointAuthMethod = "client_secret_post"; 222 + }; 223 + 224 + passwordLogin.enabled = false; 225 + reverseGeocoding.enabled = true; 226 + 227 + server = { 228 + externalDomain = "https://${cfg.domain}"; 229 + loginPageMessage = ""; 230 + publicUsers = false; 231 + }; 232 + 233 + storageTemplate = { 234 + enabled = true; 235 + hashVerificationEnabled = true; 236 + template = "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"; 237 + }; 238 + 239 + templates.email = { 240 + albumInviteTemplate = ""; 241 + albumUpdateTemplate = ""; 242 + welcomeTemplate = ""; 243 + }; 244 + 245 + theme.customCss = ""; 246 + 247 + trash = { 248 + days = 30; 249 + enabled = true; 250 + }; 251 + 252 + user.deleteDelay = 7; 253 + }; 254 + }; 255 + 256 + cloudflared.tunnels.${config.networking.hostName} = { 257 + ingress.${cfg.domain} = "http://${cfg.host}:${toString cfg.port}"; 258 + }; 259 + }; 260 + }; 261 + }
+26
modules/nixos/services/kanidm.nix
··· 66 66 group = "kanidm"; 67 67 mode = "440"; 68 68 }; 69 + kanidm-oauth2-immich = mkSystemSecret { 70 + file = "kanidm"; 71 + key = "oauth2-immich"; 72 + owner = "kanidm"; 73 + group = "kanidm"; 74 + mode = "440"; 75 + }; 69 76 }; 70 77 71 78 services = { ··· 106 113 "forgejo.admins" 107 114 "linkwarden.access" 108 115 "wakapi.access" 116 + "immich.access" 109 117 ]; 110 118 }; 111 119 ··· 126 134 "linkwarden.access" = { }; 127 135 128 136 "wakapi.access" = { }; 137 + 138 + "immich.access" = { }; 129 139 }; 130 140 131 141 systems.oauth2 = { ··· 171 181 allowInsecureClientDisablePkce = true; 172 182 preferShortUsername = true; 173 183 scopeMaps."wakapi.access" = [ 184 + "openid" 185 + "email" 186 + "profile" 187 + ]; 188 + }; 189 + 190 + immich = { 191 + displayName = "immich"; 192 + originUrl = [ 193 + "https://${cfg'.immich.domain}/auth/login" 194 + "https://${cfg'.immich.domain}/api/oauth/mobile-redirect" 195 + ]; 196 + originLanding = "https://${cfg'.immich.domain}/"; 197 + basicSecretFile = config.sops.secrets.kanidm-oauth2-immich.path; 198 + preferShortUsername = true; 199 + scopeMaps."immich.access" = [ 174 200 "openid" 175 201 "email" 176 202 "profile"
-57
modules/nixos/services/photoprism.nix
··· 1 - { 2 - lib, 3 - self, 4 - config, 5 - ... 6 - }: 7 - let 8 - cfg = config.garden.services.photoprism; 9 - rdomain = config.networking.domain; 10 - 11 - inherit (lib) mkIf; 12 - inherit (self.lib) mkServiceOption mkSystemSecret; 13 - in 14 - { 15 - options.garden.services.photoprism = mkServiceOption "photoprism" { 16 - port = 3007; 17 - domain = "photos.${rdomain}"; 18 - }; 19 - 20 - config = mkIf cfg.enable { 21 - sops.secrets.photoprism-password = mkSystemSecret { 22 - file = "photoprism"; 23 - key = "password"; 24 - }; 25 - 26 - services = { 27 - photoprism = { 28 - enable = true; 29 - 30 - inherit (cfg) port; 31 - address = cfg.host; 32 - 33 - passwordFile = config.sops.secrets.photoprism-password.path; 34 - 35 - originalsPath = "/srv/storage/photoprism/photos"; 36 - 37 - settings = { 38 - PHOTOPRISM_SITE_URL = "https://${cfg.domain}"; 39 - PHOTOPRISM_DISABLE_WEBDAV = "true"; 40 - PHOTOPRISM_APP_NAME = "izphotos"; 41 - PHOTOPRISM_SITE_TITLE = "izphotos"; 42 - PHOTOPRISM_SITE_CAPTION = "goofy goober photos"; 43 - PHOTOPRISM_LEGAL_INFO = ""; 44 - 45 - # literally unusable without this 46 - # it flagged me a few times while setting it up :sob: 47 - # "maybe you're just that good looking?" - sketch 48 - PHOTOPRISM_UPLOAD_NSFW = "true"; 49 - }; 50 - }; 51 - 52 - cloudflared.tunnels.${config.networking.hostName} = { 53 - ingress.${cfg.domain} = "http://${cfg.host}:${toString cfg.port}"; 54 - }; 55 - }; 56 - }; 57 - }
+2 -2
systems/athena/default.nix
··· 36 36 }; 37 37 38 38 services = { 39 - cloudflared.enable = false; 40 - photoprism.enable = false; 39 + cloudflared.enable = true; 40 + immich.enable = true; 41 41 }; 42 42 }; 43 43 }