payme was designed for self-hosting in my homelab environment. Run it on a Raspberry Pi, NAS, or any always-on server to track your household finances privately without relying on third-party services. Your financial data stays on your network, under your control.
I grew tired of my spreadsheet, and did not care for any of the third party services out there. So I decided to build my own. As such, you can see this is very opinionated. The lack of advanced financial budgeting features is intentional, though, I am open to different features and components.
Generally, if you don't like it, fork it and make it your own or consider contributing to the project (read CONTRIBUTING.md for more information).
- Rust 1.75+
- Node.js 20+
- SQLite3
cd backend
cargo build --releaseEnvironment variables:
See .env.example for all available variables.
DATABASE_URL=sqlite:payme.db?mode=rwc
JWT_SECRET=some-random-string
PORT=3001The run.sh script starts both the backend and frontend simultaneously:
chmod +x run.sh
./run.shThis launches:
- Backend at http://localhost:3001
- Frontend at http://localhost:3000
Press Ctrl+C to stop both services.
You can obviously run the backend and frontend separately if you want to by navigating to the respective directories and running the commands there.
SQLite database created at backend/payme.db. Tables auto-migrate on startup.
Export/import database via the UI download button or /api/export endpoint.
To view all the api endpoints and schemas, go to: http://localhost:3001/swagger-ui
Docker is the recommended way to deploy payme in a homelab. The multi-stage build creates a minimal image with just the compiled binary and static frontend assets.
# Set a secure JWT secret
echo "JWT_SECRET=$(openssl rand -base64 32)" > .env
# Build and start
docker compose up -dAccess payme at http://your-ip:3001
docker build -t payme .
docker run -d \
--name payme \
-p 3001:3001 \
-v payme_data:/data \
-e JWT_SECRET=your-secret-key \
paymeThe SQLite database is stored in a Docker volume at /data. To backup:
docker cp payme:/data/payme.db ./backup.dbFor production, place payme behind a reverse proxy (nginx, Caddy, Traefik) with HTTPS. Example nginx config:
server {
listen 443 ssl;
server_name finance.yourdomain.com;
location / {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}