Invoice Ninja 5: self-hosted invoicing, quotes and time tracking in Laravel
A source-available invoice, quote, project and time-tracking app built with Laravel
At a glance
- What is it?
- Invoice Ninja 5 is a Laravel application for invoices, quotes, projects and time tracking, shipped as a hosted service or as a self-hosted install. The code is source-available, the API is documented, and the release cadence is fast, but the self-hosted path asks for real operational work.
- Who is it for?
- Adopt Invoice Ninja 5 if you want invoices, quotes, projects and time tracking in one Laravel codebase and you are willing to run PHP, MySQL and a queue yourself, or if you would rather pay for the hosted version and skip that work. Do not pick it if nobody on the team can read a Laravel stack trace or manage a database backup, and do not treat the self-hosted route as a five-minute install.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Invoice Ninja 5 solves, and for whom
Invoice Ninja 5 bundles four jobs that small businesses usually split across separate tools: invoicing, quotes, project tracking and time tracking. The repository topics list the same set (invoices, quotes, projects, tasks, time-tracker) alongside payments and expenses, so the scope is deliberate rather than incidental. The target user in the README is split in two. The hosted version is described as a SaaS solution where you are running in under five minutes with no server infrastructure to manage. The self-hosted version is for people who want to manage their own hosting and full control of the data.
The second group is the interesting one. Anyone can sign up for hosted invoicing. What pulls people toward the self-hosted build is the combination of a documented REST API, a client portal, and the fact that the README states all Pro and Enterprise features from the hosted app are included in the source-available code. That last sentence is the real pitch: you are not getting a crippled community edition. The one paid piece the README names is a $40 per year white-label license to remove Invoice Ninja branding from client-facing parts of the app.
It is a poor fit for someone who wants an invoice tool and nothing else. The Laravel codebase, the database, the queue and the PDF generator are all part of the deal. If you only send a handful of invoices a year and you have no interest in an API, the operational cost of self-hosting is larger than the problem.
The request path through the Laravel application
The README's developer guide is unusually concrete about how a request moves. It says the API and client portal are built with Laravel, and that the best starting point for inspecting functionality is routes/api.php, which describes the available API endpoints. Controller methods are described as the entry points into each domain, naming InvoiceController and QuoteController as examples.
The documented flow is: middleware processes the request first, inspecting the requested domain and providing authentication. The request then passes into a Form Request, type-hinted in the controller method, which handles authorization and validation. Only then does it reach the controller. The README gives a store method as the illustration: the validated request plus a factory go into the invoice repository, the returned invoice passes through its service class in app/Services/Invoice where actions such as fillDefaults, triggeredActions and adjustInventory run, and an event is fired that notifies listeners registered in app/Providers/EventServiceProvider.
That layering is the part worth judging before you adopt. Repository, service and event layers mean business logic is not sitting in controllers, which makes the codebase approachable if you already know Laravel and frustrating if you do not. The README states plainly that familiarity with Laravel is essential for contributing. The same applies to debugging it in production.
The repository layout backs this up. There is a modules_statuses.json at the top level, an openapi/ directory, a lang/ directory for translations, and separate Vite configs (vite.config.ts and vite.config.ts.react), which suggests the front end is mid-migration between two build setups rather than settled on one.
Installing Invoice Ninja 5 from a tagged release
The README points to the official self-hosted installation guide and then offers an advanced quick setup. The commands clone a specific tag rather than a branch. The README is explicit about why: replace the tag with the latest version, and when updating, use the latest tag rather than a particular branch such as v5-develop, so you are not pulling in work in progress code.
git clone --depth 1 -b v5.11.53 https://github.com/invoiceninja/invoiceninja.git
cp .env.example .env
composer i -o --no-devThe .env.example file ships with DB_CONNECTION=mysql, DB_HOST=localhost, DB_DATABASE=ninja, DB_USERNAME=ninja, DB_PASSWORD=ninja and DB_PORT=3306, so MySQL on the default port is the assumed starting point. Set those to match your database before continuing. If you want sample data loaded, the README gives this sequence, and notes you should configure .env first:
php artisan migrate:fresh --seed && php artisan db:seed && php artisan ninja:create-test-dataTo bring the application up locally, the README uses the built-in server:
php artisan serveThen the README directs you to http://localhost:8000/setup for initial configuration if you did not load sample data, and http://localhost:8000/ for administrator logon. With sample data loaded, the README lists [email protected] with the password password for the admin account, and http://localhost:8000/client/login with [email protected] and password for the client portal. Those credentials come from the seeded test data and should never survive into anything reachable from the internet.
One warning in the README deserves repeating in full: your APP_KEY in the .env file is used to encrypt data, and if you lose it you will not be able to run the application. Back it up somewhere other than the server.
Docker, PDF generation and the settings that bite later
The README lists a Docker image at hub.docker.com/r/invoiceninja/invoiceninja, alongside Cloudron, Softaculous, Elestio and YunoHost as self-hosted options. The README does not include a compose file, so anyone searching for a docker compose setup has to take it from the image documentation rather than this repository. That is a gap worth knowing about before you plan a deployment around it.
PDF_GENERATOR in .env.example is set to hosted_ninja, with snappdf and phantom described as the alternatives in the comment above it. The default therefore routes PDF rendering through a hosted service. If your reason for self-hosting is to keep client data on your own infrastructure, that default is the opposite of what you want, and you need to confirm what snappdf requires on your server before switching. PHANTOMJS_KEY and PHANTOMJS_SECRET also appear in .env.example, with the key set to a demo value that carries a low quota per IP address. Leaving that in place is a configuration mistake, not a default you can ignore.
Several other keys change behaviour in ways that are easy to miss. QUEUE_CONNECTION is sync out of the box, which means queued work runs inside the request rather than in a worker. SESSION_DRIVER and CACHE_DRIVER are both file. NINJA_AUTO_BILL_TIME is set to 06:20 in UTC, so recurring billing depends on a scheduler being wired up on the host. DELETE_PDF_DAYS and DELETE_BACKUP_DAYS are both 60, which means retention is enforced by the app unless you change those values. UPDATE_SECRET is set to the literal string secret. None of these are wrong for a local trial. All of them need review before the instance is public.
There is also an OIDC block in .env.example, commented out, with OIDC_WELL_KNOWN, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_SCOPES and OIDC_PROVIDER_LABEL. The comment states that leaving OIDC_WELL_KNOWN blank hides the sign-in button. Microsoft and Apple client credentials appear in the same file. The breadth of that file is a fair signal of how much surface area the application has.
Where Invoice Ninja 5 is the wrong tool
The licence is the first thing to check, and the repository metadata does not resolve it. The LICENSE file is present at the top level, but the licence field reports NOASSERTION, meaning GitHub could not classify it automatically. The README calls the code source-available rather than open source and mentions a paid white-label licence. Those two statements are consistent with each other, but neither tells you what you may do with a modified build. Read the LICENSE file itself rather than assuming it behaves like MIT or AGPL.
The second limitation is the one the README does not address at all: upgrades. The quick setup tells you to clone a specific tag and warns against tracking a branch, but nothing in the README describes a supported upgrade path from one tag to the next, and there is no documented rollback. The release history shows why this matters. Three releases landed within roughly two days of each other in September 2026 (v5.13.41, v5.13.42, v5.13.43), which is a fast cadence. Fast cadences are good for fixes and expensive for operators who have to test each jump themselves. If you cannot tolerate reading release notes before every upgrade, the hosted version removes that task.
The third case is any environment where you cannot run a PHP application with a MySQL database and a scheduler. The README lists mobile and desktop clients for iPhone, Android, F-Droid, macOS, Windows, Linux via Snap and Flatpak, and states that the self-hosted options support those clients. That is a genuinely useful property, but the clients are clients. The server still has to live somewhere.
Invoice Ninja 5 compared with Akaunting and InvoicePlane
The two comparisons that come up most often are Akaunting and InvoicePlane, and the difference is mostly about scope. InvoicePlane is a PHP invoicing application in the older, narrower tradition: invoices, clients, quotes. It does not carry project tracking, tasks or a time tracker in its topic list, and it does not present itself as a platform with a documented REST API and a first-party mobile client. If your need is invoices and nothing else, that narrower surface is a feature, because there is less to configure and less to keep patched.
Akaunting is the closer comparison, since it is also a Laravel-based business finance application. The distinction the Invoice Ninja README makes is that all Pro and Enterprise features from the hosted app are included in the source-available code, so the self-hosted build is not a reduced tier. It also names a specific paid item, the $40 per year white-label licence. Anyone weighing the two should compare what each project gates behind a paid tier, because that is where the practical difference shows up after installation rather than during it.
The honest summary is that Invoice Ninja 5 is the heavier of the three. It brings time tracking, projects, a client portal, an API documented at api-docs.invoicing.co, and a Go SDK listed in the README. If you do not want those, you are paying the operational cost of the Laravel stack for features you will not use.
Maintenance, releases and licence cost
The repository is not archived, and the last push was on 2026-09-20, one day before the date used for this review. The most recent release in the list is v5.13.43 on 2026-09-18. Whatever else is uncertain, this is not an abandoned codebase, and the default branch is v5-stable rather than a development branch, which matches the README's instruction to install from tags.
The maintenance cost you take on is not the project's, it is yours. You are responsible for the PHP runtime, the MySQL database, the queue worker, the scheduler that drives NINJA_AUTO_BILL_TIME, and the PDF rendering path. The README's own instruction to install from tags rather than branches is the single most useful piece of operational guidance in the document, and it implies a workflow: read the release notes, pin the new tag, test, and keep the old checkout until the new one is verified. Because the README does not document a rollback procedure, that old checkout plus a database backup is your rollback.
On licensing, the practical points are that the code is described as source-available, the licence identifier is unresolved in the repository metadata, and a white-label licence is sold separately at $40 per year to remove branding from client-facing parts of the app. Whether that branding removal is required for your use, and what the LICENSE file permits for a modified build, are questions for the licence text and, if the answer matters commercially, for a lawyer. Nothing here should be read as legal advice.
One more operational detail from .env.example: COMPOSER_AUTH is present with a GitHub OAuth token placeholder referencing a secrets variable. That is a CI pattern, not something a self-hoster needs, but it is a reminder that the install path assumes composer can reach GitHub.
Editorial conclusion
Adopt Invoice Ninja 5 if you want invoices, quotes, projects and time tracking in one Laravel codebase and you are willing to run PHP, MySQL and a queue yourself, or if you would rather pay for the hosted version and skip that work. Do not pick it if nobody on the team can read a Laravel stack trace or manage a database backup, and do not treat the self-hosted route as a five-minute install. Before committing, verify three things: that your chosen tag builds with composer on your PHP version, that PDF_GENERATOR is set to a value your server can actually satisfy, and that you have a copy of APP_KEY somewhere you will still have it after a disk failure.
Frequently asked questions
Is Invoice Ninja really free?
The README states that all Pro and Enterprise features from the hosted app are included in the source-available code, so the self-hosted build is not a reduced tier. The one paid item the README names is a $40 per year white-label licence to remove Invoice Ninja branding from client-facing parts of the app. Hosting, servers and any third-party services you route through remain your cost.
How does Invoice Ninja work?
It is a Laravel application. The README describes the request path as middleware, then a Form Request for authorization and validation, then a controller, then a repository and service class, then an event that notifies listeners registered in app/Providers/EventServiceProvider. The API and client portal are both built on Laravel, and routes/api.php lists the available API endpoints.
How do I install Invoice Ninja?
The README gives an advanced quick setup: clone a specific tag with git, copy .env.example to .env, and run composer i -o --no-dev, then configure the database settings. It points to the official self-hosted installation guide for the full procedure, and warns that you should install from the latest tag rather than a branch such as v5-develop.
How do I install Invoice Ninja with Docker?
The README lists a Docker image at hub.docker.com/r/invoiceninja/invoiceninja among the self-hosted server options. The repository does not include a compose file, so the image documentation is where the deployment details live.
What is Invoice Ninja?
It is a source-available invoice, quote, project and time-tracking application built with Laravel. The README offers it two ways: a hosted SaaS version, and a self-hosted version for people who want to manage their own hosting and server infrastructure.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/invoiceninja-invoiceninja)