payme was designed for self-hosting in my homelab environment. You can run it on a Raspberry Pi, NAS, or any always-on server. There should be no reason that you need to pay for a subscription or learn complex platforms just to track your finances.
I grew tired of tracking everything in a 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.
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+
- Bun 1.3+
- 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
PAYME_BIND=127.0.0.1:3001
PAYME_STATIC_DIR=frontend/distThe 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://your-ip/swagger-ui
In the Rafael monorepo, payme runs as a user-level systemd service:
mkdir -p ~/rafael/data/payme
printf 'JWT_SECRET=%s\n' "$(openssl rand -base64 32)" > ~/rafael/data/payme/payme.env
chmod 600 ~/rafael/data/payme/payme.env
cd ~/rafael/services/payme/frontend
bun install --frozen-lockfile
bun run build
cd ~/rafael
cargo build --release -p payme
mkdir -p ~/.config/systemd/user
ln -sf ~/rafael/infra/systemd/rafael-payme.service ~/.config/systemd/user/rafael-payme.service
systemctl --user daemon-reload
systemctl --user enable --now rafael-payme.serviceThe service binds to 127.0.0.1:3032 by default. Rafael exposes it publicly
through Tailscale Funnel on:
https://rafael.taild0efc0.ts.net:8443/The backend auth cookie is named payme_token so it does not collide with
other apps on the same Tailscale hostname.