Run it locally
The whole stack in Docker, or the API and web app from source with reload.
Developers run exactly what operators run, on their own machine. There is no shared development environment: everything you create stays on your laptop.
Get the code
gh repo clone LeeMinNguyeen/msaving # or git clone https://github.com/LeeMinNguyeen/msaving
cd msaving && git switch dev # pull requests go to dev
python3.14 -m venv backend/.venv && backend/.venv/bin/pip install -r backend/requirements-dev.txt
(cd web && npm install)
The whole stack (as an operator gets it)
cd msaving
docker compose up -d --build # builds the image from your checkout
docker compose logs msaving # the setup code
Open http://localhost:8080, enter the setup code, create the admin. docker compose down -v deletes the database,
secrets and backups for a fresh start (the next start prints a new setup code).
From source, reloading on change
Two terminals:
# 1. The API on http://127.0.0.1:8000, against the compose stack's database
cd msaving/backend && source .venv/bin/activate
scripts/dev.sh
# 2. The web app on http://localhost:5173, /v1 proxied to the API
cd msaving/web && npm run dev
dev.sh starts the compose database published on 127.0.0.1:5433 (docker-compose.dev.yml, development only),
runs the server’s own launcher with --reload, and keeps its secrets and backups in backend/.dev/ (untracked).
It uses the same database as docker compose up, so the setup code is in dev.sh’s output on a fresh one.
Against the compose stack instead of dev.sh: MSAVING_API=http://127.0.0.1:8080 npm run dev.
Trying things an operator would do
| Try | How |
|---|---|
| Invites, joining | Server admin → Create invite; open the link in a private window |
| Updates notice | UPDATE_CHECK=on (default); the newest release comes from GitHub |
| One-click update | COMPOSE_PROFILES=updater docker compose up -d (runs git pull in your checkout: commit or stash first) |
| HTTPS with a domain | COMPOSE_PROFILES=https DOMAIN=<a domain pointing at you> docker compose up -d |
| Restore | The README’s commands, on a backup from docker compose cp msaving:/backups . |
| Own database | ADMIN_DATABASE_URL=... docker compose up -d --scale db=0 |
| A locked-out admin | docker compose exec msaving python -m app.admin reset-password <username> |
Next: Tests.