InvoiceShelf

InvoiceShelf

Official

Docker app from samuel3889's Repository

Overview

InvoiceShelf is a self-hosted, open source invoicing and estimates app built with Laravel and VueJS. ===================================================== READ THIS FIRST - 3 STEPS, THEN YOU'RE DONE ===================================================== STEP 1 - Create the database. This template runs the webapp only (pgsql variant). It does NOT deploy its own database and expects an external PostgreSQL 16 server or container to already be running. On that Postgres instance, create a database and a dedicated user that owns it, then fill in the DB_* fields below. Use a real password, not the Postgres superuser. Reference compose file: https://github.com/InvoiceShelf/docker/blob/master/docker-compose.pgsql.yml STEP 2 - Create the two appdata folders BEFORE clicking Apply. Paste this into the Unraid terminal (adjust paths if you changed the Uploads/Logs mappings below): mkdir -p /mnt/user/appdata/InvoiceShelf/uploads /mnt/user/appdata/InvoiceShelf/logs chown -R 82:82 /mnt/user/appdata/InvoiceShelf chmod -R 775 /mnt/user/appdata/InvoiceShelf Why: this image runs as the unprivileged user www-data (UID/GID 82:82 on Alpine). If Unraid creates these folders itself they come out root-owned and the setup wizard's permission check will fail. This is a one-time command - the ownership survives container recreation, image pulls and app updates, so you never run it again. STEP 3 - Run the setup wizard, and expect one red dot. On the wizard's Permissions screen, bootstrap/cache/ shows red. This is expected and harmless. That folder ships inside the image as mode 755, and the wizard compares the octal mode against 775 instead of testing whether the folder is actually writable. It IS writable - it is owned by www-data and Laravel caches config and routes into it successfully on every boot. Click Continue. storage/framework/ and storage/logs/ should both be green. If storage/logs/ is red, you skipped Step 2. ===================================================== STORAGE LAYOUT ===================================================== The full Laravel storage tree lives on a Docker-managed named volume (invoiceshelf_storage) which Docker auto-populates from the image on first start. Two folders are bind-mounted on top of it into /mnt/user/appdata so the Appdata Backup plugin can see them: Uploads = company logos and files added through the UI (Laravel's public disk). Logs = laravel.log, for troubleshooting. DO NOT bind-mount the whole /var/www/html/storage directory to an empty appdata folder. Unlike named volumes, bind mounts do not copy content out of the image, so doing that erases the shipped PDF templates and the container dies on boot with: The "/var/www/html/storage/app/templates/pdf" directory does not exist. The nested layout in this template exists specifically to avoid that. Consequence: the stock PDF templates stay inside the named volume and are not covered by Appdata Backup. That is fine for almost everyone, since they ship with the image and are restored on every pull. If you hand-edit them, back up the named volume separately. Your invoices, customers and payments live in your external Postgres database. Back that database up - this template cannot do it for you. ===================================================== REVERSE PROXY ===================================================== If running behind Nginx reverse proxy with a nonstandard port (eg. https://your-domain.com:50443), the custom configuration for location '/' must be: proxy_set_header X-Forwarded-Host $host:50443; proxy_set_header X-Forwarded-Port 50443; If login bounces you back to the login screen or throws a 419 / CSRF token mismatch, the host:port you typed in the browser is missing from SANCTUM_STATEFUL_DOMAINS. That variable must list every address you load the app from, including the port whenever it is not 80 or 443.

InvoiceShelf

Open-source invoicing for people who want to own their business data.

Download InvoiceShelf · Documentation · Join Discord

[!WARNING] The default 3.x branch is an alpha preview. It is ready for testing and feedback, but not for production data. Use the supported 2.x release for a production installation.

InvoiceShelf dashboard

Run your invoicing from one place

InvoiceShelf is a self-hosted web application for creating invoices, tracking payments and expenses, and keeping customer accounts organised. It is built for freelancers and small businesses that want a focused workflow without giving up control of their data.

  • Create invoices and estimates, then export polished PDFs.
  • Record payments and see what each customer still owes.
  • Track expenses, taxes, and business reports.
  • Schedule recurring invoices for repeat work.
  • Give customers a portal for invoices, estimates, and payment history.
  • Manage multiple companies and invite team members with scoped roles.

Optional official modules can add specialised features without making the core application heavier.

Install InvoiceShelf

Production: InvoiceShelf 2.x

Install the current stable release from the self-hosted download page, or run the official Docker image with the :latest tag. Follow the installation guide for the complete setup and upgrade instructions.

Preview: InvoiceShelf 3.x

Use the preview only with disposable or backed-up data:

A minimal SQLite Docker setup looks like this:

git clone https://github.com/InvoiceShelf/docker.git invoiceshelf
cd invoiceshelf
cp docker-compose.sqlite.yml docker-compose.yml
# For the 3.x preview, change the image tag in docker-compose.yml to :next.
docker compose up -d

Open http://localhost:8090 and finish the setup wizard. Read the Docker guide before using InvoiceShelf on a public server.

For a traditional web-server installation, see the manual installation guide. InvoiceShelf 3.x requires PHP 8.4 and supports MySQL/MariaDB, PostgreSQL, and SQLite. Docker includes the required application runtime.

Learn and get help

Contribute

Code contributions are welcome. Start with the contribution guide and use the development environment in docker/development.

You can also help translate InvoiceShelf on Crowdin.

License

InvoiceShelf is released under the GNU Affero General Public License v3.0.

Install InvoiceShelf on Unraid in a few clicks.

Find InvoiceShelf in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for InvoiceShelf Review the template variables and paths Click Install

Requirements

1) An already-running external PostgreSQL 16 server with a database + user created for InvoiceShelf - this template does not create it for you. 2) The two appdata folders created and chowned to 82:82 before first start (see Step 2 in the description above).

Categories

Download Statistics

644,777
Total Downloads
39,858
This Month
25,512
Avg / Month

Total Downloads Over Time

Loading chart...

Related apps

Explore more like this

Explore all

Details

Repository
invoiceshelf/invoiceshelf:latest
Last Updated2026-08-13
First Seen2025-02-11

Runtime arguments

Web UI
http://[IP]:[PORT:8080]/
Network
bridge
Shell
sh
Privileged
false
Extra Params
-v invoiceshelf_storage:/var/www/html/storage/ -v invoiceshelf_modules:/var/www/html/Modules/

Template configuration

WebUI PortPorttcp

Host port for the InvoiceShelf web UI. Change the left-hand host port if 8090 is already taken. If you route to this container by name through a reverse proxy on a custom network, you can remove this mapping entirely.

Target
8080
Default
8090
Value
8090
UploadsPathrw

Company logos and files uploaded through the web UI. Kept in appdata so the Appdata Backup plugin picks them up. IMPORTANT: create this folder and chown it to 82:82 before first start - see Step 2 in the description above.

Target
/var/www/html/storage/app/public
Default
/mnt/user/appdata/InvoiceShelf/uploads
Value
/mnt/user/appdata/InvoiceShelf/uploads
LogsPathrw

Laravel application logs (laravel.log), for troubleshooting. IMPORTANT: create this folder and chown it to 82:82 before first start - see Step 2 in the description above.

Target
/var/www/html/storage/logs
Default
/mnt/user/appdata/InvoiceShelf/logs
Value
/mnt/user/appdata/InvoiceShelf/logs
DB_HOSTVariable

Hostname, container name, or IP of your existing PostgreSQL 16 server. If it shares a custom Docker network with this container, the container name works; otherwise use your Unraid server IP.

DB_DATABASEVariable

Database name. Must already exist on the external Postgres server.

Default
invoiceshelf
Value
invoiceshelf
DB_USERNAMEVariable

Database user. Must already exist and own the database above. Use a dedicated user - do NOT use the postgres superuser, since that account can read and modify every other database on the server.

Default
invoiceshelf
Value
invoiceshelf
DB_PASSWORDVariable

Password for the database user above. Set a strong unique value - this protects your invoices, customers and payment records.

DB_PORTVariable

PostgreSQL port

Default
5432
Value
5432
APP_URLVariable

Primary public URL, used for links in emails and PDFs. Use your external https URL if you access from outside. Local network access still works independently, as long as SANCTUM_STATEFUL_DOMAINS below also lists it.

Default
https://YOUR-DOMAIN.COM
Value
https://YOUR-DOMAIN.COM
SANCTUM_STATEFUL_DOMAINSVariable

Comma-separated list of every host:port you will load the app from - typically your LAN IP with the host port, plus your external reverse-proxy domain. Include the port whenever it is not 80 or 443. Getting this wrong is the #1 cause of login failing with a 419 / CSRF token mismatch.

Default
SERVER-IP:8090,YOUR-DOMAIN.COM
Value
SERVER-IP:8090,YOUR-DOMAIN.COM
TRUSTED_PROXIESVariable

Required for correct HTTPS and host detection behind a reverse proxy. Leave as * to trust all proxies, or restrict to your reverse proxy's container/LAN IP for tighter security.

Default
*
Value
*
APP_NAMEVariable

Application name shown in the UI.

Default
InvoiceShelf
Value
InvoiceShelf
SESSION_DOMAINVariable

Leave BLANK if you reach InvoiceShelf from more than one hostname or IP (e.g. LAN IP plus external domain) - blank lets the session cookie scope itself to whichever host was used. Only set a single domain here if you exclusively use that one domain.

TZVariable

Container timezone, used for timestamps on invoices and logs.

Default
America/New_York
Value
America/New_York
APP_ENVVariable

Application environment. Leave as production.

Default
production
Value
production
APP_DEBUGVariable

Debug mode. Leave false in production - true leaks stack traces and config values to anyone who can reach the app.

Default
false
Value
false
DB_CONNECTIONVariable

Database driver. This template is the pgsql variant - do not change.

Default
pgsql
Value
pgsql
DB_PASSWORD_FILEVariable

Optional: path to a Docker secret file containing the DB password, used instead of DB_PASSWORD.

CACHE_STOREVariable

Cache driver.

Default
file
Value
file
SESSION_DRIVERVariable

Session driver.

Default
file
Value
file
SESSION_LIFETIMEVariable

Session lifetime in minutes before an idle user is logged out.

Default
240
Value
240
AUTORUN_ENABLEDVariable

Run startup automation (config/route/view caching, storage symlink) on container boot.

Default
true
Value
true
AUTORUN_LARAVEL_MIGRATIONVariable

Auto-run database migrations on boot. Leave false - the setup wizard handles the initial schema. Set true temporarily only if an app update tells you migrations are pending.

Default
false
Value
false
AUTORUN_LARAVEL_OPTIMIZEVariable

Auto-run Laravel optimize on boot.

Default
false
Value
false
PHP_OPCACHE_ENABLEVariable

Enable PHP OPcache. Recommended for production performance.

Default
1
Value
1