# MoneyApp Self-hosted money management for one or more users in a household. Recurring rules, projected ledger, budgets, savings goals + compound-interest calculator, and a 12-month forecast with what-if sliders. Stack: Next.js 15 + SQLite (Drizzle ORM) + Auth.js. Runs as a single Docker container. ## Requirements - Docker 20.10+ with Compose v2 (`docker compose version` should print v2.x or v5.x) - Port 3000 free on the host ## Install ```bash # 1. From inside the MoneyApp folder, create the environment file cp .env.example .env # 2. Edit .env and set AUTH_SECRET to a random 32-byte string. # Generate one with: echo "AUTH_SECRET=$(openssl rand -base64 32)" >> .env # 3. Build and start docker compose up -d --build ``` The first build takes 3-5 minutes (it compiles `better-sqlite3` natively and runs `next build` inside the container). Subsequent starts are instant. Open and sign up. The first account becomes the household owner. ## Daily commands | What | Command | |---|---| | Start | `docker compose up -d` | | Stop | `docker compose down` (data preserved) | | Logs | `docker compose logs -f` | | Restart after pulling new code | `docker compose up -d --build` | | Shell inside container | `docker compose exec moneyapp sh` | ## Updating Replace the source folder with the new version (keep your `.env` and the `moneyapp-data` Docker volume), then: ```bash docker compose up -d --build ``` Migrations run automatically on container start. ## Backup The entire database is one SQLite file at `/data/moneyapp.db` inside the container, mounted from the named volume `moneyapp-data`. ```bash # Snapshot docker compose exec moneyapp sh -c 'cat /data/moneyapp.db' > backup-$(date +%F).db # Restore (with the app stopped) docker compose down docker run --rm -v moneyapp_moneyapp-data:/data -v "$PWD":/host alpine \ sh -c 'cp /host/backup-2026-05-07.db /data/moneyapp.db' docker compose up -d ``` ## Accessing from other devices on the LAN By default the container listens on `0.0.0.0:3000`, so from the same network just use the host's IP: `http://:3000`. For HTTPS or remote access, put a reverse proxy (Caddy, Traefik, nginx) in front. If you do put it behind a domain, update `AUTH_URL` in `.env` to the public URL — Auth.js uses it to construct callback URLs. ## Troubleshooting - **`set AUTH_SECRET in .env`** on `up` — you skipped step 2 above. Create `.env` and set `AUTH_SECRET`. - **Port 3000 already in use** — stop whatever else is on 3000, or change the host-side port in `docker-compose.yml` (e.g. `"3001:3000"`). - **Database looks empty after a rebuild** — that means the volume was removed. `docker compose down` keeps it; `docker compose down -v` deletes it. Restore from a backup if needed. ## Project layout ``` MoneyApp/ ├── Dockerfile multi-stage build (deps → build → runtime) ├── docker-compose.yml service + volume definition ├── .dockerignore ├── .env.example template; copy to .env and fill in ├── README.md └── app/ the Next.js project ├── src/ application code ├── drizzle/ generated SQL migrations ├── public/ static assets ├── package.json + lock └── *.ts/.mjs build configs (tsconfig, tailwind, postcss, etc.) ``` The deployment files stay at the root so it's clear what the installer interacts with. Everything inside `app/` is the application itself — the Dockerfile copies it in during the build.