Update Docs
This commit is contained in:
@@ -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
|
||||
|
||||
[](https://frappe.school)<br><br>
|
||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
|
||||
[](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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user