alexei.dolgolyov 592e1b6114 perf(docker): split external deps into a cacheable layer, swap pip for uv
Stage 3's `pip install /tmp/wheels/*.whl` re-resolved and re-downloaded
~50 transitive deps on every build, because the wheel filenames (and
thus the layer hash) changed on every version bump.

Two changes:
  1. Emit /wheels/deps.txt in the build stage — external deps only,
     notify-bridge-* siblings filtered out. The runtime stage installs
     from this file first, so the cache key is the pyproject.toml deps
     (stable across releases) instead of the local wheel filenames
     (changes every release). Registry buildcache now serves the whole
     install layer on version-only bumps.

  2. Swap pip for uv (ghcr.io/astral-sh/uv:0.11.7). uv resolves and
     downloads ~10x faster than pip; combined with a BuildKit cache
     mount on /root/.cache/uv and UV_COMPILE_BYTECODE=1, a cold install
     drops from ~60-90s to a few seconds.

Local wheels are now installed with --no-deps since externals are
already satisfied.
2026-04-23 20:52:36 +03:00
2026-04-23 20:18:34 +03:00
2026-04-23 20:18:34 +03:00
2026-04-23 20:18:34 +03:00

Notify Bridge

A generic bridge between service providers and notification targets.

Notify Bridge monitors services (like Immich photo servers) for changes and dispatches notifications to configurable targets (Telegram, webhooks) using customizable templates.

Architecture

  • Service Providers — Connectors to external services (Immich, more coming)
  • Trackers — Monitor specific collections within a provider for changes
  • Tracking Configs — Define what events to watch for and scheduling rules
  • Notification Targets — Where to send notifications (Telegram chats, webhook URLs)
  • Template Configs — Jinja2 templates that format notifications per provider type

Project Structure

packages/
  core/       — Shared library: providers, models, notifications, templates
  server/     — FastAPI REST server with SQLite database
frontend/     — SvelteKit dashboard (Svelte 5, Tailwind CSS v4)

Quick Docker Deploy

docker run -d \
  --name notify-bridge \
  --restart unless-stopped \
  -p 8420:8420 \
  -v notify-bridge-data:/data \
  -e NOTIFY_BRIDGE_SECRET_KEY=$(openssl rand -hex 32) \
  git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge:latest

Then open http://localhost:8420 in your browser.

Environment Variables

Variable Required Default Description
NOTIFY_BRIDGE_SECRET_KEY Yes Secret key for JWT tokens (min 32 chars)
NOTIFY_BRIDGE_PORT No 8420 Server listen port
NOTIFY_BRIDGE_CORS_ALLOWED_ORIGINS No * Comma-separated allowed CORS origins
NOTIFY_BRIDGE_DEBUG No false Enable debug logging

Docker Compose

services:
  notify-bridge:
    image: git.dolgolyov-family.by/alexei.dolgolyov/notify-bridge:latest
    container_name: notify-bridge
    restart: unless-stopped
    ports:
      - "8420:8420"
    volumes:
      - notify-bridge-data:/data
    environment:
      - NOTIFY_BRIDGE_SECRET_KEY=your-secret-key-min-32-characters

volumes:
  notify-bridge-data:

Quick Start (Development)

# Backend
cd packages/server
pip install -e .
NOTIFY_BRIDGE_DATA_DIR=./test-data NOTIFY_BRIDGE_SECRET_KEY=your-secret-key-min-32chars \
  python -m uvicorn notify_bridge_server.main:app --host 0.0.0.0 --port 8420

# Frontend
cd frontend
npm install
npm run dev

Supported Providers

  • Immich — Photo/video server with album change detection
S
Description
Bridge service events (Immich, …) to notification targets (Telegram, webhooks) via customizable Jinja2 templates and commands.
Readme 9.9 MiB
2026-06-05 21:04:57 +03:00
Languages
Python 59.9%
Svelte 26.1%
HTML 7.6%
TypeScript 3.7%
Jinja 2%
Other 0.6%