Để phục vụ cho công việc kinh doanh, mình đang sử dụng khá nhiều các ứng dụng mã nguồn mở để tiết kiệm chi phí vận hành:
- Odoo: quản lý tồn kho, xuất nhập khẩu, kế toán,…
- Paperless-ngx: quản lý hồ sơ, biên lai, hóa đơn điện tử
- WordPress / Woocommerce: tạo blog / trang bán hàng e-commerce
- Proxmox: quản lý máy ảo, container để cài đặt các ứng dụng web
Từ ngày dọn nhà qua Nhật, có thêm 1 ứng dụng đã nhanh chóng trở thành một phần không thể thiếu cho công ty mới của mình ở Nhật. Đó là Invoice Ninja – ứng dụng tạo và quản lý hóa đơn cho khách hàng. Mình đang sử dụng Invoice Ninja để nhận thanh toán từ khách hàng ở nhiều quốc gia khác nhau, thông qua cổng thanh toán Stripe.
Bài viết này sẽ hướng dẫn bạn cách cài đặt Invoice Ninja để sử dụng cho mục đích kinh doanh của mình
Mục Lục
I. Invoice Ninja là gì?
Invoice Ninja là một phần mềm mã nguồn mở giúp bạn quản lý hóa đơn, báo giá, và các khoản thanh toán cho công việc kinh doanh. Nó được thiết kế phù hợp cho các doanh nghiệp nhỏ, freelancer cần một công cụ đơn giản nhưng mạnh mẽ để quản lý tài chính.
Các tính năng nổi bật của Invoice Ninja:
- Tạo hóa đơn và báo giá chuyên nghiệp.
- Tích hợp với các cổng thanh toán như Stripe, PayPal, …
- Hỗ trợ theo dõi chi phí và quản lý dự án.
- Có thể tự cài đặt lên máy chủ cá nhân để sử dụng miễn phí,
II. Cài đặt Invoice Ninja bằng Docker Compose
Bạn có thể cài đặt Invoice Ninja trực tiếp lên server, hoặc sử dụng Docker. Mình sẽ cài đặt thông qua Docker Compose cho nhanh gọn.
Yêu cầu máy chủ đã được cài đặt sẵn Docker và Docker Compose.
1. Clone Invoice Ninja về server
SSH vào máy chủ và clone repo của Invoice Ninja về máy chủ
git clone https://github.com/invoiceninja/dockerfiles.git -b master invoice-ninja
cd invoice-ninja
Code language: Bash (bash)
File docker-compose.yml
sẽ có nội dung tương tự như sau
version: '3.7'
services:
server:
image: nginx
restart: always
env_file: env
volumes:
# Vhost configuration
#- ./config/caddy/Caddyfile:/etc/caddy/Caddyfiledocker-com
- ./config/nginx/in-vhost.conf:/etc/nginx/conf.d/in-vhost.conf:ro
- ./docker/app/public:/var/www/app/public:ro
depends_on:
- app
# Run webserver nginx on port 80
# Feel free to modify depending what port is already occupied
ports:
- "80:80"
#- "443:443"
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
app:
image: invoiceninja/invoiceninja:5
env_file: env
restart: always
volumes:
- ./config/hosts:/etc/hosts:ro
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
- ./config/php/php.ini:/usr/local/etc/php/php.ini
- ./config/php/php-cli.ini:/usr/local/etc/php/php-cli.ini
depends_on:
- db
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
db:
image: mysql:8
# When running on ARM64 use MariaDB instead of MySQL
# image: mariadb:10.4
# For auto DB backups comment out image and use the build block below
# build:
# context: ./config/mysql
restart: always
env_file: env
volumes:
- ./docker/mysql/data:/var/lib/mysql:rw,delegated
# remove comments for next 4 lines if you want auto sql backups
#- ./docker/mysql/bak:/backups:rw
#- ./config/mysql/backup-script:/etc/cron.daily/daily:ro
#- ./config/mysql/backup-script:/etc/cron.weekly/weekly:ro
#- ./config/mysql/backup-script:/etc/cron.monthly/monthly:ro
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
# THIS IS ONLY A VALID CONFIGURATION FOR IN 4. DO NOT USE FOR IN 5.
# cron:
# image: invoiceninja/invoiceninja:alpine-4
# volumes:
# - ./docker/app/public:/var/www/app/public:rw,delegated
# - ./docker/app/storage:/var/www/app/storage:rw,delegated
# - ./docker/app/public/logo:/var/www/app/public/logo:rw,delegated
# entrypoint: |
# /bin/sh -c 'sh -s <<EOF
# trap "break;exit" SIGHUP SIGINT SIGTERM
# sleep 300s
# while /bin/true; do
# ./artisan ninja:send-invoices
# ./artisan ninja:send-reminders
# sleep 1d
# done
# EOF'
# networks:
# - invoiceninja
#
networks:
invoiceninja:
Code language: YAML (yaml)
3. Thay thế nginx bằng Caddy
File docker-compose.yml
đã được tích hợp Nginx làm Reverse Proxy. Bạn có thể xóa phần khai báo nginx nếu trên hệ thống đã có sẵn Reverse Proxy.
MÌnh không thích dùng nginx
nên sẽ thay bằng caddy
để làm Reverse Proxy. Đổi lại nội dung file docker-compose.yml
như bên dưới
services:
server:
image: caddy:alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
- ./docker/app/public:/var/www/app/public:ro
networks:
- invoiceninja
app:
image: invoiceninja/invoiceninja:5
container_name: invoiceninja
env_file: env
restart: always
volumes:
- ./config/hosts:/etc/hosts:ro
- ./docker/app/public:/var/www/app/public:rw,delegated
- ./docker/app/storage:/var/www/app/storage:rw,delegated
- ./config/php/php.ini:/usr/local/etc/php/php.ini
- ./config/php/php-cli.ini:/usr/local/etc/php/php-cli.ini
depends_on:
- db
networks:
- invoiceninja
db:
image: mariadb:10.4
restart: always
env_file: env
volumes:
- ./docker/mysql/data:/var/lib/mysql:rw,delegated
networks:
- invoiceninja
extra_hosts:
- "in5.localhost:192.168.0.124 " #host and ip
networks:
invoiceninja:
Code language: YAML (yaml)
Tạo thêm file Caddyfile
với nội dung sau
invoice.thuanbui.me {
root * /var/www/app/public
php_fastcgi invoiceninja:9000
encode zstd gzip
file_server browse
}
Code language: PHP (php)
Bạn cần thay thế invoice.thuanbui.me
bằng tên miền bạn sử dụng để truy cập Invoice Ninja.
2. Tạo APP_KEY
Trước khi kích hoạt dịch vụ, cần phải tạo APP_KEY bằng lệnh sau
docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --show
Code language: Dockerfile (dockerfile)
Chờ vài phút để hệ thống xử lý, bạn sẽ nhận được kết quả trả về tương tự như bên dưới
base64:5fOFQtFaQcwFxQ2nAEwBdMUWzB5DcOGS7y+uvkL5W2c=
3. Cập nhật thông số env
Chỉnh sửa lại file env
bằng lệnh
nano env
Code language: Nginx (nginx)
APP_URL
: nhập vào tên miền bạn sử dụng để truy cập Invoice NinjaAPP_KEY
: nhập vào thông số đã APP_KEY vừa tạo ở trên
# IN application vars
APP_URL=https://invoice.thuanbui.me
APP_KEY=base64:5fOFQtFaQcwFxQ2nAEwBdMUWzB5DcOGS7y+uvkL5W2c=
APP_DEBUG=true
REQUIRE_HTTPS=false
PHANTOMJS_PDF_GENERATION=false
PDF_GENERATOR=snappdf
TRUSTED_PROXIES='*'
Code language: PHP (php)
Cập nhật thêm thông số tài khoản admin và mật khẩu
# Create initial user
# Default to these values if empty
# IN_USER_EMAIL=admin@example.com
# IN_PASSWORD=changeme!
IN_USER_EMAIL=thuan@thuanbui.me
IN_PASSWORD=123456
Code language: Bash (bash)
Ngoài ra, để Invoice Ninja có thể gửi email đến khách hàng, cần phải cấu hình thêm mục #Mail options
, cần khai báo các thông số cần thiết tương tự như sau
# Mail options
MAIL_MAILER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=SG.wPFD3423dffdsfdsfdsfdsfZxRjSi0T4T-Rn7UsSd2F_-5ySJUV_4
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@thuanbui.me
MAIL_FROM_NAME=ThuanBui
Code language: Bash (bash)
Sau khi hoàn thành, lưu lại (Ctrl + O) và thoát ra (Ctrl + X)
4. Chỉnh sửa permission
Để đảm bảo quyền thư mục được thiết lập chính xác khi container khởi động, cần sử dụng lệnh sau thiết lập đúng quyền truy cập cho thư mục Docker.
chmod 755 docker/app/public
sudo chown -R 1500:1500 docker/app
Code language: YAML (yaml)
3. Kích hoạt dịch vụ
Khởi động Invoice Ninja bằng lệnh
docker compose up -d
Code language: Nginx (nginx)
Truy cập vào Invoice Ninja thông qua tên miền bạn đã cấu hình. Chúng ta sẽ bắt đầu phần cấu hình thông số ban đầu cho Invoice Ninja
III. Cấu hình Invoice Ninja
Bạn cần đăng nhập vào invoice Ninja bằng thông tin email và mật khẩu đã thiết lập trong file env
1. Thông tin công ty
Ở lần đăng nhập đầu tiên, chúng ta cần phải thiết lập tên công ty (Company Name), ngôn ngữ (Language) và tiền tệ (Currency)
Giao diện trang Dashboard của Invoice Ninja sẽ hiện ra như bên dưới
Truy cập thêm vào phần Setting / Company Details để khai báo thêm các thông tin liên quan: Website, Email, Địa chỉ,… Các thông tin này sẽ hiển thị trên các hóa đơn gửi cho khách hàng.
2. Kết nối với Stripe & PayPal
Invoice Ninja hỗ trợ kết nối với cổng thanh toán như Stripe và PayPal giúp khách hàng có thẻ thanh toán trực tiếp từ các hóa đơn được tạo từ hệ thống.
Truy cập vào mục Settings > Payment Settings, chọn Add Gateway, chọn Stripe hoặc Paypal, sau đó nhập các thông tin cần thiết (API Keys) lấy từ tài khoản Stripe / Paypal của bạn
IV. Tạo hóa đơn và nhận thanh toán
1. Tạo hóa đơn mới
- Truy cập vào Invoices và chọn Create Invoice.
- Thêm thông tin khách hàng, dịch vụ/sản phẩm, thuế (nếu có).
- Tùy chỉnh hóa đơn theo ý muốn (logo, màu sắc, điều khoản).
Sau khi hoàn tất, nhấn nút Save để lưu lại invoice.
2. Gửi invoice cho khách hàng
Bạn có thể gửi invoice cho khách hàng bằng 2 cách:
- Bấm vào nút mũi tên bên cạch nút Save và chọn Email Invoice để gửi invoice qua email
- Right click vào dòng View in Portal, chọn Copy Link. Sau đó gửi link này cho khách hàng qua Zalo / Facebook / SMS/…
3. Nhận thanh toán
Khách hàng sau khi nhận invoice email / portal link có thể thanh toán bằng Stripe / Paypal (nếu bạn đã cấu hình). Sau khi thanh toán thành công, hóa đơn sẽ được tự động cập nhật trạng thái từ Sent thành Paid.
Invoice Ninja đã giúp mình tiết kiệm rất nhiều thời gian và công sức trong việc quản lý hóa đơn cho công ty. Nếu bạn đang tìm kiếm một công cụ quản lý hóa đơn và để nhận thanh toán từ khách hàng hãy thử cài đặt và sử dụng Invoice Ninja.
Chúc bạn thực hiện thành công!
Nếu bạn cần hỗ trợ thiết lập Invoice Ninja, tham khảo dịch vụ cài đặt Self-Hosting app của mình bên dưới nhé
Cài đặt Invoice Ninja
(~ 4.904 JPY)
Bài viết liên quan
Nếu bạn cần hỗ trợ kỹ thuật miễn phí, vui lòng gửi câu hỏi trực tiếp ở phần Thảo luận bên dưới, mình sẽ trả lời trong thời gian sớm nhất.
Bạn cần hỗ trợ kỹ thuật chuyên sâu?
Khám phá các gói dịch vụ giúp bạn tối ưu công việc và vận hành hệ thống hiệu quả hơn. Từ chăm sóc website đến hỗ trợ kỹ thuật, mọi thứ đều linh hoạt và phù hợp với nhu cầu của bạn.