Setup storage of immich resouces and add tailscale access to allow uploading files too large to go over cloudflare (<100mb) See https://github.com/immich-app/immich/issues/17729 and https://github.com/immich-app/immich/pull/22385
This commit is contained in:
@@ -35,13 +35,16 @@ job "immich" {
|
|||||||
tags = [
|
tags = [
|
||||||
"traefik.enable=true",
|
"traefik.enable=true",
|
||||||
"traefik.http.routers.immich.middlewares=auth@file",
|
"traefik.http.routers.immich.middlewares=auth@file",
|
||||||
|
"traefik.http.routers.immich-token.rule=Host(`c3ll7nbevl5j4j8rcnfxnr95q48fuayz-immich.othrayte.one`)",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Todo try GET /server/ping (https://api.immich.app/endpoints/server/pingServer)
|
# Use the Immich server ping endpoint
|
||||||
# https://github.com/immich-app/immich-charts/blob/main/charts/immich/templates/server.yaml#L57
|
# See: https://api.immich.app/endpoints/server/pingServer
|
||||||
check {
|
check {
|
||||||
name = "alive"
|
name = "alive"
|
||||||
type = "tcp"
|
type = "http"
|
||||||
|
path = "/api/server/ping"
|
||||||
|
method = "GET"
|
||||||
port = "http"
|
port = "http"
|
||||||
interval = "10s"
|
interval = "10s"
|
||||||
timeout = "2s"
|
timeout = "2s"
|
||||||
@@ -49,10 +52,11 @@ job "immich" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
UPLOAD_LOCATION = "./library"
|
IMMICH_LOG_LEVEL = "log"
|
||||||
TZ = "Australia/Melbourne"
|
TZ = "Australia/Melbourne"
|
||||||
REDIS_HOSTNAME = "localhost"
|
REDIS_HOSTNAME = "localhost"
|
||||||
DB_HOSTNAME = "localhost"
|
DB_HOSTNAME = "localhost"
|
||||||
|
IMMICH_IGNORE_MOUNT_CHECK_ERRORS = "true" # Let immich start whilst we figure out what's wrong with the mount permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
volume_mount {
|
volume_mount {
|
||||||
@@ -61,9 +65,28 @@ job "immich" {
|
|||||||
read_only = false
|
read_only = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
volume = "unraid_media_photosvideos"
|
||||||
|
destination = "/data/library"
|
||||||
|
read_only = false
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
volume = "unraid_media_immich_encodedvideo"
|
||||||
|
destination = "/data/encoded-video"
|
||||||
|
read_only = false
|
||||||
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
volume = "unraid_mediadump_photosvideos"
|
||||||
|
destination = "/data/upload"
|
||||||
|
read_only = false
|
||||||
|
}
|
||||||
|
|
||||||
resources {
|
resources {
|
||||||
cpu = 200
|
cpu = 200
|
||||||
memory = 1024
|
memory = 512
|
||||||
|
memory_max = 1500
|
||||||
}
|
}
|
||||||
|
|
||||||
template {
|
template {
|
||||||
@@ -88,11 +111,53 @@ EOH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volume "unraid_media_photosvideos" {
|
||||||
|
type = "csi"
|
||||||
|
read_only = false
|
||||||
|
source = "unraid_media_photosvideos"
|
||||||
|
access_mode = "single-node-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
|
||||||
|
mount_options {
|
||||||
|
mount_flags = ["uid=1000", "gid=1000"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volume "unraid_media_immich_encodedvideo" {
|
||||||
|
type = "csi"
|
||||||
|
read_only = false
|
||||||
|
source = "unraid_media_immich_encodedvideo"
|
||||||
|
access_mode = "single-node-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
|
||||||
|
mount_options {
|
||||||
|
mount_flags = ["uid=1000", "gid=1000"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volume "unraid_mediadump_photosvideos" {
|
||||||
|
type = "csi"
|
||||||
|
read_only = false
|
||||||
|
source = "unraid_mediadump_photosvideos"
|
||||||
|
access_mode = "single-node-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
|
||||||
|
mount_options {
|
||||||
|
mount_flags = ["uid=1000", "gid=1000"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
task "immich-machine-learning" {
|
task "immich-machine-learning" {
|
||||||
driver = "docker"
|
driver = "docker"
|
||||||
config {
|
config {
|
||||||
image = "ghcr.io/immich-app/immich-machine-learning:release"
|
image = "ghcr.io/immich-app/immich-machine-learning:release"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 200
|
||||||
|
memory = 500
|
||||||
|
memory_max = 2000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task "redis" {
|
task "redis" {
|
||||||
@@ -101,6 +166,44 @@ EOH
|
|||||||
config {
|
config {
|
||||||
image = "docker.io/valkey/valkey:8-bookworm@sha256:fea8b3e67b15729d4bb70589eb03367bab9ad1ee89c876f54327fc7c6e618571"
|
image = "docker.io/valkey/valkey:8-bookworm@sha256:fea8b3e67b15729d4bb70589eb03367bab9ad1ee89c876f54327fc7c6e618571"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 30
|
||||||
|
memory = 10
|
||||||
|
memory_max = 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task "tailscale" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "tailscale/tailscale:latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
env = {
|
||||||
|
TS_HOSTNAME = "immich"
|
||||||
|
TS_EXTRA_ARGS = "--advertise-tags=tag:nomad"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 100
|
||||||
|
memory = 100
|
||||||
|
memory_max = 300
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
hook = "prestart"
|
||||||
|
sidecar = true
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
data = <<EOH
|
||||||
|
TS_AUTHKEY="{{ with nomadVar "nomad/jobs/immich" }}{{ .tailscale_oauthsecret }}{{ end }}?ephemeral=true"
|
||||||
|
EOH
|
||||||
|
destination = "secrets/ts_oauth.env"
|
||||||
|
env = true # Load the file as environment variables
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ resource "postgresql_extension" "immich_earthdistance" {
|
|||||||
resource "nomad_variable" "immich" {
|
resource "nomad_variable" "immich" {
|
||||||
path = "nomad/jobs/immich"
|
path = "nomad/jobs/immich"
|
||||||
items = {
|
items = {
|
||||||
database_pw = data.sops_file.secrets.data["immich.database_pw"]
|
database_pw = data.sops_file.secrets.data["immich.database_pw"]
|
||||||
|
tailscale_oauthsecret = data.sops_file.secrets.data["tailscale.oauthsecret"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,3 +59,82 @@ resource "nomad_csi_volume_registration" "unraid_appdata_immich" {
|
|||||||
"password" = data.sops_file.secrets.data["unraid.nomad"]
|
"password" = data.sops_file.secrets.data["unraid.nomad"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "nomad_csi_volume_registration" "unraid_media_photosvideos" {
|
||||||
|
#Note: Before chaning the definition of this volume you need to stop the jobs that are using it
|
||||||
|
depends_on = [data.nomad_plugin.smb]
|
||||||
|
plugin_id = "smb"
|
||||||
|
|
||||||
|
volume_id = "unraid_media_photosvideos"
|
||||||
|
name = "unraid_media_photosvideos"
|
||||||
|
|
||||||
|
external_id = "unraid_media_photosvideos"
|
||||||
|
|
||||||
|
capability {
|
||||||
|
access_mode = "single-node-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
}
|
||||||
|
|
||||||
|
context = {
|
||||||
|
source = "//192.168.1.192/media"
|
||||||
|
subDir = "Photos and Videos" # Note: Needs to be manually created on the share
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets = {
|
||||||
|
"username" = "nomad"
|
||||||
|
"password" = data.sops_file.secrets.data["unraid.nomad"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "nomad_csi_volume_registration" "unraid_media_immich_encodedvideo" {
|
||||||
|
#Note: Before chaning the definition of this volume you need to stop the jobs that are using it
|
||||||
|
depends_on = [data.nomad_plugin.smb]
|
||||||
|
plugin_id = "smb"
|
||||||
|
|
||||||
|
volume_id = "unraid_media_immich_encodedvideo"
|
||||||
|
name = "unraid_media_immich_encodedvideo"
|
||||||
|
|
||||||
|
external_id = "unraid_media_immich_encodedvideo"
|
||||||
|
|
||||||
|
capability {
|
||||||
|
access_mode = "single-node-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
}
|
||||||
|
|
||||||
|
context = {
|
||||||
|
source = "//192.168.1.192/media"
|
||||||
|
subDir = "immich/encoded-video" # Note: Needs to be manually created on the share
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets = {
|
||||||
|
"username" = "nomad"
|
||||||
|
"password" = data.sops_file.secrets.data["unraid.nomad"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "nomad_csi_volume_registration" "unraid_mediadump_photosvideos" {
|
||||||
|
#Note: Before chaning the definition of this volume you need to stop the jobs that are using it
|
||||||
|
depends_on = [data.nomad_plugin.smb]
|
||||||
|
plugin_id = "smb"
|
||||||
|
|
||||||
|
volume_id = "unraid_mediadump_photosvideos"
|
||||||
|
name = "unraid_mediadump_photosvideos"
|
||||||
|
|
||||||
|
external_id = "unraid_mediadump_photosvideos"
|
||||||
|
|
||||||
|
capability {
|
||||||
|
access_mode = "single-node-writer"
|
||||||
|
attachment_mode = "file-system"
|
||||||
|
}
|
||||||
|
|
||||||
|
context = {
|
||||||
|
source = "//192.168.1.192/media-dump"
|
||||||
|
subDir = "Photos and Videos" # Note: Needs to be manually created on the share
|
||||||
|
}
|
||||||
|
|
||||||
|
secrets = {
|
||||||
|
"username" = "nomad"
|
||||||
|
"password" = data.sops_file.secrets.data["unraid.nomad"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,3 +40,9 @@ data "nomad_plugin" "smb" {
|
|||||||
plugin_id = "smb"
|
plugin_id = "smb"
|
||||||
wait_for_healthy = true
|
wait_for_healthy = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "nomad_scheduler_config" "config" {
|
||||||
|
memory_oversubscription_enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user