73 lines
3.3 KiB
Markdown
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.
|