invoice-ninja: Deploy Invoice Ninja
Invoice Ninja is a small business management tool. Tabitha wants to use it for HLC. I am a bit concerned about the code quality of this application, and definitely alarmed at the data it send upstream, so I have tried to be extra careful with it. All privileges are revoked, including access to the Internet.
This commit is contained in:
72
invoice-ninja/README.md
Normal file
72
invoice-ninja/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user