Skip to content

ryanlane/Mimir-Platform

Repository files navigation

Mimir Server

The Mimir service stack: FastAPI backend (mimir-api/), React web UI (mimir-web/mimir-ui/), and mDNS discovery (mimir-discovery/), orchestrated with Docker Compose and Task.

Mimir web UI — Screens page

Index

Which stack do I run?

Situation Command Compose file
Local dev, browser/API work (WSL or Linux) task wsl:up:build docker-compose.wsl.yml
Local dev with hot reload (API + UI) task dev docker-compose.dev.yml
Production from source on a native Linux server task up:build docker-compose.yml
Production from released images (recommended) see mimir-release mimir-release/deploy/

The production compose uses host networking and an authenticated MQTT broker — it will refuse to start without mosquitto/passwd (generated by scripts/phase0_harden.sh). The local/dev stacks use bridge networking and an anonymous dev broker (mosquitto/mosquitto.dev.conf); they are not valid for real-device onboarding (mDNS/multicast doesn't survive WSL/bridge networking).

Prerequisites

  • Docker + Docker Compose (on Windows: Docker Desktop running, with WSL integration enabled for your distro)
  • Task:
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin

Run task from this directory to list all available commands.

Running locally

First-time setup

cp .env.example .env    # browser-only local use: PUBLIC_HOST can stay blank
task setup              # installs API .venv + UI node_modules

Run task setup before starting any Docker dev stack the first time — otherwise Docker creates a root-owned node_modules mountpoint and host npm installs fail with EACCES (see Troubleshooting).

Option A — local stack (WSL or Linux)

Full stack in containers, served on localhost. Best for using the app locally and for API work where you don't need live reload.

task wsl:up:build       # build + start
task health:wsl         # check the API responds
task wsl:down           # stop

Option B — dev mode with hot reload

FastAPI with --reload and the CRA dev server with file watching. Best for active development on API or UI code.

task dev                # start full dev stack
task dev:logs:api       # follow API logs only
task dev:down           # stop
task dev:reset          # wipe volumes and start fresh (asks for confirmation)
task dev:discovery      # optional: mDNS discovery sidecar (Linux/WSL only)

pgAdmin (optional, either stack):

docker compose -f docker-compose.dev.yml --profile tools up -d --build   # http://localhost:5050

Local URLs

What Local stack (A) Dev mode (B)
Web UI http://localhost:8080 http://localhost:3000
API http://localhost:5000 http://localhost:5000
API health http://localhost:5000/api/health same
Postgres localhost:5432 same
Redis localhost:6379 same
MQTT (anonymous, dev) localhost:1883 same

LAN URLs (production server)

When running on a native Linux server, Mimir advertises itself as mimir.local via mDNS. Other devices on the network can reach it at:

What URL
Web UI http://mimir.local:8080
API http://mimir.local:5000

No IP address configuration is needed for most setups. PUBLIC_HOST in .env is only required if mDNS doesn't reach your displays (e.g. separate VLANs).

Production deployment

Recommended: deploy released GHCR images with the auto-update timer from mimir-release — see its README. The server then converges to the pinned versions in versions.yml every 15 minutes; releasing is a pin-bump PR.

From source (native Linux server with displays on the LAN):

cp .env.hybrid.example .env     # PUBLIC_HOST optional — mDNS handles LAN discovery
bash scripts/phase0_harden.sh   # secrets, mosquitto passwd, hardened restart
task up:build

Details and the discovery-service setup: HYBRID_LINUX_DEPLOYMENT.md.

MQTT broker & auth

Production (mosquitto/mosquitto.conf) runs two listeners:

  • 1883 on 0.0.0.0 — LAN listener for displays. Requires credentials from mosquitto/passwd (gitignored; generated by scripts/phase0_harden.sh). Displays receive the credentials automatically during bootstrap when the API has MQTT_EXPOSE_CREDENTIALS=true.
  • 1884 on 127.0.0.1 — anonymous localhost listener used by the host-networked API, the compose healthcheck, and task mqtt:sub / mqtt:pub.

Dev/WSL stacks use mosquitto/mosquitto.dev.conf: anonymous on 1883, no password file, bridge networking.

Configuration

  • .env.example — local/WSL development (PUBLIC_HOST can stay blank)
  • .env.hybrid.example — production server template (PUBLIC_HOST optional — mDNS handles LAN discovery; set it only for multi-VLAN or non-mDNS environments)
  • mimir-api/mimir-api.docker.env — Docker defaults for the API (no secrets); compose environment: entries override it
  • The web UI auto-detects the API URL at runtime and can be overridden in the Settings page; REACT_APP_API_URL is only needed for unusual setups.

Common tasks

# Database
task db:migrate               # run migrations in the dev API container
task db:revision -- 'add x'   # generate a new Alembic migration
task db:psql                  # psql shell on the dev DB

# Code quality
task api:lint                 # ruff + mypy
task api:format
task api:test                 # pytest

# Physical displays (dev loop; production updates go through OTA)
task display:deploy -- pi@display-pi-01.local   # rsync ../mimir-display + restart
task display:logs   -- pi@display-pi-01.local
task display:restart -- pi@display-pi-01.local

# MQTT debugging (localhost listener)
task mqtt:sub                 # subscribe to mimir/#
task mqtt:pub -- topic msg

# Health
task health                   # local API
task health:prod              # server at PUBLIC_HOST

Database

Postgres 16 runs as the db service, bound to 127.0.0.1:5432. Credentials: user mimir, database mimir; password from POSTGRES_PASSWORD in .env (dev default: mimir). The API runs alembic upgrade head automatically on startup.

Troubleshooting

npm ci fails with EACCES: permission denied, mkdir .../node_modules/... The Docker dev stack created node_modules as a root-owned volume mountpoint before a host-side install existed. Fix:

sudo rm -rf mimir-web/mimir-ui/node_modules && task ui:install

task up:build fails: mosquitto/passwd is missing You're running the production compose. For local work use task wsl:up:build. On a real server, run bash scripts/phase0_harden.sh first. If a previous attempt left a mosquitto/passwd directory: sudo rm -rf mosquitto/passwd.

unable to get image ...: cannot connect to the docker API The Docker daemon isn't reachable from WSL. Docker Desktop: start it and enable WSL integration for your distro (Settings → Resources → WSL Integration). Native engine: sudo systemctl start docker (or sudo service docker start).

Discovery finds 0 devices on Windows/WSL Expected — multicast doesn't traverse WSL/bridge networking. Validate onboarding on a native Linux server. For Windows-host discovery experiments see WINDOWS_MDNS_FIREWALL.md and MDNS_EDGE_DISCOVERY.md.

Notes & limitations

  • A native Linux server is the reference environment for real-device onboarding (host-network mDNS). Develop locally; validate hardware there.
  • Dev channel linking (Developer Mode): the path you enter must exist inside the API container. The dev compose mounts the sibling channel repos at /plugins/<repo-name>, e.g. /plugins/image-frame-channel-mimir/channels/photo_frame. Linked dev channels are watched (polling) and reload automatically.
  • The web UI's optional PWA/service worker is disabled by default for local Docker (a stale SW can serve the offline page); enable intentionally with REACT_APP_ENABLE_PWA=true at build time.
  • pgAdmin and the DB/Redis ports are bound to 127.0.0.1 — use an SSH tunnel for remote access, e.g. ssh -L 5050:127.0.0.1:5050 user@server.

License

Mimir is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE for the full text.

Free for: personal use, non-profits, and open source projects (under AGPL terms).

Commercial license: If you want to use Mimir in a proprietary product or service without the AGPL's source-sharing obligations, a commercial license is available. See COMMERCIAL_LICENSE.md or contact contact@mimirframe.com.

Contributing: By submitting a pull request you agree to the terms in CLA.md, which allows Mimir to be offered under both open source and commercial licenses.

Copyright (C) 2026 Ryan Lane

About

Mimir platform services: API, Web UI, Discovery, and Plugin SDK

Resources

License

Stars

5 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors