Open source Β· AGPLv3
Self-hosted accounting software
Own your books, not just rent them. LineLedger is open source double-entry accounting that runs on your own server and nowhere else β free under the AGPLv3, installed with Docker in about five minutes.
Quick start
Up and running in five minutes
One prebuilt multi-arch image runs the app, the queue worker, and the scheduler alongside MySQL. Docker and Docker Compose are the only requirements β there is nothing to clone and nothing to build.
mkdir lineledger && cd lineledger
base=https://raw.githubusercontent.com/lineledger/lineledger/v1.2.0/docker
curl -fsSLO "$base/docker-compose.yml"
curl -fsSL "$base/.env.example" -o .env
curl -fsSLO "$base/backup.sh"
curl -fsSLO "$base/restore.sh"
chmod +x backup.sh restore.sh
# Edit .env: set DB_PASSWORD, DB_ROOT_PASSWORD, APP_URL, and your mail settings,
# and add DB_QUEUE_RETRY_AFTER=3700 (the queue worker runs --timeout=120).
# Then generate the encryption key and paste it into .env as APP_KEY=...
docker compose run --rm --no-deps app php artisan key:generate --show
docker compose up -d
Then open http://localhost:8080
and register. The first user you create becomes the site admin and sets up the first
organization. On boot the app container runs
php artisan app:upgrade
(migrations plus the release’s own upgrade steps), links storage, and generates the
OAuth keys.
Mail has to work before anyone can get in
Email verification is enforced: a new account can’t create its organization until it
clicks the verification link, so a blank MAIL_HOST leaves a
fresh install stuck at the verify-email screen. Point the MAIL_*
settings at a real mailer. For a trial run, start the bundled Mailpit with
docker compose --profile mail up -d and set
MAIL_HOST=mailpit and MAIL_PORT=1025;
its inbox is at 127.0.0.1:8025.
Back up your .env
APP_KEY encrypts sessions and secrets, and
PASSKEYS_USER_HANDLE_SECRET anchors every registered
passkey. Losing either one is unrecoverable β no one, including us, can restore them for you.
backup.sh copies .env
alongside every backup for exactly this reason.
Upgrading
# 1. Back up the database, storage volume and .env into ./backups
./backup.sh
# 2. In .env, pin the release: LINELEDGER_VERSION=1.2.0
# 3. Pull the new image; app:upgrade runs on boot
docker compose pull && docker compose up -d
# 4. Confirm, and prove the books still reconcile
docker compose exec app php artisan app:upgrade --verify
The app container runs app:upgrade on every boot, and the
workers wait for it to become healthy. Step 4 is safe to repeat: with nothing left to migrate it
just runs the integrity check. Pin LINELEDGER_VERSION to
1.2.0 for this exact release, or to
1.2 to follow its patch releases. Images are built for
amd64 and arm64.
Coming from 1.1.0?
The compose file and the backup scripts are unchanged since 1.1.0, so there is nothing new to
download β pin the version, pull, and run the verify step. Take a backup first: one of this
release’s migrations rewrites data and cannot be rolled back. Installing without Docker?
1.2.0 needs the intl PHP extension, and a
time-zone database new enough to know that British Columbia stays on UTC−7 this winter.
1.2.0 also fixes a sign-in flaw where a customer-portal session could
authenticate on another organization’s portal, so don’t sit on it.
The upgrade guide
has every step.
Backups
./backup.sh
# or write them elsewhere: BACKUP_DIR=/mnt/backups ./backup.sh
# Restore from a backup pair:
./restore.sh backups/lineledger-db-<ts>.sql.gz backups/lineledger-storage-<ts>.tar.gz
# Unattended nightly database dumps (kept 14 days by default):
docker compose --profile backup up -d backup.sh captures the database (with the audit-log
triggers), the storage volume, and .env in one run.
restore.sh puts them back and re-verifies the books. Two
Docker volumes hold all your data, and docker compose down -v
deletes both, so keep ./backups somewhere other than
the machine it describes.
Make it yours
A handful of settings in .env decide how the install presents
itself, and none of them need a fork:
-
APP_NAME,BRAND_LOGOandBRAND_FOOTER_OWNERput your own name and mark on the sign-in, registration and onboarding screens. The AGPLv3 still asks you to keep the source offer visible β the app ships a note about section 13 next to the setting. -
APP_LOCALEsets the default language, English or French. Each person, organization and customer can override it. -
APP_REGION(CA,USorGB) decides which legal documents the footer points at. It does not limit the books: one install holds Canadian, US and UK organizations side by side. -
SUPPORT_ENABLED=falsehides the in-app support desk when your support lives somewhere else. Tickets already raised stay readable.
Why it works this way
Running it yourself isn’t a compromise we ask you to accept β it’s the point.
Read every line
LineLedger is open source under the GNU AGPLv3. You β or your accountant β can audit exactly how every balance, tax figure, and report is calculated. No black box.
Your data, your server
The books run on infrastructure you control. Your ledger never reaches us, because there is nowhere on our side for it to go β and the application ships no third-party analytics.
No bill, no ratchet
You owe us nothing β ever. No per-seat fees, no annual price increases, no tier to climb to unlock a feature, and no paid edition held back from the one you downloaded.
Never locked in
Export any company to a portable ZIP and move it between your own machines whenever you like. The audit chain stays verifiable across the move.
Bring your history with you
Once it’s running, import your QuickBooks chart of accounts and replay your full general-ledger history β accounts mapped, contacts linked, no fresh start required.
Common questions
- Is LineLedger really free?
- Yes. LineLedger is open source under the GNU AGPLv3 and you run it yourself, so there is nothing to pay us β no plans, no seats, no paid edition. Self-hosting is not a cheaper option alongside a subscription; it is the only way LineLedger runs.
- What do I need to run it?
- Docker and Docker Compose, and a machine to put them on. The prebuilt multi-arch image (amd64 and arm64) runs the web app, the queue worker, and the scheduler as three containers alongside MySQL. A small VPS is plenty for a single business; a spare box on your own network works just as well.
- What does the server cost?
- That is the only bill involved, and it comes from your hosting provider rather than from us. A small VPS runs about Β£8β15 a month, and hardware you already own costs nothing extra.
- How do upgrades work?
- Back up with ./backup.sh, set LINELEDGER_VERSION in your .env to the new release, then run docker compose pull && docker compose up -d. On boot the app container runs php artisan app:upgrade (pending migrations plus any data steps the release ships), and the worker and scheduler wait until it is healthy. Finish with docker compose exec app php artisan app:upgrade --verify, which checks that the books still reconcile. Go one release at a time, and read that release's section in UPGRADING.md first.
- How do I back it up?
- Run ./backup.sh. It writes a database dump (with the audit-log triggers), an archive of the storage volume, and a copy of your .env into ./backups, and prints the matching ./restore.sh command. For unattended nightly database dumps, start the backup profile with docker compose --profile backup up -d. Copy ./backups off the machine either way.
- What happens if you stop working on it?
- Your install keeps running. It does not phone home, there is no licence to expire, and nothing about your books depends on us still being here. The AGPLv3 gives you the source, the right to modify it, and the right to hand it to someone else to maintain.