Files
espresso_frame/server/app/config.py
T
tfaour e7f096ac23
Build and push server image / build-and-push (push) Successful in 33s
Support Immich URL/API key via docker-compose env vars
docker-compose.yml is tracked in a repo meant for publishing, so it can't
hold a real API key. Renamed it to docker-compose.yml.example (placeholder
values, safe to commit) and gitignored the real docker-compose.yml --
deploying is now "cp the example, fill in real values, docker compose up",
no .env file needed.

config.load() now reads IMMICH_URL/IMMICH_API_KEY from the environment
and applies them on top of whatever's in config.json, so setting them in
the compose file's environment: block takes effect without ever touching
the web UI. Env vars always win over the UI-saved values when both are
present -- verified they survive a save() with different UI-entered
values still in place.
2026-07-18 16:05:06 -04:00

52 lines
1.4 KiB
Python

"""JSON-file-backed config: Immich connection, selected album, and cursor
state (which photo /frame/image serves next)."""
from __future__ import annotations
import json
import os
from pathlib import Path
from threading import Lock
from pydantic import BaseModel
CONFIG_PATH = Path(os.environ.get("CONFIG_PATH", "/data/config.json"))
_lock = Lock()
class FrameConfig(BaseModel):
immich_url: str = ""
immich_api_key: str = ""
album_id: str = ""
order: str = "sequential" # or "shuffle"
cursor: int = 0
refresh_interval_s: int = 3600
smart_crop_faces: bool = True
def load() -> FrameConfig:
with _lock:
if not CONFIG_PATH.exists():
cfg = FrameConfig()
else:
cfg = FrameConfig(**json.loads(CONFIG_PATH.read_text()))
# IMMICH_URL/IMMICH_API_KEY set in the environment (e.g. docker-compose.yml,
# see docker-compose.yml.example) take precedence over whatever's saved
# in CONFIG_PATH, so credentials never need to go through the web UI.
env_url = os.environ.get("IMMICH_URL")
env_key = os.environ.get("IMMICH_API_KEY")
if env_url:
cfg.immich_url = env_url
if env_key:
cfg.immich_api_key = env_key
return cfg
def save(cfg: FrameConfig) -> None:
with _lock:
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
CONFIG_PATH.write_text(cfg.model_dump_json(indent=2))