Skip to main content

Terraform module reference

Module usage​

First vendor the pinned release bundle at vendor/immich-memories.

module "immich_memories" {
source = "./vendor/immich-memories/deploy/terraform"

# Required
immich_url = "https://photos.example.com"
immich_api_key = var.immich_api_key

# The reader, a separate deployment. It reads text only and must hold 32k of context; `llm_model`
# is the tag that server reports at /v1/models.
llm_base_url = "http://your-model-host:8000/v1"
llm_model = "gemma-4-e4b-it-6bit"

# Optional: the in-pod daily run, NVIDIA nodes, bigger claims
env = {
IMMICH_MEMORIES_LLM__ENABLED = "true"
IMMICH_MEMORIES_AUTOMATION__ENABLED = "true"
IMMICH_MEMORIES_AUTOMATION__DAILY_AT = "09:00"
}
gpu_enabled = true
output_storage_size = "100Gi"
cache_storage_size = "50Gi"
}

Which model to serve at llm_base_url is on Readers. Preparation goes through the same env map: Inference on a GPU box and Add captions. So do the render worker and ACE-Step (Generated music); MusicGen has its own musicgen_* variables. The module can deploy a caption service or render sidecar through explicit inputs; other endpoints are existing services.

gpu_enabled schedules on an NVIDIA node for NVENC and the title kernels (Hardware encoding). Intel Quick Sync and AMD VA-API need /dev/dri in the pod, which the module does not map: those encode on the CPU here.

Setting database_url moves the store off the default SQLite file onto PostgreSQL. The four modes, and the SQL for a dedicated schema in Immich's own database, are on Database and the store.

Variables​

immich_url and immich_api_key are required. Everything else has a default:

NameDescriptionDefault
namespace, create_namespaceKubernetes namespace, and whether to create it"immich-memories", true
image_repository, image_tagContainer image. No v prefix, so release vX.Y.Z is tag X.Y.Zghcr.io/sam-dumont/immich-memories, "latest"
replicasKeep at 1; the UI is single-replica1
resourcesRequests/limits object (requests.memory/cpu, limits.memory/cpu)2Gi/1000m to 8Gi/4000m
tmp_size/tmp emptyDir for FFmpeg intermediates (8Gi for 4K)"4Gi"
env, secret_envExtra env vars, the second stored in the Secret{}
labelsExtra labels on every resource{}
gpu_enabled, gpu_countSchedule on NVIDIA GPU nodes: RuntimeClass, nvidia.com/gpu, node selector, toleration, NVIDIA_* envfalse, 1
gpu_node_selector, runtime_class_namehow GPU nodes are found{"nvidia.com/gpu.present": "true"}, "nvidia"
output_storage_size, cache_storage_sizePVC sizes"50Gi", "30Gi"
models_storage_sizeModels PVC size (the Kubernetes manifests ship 5Gi)"10Gi"
storage_class_nameStorage class for all three PVCsnull (cluster default)
ingress_enabled, ingress_class_name, ingress_hostIngress, off by defaultfalse, "nginx", "memories.example.com"
ingress_tls_enabled, ingress_tls_secret_name, ingress_annotationsTLS and extras for itfalse, "immich-memories-tls", {}
llm_base_url, llm_model, llm_api_keyOptional text reader (Ollama: append /v1). URL and model do not enable it; set IMMICH_MEMORIES_LLM__ENABLED = "true" in env""
musicgen_enabled, musicgen_base_url, musicgen_api_keyAI music through a MusicGen serverfalse, the in-cluster service, ""
database_url, database_schemaThe store on PostgreSQL instead of the default SQLite file. Empty stays SQLite"", "immich_memories"
output_resolution720p, 1080p or 4k"1080p"

For a local-network reader, set IMMICH_MEMORIES_LLM__ENABLED = "true" in env and provide an external server. The app image does not include llama-server. Follow reader setup.

terraform output gives the namespace, service name and endpoint, the ingress host, the deployment and PVC names, whether GPU is on, and a ready-to-run port_forward_command.

Troubleshooting​

# Pod events: scheduling, PVC binding, GPU
kubectl describe pod -n immich-memories -l app.kubernetes.io/name=immich-memories
kubectl get pvc -n immich-memories

# Readiness stays 503 until Immich answers: check the payload
kubectl port-forward -n immich-memories svc/immich-memories 8080:80
curl -s localhost:8080/health/ready

# GPU: operator pods, node label, RuntimeClass
kubectl get pods -n gpu-operator
kubectl get nodes -L nvidia.com/gpu.present
kubectl get runtimeclass nvidia

A Pending pod is usually a storage class that does not exist, resource requests the cluster cannot meet, or gpu_enabled = true without GPU nodes.

Additional supported inputs​

InputWhat it controls
config_yamlOptional ConfigMap and init container to install a declarative config file
render_worker_sidecar_enabled, render_worker_tokenWorker sidecar; a token is required when enabled (32+ random characters, no placeholder words). Generate with openssl rand -hex 32; empty is accepted only with the sidecar off
captioner_enabled, captioner_cuda, captioner_storage_sizeCaption service deployment
oidc_*, secure_cookiesSSO and HTTPS session settings
network_geocoding, network_map_tilesOptional outside map calls
ace_step_enabled, ace_step_api_url, ace_step_api_keyExisting music API integration
cache_video_max_size_gb, cache_thumbnail_max_size_mbCache limits

The exact types and defaults are in variables.tf. The module does not deploy an inference or reader server. A caption service and render sidecar are available through the explicit inputs above; the app's gpu_enabled only schedules encoding/title GPU use.

Persistent mount and probes​

The data PVC mounts at /home/immich/.immich-memories; output at /app/output, models at /models. The module probes /health/live and /health/ready, just like the Kustomize base. Terraform waits for rollout completion: an app pod must become Ready before apply succeeds. /health/ready requires configuration and a reachable Immich server. Check pod events and logs when apply waits or times out.