Support Immich URL/API key via docker-compose env vars
Build and push server image / build-and-push (push) Successful in 33s
Build and push server image / build-and-push (push) Successful in 33s
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.
This commit is contained in:
@@ -11,6 +11,9 @@ server/**/__pycache__/
|
||||
server/.venv/
|
||||
server/*.egg-info/
|
||||
server/data/
|
||||
# Real deploy config, copied from docker-compose.yml.example -- holds the
|
||||
# Immich API key, must never be committed.
|
||||
server/docker-compose.yml
|
||||
.env
|
||||
|
||||
# Editor / OS cruft
|
||||
|
||||
+20
-8
@@ -10,13 +10,22 @@ algorithm itself -- it just streams the response straight to the panel.
|
||||
|
||||
1. **Get an Immich API key**: in Immich, go to Account Settings -> API Keys
|
||||
-> New API Key. Read-only access to albums/assets is enough.
|
||||
2. **Run the server**:
|
||||
2. **Copy the compose file and fill in your Immich details**:
|
||||
```
|
||||
cp docker-compose.yml.example docker-compose.yml
|
||||
```
|
||||
Edit `docker-compose.yml` and set `IMMICH_URL`/`IMMICH_API_KEY` under
|
||||
`environment:`. `docker-compose.yml` is gitignored (it'll hold your real
|
||||
API key) -- `docker-compose.yml.example` is the one that's committed.
|
||||
3. **Run the server**:
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
3. Open `http://<this-machine>:8420/` in a browser, enter your Immich URL
|
||||
and API key, click **Load Albums**, pick one, and **Save**.
|
||||
4. On the ESP32's captive portal setup form, set the **Tools Server** field
|
||||
4. Open `http://<this-machine>:8420/` in a browser, click **Load Albums**,
|
||||
pick one, and **Save**. (The Immich URL/API key fields will already be
|
||||
populated from the environment; changing them in the UI has no effect
|
||||
as long as the env vars are set -- they win on every load.)
|
||||
5. On the ESP32's captive portal setup form, set the **Tools Server** field
|
||||
to `<this-machine>:8420`.
|
||||
|
||||
## Endpoints
|
||||
@@ -31,8 +40,10 @@ algorithm itself -- it just streams the response straight to the panel.
|
||||
|
||||
## Notes
|
||||
|
||||
- Config (including the Immich API key) is stored in `./data/config.json`
|
||||
on the host via the compose volume mount.
|
||||
- Album/order/refresh-interval/etc. are stored in `./data/config.json` on
|
||||
the host via the compose volume mount. Immich URL/API key are too if set
|
||||
via the web UI, but `IMMICH_URL`/`IMMICH_API_KEY` env vars (see Setup
|
||||
above) always take precedence when present.
|
||||
- `/frame/image` isn't authenticated yet. That's fine on a trusted home
|
||||
LAN for now, but worth revisiting once the ESP32 side is wired up to
|
||||
send a shared device token.
|
||||
@@ -47,8 +58,9 @@ Every push to `main` that touches `server/` triggers a Gitea Actions
|
||||
workflow (`.gitea/workflows/server-docker-build.yml`) that builds this
|
||||
image and pushes it to this repo's Gitea Container Registry at
|
||||
`git.thumeit.com/tfaour/espresso-frame-server`. `docker-compose.yml`
|
||||
already points at that image, so a deploy host doesn't need this repo's
|
||||
build context at all -- just the compose file:
|
||||
(copied from `docker-compose.yml.example`, see Setup above) already
|
||||
points at that image, so a deploy host doesn't need this repo's build
|
||||
context at all -- just the compose file:
|
||||
|
||||
```
|
||||
docker compose pull
|
||||
|
||||
+15
-2
@@ -28,8 +28,21 @@ class FrameConfig(BaseModel):
|
||||
def load() -> FrameConfig:
|
||||
with _lock:
|
||||
if not CONFIG_PATH.exists():
|
||||
return FrameConfig()
|
||||
return FrameConfig(**json.loads(CONFIG_PATH.read_text()))
|
||||
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:
|
||||
|
||||
@@ -8,4 +8,6 @@ services:
|
||||
- ./data:/data
|
||||
environment:
|
||||
- CONFIG_PATH=/data/config.json
|
||||
- IMMICH_URL=http://your-immich-host:2283
|
||||
- IMMICH_API_KEY=your-immich-api-key-here
|
||||
restart: unless-stopped
|
||||
Reference in New Issue
Block a user