1
0
Fork 0
kubernetes/invoice-ninja/README.md

73 lines
3.3 KiB
Markdown

# Invoice Ninja
[Invoice Ninja][0] is a free invoice and customer management system. Tabitha
uses it to manage her tutoring and learning center billing and payments.
[0]: https://www.invoiceninja.org/
## Components
*Invoice Ninja* is a web-based application, written in PHP. The official
container image only includes the application itself and PHP-FPM, but no HTTP
server, so a separate *nginx* container is necessary. The image is also of
dubious quality, doing weird things like copying "backup" files to persistent
storage at startup, then deleting them from the container filesystem. To
work around this, an init container is necessary to copy the application into
writable ephemeral storage.
Persistent storage is handled in a somewhat ad-hoc way. There are three paths
that are expected to be persistent:
* `/var/www/app/public`
* `/var/www/app/storage`
* `/var/www/app/public/storage`
The distinction between these is not really clear. Both "public" directories
have to be served by the web server, as well.
In addition to the main process, a "cron" process is required. This has to
run every minute, apparently.
*Invoice Ninja* also requires a MySQL or MariaDB database. Supposedly,
PostgreSQL can be used as well, but it is not supported by upstream and
apparently requires patching some PHP code.
## Phone Home
Although *Invoice Ninja* can be self hosed, it relies on some cloud services
for some features. Notably, generating PDF invoices makes a few connections to
external services:
* *fonts.googleapis.com*: Fetches CSS resources
* *invoicing.io*: Fetches the *Invoice Ninja* logo to print at the bottom
Both of these remote resources are hard-coded into the HTML document template
that is used to render the PDF. The former is probably innocent, but I suspect
the latter is some kind of "phone home," informing upstream of field deployments.
Additionally, when certain actions are performed in the web UI, the backend
makes requests to *www.google-analytics.com*, obviously for telemetry.
Further, the *Invoice Ninja* documentation lists some "terms of service" for
self-hosting, which include sending personally identifiable information to
the *Invoice Ninja*, including company name and contact information, email
addresses, etc.
The point of self-hosting applications is not to avoid paying for them (in
fact, I pay for some cloud services offered by open source developers, even
though I self-host their software), but to avoid dependencies on cloud
services. For *Invoice Ninja*, that means we should be able to make invoices
any time, even if upstream ceases offering their cloud service. Including a
"phone home" in the invoice generation that can prevent the feature from
working, even if it is by accident, is unacceptable.
To that end, I have neutered *Invoice Ninja*'s phone-home capabilities. First,
a script runs before the main container starts that replaces the hard-coded
URL of the *Invoice Ninja* logo with the URL to the same logo in the local
installation. Next, I have blocked all outbound communication from *Invoice
Ninja* pods using a NetworkPolicy, except for Kubernetes services and the
forward proxy on the firewall. Finally, I have configured the forward proxy
(Squid) on the firewall to *only* allow access to *fonts.googleapis.com*, so
that invoices render correctly, blocking all telemetry and other phone-home
communication.