自架發票軟體比較:Invoice Ninja、InvoiceShelf 等 5 款
比較 Invoice Ninja、InvoiceShelf、InvoicePlane、Kimai 與 ERPNext 在單一 VPS 的週期性帳單、稅務、客戶入口網站、付款閘道及授權條款。
應該選擇哪一套自架發票軟體?
在單一 VPS 上,自架發票軟體主要有 5 個實際可行的選擇,而且它們並不是相近的替代品。Invoice Ninja 是功能最完整的產品:週期性發票、客戶入口網站、付款閘道與電子發票格式,在安裝完成後即可使用。InvoiceShelf 是較輕量、完全開放原始碼的選項。InvoicePlane 是單純的 PHP 應用程式,不需要額外協調元件。Kimai 用來記錄工時並據此計費,而不是處理明細項目。ERPNext 是完整的會計系統,也能列印發票。
有兩個問題,比缺少某項功能更常讓自架發票系統失效。第一個是電子郵件。發票若停留在垃圾郵件資料夾,就等於尚未收款,而且你不會收到任何通知。第二個是備份。這是唯一一種資料庫,一旦遺失,造成的會是稅務問題,而不只是使用上的不便。
請先閱讀授權條款,再查看功能清單。這 5 個選項中,有 3 個採用著作傳式授權、1 個採用寬鬆授權,另 1 個則提供原始碼,但對可進行的操作設有實際限制。
5 個選項及其適用對象
Invoice Ninja
這是一個 Laravel 應用程式,目前採用 v5 系列。自行託管免費且功能不受限,包含週期性發票、報價單、專案、工時追蹤、費用、客戶入口網站,以及 Stripe 和 PayPal 等付款閘道。該專案自稱為「使用 Laravel 建置的可取得原始碼發票、報價單、專案與工時追蹤應用程式」。唯一付費項目是品牌移除。根據專案本身的說明:「我們提供每年 $40 的白標授權,用於移除應用程式面向客戶部分的 Invoice Ninja 品牌。」截至 August 2026,價格仍為此金額。
如果你需要功能最完整的產品,且能接受執行規模最大的軟體堆疊,請選擇它。
InvoiceShelf
這是 Crater 的分支,採用 GNU Affero General Public License version 3 (AGPL-3.0)。功能涵蓋發票、估價單、週期性帳單、費用、稅務、多幣別、客戶入口網站及多公司管理。付款與白標功能位於個別的官方模組儲存庫,兩者都採用 AGPL-3.0,且均可免費使用。卡片付款透過 Stripe checkout 處理。
如果你需要小型且完全開放原始碼的應用程式,不需要三十個付款閘道,請選擇它。
InvoicePlane
這是一個以 CodeIgniter 建置的 PHP 應用程式,採用 MIT licence,也是這裡唯一透過將檔案解壓縮至 web root 來安裝的選項。不需要 Docker,也不需要 Node 建置步驟。PDF 由 mPDF 產生,因此範本採用 HTML 和 CSS。客戶會取得訪客連結,用於檢視及支付發票。
問題在於付款功能。文件明確指出,InvoicePlane 1.6 預設只支援 Stripe,其他供應商已在該版本移除。1.6 系列公布的需求為 PHP 8.0 至 8.1,以及 MySQL 5.5 或相容的 MariaDB。請閱讀所下載版本的說明,因為 1.7 系列仍在持續變動。
如果你使用 shared hosting 或 512 MB VPS,請選擇它。
Kimai
這是一個 AGPL-3.0 工時追蹤器,可根據工時表產生發票。對於按工時收費的人來說,這是合適的選擇。發票範本以 DOCX、ODS 或 XLSX 檔案上傳。文件確認這些是唯一接受的格式,之後會轉換為 PDF 或 HTML。你可以使用文書處理器排版發票,而不是撰寫 CSS,多數人會覺得這比較容易。
Kimai 沒有客戶入口網站或付款閘道,因此你必須以電子郵件寄送 PDF。結構化電子發票功能是付費商店外掛 E-Invoice Plus。截至 August 2026,自行託管安裝的價格為每年 99 EUR,未含 VAT,支援 EN16931、XRechnung、ZUGFeRD、Factur-X 及 Peppol 設定檔。
如果發票是追蹤工時後產生的結果,請選擇它。
ERPNext
它採用 GPL-3.0,且屬於不同類別的軟體。銷售發票只是完整會計系統中的一種文件類型。系統還包含會計科目表、日記帳分錄、庫存及薪資管理。當開立發票不再是全部工作時,這是合適的選擇。對只有八個客戶的單一自由工作者而言,這套軟體過於龐大。部署本身就是一個專案,詳見 在 VPS 上執行 ERPNext。
週期性發票依賴一個你看不見的排程器
Invoice Ninja、InvoiceShelf、InvoicePlane 和 ERPNext 都能產生週期性發票。Kimai 的核心沒有週期性發票功能,因為它會根據特定期間的工時表項目建立發票。
所有以 Laravel 為基礎的系統,其失敗模式都相同,而且不會顯示明顯錯誤。週期性發票由排程工作 php artisan schedule:run 建立,應用程式外部的某個元件必須每分鐘呼叫它。如果沒有任何元件呼叫它,週期性發票清單仍會顯示下次寄送日期,但日期會直接過去。發票不會產生。日誌也不會記錄錯誤,因為根本沒有程式碼執行。
因此,建立第一張週期性發票後,請將下次寄送日期設為幾分鐘後,然後等待。如果沒有收到發票,表示排程器沒有執行。在 Docker 安裝中,通常是 compose 檔案中的 cron 或 scheduler 服務從未啟動,或服務已結束。
docker compose ps
docker compose logs --tail 50檔案中的每個服務都應回報 running。處於 exited 狀態的服務,就是你需要讀取其日誌的服務。
多幣別與稅務:決定採用前應檢查的項目
功能清單中的「多幣別」可能代表差異很大的功能。請在示範執行個體上執行以下 4 項檢查,並使用自己業務中的實際數字。因為這類錯誤通常是由會計師發現,而不是由你自己發現。
- 發票是否儲存開立日期所適用的匯率?這是必要條件。如果應用程式使用即時匯率重新計算總額,上一季的報表會在每次開啟時變更,帳簿也會與已申報的資料不一致。
- 稅額是按明細項目、按發票,還是兩者都計算?在其中一個明細項目適用 0 稅率之前,單一發票層級的稅率看似沒有問題。
- 是否可以輸入含稅價格,也可以輸入未稅價格?事後轉換會使每個明細項目產生 1 分的四捨五入差異,而這些差異會在一年內累積。
- 對於不必繳納 VAT 的其他國家客戶,文件會顯示哪些內容?發票上必須列印免稅說明,不能只在稅額欄顯示 0。
Invoice Ninja 和 ERPNext 可處理以上 4 項需求。InvoiceShelf 將稅務與多幣別列為功能。InvoicePlane 和 Kimai 的功能較簡單,因此請使用最棘手的發票測試,而不是最容易處理的發票。
客戶入口網站與付款閘道
客戶入口網站是讓客戶查看發票、下載 PDF 並付款的頁面。這項功能的重要性超出一般預期,因為透過電子郵件催款所耗費的時間,可能比製作發票還多。
Invoice Ninja 在這方面最完整,提供完整的入口網站、多種付款閘道、已儲存的付款方式,以及週期性發票的自動計費。InvoiceShelf 提供客戶入口網站,並透過其 payments 模組加入 Stripe checkout。InvoicePlane 會為每張發票提供訪客連結,並支援 Stripe。Kimai 兩者皆不支援,因此只能將 PDF 以附件寄出。
有一點經常被混淆。自行代管開立發票的應用程式,不代表要保存卡號。使用 Stripe checkout 時,客戶會被重新導向至 Stripe,並在 Stripe 上輸入卡號;你的 VPS 完全不會看到這組號碼。你的 PCI(payment card industry)合規範圍之所以能維持在較小程度,正是因為你沒有自行建立付款表單。如果之後需要多個付款處理商,或希望依國家分流付款,應將這項功能放在獨立的層中,例如 使用 Hyperswitch 自行代管付款編排。
PDF 品質,以及最後要編輯的範本
您會編輯這份範本。這裡的每個預設值,都會將您的地址放在不符合所在國家規範的位置。
Invoice Ninja 使用映像檔內建的無頭 Chromium,將 HTML 與 CSS 範本轉換成 PDF,因此容器映像檔較大。請為此預留記憶體:無頭瀏覽器是整個軟體堆疊中最耗用資源的程序,因此 1 GB VPS 的容量相當吃緊。InvoicePlane 使用 mPDF。mPDF 純粹以 PHP 實作,資源用量低,但會忽略部分新式 CSS。Kimai 則採取相反的方式,要求您上傳 DOCX 或 ODS 檔案,再由不曾撰寫樣式表的人員使用 LibreOffice 或 Word 完成版面配置。
如果發票的設計對您很重要,而 CSS 不是重點,Kimai 的方式較適合。如果您希望範本能納入版本控制並可比較差異,HTML 是較佳選擇。
授權條款是否允許商業使用?
這 5 個專案都允許你向自己的客戶開立發票。差異會在你進一步使用它們時出現。
Invoice Ninja 採用 Elastic License 2.0。其中有 2 個條款需要注意。
你不得以代管或受管理服務的形式,向第三方提供本軟體,且該服務讓使用者存取本軟體的大部分功能。
你不得移動、變更、停用或規避本軟體中的授權金鑰功能。
因此,為自己的企業執行它沒有問題;但若將執行個體作為產品提供給客戶,則不允許。第二個條款也是移除品牌標示需要支付 $40 授權費,而不是直接修改原始碼的原因。
InvoiceShelf、Kimai 和 Crater 採用 AGPL-3.0。商業使用免費,也沒有更高階的方案。相關義務位於第 13 節:如果你修改程式碼,並讓其他人透過網路使用修改後的版本,就必須向他們提供你的修改內容原始碼。未修改的執行個體已受到上游公開原始碼涵蓋,因此大多數自行代管者不會遇到這項要求。
InvoicePlane 採用 MIT,是這些專案中限制最少的授權條款。不過,其 README 指出名稱與標誌仍歸專案所有。
ERPNext 採用 GPL-3.0。你散布的修改內容必須一併提供,而私下執行則沒有相關義務。
以上是對授權條款內容的說明,不構成法律建議。
專案仍在維護嗎?請檢查提交記錄
Crater 多年來一直是廣受使用的開放原始碼發票應用程式,許多指南至今仍推薦使用它。但其預設分支已有 741 天未提交任何變更。
The data behind this chart
[
{
"label": "ERPNext",
"commit_gap": 0
},
{
"label": "Invoice Ninja",
"commit_gap": 1
},
{
"label": "Kimai",
"commit_gap": 1
},
{
"label": "InvoicePlane",
"commit_gap": 3
},
{
"label": "InvoiceShelf",
"commit_gap": 4
},
{
"label": "Crater",
"commit_gap": 741
}
]該區塊中的 6 個專案裡,只有五個在過去一週內有提交記錄。InvoiceShelf 是延續 Crater 開發工作的分支,採用相同的 AGPL-3.0 授權條款與相同的資料模型,因此遷移過去屬於資料移轉,而不是重新開發。請安裝 InvoiceShelf,不要安裝 Crater。
在 VPS 上安裝各項應用程式
除了 InvoicePlane 之外,其他應用程式都最適合使用 Docker Compose 執行。如果你不熟悉 Docker Compose,請先閱讀在 VPS 上建立第一個 Docker Compose 堆疊,再回到這裡。
Invoice Ninja 提供自己的 compose repository。
git clone https://github.com/invoiceninja/dockerfiles.git
cd dockerfiles
docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --show將該金鑰複製到 repository 中的 env 檔案,並填入實際的 APP_URL。接著設定映像檔預期的擁有權,再啟動服務。
chmod 755 docker/app/public
sudo chown -R 1500:1500 docker/app
docker compose up -d1500:1500 擁有權必須符合映像檔內部的使用者。若略過此步驟,應用程式將無法寫入快取或產生的 PDF。在設定精靈中,將 db 設為資料庫主機,因為這是 compose network 上的服務名稱。localhost 則指向應用程式容器本身。
InvoiceShelf 針對各種資料庫引擎提供現成的 compose 檔案。
curl -fLO https://raw.githubusercontent.com/InvoiceShelf/docker/master/docker-compose.mysql.yml
mv docker-compose.mysql.yml docker-compose.yml啟動前先開啟該檔案。檔案中的所有密碼都是預留位置,註解也已明確說明這點。APP_URL、SESSION_DOMAIN 和 SANCTUM_STATEFUL_DOMAINS 預設都設為 localhost;首次登入前,這 3 個值都必須改成實際的主機名稱。接著啟動服務。
docker compose up -d它會在主機上發布 8090 埠,並在容器內提供 8080 埠。在讓任何用戶端連線之前,先在前方設定具備 TLS(transport layer security)的反向代理。
Kimai 正式環境 compose 檔案,取自專案文件
services:
sqldb:
image: mysql:8.3
volumes:
- mysql:/var/lib/mysql
environment:
- MYSQL_DATABASE=kimai
- MYSQL_USER=kimaiuser
- MYSQL_PASSWORD=kimaipassword
- MYSQL_ROOT_PASSWORD=changemeplease
command: --default-storage-engine innodb
restart: unless-stopped
healthcheck:
test: mysqladmin -uroot -p$$MYSQL_ROOT_PASSWORD ping -h 127.0.0.1 --silent
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
kimai:
image: kimai/kimai2:stable
depends_on:
sqldb:
condition: service_healthy
restart: true
volumes:
- data:/opt/kimai/var/data
- plugins:/opt/kimai/var/plugins
ports:
- 8001:8001
environment:
- APP_SECRET=your-fantastic-long-random-and-ultra-secure-secret
- TRUSTED_HOSTS=kimai.example.com
- ADMINMAIL=admin@example.com
- ADMINPASS=changemeplease
- DATABASE_URL=mysql://kimaiuser:kimaipassword@sqldb/kimai?charset=utf8mb4&serverVersion=8.3.0
restart: unless-stopped
volumes:
data:
mysql:
plugins:將 APP_SECRET 設為自行產生的長隨機字串,並將 TRUSTED_HOSTS 設為實際使用的網域。ADMINMAIL 和 ADMINPASS 會在首次啟動時建立第一個管理員帳號,因此之後請在介面中變更該密碼,並將密碼從檔案中移除。
InvoicePlane 沒有容器。請先建立空白資料庫。
sudo mysql -e "CREATE DATABASE invoiceplane CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"從專案的 releases 頁面下載封存檔,將其解壓縮到 Web 根目錄,將 ipconfig.php.example 複製為 ipconfig.php,再依照該檔案中的註解設定 URL。接著開啟 https://your-domain.example/index.php/setup,依照安裝程式完成設定。
為什麼你的發票會落入垃圾郵件資料夾
這是會讓你損失金錢的故障,而且應用程式仍會顯示發票已傳送。
不要使用 VPS 自己的 IP 位址傳送發票郵件。新的 VPS IP 沒有寄信歷史,大型收件服務通常會預設將來自託管網段中未知位址的第一封郵件視為可疑。請透過你已完成驗證之網域上的 SMTP (simple mail transfer protocol) relay 傳送。完整完成這項設定需要另一份指南,從自架應用程式可靠地傳送郵件涵蓋 relay、DNS 記錄與測試。
From 位址是大多數開票設定最容易出錯的地方。它必須使用你控制的網域,而且 relay 必須以 DKIM (domainkeys identified mail) 為該網域簽署。將客戶自己的位址放在 From 看似禮貌,卻會破壞寄送作業,因為收件伺服器會檢查 From 網域是否與驗證郵件的網域相符。Gmail 會直接拒絕不相符的郵件:
550 5.7.1 Unauthenticated email from example.com is not accepted due to domain's DMARC policy在 From 保留你自己的位址,並將客戶的位址放在 Reply-To。開始傳送正式郵件前,先檢查已發布的記錄。
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short TXT selector1._domainkey.example.com第一個查詢應回傳 SPF (sender policy framework) 記錄,並指出你的 relay。第二個查詢應回傳 DMARC (domain-based message authentication, reporting and conformance) 政策。第三個查詢取決於 relay 提供的 selector;如果沒有回應,表示 DKIM 記錄遺失,或是發布在錯誤的名稱下,因此你傳送的每封郵件都會在簽章檢查時失敗。
接著,將一張正式發票傳送到你在大型服務商擁有的帳戶,並閱讀原始標頭。Authentication-Results 標頭中的 dkim=pass 與 spf=pass 才是唯一有效的證明。應用程式自己的「已傳送」旗標只表示它已將郵件交給 relay。
備份:唯一不能遺失的資料庫
遺失媒體伺服器只代表需要重新下載檔案。即使是 PhotoPrism 或 Immich 等自架相片伺服器,通常也只是保存手機上的原始檔副本,而原始檔仍存在於拍攝這些照片的手機中。遺失開票資料庫則代表你無法證明開立過哪些帳單、已收取哪些款項,或仍欠哪些款項。請以相應的嚴謹程度處理。
請備份 4 項內容。資料庫。儲存磁碟區,其中包含標誌、產生的 PDF 和費用收據。應用程式的環境檔案。以及以一般檔案保存的產生後 PDF,因為即使沒有產生該 PDF 的應用程式,10 年後仍能開啟它。
環境檔案的重要性超乎許多人預期。Laravel 會使用該檔案中的 APP_KEY,加密包括付款閘道憑證在內的敏感儲存值。若將資料庫還原到使用新產生金鑰的環境中,這些值便無法解密。你的發票全部存在,但付款閘道設定已無法讀取。
InvoiceShelf stack 的傾印方式如下。其資料庫服務執行於 mariadb:10,因此容器內使用的工具是 mariadb-dump。
docker compose exec -T database mariadb-dump \
--user=root --password=YOUR_ROOT_PASSWORD \
--single-transaction --databases invoiceshelf > invoiceshelf.sql--single-transaction 會在不鎖定 InnoDB 資料表的情況下建立一致的快照,因此傾印執行期間應用程式仍可提供服務。-T 會阻止 Docker 配置終端機,否則可能損毀重新導向的輸出,產生無法匯入的傾印檔案。
請依排程,使用 加密的 restic 備份將資料傳送至異地儲存,並將保留期限設定為足以涵蓋會計師指定的期間。
接著進行還原。將傾印載入一次性容器,登入後開啟上個月的發票。在你完成這項操作前,無法確認備份是否可用。
會計師會要求的資料
不要把教學文章當作稅務建議。以下列出的是這套軟體可以產生的資料,方便你將清單提供給負責提供建議的人員。
可匯出的資料。 你應該能直接從介面將發票與付款資料匯出為 CSV,不需要資料庫用戶端,也不需要開立支援請求。SQL 傾印是備份,不是匯出,因為你的會計師無法直接開啟。
不可變更的編號。 發票編號應依序編排,且不得重複使用,也不應出現缺號。刪除發票會留下缺號,之後必須說明原因。請改用取消或折讓處理,這裡的每個應用程式都支援這兩種方式。是否必須使用無缺號編排,取決於你的登記所在地,因此值得及早詢問。
保存期限。 依規定保存資料庫傾印檔與產生的 PDF。PDF 是實際寄出的文件;如果日後有人對發票提出爭議,這才是重要的憑證。
變更記錄。 能夠顯示誰在何時編輯過發票很有價值,而這也是這些應用程式之間差異最大的功能之一。Invoice Ninja 會為每筆記錄保留活動日誌。
在 EU 部分地區,結構化電子發票已成為實際要求,不再只是額外功能。Invoice Ninja 可產生常見格式,包括 ZUGFeRD 與 XRechnung、Facturae、FatturaPA,以及通用的 EN16931。從自架執行個體透過 Peppol network 傳送時,必須使用 Invoice Ninja 自有的 access point:你需要向他們登記你的組織,並按每次提交購買 credits,因此截至 August 2026 這是付費服務。Kimai 透過其付費 plugin 也能支援相同格式。其他 3 個應用程式目前完全無法產生結構化電子發票;如果你在 EU 內開立發票,這是選擇 Invoice Ninja 最充分的單一理由。
FAQ
我應該安裝 Crater 還是 InvoiceShelf?
InvoiceShelf。Crater 的預設分支截至 21 August 2026 已有 741 天沒有提交,且其 issue tracker 也引導使用者改用 fork。InvoiceShelf 採用相同的 AGPL-3.0 授權與資料模型,因此兩者之間的遷移是資料庫遷移,而不是重新開發。任何仍建議使用 Crater 的指南,都是在該專案停止活躍前撰寫的。
我可以不付費,將 Invoice Ninja 用於自己的企業嗎?
可以。自行代管的 Invoice Ninja 依 Elastic License 2.0 提供完整功能,無須付費,包括週期性發票、客戶入口網站與付款閘道。以下兩項功能需要付費。若要移除面向客戶頁面上的 Invoice Ninja 品牌,必須購買 white-label 授權;依該專案截至 August 2026 的說明,費用為「每年 $40」。透過 Peppol network 傳送電子發票則另行計費。該授權禁止的是將軟體作為代他人代管的服務執行。
為什麼我的發票電子郵件會進入垃圾郵件資料夾?
幾乎總是因為郵件的 From 位址未通過該網域的驗證。請透過 SMTP relay 寄送,而不要直接從 VPS 寄出;接著為網域發布 SPF 與 DMARC 記錄,並依 relay 提供的 selector 新增 DKIM 記錄。將自己的位址保留在 From,並將客戶位址放在 Reply-To。若將客戶位址設為寄件者,Gmail 會以 550 5.7.1 Unauthenticated email from example.com is not accepted due to domain's DMARC policy 拒絕郵件。請在測試郵件的 Authentication-Results 標頭中找到 dkim=pass 與 spf=pass,以確認修正已生效。
如果我按小時計費,應該選哪一個?
Kimai。它首先是時間追蹤工具,因此發票會由已核准的工時表項目產生,明細項目就是你記錄的工作內容。範本是 DOCX、ODS 或 XLSX 檔案,可在文書處理器中設計,比編輯 CSS 更容易。代價是 Kimai 沒有客戶入口網站或付款閘道,因此你必須寄送 PDF,並透過轉帳收款。Invoice Ninja 也能追蹤時間,且提供入口網站;如果線上刷卡付款比工時表細節更重要,請改選 Invoice Ninja。
我究竟需要備份哪些內容?
資料庫、存放標誌與產生之 PDF 的儲存磁碟區、環境檔案,以及以純檔案形式保存的已轉譯 PDF。環境檔案最容易被遺漏:Invoice Ninja 與 InvoiceShelf 等 Laravel 應用程式會使用 APP_KEY 加密儲存的認證資料,因此,若將資料庫還原到使用新產生金鑰的環境旁,付款閘道設定將無法讀取。請完整還原到一次性測試環境,並開啟一張舊發票,因為這是確認備份可用的唯一方法。