- DEMO_MODE=true env flag: disables password changes and backup endpoints (403), exposes GET /demo/status for frontend detection - Auto-seed on first startup: creates demo user (demo@mymidas.app / demo123) with 6 months of transactions, investments, budgets, subscriptions, and tax payslips; takes a pg_dump snapshot immediately after for hourly restore - Hourly reset: resetter Alpine container with cron restores DB from snapshot and purges uploaded attachments every hour on the hour - Frontend: amber demo banner on all pages, login page shows credentials, password change disabled with notice, backups section replaced with notice - demo/ directory: self-contained docker-compose.yml (ports 4001/8091), .env.example, reset.sh, and step-by-step Portainer DEPLOY.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.6 KiB
MyMidas Demo — Deployment Guide (Portainer)
This guide deploys the public demo instance on a separate server using Portainer Stacks.
What you get: a fully seeded MyMidas instance at port 4001, with demo data and an hourly auto-reset. No manual steps after initial deploy.
Prerequisites
- Docker and Portainer installed on the demo server
- SSH or console access to the demo server (for the initial clone and key generation)
- Your reverse proxy pointing a public domain at port
4001on this server
Step 1 — Clone the repo
On the demo server, clone into your preferred location:
git clone https://git.rdx4.com/megaproxy/MyMidas.git
cd MyMidas
Step 2 — Generate JWT keys
The demo shares the secrets/ directory with the main app structure. If you've already generated keys on this server you can skip this.
mkdir -p secrets
openssl genrsa -out secrets/jwt_private.pem 4096
openssl rsa -in secrets/jwt_private.pem -pubout -out secrets/jwt_public.pem
Step 3 — Create the demo .env file
cd demo
cp .env.example .env
Open .env and fill in the three required values:
| Variable | How to generate |
|---|---|
ENCRYPTION_KEY |
python3 -c "import secrets; print(secrets.token_hex(32))" |
DB_PASSWORD |
Any strong random string |
REDIS_PASSWORD |
Any strong random string |
Leave ENVIRONMENT=production.
Step 4 — Deploy the stack in Portainer
- Open Portainer → Stacks → Add stack
- Name it
mymidas-demo - Select Repository as the build method
- Set the repository URL to your Gitea URL and branch
main - Set Compose path to
demo/docker-compose.yml - Under Environment variables, add the four variables from your
.env:ENCRYPTION_KEYDB_PASSWORDREDIS_PASSWORDENVIRONMENT=production
- Click Deploy the stack
Alternative (upload method): If you prefer to upload the compose file directly, paste the contents of
demo/docker-compose.ymlinto Portainer's web editor and add the environment variables manually.
Step 5 — Wait for first-time seeding
On first startup, the backend will:
- Run database migrations
- Detect that
DEMO_MODE=trueand no users exist - Seed the full demo dataset (~180 transactions, investments, budgets, tax data)
- Save a compressed snapshot (
demo_snapshot.sql.gz) for hourly resets
This takes about 30–60 seconds. Watch progress in Portainer → Containers → mymidas-demo-backend-1 → Logs.
You'll see these log lines when ready:
demo_seed_complete
demo_snapshot_created
Uvicorn running on http://0.0.0.0:8000
Step 6 — Configure your reverse proxy
Point your public domain at http://<demo-server-ip>:4001.
The frontend serves the React app and proxies all /api/ calls to the backend internally — so you only need to expose port 4001.
nginx proxy manager example:
- Scheme:
http - Forward hostname/IP:
<demo-server-ip> - Forward port:
4001 - Enable websockets: off
Step 7 — Verify
Open your domain in a browser. You should see the MyMidas login page with a yellow demo credentials banner:
Email: demo@mymidas.app
Password: demo123
Log in and confirm the data is populated (accounts, transactions, investments, tax page).
Hourly reset
The resetter container runs a cron job at the top of every hour that:
- Restores the database from the snapshot taken on first boot
- Deletes any files uploaded by demo users
No action needed — it runs automatically. You can check reset logs in Portainer → Containers → mymidas-demo-resetter-1 → Logs.
Updating the demo
When you push code changes to main:
- In Portainer → Stacks →
mymidas-demo→ Editor → Update the stack - This rebuilds the images and restarts all containers
- On restart, migrations run automatically; the seed check runs and skips if already seeded (snapshot is preserved on the
demo_snapshotvolume)
If you want to force a full re-seed (e.g. after adding more demo data): in Portainer, delete the
demo_snapshotvolume, then redeploy. The backend will re-seed and take a new snapshot on next startup.
Troubleshooting
| Symptom | Check |
|---|---|
| Blank page / 502 | Backend still starting — wait 60 s and refresh |
| Login fails | Seeding still in progress — check backend logs |
| Data not resetting | Check resetter logs; confirm demo_snapshot volume has the .sql.gz file |
| "Snapshot not found" in resetter log | Backend may not have finished first-time seed — redeploy backend only |