Run it yourself
Sundry is MIT licensed, and running it on your own machine is free. It stays free — self-hosting is the free tier.
Two containers and one folder of data:
docker compose up --build
Then open http://localhost:8847. There is no config file to write and no
database to create. To reach it from the other devices in the house, use the machine's LAN
address on the same port and set a password first.
Your data
Everything sits in ./data beside the compose file: one SQLite database and your
receipt photos. Stop the app, copy the folder, and you have a backup. The app also exports
to CSV and .xlsx when you want a file to hand someone.
The variables that matter
-
APP_PASSWORD— the password gate. Unset, the API is open, which suits localhost and nothing else. Set it on anything the network can reach. -
AUTH_SECRET— an independent signing key for the login token. Without one, tokens are signed with the password itself. -
DB_PATH— where the SQLite file lives. Defaults todata/expenses.db. -
RECEIPTS_ENABLED— receipt upload and OCR. Turn it off on any instance a stranger can open without a password: the text is read on your own CPU, and an open endpoint is a free compute service for whoever finds it. -
TESSERACT_LANG_PATH— a local copy of the OCR language data. See the next section.
The full list, with defaults, is in backend/.env.example and
docs/DEPLOYMENT.md.
No outbound requests
Polish and English language data ships inside the image, so a receipt scan reads the text on
your own machine and calls nobody. Set RECEIPT_OCR_LANGS to a language the image
does not carry and it fetches the whole set from a public CDN instead — point
TESSERACT_LANG_PATH at your own folder of .traineddata files to
keep it offline. The photograph never leaves the machine either way.
The source
MIT licensed, on GitHub: ptrio42/sundry.cash.
Or do not run it
A hosted instance is planned: your own address, nothing to run. It is not available yet — hello@sundry.cash if you want to know when it is.