Docker Deployment Recommended
Works on any host OS and is the simplest option. It ships with MySQL / Redis / app container orchestration and persistent volumes — ready to run out of the box.
⬇ Download Docker package (compose / scripts)
1. Requirements
| Component | Version | Notes |
| Docker | 20.10+ | Docker Compose v2 plugin required |
| Memory | 2 GB+ | Three containers (MySQL / Redis / app) |
ⓘ
The front-end pages and Tomcat are embedded in the JAR; only port 8080 needs to be exposed.
2. Package layout
crm-system-<version>-docker/
├── crm-system.jar # Executable backend jar (embedded front-end, default config and DDL SQL)
├── application.yml # Editable config (mounted into the container; restart app after changes)
├── init.sql # DDL SQL (schema is created automatically; kept for manual init / audit)
├── demo-data.sql # Optional demo business data (import after tables are created)
├── Dockerfile # Application image
├── docker-compose.yml # One-click orchestration (MySQL + Redis + app)
├── .env.example # Template of license master key and other variables
└── VERSION
3. Steps
3.1 Unzip and run
A demo master key is bundled (Crm2026@MasterKey!X8zQwL9p, matching the ciphertext inside the code). Database / Redis connections and the license key are pre-configured, so no .env file is needed — just unzip and start.
3.2 One command startup
docker compose up -d --build
On first start it pulls the MySQL / Redis images, builds the application image, and creates the database and tables automatically (no manual SQL import). After about 1–2 minutes, visit:
http://<server-ip>:8080
3.3 Common commands
docker compose ps # Show status
docker compose logs -f app # Follow application logs
docker compose restart app # Restart app (after config changes)
docker compose down # Stop and remove containers (volumes kept)
docker compose down -v # Stop and remove containers and volumes (destroys data)
4. Changing configuration
Built-in defaults: MySQL user root / password rootroot, Redis without password.
Host port mapping (high ports are used so they never clash with a MySQL / Redis already listening on 3306 / 6379; inside the containers the default ports are still used):
| Service | Host port | Container port |
| Web | 8080 | 8080 |
| MySQL | 13306 | 3306 |
| Redis | 16379 | 6379 |
If host port 8080 is taken too, change the app service mapping from - "8080:8080" to - "8081:8080".
There are two ways to configure the app (priority: environment variables > application.yml):
Option A: edit application.yml in the package root (mounted into the container as /app/application.yml)
Apply the change with:
docker compose restart app
Option B: change the environment variables in docker-compose.yml
For example to change the MySQL password: update MYSQL_ROOT_PASSWORD on the mysql service and DB_PASSWORD on the app service, then rebuild:
docker compose up -d --build
ⓘ
init.sql is the full DDL script. The application creates the schema automatically on first start — no manual import is required; the file is kept for manual initialization or structure auditing.
ⓘ
Optional demo data: a fresh deployment contains no business data. To preload demo customers / leads / contracts, run this after tables are created (empty database or demo environments only):
docker compose exec -T mysql mysql -uroot -prootroot crm_db --default-character-set=utf8mb4 < demo-data.sql
The script is idempotent, so repeated runs never duplicate rows; if legacy demo data has grown, clean it up with fix-dup-data.sql.
⚠
About the license master key: this Docker package is encrypted with the demo master key so it works out of the box. Do not change CRM_LICENSE_MASTER_KEY casually — for a custom key, use ./start.sh configure from the Linux/Windows native package to regenerate the matching ciphertext from your new master key and fill in both values together; otherwise the app fails to start (error: license master key does not match the ciphertext / Tag mismatch).
5. License activation
- After the first login, follow the dialog to start a “free trial” (14 days) or upload a formal License Key
- Manage licenses: log in as
admin → System → License Management (view / issue licenses)
- The machine fingerprint is derived from the host hardware serial + MAC address, so keep the hardware stable; replacing the machine requires a new license
6. Demo accounts
| Account | Password | Role |
admin | 123456 | Super Administrator |
sales01 | 123456 | Sales Manager |
sales02 | 123456 | Sales Rep |
market01 | 123456 | Marketing Administrator |
⚠
Change these default passwords immediately after the first login in production.
YunFan Intelligence CRM - Windows Deployment
For Windows Server or desktop editions: unzip the package and double-click the script.
⬇ Download package (Windows)
1. Requirements
| Component | Version | Notes |
| JDK | 17+ | Must be on PATH (java -version has to work) |
| MySQL | 8.0+ | Local install, root/rootroot suggested (schema is created automatically, no manual SQL import) |
| Redis | 6.0+ | Local install (Windows build) |
ⓘ
The front-end pages and Tomcat are embedded in the JAR; only port 8080 needs to be exposed.
2. Package layout
crm-system-<version>-windows/
├── crm-system.jar # Executable backend jar (embedded front-end, default config and DDL SQL)
├── application.yml # Deployment config (database connection; takes effect after restart)
├── init.sql # DDL SQL (schema is created automatically; kept for manual init / audit)
├── demo-data.sql # Optional demo business data (import after tables are created)
├── start.bat # Start (generates config on first run)
├── stop.bat # Stop
├── restart.bat # Restart
├── configure.ps1 # Generate .env (random license master key)
├── .env.example # Environment template (license key / JWT / Redis; DB settings live in application.yml)
└── VERSION
3. Steps
3.1 Unzip and start
Unzip anywhere (for example D:\crm), then double-click start.bat or run:
cd D:\crm
start.bat
The first run generates .env (random license master key plus matching ciphertext), then creates the database and tables and starts the app in the background. When ready, visit:
http://127.0.0.1:8080
ⓘ
Configuration priority (high → low):
1. application.yml in the package root (loaded by Spring Boot; restart to apply — recommended for regular settings)
2. Default values bundled in the jar
Anything unset falls back to built-in defaults (database localhost:3306/crm_db root/rootroot, Redis localhost:6379 without password).
To change the database connection: edit the spring.datasource section of application.yml in the package root — password is the DB password, url holds host / port / database name, username is the account; then run restart.bat. Keep these consistent with the real MySQL credentials.
Database initialization: the schema is created automatically on first start — nothing to import manually. init.sql in the package root is the full DDL script for manual initialization or auditing: mysql -uroot -prootroot < init.sql
Optional demo data: a fresh deployment contains no business data. To preload demo customers / leads / contracts, run this after tables are created (empty database or demo environments only):
mysql -uroot -prootroot crm_db --default-character-set=utf8mb4 < demo-data.sql
The script is idempotent; if legacy demo data has grown, clean it up with fix-dup-data.sql.
3.2 Stop / restart
stop.bat
restart.bat
3.3 Fix a master key mismatch (upgrade scenario)
If .env already exists from an older release and its master key does not match the ciphertext bundled in the code, the app fails to start. Run:
start.bat configure
This regenerates the matching ciphertext for the master key currently in .env, so no master key replacement is needed.
3.4 Register as a Windows service (optional)
Use NSSM to register java -jar D:\crm\crm-system.jar as an auto-start service.
4. Changing database / Redis credentials
Database (MySQL): edit the spring.datasource section of application.yml:
password — MySQL password (default rootroot)
url — MySQL host / port / database (default jdbc:mysql://localhost:3306/crm_db?...)
username — MySQL account (default root)
Save and run restart.bat to apply.
Redis: if Redis is password-protected, edit REDIS_PASSWORD in .env and run restart.bat.
5. License activation
- After the first login, follow the dialog to start a “free trial” (14 days) or upload a formal License Key
- Manage licenses: log in as
admin → System → License Management (view / issue licenses)
- The machine fingerprint is derived from the host hardware serial + MAC address, so keep the hardware stable; replacing the machine requires a new license
6. Demo accounts
| Account | Password | Role |
admin | 123456 | Super Administrator |
sales01 | 123456 | Sales Manager |
sales02 | 123456 | Sales Rep |
market01 | 123456 | Marketing Administrator |
⚠
Change these default passwords immediately after the first login in production.
7. Troubleshooting
7.1 Exits right after start with Unable to connect to Redis (Connection refused localhost:6379)
⚠
Symptom: the app stops soon after start.bat, and the log ends with Caused by: java.net.ConnectException: Connection refused: localhost/127.0.0.1:6379 (or io.lettuce.core.RedisConnectionException: Unable to connect to localhost/<unresolved>:6379).
Cause: Redis is not installed or not running. Redis is a hard dependency (login state, sessions and caching all rely on it). During startup WebMvcConfig reads the system config, and an unreachable Redis aborts Spring context initialization.
Fix: install and start Redis:
- Recommended (native Windows service): install Memurai (Redis 6 compatible Windows build, free developer license). It runs as a Windows service with auto-start; verify with
redis-cli ping → PONG.
- Using WSL:
wsl -e sudo apt install redis-server -y && wsl -e sudo service redis-server start (Windows 10 2004+ / Windows 11 forwards localhost:6379 to the jar on Windows by default).
- Redis elsewhere, or custom port / password: edit
REDIS_HOST / REDIS_PORT / REDIS_PASSWORD in .env and run restart.bat.
7.2 Double-clicking start.bat prints “not recognized as an internal or external command” / mojibake such as 鋸扔敘…
⚠
Symptom: the console window flashes and closes with errors like 'M' is not recognized..., 'ver' is not..., '""', '{', PIDOLDlPID" >nul && (, or lots of GBK mojibake.
Cause: the .bat / .ps1 scripts were saved as UTF-8 without BOM with LF line endings, which cmd.exe mis-parses — it reads the whole file as one line, CJK text becomes garbage, and the ^ continuation plus bracket pairing break, so fragments are executed as separate commands.
Fix: use the scripts shipped in the release package, which are already fixed (UTF-8 BOM + CRLF). If you edited them yourself, save them as UTF-8 with BOM and CRLF (Windows) line endings; in VS Code you can switch from the bottom-right corner.
YunFan Intelligence CRM - Linux Deployment
Works on CentOS, Ubuntu, Debian and other mainstream distributions.
⬇ Download package (Linux / macOS)
1. Requirements
| Component | Version | Notes |
| JDK | 17+ | Runs the backend jar (embedded static assets and Tomcat) |
| MySQL | 8.0+ | Business database crm_db (schema created automatically, no manual SQL import) |
| Redis | 6.0+ | Verification codes / session cache |
| Nginx | Optional | Port 80 reverse proxy / HTTPS (port 8080 works fine without it) |
2. Package layout
crm-system-<version>/
├── crm-system.jar # Executable backend jar (embedded front-end, default config and DDL SQL)
├── application.yml # Deployment config (database connection; takes effect after restart)
├── init.sql # DDL SQL (schema is created automatically; kept for manual init / audit)
├── demo-data.sql # Optional demo business data (import after tables are created)
├── VERSION
├── start.sh # Start / stop / restart / status / configure
├── stop.sh
├── restart.sh
├── crm.service # systemd unit (recommended for production)
├── .env.example # Environment template (license key / JWT / Redis; DB settings live in application.yml)
├── nginx/crm-nginx.conf # Nginx reverse proxy sample
└── README.md # This document
3. Steps
3.1 Place the package
mkdir -p /opt/crm && cp -r crm-system-<version>/* /opt/crm/
ⓘ
start.sh generates .env automatically on the first run (random license master key plus matching ciphertext) — no manual editing needed.
3.2 Start
cd /opt/crm
bash start.sh start # First run creates the schema, generates config and starts (log: logs/app.log, PID: crm.pid)
bash start.sh status # Show status
bash start.sh restart # Restart
bash start.sh configure # Generate / show .env only, do not start
Once started, visit: http://<server-ip>:8080
ⓘ
Configuration priority (high → low):
1. application.yml in the package root (loaded by Spring Boot; restart to apply — recommended for regular settings)
2. Default values bundled in the jar
Anything unset falls back to built-in defaults (Redis localhost:6379 without password).
To change the database connection: edit the spring.datasource section of application.yml in the package root — password is the DB password, url holds host / port / database name, username is the account (defaults localhost:3306/crm_db, root/rootroot); then apply with bash start.sh restart. Keep these consistent with the real MySQL credentials.
Database initialization: the schema is created automatically on first start — nothing to import manually. init.sql in the package root is the full DDL script for manual initialization or auditing: mysql -uroot -p < init.sql
Optional demo data: a fresh deployment contains no business data. To preload demo customers / leads / contracts, run this once tables exist (empty database or demo environments only):
mysql -uroot -p crm_db --default-character-set=utf8mb4 < demo-data.sql
The script is idempotent, so repeated runs never duplicate rows; if legacy demo data has grown, clean it up with fix-dup-data.sql.
3.3 Run under systemd (recommended for production)
# Run once first so /opt/crm/.env is generated (random license master key)
bash /opt/crm/start.sh start
useradd -r -s /sbin/nologin crm
mkdir -p /var/log/crm && chown -R crm:crm /opt/crm /var/log/crm
cp /opt/crm/crm.service /etc/systemd/system/crm.service
systemctl daemon-reload
systemctl enable --now crm
systemctl status crm
ⓘ
If you place the jar elsewhere, update the WorkingDirectory, ExecStart and EnvironmentFile paths in crm.service accordingly.
4. Nginx reverse proxy (optional, for port 80 / HTTPS)
cp /opt/crm/nginx/crm-nginx.conf /etc/nginx/conf.d/crm.conf
# Adjust server_name and the /uploads directory as needed
nginx -t && nginx -s reload
5. Demo accounts
| Account | Password | Role |
admin | 123456 | Super Administrator |
sales01 | 123456 | Sales Manager |
sales02 | 123456 | Sales Rep |
market01 | 123456 | Marketing Administrator |
⚠
Change these default passwords immediately after the first login in production.
6. License activation
The system is license-based:
- After the first login, follow the dialog to start a “free trial” (14 days) or upload a formal License Key
- Manage licenses: log in as
admin → System → License Management (view / issue licenses)
- The machine fingerprint is derived from the host hardware serial + MAC address, so keep the hardware stable; replacing the machine requires a new license
7. Troubleshooting
| Issue | Fix |
| Exits at once, log says the master key is missing | Check that CRM_LICENSE_MASTER_KEY is set in .env |
| Database connection fails | Check spring.datasource (url / username / password) in application.yml and the MySQL grants |
| Redis connection fails | Check REDIS_HOST/REDIS_PORT/REDIS_PASSWORD in .env |
| Port already in use | Change SERVER_PORT in .env |
| Cannot find the log | Manual start: logs/app.log; under systemd: /var/log/crm/app.log |
7.1 Redis connection failure / app exits right after start
⚠
Symptom: the app stops soon after bash start.sh start, and logs/app.log ends with Caused by: java.net.ConnectException: Connection refused: localhost/127.0.0.1:6379 (or io.lettuce.core.RedisConnectionException: Unable to connect to localhost/...:6379).
Cause: Redis is not installed or not running. Redis is a hard dependency (login state, sessions and caching). During startup WebMvcConfig reads the system config, and an unreachable Redis aborts Spring context initialization.
Fix: install and start Redis:
sudo apt install redis-server -y && sudo systemctl enable --now redis-server (verify with redis-cli ping → PONG)
- Container / source build: start
redis-server and make sure it listens on 6379.
- Redis elsewhere, or custom port / password: edit
REDIS_HOST/REDIS_PORT/REDIS_PASSWORD in .env and run bash start.sh restart (or systemctl restart crm).
Note (2.6.1+): since 2.6.1 RedisService degrades gracefully — get returns null and falls back to the database, while set/delete become no-ops, so the app can start and survive runtime Redis hiccups. Login, sessions and caching still require a running Redis; otherwise login writes are dropped, isTokenValid fails and login cannot succeed. When you see Redis 不可用, 已降级处理... in the log, degradation has kicked in (limited functionality) — make sure Redis is actually running.
7.2 Startup fails: JDK 17 or higher required
⚠
Symptom: ./start.sh exits immediately with 启动失败:需要 JDK 17 及以上(jar 由 Java 17 编译,Spring Boot 3.2 要求 17+); or the app fails right after starting with UnsupportedClassVersionError: class file version 61.0.
Cause: the default java on this machine is 8 / 11. The package is compiled with JDK 17 (class file version 61.0), which older JVMs cannot load.
Fix:
- CentOS / RHEL / Rocky / TencentOS:
sudo yum install -y java-17-openjdk-devel (or dnf install)
- Ubuntu / Debian / Kylin / UOS:
sudo apt install -y openjdk-17-jdk
- Confirm with
java -version that it reports 17+, then run ./start.sh
- JDK 17 installed but the default java still points to an older release: list the paths with
ls /usr/lib/jvm, then run JAVA_HOME=/usr/lib/jvm/java-17-openjdk ./start.sh; you can also switch the default with sudo alternatives --config java
Note (2.6.5+): the start script now auto-scans common directories such as /usr/lib/jvm, /usr/java, /opt/jdk and /Library/Java/JavaVirtualMachines. Any installed JDK 17+ is picked up automatically even if it is not the default java, so no manual JAVA_HOME is needed. It only errors out when no JDK 17+ is found, and the message lists every java it scanned with its version.
7.3 Running node prerender.js prints node: command not found
⚠
Symptom: bash: node: command not found.
Cause: Node.js is not installed on the server. This command is not mandatory — prerender.js only generates static HTML copies of the news / case pages for search engines; the package already ships pre-generated web/news/*.html, web/case/*.html and sitemap.xml.
You can skip it: just use the bundled pre-rendered files — pages work normally with no 404. Only rerun it when you added or edited news / cases in the admin and want the static pages to match the latest content.
If you do need it, install Node 18+ first:
- CentOS / RHEL / TencentOS:
sudo dnf module install -y nodejs:20 (CentOS 7: sudo yum install -y nodejs)
- Ubuntu / Debian:
sudo apt install -y nodejs npm
- Offline / specific version: download the Linux binary from nodejs.org, extract it and add its
bin directory to PATH
- Verify:
node -v should show v18+
Then install the prerender dependencies and generate:
npm i playwright && npx playwright install chromium (first run downloads ~100–200 MB; the backend must already be running on port 8099 because the script reads local APIs for data)
OUT_DIR=web node prerender.js (defaults to web/)
Note: if the site is served by Nginx, Node is not needed at all; it is only required when you choose node serve.js as the static server.