165 lines
5.3 KiB
Markdown
165 lines
5.3 KiB
Markdown
# Immich Postgres Diagnostics (No API Key)
|
|
|
|
When you don't have an Immich API key handy, you can check server health, job progress,
|
|
ML state, and config directly via the Postgres database inside the Immich Postgres container.
|
|
|
|
## Finding DB Credentials
|
|
|
|
The DB creds are set on the Postgres container at creation time. Get them from Docker:
|
|
|
|
```bash
|
|
docker inspect immich_postgres --format '{{json .Config.Env}}' | python3 -c "
|
|
import json,sys
|
|
env = json.load(sys.stdin)
|
|
for e in env:
|
|
if 'POSTGRES' in e.upper() or 'DB_' in e:
|
|
print(e)
|
|
"
|
|
```
|
|
|
|
Expected output:
|
|
```
|
|
POSTGRES_PASSWORD=ab496a...17a2
|
|
POSTGRES_USER=postgres
|
|
POSTGRES_DB=immich
|
|
```
|
|
|
|
Run queries with:
|
|
```bash
|
|
docker exec immich_postgres psql -U postgres -d immich -c "SQL HERE"
|
|
```
|
|
|
|
If password is required, pass via env:
|
|
```bash
|
|
docker exec -e PGPASSWORD=PASS immich_postgres psql -U postgres -d immich -c "SQL HERE"
|
|
```
|
|
|
|
## Job Queue Progress (per-asset job status)
|
|
|
|
Immich v2.7+ tracks per-asset job completion in `asset_job_status`. This is NOT a
|
|
traditional queue — it shows which assets have had each job type complete:
|
|
|
|
```sql
|
|
SELECT
|
|
COUNT(*) as total_assets,
|
|
COUNT(*) FILTER (WHERE ajs."facesRecognizedAt" IS NOT NULL) as faces_done,
|
|
COUNT(*) FILTER (WHERE ajs."metadataExtractedAt" IS NOT NULL) as metadata_done,
|
|
COUNT(*) FILTER (WHERE ajs."duplicatesDetectedAt" IS NOT NULL) as dedup_done,
|
|
COUNT(*) FILTER (WHERE ajs."ocrAt" IS NOT NULL) as ocr_done
|
|
FROM asset a
|
|
LEFT JOIN asset_job_status ajs ON a.id = ajs."assetId";
|
|
```
|
|
|
|
**Table schema** (`\d asset_job_status`):
|
|
```
|
|
assetId | uuid | not null
|
|
facesRecognizedAt | timestamp with time zone|
|
|
metadataExtractedAt | timestamp with time zone|
|
|
duplicatesDetectedAt | timestamp with time zone|
|
|
ocrAt | timestamp with time zone|
|
|
```
|
|
|
|
## System Metadata
|
|
|
|
The `system_metadata` table holds Immich's key state as JSONB:
|
|
|
|
```sql
|
|
SELECT * FROM system_metadata;
|
|
```
|
|
|
|
Key entries:
|
|
|
|
| key | value (snippet) | purpose |
|
|
|-----|-----------------|---------|
|
|
| `system-config` | `{"ffmpeg": {"transcode":"disabled"}, "storageTemplate": {"enabled": true}}` | Server config |
|
|
| `facial-recognition-state` | `{"lastRun": "2026-05-31T00:00:05.175Z"}` | Last ML face run |
|
|
| `reverse-geocoding-state` | `{"lastUpdate": "...", "lastImportFileName": "cities500.txt"}` | Geo data freshness |
|
|
| `version-check-state` | `{"checkedAt": "...", "releaseVersion": "v2.7.5"}` | Version tracking |
|
|
| `memories-state` | `{"lastOnThisDayDate": "..."}` | Memories feature state |
|
|
| `system-flags` | `{"mountChecks": {"thumbs": true, "upload": true, ...}}` | Mount health |
|
|
| `admin-onboarding` | `{"isOnboarded": true}` | Admin setup status |
|
|
|
|
To extract just the ML config:
|
|
```sql
|
|
SELECT json_data -> 'machineLearning' as ml_config FROM system_metadata WHERE key='system-config';
|
|
```
|
|
|
|
## Asset & People Counts
|
|
|
|
```sql
|
|
SELECT COUNT(*) as total_assets FROM asset;
|
|
SELECT COUNT(*) as total_albums FROM album;
|
|
SELECT COUNT(*) as total_people FROM person;
|
|
```
|
|
|
|
## ML Container GPU Check
|
|
|
|
The ML container uses ONNX Runtime (not PyTorch directly). Check GPU availability:
|
|
|
|
```bash
|
|
docker exec immich_machine_learning python3 -c "
|
|
import onnxruntime as ort
|
|
print(f'ONNX Runtime: {ort.__version__}')
|
|
print(f'Providers: {ort.get_available_providers()}')
|
|
print(f'CUDA: {\"CUDAExecutionProvider\" in ort.get_available_providers()}')
|
|
"
|
|
```
|
|
|
|
Check the container's configured device mode:
|
|
```bash
|
|
docker inspect immich_machine_learning --format '{{json .Config.Env}}' | python3 -c "
|
|
import json,sys
|
|
env = json.load(sys.stdin)
|
|
for e in env:
|
|
if 'DEVICE' in e or 'GPU' in e or 'CUDA' in e:
|
|
print(e)
|
|
"
|
|
```
|
|
|
|
Expected output for GPU-enabled:
|
|
```
|
|
DEVICE=cuda
|
|
NVIDIA_VISIBLE_DEVICES=all
|
|
CUDA_VERSION=12.2.2
|
|
```
|
|
|
|
ONNX Runtime 1.24+ typically offers `TensorrtExecutionProvider`, `CUDAExecutionProvider`,
|
|
`CPUExecutionProvider`. If `CUDAExecutionProvider` is in the list, GPU ML is active.
|
|
|
|
## Quick All-in-One Health Check
|
|
|
|
```bash
|
|
docker exec immich_postgres psql -U postgres -d immich -c "
|
|
SELECT 'assets' as check, COUNT(*)::text FROM asset
|
|
UNION ALL
|
|
SELECT 'people', COUNT(*)::text FROM person
|
|
UNION ALL
|
|
SELECT 'albums', COUNT(*)::text FROM album
|
|
UNION ALL
|
|
SELECT 'faces_done', COUNT(*) FILTER (WHERE ajs.\"facesRecognizedAt\" IS NOT NULL)::text
|
|
FROM asset a LEFT JOIN asset_job_status ajs ON a.id = ajs.\"assetId\"
|
|
UNION ALL
|
|
SELECT 'metadata_done', COUNT(*) FILTER (WHERE ajs.\"metadataExtractedAt\" IS NOT NULL)::text
|
|
FROM asset a LEFT JOIN asset_job_status ajs ON a.id = ajs.\"assetId\"
|
|
UNION ALL
|
|
SELECT 'ocr_done', COUNT(*) FILTER (WHERE ajs.\"ocrAt\" IS NOT NULL)::text
|
|
FROM asset a LEFT JOIN asset_job_status ajs ON a.id = ajs.\"assetId\"
|
|
UNION ALL
|
|
SELECT 'face_last_run', value->>'lastRun' FROM system_metadata WHERE key='facial-recognition-state'
|
|
UNION ALL
|
|
SELECT 'version', value->>'releaseVersion' FROM system_metadata WHERE key='version-check-state'
|
|
UNION ALL
|
|
SELECT 'transcoding', CASE WHEN value->'ffmpeg'->>'transcode' = 'disabled' THEN 'disabled' ELSE 'enabled' END
|
|
FROM system_metadata WHERE key='system-config';
|
|
"
|
|
```
|
|
|
|
## When to use Postgres diagnostics vs API
|
|
|
|
| Situation | Best approach |
|
|
|-----------|---------------|
|
|
| You have an API key | `/api/jobs` endpoint (richer data: active, waiting, failed, paused counts) |
|
|
| No API key / lost access | Postgres queries above |
|
|
| Checking ML container health | `docker exec` + ONNX Runtime check |
|
|
| GPU detection | `docker inspect` ML container env vars |
|