Update Docs

This commit is contained in:
Hanzo Dev
2025-05-22 20:18:00 -05:00
parent 30e23a8c74
commit 71116d2876
6 changed files with 1069 additions and 128 deletions
+115 -128
View File
@@ -1,161 +1,148 @@
<div align="center">
<a href="https://frappe.io/erpnext">
<img src="./erpnext/public/images/v16/erpnext.svg" alt="ERPNext Logo" height="80px" width="80xp"/>
</a>
<h2>ERPNext</h2>
<p align="center">
<p>Powerful, Intuitive and Open-Source ERP</p>
</p>
# ERPNext Docker Deployment for Hanzo
[![Learn on Frappe School](https://img.shields.io/badge/Frappe%20School-Learn%20ERPNext-blue?style=flat-square)](https://frappe.school)<br><br>
[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml/badge.svg?event=schedule)](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
[![docker pulls](https://img.shields.io/docker/pulls/frappe/erpnext-worker.svg)](https://hub.docker.com/r/frappe/erpnext-worker)
Self-initializing Docker configurations for deploying ERPNext on Hanzo (Dokploy). No manual setup required - just deploy and go!
</div>
## 🌐 Environments
<div align="center">
<img src="./erpnext/public/images/v16/hero_image.png"/>
</div>
- **Production**: https://erp.hanzo.ai (single domain for all services)
- **Development**: https://erp-dev.hanzo.ai (single domain for all services)
<div align="center">
<a href="https://erpnext-demo.frappe.cloud/api/method/erpnext_demo.erpnext_demo.auth.login_demo">Live Demo</a>
-
<a href="https://frappe.io/erpnext">Website</a>
-
<a href="https://docs.frappe.io/erpnext/">Documentation</a>
</div>
## 📁 Files
## ERPNext
- **`compose.prod.yml`** - Production Docker Compose (self-initializing)
- **`compose.dev.yml`** - Development Docker Compose (self-initializing)
- **`ENVIRONMENT_VARIABLES.md`** - Environment variables reference
- **`ROUTING_ARCHITECTURE.md`** - How routing and services work
- **`HANZO_DEPLOYMENT.md`** - Detailed deployment guide
100% Open-Source ERP system to help you run your business.
## 🚀 Quick Start
### Motivation
### 1. Set Environment Variables in Hanzo
Running a business is a complex task - handling invoices, tracking stock, managing personnel and even more ad-hoc activities. In a market where software is sold separately to manage each of these tasks, ERPNext does all of the above and more, for free.
In your Hanzo/Dokploy UI, set these two variables:
### Key Features
- **Accounting**: All the tools you need to manage cash flow in one place, right from recording transactions to summarizing and analyzing financial reports.
- **Order Management**: Track inventory levels, replenish stock, and manage sales orders, customers, suppliers, shipments, deliverables, and order fulfillment.
- **Manufacturing**: Simplifies the production cycle, helps track material consumption, exhibits capacity planning, handles subcontracting, and more!
- **Asset Management**: From purchase to perishment, IT infrastructure to equipment. Cover every branch of your organization, all in one centralized system.
- **Projects**: Delivery both internal and external Projects on time, budget and Profitability. Track tasks, timesheets, and issues by project.
<details open>
<summary>More</summary>
<img src="https://erpnext.com/files/v16_bom.png"/>
<img src="https://erpnext.com/files/v16_stock_summary.png"/>
<img src="https://erpnext.com/files/v16_job_card.png"/>
<img src="https://erpnext.com/files/v16_tasks.png"/>
</details>
### Under the Hood
- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework written in Python and Javascript. The framework provides a robust foundation for building web applications, including a database abstraction layer, user authentication, and a REST API.
- [**Frappe UI**](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface. The Frappe UI library provides a variety of components that can be used to build single-page applications on top of the Frappe Framework.
## Production Setup
### Managed Hosting
You can try [Frappe Cloud](https://frappecloud.com), a simple, user-friendly and sophisticated [open-source](https://github.com/frappe/press) platform to host Frappe applications with peace of mind.
It takes care of installation, setup, upgrades, monitoring, maintenance and support of your Frappe deployments. It is a fully featured developer platform with an ability to manage and control multiple Frappe deployments.
<div>
<a href="https://erpnext-demo.frappe.cloud/app/home" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/try-on-fc-white.png">
<img src="https://frappe.io/files/try-on-fc-black.png" alt="Try on Frappe Cloud" height="28" />
</picture>
</a>
</div>
### Self-Hosted
#### Docker
Prerequisites: docker, docker-compose, git. Refer [Docker Documentation](https://docs.docker.com) for more details on Docker setup.
Run following commands:
```
git clone https://github.com/frappe/frappe_docker
cd frappe_docker
docker compose -f pwd.yml up -d
```bash
DB_PASSWORD=<generate_secure_password>
ADMIN_PASSWORD=<your_admin_password>
```
After a couple of minutes, site should be accessible on your localhost port: 8080. Use below default login credentials to access the site.
- Username: Administrator
- Password: admin
Generate a secure DB_PASSWORD:
```bash
openssl rand -base64 32
```
See [Frappe Docker](https://github.com/frappe/frappe_docker?tab=readme-ov-file#to-run-on-arm64-architecture-follow-this-instructions) for ARM based docker setup.
### 2. Deploy
1. Create new app in Hanzo
2. Choose "Docker Compose" deployment type
3. Upload the appropriate compose file:
- Production: `compose.prod.yml`
- Development: `compose.dev.yml`
4. Click Deploy
## Development Setup
### Manual Install
That's it! The system will automatically:
- Configure all services
- Create the database
- Initialize the ERPNext site
- Set up the scheduler
- Configure production/development settings
The Easy Way: our install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench for more details.
### 3. Access Your Instance
New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
Once deployment is complete (3-5 minutes):
- **Production**: https://erp.hanzo.ai
- **Development**: https://erp-dev.hanzo.ai
### Local
Login with:
- Username: `Administrator`
- Password: The `ADMIN_PASSWORD` you set in Hanzo
To setup the repository locally follow the steps mentioned below:
## 🔧 Architecture
1. Setup bench by following the [Installation Steps](https://frappeframework.com/docs/user/en/installation) and start the server
```
bench start
```
Each environment includes:
2. In a separate terminal window, run the following commands:
```
# Create a new site
bench new-site erpnext.localhost
```
- **MariaDB** - Database server
- **Redis** (2 instances) - Cache and queue management
- **Backend** - Frappe/ERPNext application server
- **Frontend** - Nginx web server (only service exposed via Traefik)
- **WebSocket** - Real-time communication
- **Workers** - Background job processors (short & long queues)
- **Scheduler** - Scheduled task runner
- **Configurator** - One-time setup service (auto-creates site)
3. Get the ERPNext app and install it
```
# Get the ERPNext app
bench get-app https://github.com/frappe/erpnext
**Note**: All traffic routes through the Frontend service. No additional domains or ports needed!
# Install the app
bench --site erpnext.localhost install-app erpnext
```
## 🔐 Security Features
4. Open the URL `http://erpnext.localhost:8000/app` in your browser, you should see the app running
- External `hanzo-network` for isolation
- Traefik SSL/TLS termination
- Content Security Policy headers
- HTTPS redirect middleware
- tmpfs for temporary files
## Learning and community
## 📊 Resource Allocation
1. [Frappe School](https://school.frappe.io) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
2. [Official documentation](https://docs.erpnext.com/) - Extensive documentation for ERPNext.
3. [Discussion Forum](https://discuss.erpnext.com/) - Engage with community of ERPNext users and service providers.
4. [Telegram Group](https://erpnext_public.t.me) - Get instant help from huge community of users.
### Production
- MariaDB: 1GB buffer pool, 200 max connections
- Redis Cache: 512MB max memory
- Production mode enabled
### Development
- MariaDB: 512MB buffer pool, 100 max connections
- Redis Cache: 256MB max memory
- Developer mode enabled
## Contributing
## 🛠️ Maintenance
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
1. [Report Security Vulnerabilities](https://erpnext.com/security)
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
2. [Translations](https://crowdin.com/project/frappe)
### Backup
```bash
# Find your backend container
docker ps | grep backend
# Run backup
docker exec <backend-container> bench --site <domain> backup --with-files
```
## Logo and Trademark Policy
### Clear Cache
```bash
docker exec <backend-container> bench --site <domain> clear-cache
```
Please read our [Logo and Trademark Policy](TRADEMARK_POLICY.md).
### View Logs
```bash
# All services
docker-compose -f compose.prod.yml logs
<br />
<br />
<div align="center" style="padding-top: 0.75rem;">
<a href="https://frappe.io" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/Frappe-white.png">
<img src="https://frappe.io/files/Frappe-black.png" alt="Frappe Technologies" height="28"/>
</picture>
</a>
</div>
# Specific service
docker logs <container-name> -f
```
### Update ERPNext Version
1. Update the image tag in compose file (all services use same version)
2. Redeploy in Hanzo
3. System will automatically run migrations
## 🐛 Troubleshooting
### Check Service Health
```bash
docker ps
```
### Database Issues
Check the configurator logs - it handles all initialization:
```bash
docker logs <configurator-container>
```
### Frontend Not Accessible
- Verify Traefik labels in compose file
- Check domain configuration in Hanzo
- Ensure `hanzo-network` exists
## 📚 Resources
- [ERPNext Documentation](https://docs.erpnext.com)
- [Frappe Framework](https://frappeframework.com)
- [Hanzo Platform](https://hanzo.ai)
+310
View File
@@ -0,0 +1,310 @@
# Development Docker Compose for ERPNext on Hanzo
# Domain: erp-dev.hanzo.ai
# Self-initializing - no manual setup required
services:
# Database Service
db:
restart: always
image: mariadb:10.6
platform: linux/amd64
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed
- --max_connections=100
- --innodb_buffer_pool_size=512M
- --innodb_log_file_size=128M
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: erpnext_dev
volumes:
- erp-mariadb-dev:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "--password=${DB_PASSWORD}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- hanzo-network
# Redis Services
redis-cache:
restart: always
image: redis:7-alpine
platform: linux/amd64
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- erp-redis-cache-dev:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
networks:
- hanzo-network
redis-queue:
restart: always
image: redis:7-alpine
platform: linux/amd64
command: redis-server --appendonly yes
volumes:
- erp-redis-queue-dev:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
networks:
- hanzo-network
# Configurator - sets up config AND creates site if needed
configurator:
image: frappe/erpnext:v15.62.0
platform: linux/amd64
restart: "no"
entrypoint:
- bash
- -c
command:
- |
# Configure bench
ls -1 apps > sites/apps.txt
bench set-config -g db_host db
bench set-config -gp db_port 3306
bench set-config -g redis_cache "redis://redis-cache:6379"
bench set-config -g redis_queue "redis://redis-queue:6379"
bench set-config -g redis_socketio "redis://redis-queue:6379"
bench set-config -gp socketio_port 9000
# Wait for DB to be fully ready
echo "Waiting for database..."
until mysql -h db -u root -p${DB_PASSWORD} -e "SELECT 1" > /dev/null 2>&1; do
sleep 2
done
# Check if site exists
if bench --site erp-dev.hanzo.ai list 2>/dev/null | grep -q "erp-dev.hanzo.ai"; then
echo "Site erp-dev.hanzo.ai already exists"
else
echo "Creating new site erp-dev.hanzo.ai"
bench new-site erp-dev.hanzo.ai \
--mariadb-root-password ${DB_PASSWORD} \
--admin-password ${ADMIN_PASSWORD} \
--install-app erpnext \
--set-default
fi
# Set as default site
bench use erp-dev.hanzo.ai
# Enable scheduler
bench --site erp-dev.hanzo.ai enable-scheduler
# Set development settings
bench --site erp-dev.hanzo.ai set-config developer_mode 1
bench --site erp-dev.hanzo.ai set-config host_name "https://erp-dev.hanzo.ai"
# Clear cache
bench --site erp-dev.hanzo.ai clear-cache
echo "Development site configuration completed"
environment:
DB_PASSWORD: ${DB_PASSWORD}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
depends_on:
db:
condition: service_healthy
redis-cache:
condition: service_healthy
redis-queue:
condition: service_healthy
networks:
- hanzo-network
# Backend Service
backend:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
extra_hosts:
- "erp-dev.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
DEVELOPER_MODE: "1"
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
db:
condition: service_healthy
redis-cache:
condition: service_healthy
redis-queue:
condition: service_healthy
networks:
- hanzo-network
# Frontend Service (Nginx)
frontend:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command:
- nginx-entrypoint.sh
extra_hosts:
- "erp-dev.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
BACKEND: backend:8000
SOCKETIO: websocket:9000
FRAPPE_SITE_NAME_HEADER: erp-dev.hanzo.ai
UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE: off
PROXY_READ_TIMEOUT: 120
CLIENT_MAX_BODY_SIZE: 50m
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
- backend
- websocket
labels:
- "traefik.enable=true"
# Headers middleware
- "traefik.http.middlewares.well-known.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.erp-dev-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.erp-dev-headers.headers.customRequestHeaders.X-Forwarded-Host=erp-dev.hanzo.ai"
# Redirect middleware
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true"
# CSP middleware
- "traefik.http.middlewares.erp-dev-csp.headers.customResponseHeaders.Content-Security-Policy=default-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https://erp-dev.hanzo.ai http://erp-dev.hanzo.ai wss://erp-dev.hanzo.ai ws://erp-dev.hanzo.ai; img-src 'self' data: blob: https:; font-src 'self' data:; frame-ancestors 'self';"
# HTTP router
- "traefik.http.routers.erp-dev-http.rule=Host(`erp-dev.hanzo.ai`)"
- "traefik.http.routers.erp-dev-http.entrypoints=web"
- "traefik.http.routers.erp-dev-http.middlewares=well-known,erp-dev-headers,erp-dev-csp,redirect-to-https"
# HTTPS router
- "traefik.http.routers.erp-dev-https.rule=Host(`erp-dev.hanzo.ai`)"
- "traefik.http.routers.erp-dev-https.entrypoints=websecure"
- "traefik.http.routers.erp-dev-https.middlewares=well-known,erp-dev-headers,erp-dev-csp"
- "traefik.http.routers.erp-dev-https.tls.certresolver=letsencrypt"
# Service configuration
- "traefik.http.services.erp-dev.loadbalancer.server.port=8080"
# WebSocket support
- "traefik.http.services.erp-dev.loadbalancer.passhostheader=true"
networks:
- hanzo-network
# WebSocket Service
websocket:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command:
- node
- /home/frappe/frappe-bench/apps/frappe/socketio.js
extra_hosts:
- "erp-dev.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
# Worker Queues
queue-short:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command: bench worker --queue short,default
extra_hosts:
- "erp-dev.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
queue-long:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command: bench worker --queue long,default,short
extra_hosts:
- "erp-dev.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
# Scheduler Service
scheduler:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command: bench schedule
extra_hosts:
- "erp-dev.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites-dev:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
# Volumes
volumes:
erp-mariadb-dev:
name: erp-mariadb-dev
erp-redis-cache-dev:
driver: local
erp-redis-queue-dev:
driver: local
erp-sites-dev:
name: erp-sites-dev
# Networks
networks:
hanzo-network:
external: true
+309
View File
@@ -0,0 +1,309 @@
# Production Docker Compose for ERPNext on Hanzo
# Domain: erp.hanzo.ai
# Self-initializing - no manual setup required
services:
# Database Service
db:
restart: always
image: mariadb:10.6
platform: linux/amd64
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed
- --max_connections=200
- --innodb_buffer_pool_size=1G
- --innodb_log_file_size=256M
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: erpnext_prod
volumes:
- erp-mariadb:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "--password=${DB_PASSWORD}"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
networks:
- hanzo-network
# Redis Services
redis-cache:
restart: always
image: redis:7-alpine
platform: linux/amd64
command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru
volumes:
- erp-redis-cache:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
networks:
- hanzo-network
redis-queue:
restart: always
image: redis:7-alpine
platform: linux/amd64
command: redis-server --appendonly yes
volumes:
- erp-redis-queue:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
networks:
- hanzo-network
# Configurator - sets up config AND creates site if needed
configurator:
image: frappe/erpnext:v15.62.0
platform: linux/amd64
restart: "no"
entrypoint:
- bash
- -c
command:
- |
# Configure bench
ls -1 apps > sites/apps.txt
bench set-config -g db_host db
bench set-config -gp db_port 3306
bench set-config -g redis_cache "redis://redis-cache:6379"
bench set-config -g redis_queue "redis://redis-queue:6379"
bench set-config -g redis_socketio "redis://redis-queue:6379"
bench set-config -gp socketio_port 9000
# Wait for DB to be fully ready
echo "Waiting for database..."
until mysql -h db -u root -p${DB_PASSWORD} -e "SELECT 1" > /dev/null 2>&1; do
sleep 2
done
# Check if site exists
if bench --site erp.hanzo.ai list 2>/dev/null | grep -q "erp.hanzo.ai"; then
echo "Site erp.hanzo.ai already exists"
else
echo "Creating new site erp.hanzo.ai"
bench new-site erp.hanzo.ai \
--mariadb-root-password ${DB_PASSWORD} \
--admin-password ${ADMIN_PASSWORD} \
--install-app erpnext \
--set-default
fi
# Set as default site
bench use erp.hanzo.ai
# Enable scheduler
bench --site erp.hanzo.ai enable-scheduler
# Set production settings
bench --site erp.hanzo.ai set-config developer_mode 0
bench --site erp.hanzo.ai set-config host_name "https://erp.hanzo.ai"
# Clear cache
bench --site erp.hanzo.ai clear-cache
echo "Site configuration completed"
environment:
DB_PASSWORD: ${DB_PASSWORD}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
depends_on:
db:
condition: service_healthy
redis-cache:
condition: service_healthy
redis-queue:
condition: service_healthy
networks:
- hanzo-network
# Backend Service
backend:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
extra_hosts:
- "erp.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
db:
condition: service_healthy
redis-cache:
condition: service_healthy
redis-queue:
condition: service_healthy
networks:
- hanzo-network
# Frontend Service (Nginx)
frontend:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command:
- nginx-entrypoint.sh
extra_hosts:
- "erp.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
BACKEND: backend:8000
SOCKETIO: websocket:9000
FRAPPE_SITE_NAME_HEADER: erp.hanzo.ai
UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE: off
PROXY_READ_TIMEOUT: 120
CLIENT_MAX_BODY_SIZE: 50m
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
- backend
- websocket
labels:
- "traefik.enable=true"
# Headers middleware
- "traefik.http.middlewares.well-known.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.erp-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.erp-headers.headers.customRequestHeaders.X-Forwarded-Host=erp.hanzo.ai"
# Redirect middleware
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true"
# CSP middleware
- "traefik.http.middlewares.erp-csp.headers.customResponseHeaders.Content-Security-Policy=default-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https://erp.hanzo.ai http://erp.hanzo.ai wss://erp.hanzo.ai ws://erp.hanzo.ai; img-src 'self' data: blob: https:; font-src 'self' data:; frame-ancestors 'self';"
# HTTP router
- "traefik.http.routers.erp-http.rule=Host(`erp.hanzo.ai`)"
- "traefik.http.routers.erp-http.entrypoints=web"
- "traefik.http.routers.erp-http.middlewares=well-known,erp-headers,erp-csp,redirect-to-https"
# HTTPS router
- "traefik.http.routers.erp-https.rule=Host(`erp.hanzo.ai`)"
- "traefik.http.routers.erp-https.entrypoints=websecure"
- "traefik.http.routers.erp-https.middlewares=well-known,erp-headers,erp-csp"
- "traefik.http.routers.erp-https.tls.certresolver=letsencrypt"
# Service configuration
- "traefik.http.services.erp.loadbalancer.server.port=8080"
# WebSocket support
- "traefik.http.services.erp.loadbalancer.passhostheader=true"
networks:
- hanzo-network
# WebSocket Service
websocket:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command:
- node
- /home/frappe/frappe-bench/apps/frappe/socketio.js
extra_hosts:
- "erp.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
# Worker Queues
queue-short:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command: bench worker --queue short,default
extra_hosts:
- "erp.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
queue-long:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command: bench worker --queue long,default,short
extra_hosts:
- "erp.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
# Scheduler Service
scheduler:
restart: always
image: frappe/erpnext:v15.62.0
platform: linux/amd64
command: bench schedule
extra_hosts:
- "erp.hanzo.ai:host-gateway"
- "172.17.0.1:host-gateway"
environment:
RUNNING_IN_DOCKER: "true"
volumes:
- erp-sites:/home/frappe/frappe-bench/sites
tmpfs:
- /tmp:exec,mode=1777
depends_on:
configurator:
condition: service_completed_successfully
networks:
- hanzo-network
# Volumes
volumes:
erp-mariadb:
name: erp-mariadb-prod
erp-redis-cache:
driver: local
erp-redis-queue:
driver: local
erp-sites:
name: erp-sites-prod
# Networks
networks:
hanzo-network:
external: true
+47
View File
@@ -0,0 +1,47 @@
# Environment Variables for Hanzo ERPNext
Only **TWO** environment variables are required. Set these in the Hanzo/Dokploy UI when creating your application.
## Required Variables
```bash
DB_PASSWORD=<secure_database_password>
ADMIN_PASSWORD=<administrator_password>
```
## How to Generate
### DB_PASSWORD
Generate a secure random password:
```bash
openssl rand -base64 32
```
### ADMIN_PASSWORD
Choose a strong password that you'll remember. This is used to login to ERPNext as Administrator.
## That's It!
No other configuration needed. The Docker Compose file handles everything else:
- ✅ Database name (erpnext_prod or erpnext_dev)
- ✅ Redis configuration
- ✅ Site domain (erp.hanzo.ai or erp-dev.hanzo.ai)
- ✅ All service connections
- ✅ Site creation and initialization
- ✅ Scheduler setup
- ✅ Production/development mode
## After Deployment
Login at your domain with:
- **Username**: Administrator
- **Password**: The ADMIN_PASSWORD you set
## Notes
- Both passwords should be strong and unique
- DB_PASSWORD is used internally by services
- ADMIN_PASSWORD is your login to ERPNext
- These are the ONLY variables you need to set
- Everything else is automated in the compose file
+215
View File
@@ -0,0 +1,215 @@
# Hanzo ERPNext Deployment Guide
Complete guide for deploying self-initializing ERPNext on Hanzo platform.
## Overview
This deployment is completely self-contained. Once you deploy the Docker Compose file with the required environment variables, ERPNext will:
1. Start all services
2. Wait for dependencies
3. Create the database
4. Initialize the ERPNext site
5. Configure all settings
6. Be ready to use
No manual intervention required!
## Environment Variables
Only two variables needed in Hanzo UI:
| Variable | Description | How to Generate |
|----------|-------------|-----------------|
| `DB_PASSWORD` | MariaDB root password | `openssl rand -base64 32` |
| `ADMIN_PASSWORD` | ERPNext Administrator password | Choose a strong password |
## Deployment Steps
### 1. Create Application in Hanzo
1. Log into Hanzo
2. Click "Create New Application"
3. Choose "Docker Compose"
4. Name your application:
- Production: `erp-prod`
- Development: `erp-dev`
### 2. Configure Application
1. Upload the appropriate compose file:
- Production: `compose.prod.yml`
- Development: `compose.dev.yml`
2. Set environment variables in Hanzo UI
3. Ensure domain matches:
- Production: `erp.hanzo.ai`
- Development: `erp-dev.hanzo.ai`
### 3. Deploy
Click "Deploy" and wait. The system will:
- Pull all Docker images
- Start database and Redis
- Run the configurator to:
- Set up bench configuration
- Create the ERPNext site
- Install ERPNext app
- Enable scheduler
- Configure production/dev settings
- Start all application services
### 4. Verify Deployment
After 3-5 minutes, visit your domain:
- https://erp.hanzo.ai (production)
- https://erp-dev.hanzo.ai (development)
## How It Works
### Configurator Service
The key to self-initialization is the `configurator` service that:
```yaml
configurator:
restart: "no" # Runs once and exits
command:
- |
# Configure bench settings
bench set-config -g db_host db
# Wait for database
until mysql -h db -u root -p${DB_PASSWORD} -e "SELECT 1"; do
sleep 2
done
# Create site if it doesn't exist
if ! bench --site $DOMAIN list | grep -q "$DOMAIN"; then
bench new-site $DOMAIN \
--mariadb-root-password ${DB_PASSWORD} \
--admin-password ${ADMIN_PASSWORD} \
--install-app erpnext
fi
# Configure site
bench --site $DOMAIN enable-scheduler
bench --site $DOMAIN set-config developer_mode 0
```
### Service Dependencies
All services depend on the configurator completing successfully:
```yaml
backend:
depends_on:
configurator:
condition: service_completed_successfully
```
This ensures the site is created before any service tries to use it.
## Monitoring Deployment
### Check Configurator Logs
The configurator handles all initialization. Check its logs:
```bash
docker logs $(docker ps -a | grep configurator | awk '{print $1}')
```
### Check Service Status
```bash
# See all running services
docker ps
# Check specific service logs
docker logs <container-name> -f
```
## Post-Deployment
### First Login
- URL: https://[your-domain]
- Username: `Administrator`
- Password: The `ADMIN_PASSWORD` you set
### Initial Configuration
1. **Company Setup**
- Settings > Company
- Add your company details
2. **Email Configuration**
- Settings > Email Domain
- Configure SMTP
3. **Users**
- Settings > User
- Create additional users
## Maintenance
### Backups
Automated backups can be set up in Hanzo:
```bash
# Cron job example
0 2 * * * docker exec $(docker ps -q -f name=backend) bench --site erp.hanzo.ai backup --with-files
```
### Updates
To update ERPNext:
1. Change the image version in compose file
2. Redeploy in Hanzo
3. The system automatically handles migrations
### Troubleshooting
If deployment fails:
1. Check configurator logs first - it handles all setup
2. Verify environment variables are set
3. Ensure `hanzo-network` exists
4. Check database connectivity
Common issues:
- **Configurator fails**: Usually wrong DB_PASSWORD
- **Site not accessible**: Check Traefik labels and domain
- **Services not starting**: Check depends_on conditions
## Advanced Configuration
### Custom Apps
To add custom Frappe apps:
1. Build custom image with your apps
2. Update image in compose file
3. Redeploy
### Performance Tuning
Adjust in compose file:
- Database: `innodb_buffer_pool_size`
- Redis: `maxmemory` settings
- Worker counts and queues
### SSL Certificates
Handled automatically by Hanzo's Traefik setup using Let's Encrypt.
## Support
- ERPNext Forum: https://discuss.erpnext.com
- Frappe GitHub: https://github.com/frappe/erpnext
- Hanzo Support: Contact your Hanzo administrator
+73
View File
@@ -0,0 +1,73 @@
# ERPNext Routing Architecture
## Overview
All traffic routes through a **single domain** (e.g., `erp.hanzo.ai`). No additional hostnames or subdomains are required.
## Traffic Flow
```
Internet
Traefik (SSL termination)
Frontend Service (nginx on port 8080)
├── /socket.io/* → WebSocket Service (port 9000)
├── /assets/* → Static Files (served directly)
└── /* → Backend Service (port 8000)
```
## Service Communication
All services communicate internally via the `hanzo-network`:
- **Frontend** → **Backend**: `backend:8000`
- **Frontend** → **WebSocket**: `websocket:9000`
- **Backend** → **Database**: `db:3306`
- **Backend** → **Redis Cache**: `redis-cache:6379`
- **Backend** → **Redis Queue**: `redis-queue:6379`
- **Workers** → **Redis Queue**: `redis-queue:6379`
## Exposed Services
Only the **Frontend** service is exposed to the internet via Traefik. All other services are internal only.
## Key Features
### WebSocket Support
- Proper upgrade headers configured
- CSP allows `wss://` connections
- nginx handles WebSocket proxy
### Security
- All internal services isolated
- CSP headers prevent XSS
- HTTPS enforced via redirect
- X-Frame-Options prevents clickjacking
### Headers
- `X-Forwarded-Proto`: Ensures backend knows it's HTTPS
- `X-Forwarded-Host`: Preserves original host
- `X-Frappe-Site-Name`: Routes to correct ERPNext site
## No Additional Configuration Needed
- ✅ Single domain handles everything
- ✅ WebSocket support built-in
- ✅ All routing handled by nginx
- ✅ Traefik labels properly configured
- ✅ CSP allows all necessary connections
## Troubleshooting
If WebSocket connections fail:
1. Check browser console for CSP violations
2. Ensure `wss://your-domain` is in CSP connect-src
3. Verify nginx socket.io location block
4. Check that websocket service is running
If backend connections fail:
1. Verify all services are on same network
2. Check service names match in environment variables
3. Ensure configurator completed successfully
4. Review nginx proxy_pass configuration