Quick start with Docker
The fastest way to get Halo running is with Docker and the embedded H2 database.
docker run -d \
--name halo \
-p 8090:8090 \
-v ~/.halo2:/root/.halo2 \
halohub/halo:2.22
After the container starts, access Halo at http://localhost:8090.
Environment variables
Halo supports the following environment variables for configuration:
HALO_WORK_DIR
string
default: "/root/.halo2"
Working directory for Halo data, including database, logs, and uploads
Additional Spring configuration file locations
JVM options for memory and performance tuning (e.g., -Xmx512m -Xms512m)
TZ
string
default: "Asia/Shanghai"
Timezone for the container
Production deployment
Do not use the embedded H2 database in production. Use PostgreSQL or MySQL for better performance and reliability.
With PostgreSQL
Create a docker-compose.yml file:
version : '3.8'
services :
halo :
image : halohub/halo:2.22
container_name : halo
restart : unless-stopped
ports :
- "8090:8090"
volumes :
- ./halo:/root/.halo2
command :
- --spring.r2dbc.url=r2dbc:pool:postgresql://postgres:5432/halo
- --spring.r2dbc.username=halo
- --spring.r2dbc.password=your_secure_password
- --spring.sql.init.platform=postgresql
- --halo.external-url=https://yourdomain.com
depends_on :
postgres :
condition : service_healthy
postgres :
image : postgres:15.4
container_name : halo-postgres
restart : unless-stopped
healthcheck :
test : [ "CMD" , "pg_isready" , "-U" , "halo" ]
interval : 10s
timeout : 5s
retries : 5
environment :
POSTGRES_PASSWORD : your_secure_password
POSTGRES_USER : halo
POSTGRES_DB : halo
PGUSER : halo
volumes :
- ./postgres:/var/lib/postgresql/data
With MySQL
Create a docker-compose.yml file:
version : '3.8'
services :
halo :
image : halohub/halo:2.22
container_name : halo
restart : unless-stopped
ports :
- "8090:8090"
volumes :
- ./halo:/root/.halo2
command :
- --spring.r2dbc.url=r2dbc:pool:mysql://mysql:3306/halo
- --spring.r2dbc.username=halo
- --spring.r2dbc.password=your_secure_password
- --spring.sql.init.platform=mysql
- --halo.external-url=https://yourdomain.com
depends_on :
mysql :
condition : service_healthy
mysql :
image : mysql:8.0
container_name : halo-mysql
restart : unless-stopped
command :
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
healthcheck :
test : [ "CMD" , "mysqladmin" , "ping" , "-h" , "localhost" ]
interval : 10s
timeout : 5s
retries : 5
environment :
MYSQL_ROOT_PASSWORD : your_secure_password
MYSQL_DATABASE : halo
MYSQL_USER : halo
MYSQL_PASSWORD : your_secure_password
volumes :
- ./mysql:/var/lib/mysql
Start your deployment
Update configuration
Replace your_secure_password and https://yourdomain.com with your actual values in the docker-compose.yml file.
Check logs
docker-compose logs -f halo
Wait until you see “Started HaloApplication” in the logs.
Access Halo
Open your browser and navigate to http://localhost:8090 (or your configured external URL). Complete the initial setup wizard to create your admin account.
Volume mounts
Halo requires persistent storage for data and uploads:
Application data : Mount /root/.halo2 to persist database, logs, and configuration
Database data : Mount database-specific directories (/var/lib/postgresql/data or /var/lib/mysql)
The working directory contains:
db/ - Database files (H2 only)
logs/ - Application logs
plugins/ - Installed plugins
themes/ - Installed themes
upload/ - User-uploaded files
JVM tuning
For production environments, configure JVM options based on your server resources:
services :
halo :
image : halohub/halo:2.22
environment :
- JVM_OPTS=-Xmx2g -Xms2g -XX:+UseG1GC
Recommended settings:
Small sites (< 1000 posts): -Xmx512m -Xms512m
Medium sites (1000-5000 posts): -Xmx1g -Xms1g
Large sites (> 5000 posts): -Xmx2g -Xms2g
Health checks
Halo provides health check endpoints for monitoring:
# Readiness check
curl http://localhost:8090/actuator/health/readiness
# Liveness check
curl http://localhost:8090/actuator/health/liveness
Add health checks to your Docker deployment:
services :
halo :
healthcheck :
test : [ "CMD" , "curl" , "-f" , "http://localhost:8090/actuator/health/readiness" ]
interval : 30s
timeout : 5s
retries : 5
start_period : 30s
Upgrading
Backup your data
Create a backup of your volumes before upgrading: docker-compose down
tar -czf halo-backup- $( date +%Y%m%d ) .tar.gz ./halo ./postgres
Update image version
Edit your docker-compose.yml and change the image tag: image : halohub/halo:2.23 # Update to new version
Pull and restart
docker-compose pull
docker-compose up -d
Verify upgrade
Check logs for successful startup and database migration: docker-compose logs -f halo
Next steps
Reverse proxy setup Configure Nginx or Caddy for SSL and domain routing
Backup and restore Set up automated backups for your Halo installation