Halo Docker Compose Deployment Guide – Requirements & Setup

8月5日 Published inWebsite Builders

Hardware Requirements

Server Type: Halo is not compatible with shared web hosting environments. You will require a cloud server or a Virtual Private Server (VPS). If you have not yet provisioned a server, you may use our affiliate link to get started.

CPU: There are no specialized processing requirements. The Docker image is optimized for multiple platforms and architectures.

Memory: A minimum of 1GB RAM is required to ensure stable performance.

Disk: Requirements depend on your content. If you do not plan to upload large volumes of attachments, disk space is not a significant constraint. However, using an SSD will improve overall system responsiveness.

Network: While Halo can function offline, certain themes rely on third-party resources and may require public internet access to render correctly.

Software Environment

Halo can be deployed in any environment that supports Docker or Java.

Docker (Recommended): We strongly suggest using Docker for deployment. It eliminates the complexities of manual environment configuration and ensures consistency across different systems.

JRE (Optional): You do not need to install a JRE if you are using the Docker image. For standalone JAR deployments: Halo versions 2.21+ require JRE 21; versions 2.20 and below require JRE 17.

Database: Halo supports PostgreSQL, MySQL, MariaDB, and H2. While H2 is an embedded database that does not require a separate server, the others must be managed independently. The best practice is to use Docker Compose to run Halo alongside its database. Note: Do not use the default H2 database in a production environment; it is prone to data corruption if mishandled. If you must use H2, ensure you perform regular backups.

Web Server (Optional): For production environments using a custom domain, configure a reverse proxy such as Nginx or Caddy. Please note that Halo does not support proxying to a subdirectory (e.g., yourdomain.com/blog).

Wget (Optional): This documentation uses wget for file downloads. Ensure it is installed on your system, though any equivalent download tool may be used.

VIM (Optional): We use VIM for editing configuration files in these examples. You may use any text editor you prefer.

Browser Support

  • Frontend: Compatibility is determined by your chosen theme.
  • Admin Console (Console & Personal Center): Compatible with all modern web browsers. Compatibility is dictated by the underlying Vue framework.

Terminology

~ (Tilde) – Refers to the current user's home directory.

Image – The Docker image containing the Halo application. This serves as the blueprint for starting your Halo container.

Working Directory – The location where Halo stores all persistent data. At runtime, the application creates a .halo2 folder within your user directory (absolute path: ~/.halo2). This directory holds the database, themes, plugins, attachments, logs, application.yaml, backups, and static files. When using Docker, you must map this directory to ensure data persistence.

Theme – A package consisting of page templates. The visual appearance of your site is determined by the theme activated in the admin panel.

Plugin – A modular software package that extends Halo's functionality. Plugins can be installed, upgraded, or removed independently of the core application.


Deploy Halo with Docker Compose

Before proceeding, please review the "Before You Begin" documentation for a conceptual overview of the Halo ecosystem.

Set Up the Environment

  1. Install Docker: Refer to the official Docker installation guide.
  2. Install Docker Compose: Refer to the official Docker Compose guide.

Always follow the official Docker documentation, as some Linux distributions provide outdated versions in their default software repositories.

Create the Container Stack

Halo maintains images across several registries. You may choose your preferred source:

  • registry.fit2cloud.com/halo/halo
  • halohub/halo
  • ghcr.io/halo-dev/halo

Important Note on Versioning: Halo 2 does not update the latest tag to prevent accidental breaking changes for users upgrading from 1.x. You should use a specific version tag. For example:

  • registry.fit2cloud.com/halo/halo:2 points to the latest 2.x release.
  • :2.21 points to the latest 2.21.x maintenance release.
  • :2.21.0 points to a specific version.

We will use registry.fit2cloud.com/halo/halo:2.21 for this guide. Create a dedicated directory for your deployment (e.g., ~/halo):

mkdir ~/halo && cd ~/halo

All persistent data for your Halo instance will be stored here. Ensure this directory is included in your backup routine.

Create docker-compose.yaml

The following configurations cover various database setups. All Halo settings are passed as container command arguments, eliminating the need for a manual application.yaml file.

Option 1: Halo + PostgreSQL

version: "3"
services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "8090:8090"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    environment:
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
      - --spring.r2dbc.username=halo
      - --spring.r2dbc.password=openpostgresql
      - --spring.sql.init.platform=postgresql
      - --halo.external-url=http://localhost:8090/
  halodb:
    image: postgres:15.4
    restart: on-failure:3
    networks:
      halo_network:
    volumes:
      - ./db:/var/lib/postgresql/data
    healthcheck:
      test: [ "CMD", "pg_isready" ]
      interval: 10s
      timeout: 5s
      retries: 5
    environment:
      - POSTGRES_PASSWORD=openpostgresql
      - POSTGRES_USER=halo
      - POSTGRES_DB=halo
      - PGUSER=halo
networks:
  halo_network:

Note: The PostgreSQL container does not expose ports to the host by default. If you require external database access, add a port mapping for 5432 to the halodb service.

Option 2: Halo + MySQL

version: "3"
services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "8090:8090"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    environment:
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
      - --spring.r2dbc.username=root
      - --spring.r2dbc.password=o#DwN&JSa56
      - --spring.sql.init.platform=mysql
      - --halo.external-url=http://localhost:8090/
  halodb:
    image: mysql:8.1.0
    restart: on-failure:3
    networks:
      halo_network:
    command:
      - --default-authentication-plugin=caching_sha2_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --explicit_defaults_for_timestamp=true
    volumes:
      - ./mysql:/var/lib/mysql
      - ./mysqlBackup:/data/mysqlBackup
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    environment:
      - MYSQL_ROOT_PASSWORD=o#DwN&JSa56
      - MYSQL_DATABASE=halo
networks:
  halo_network:

Note: The MySQL container does not expose ports to the host by default. Add a port mapping for 3306 if external access is needed.

Option 3: Halo + H2 (Embedded)

version: "3"
services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
    restart: on-failure:3
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "8090:8090"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    environment:
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --halo.external-url=http://localhost:8090/

Warning: Do not use H2 in production. It is highly susceptible to data corruption. Use PostgreSQL or MySQL for live sites.

Option 4: Using an External Database

version: "3"
services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
    restart: on-failure:3
    network_mode: "host"
    volumes:
      - ./halo2:/root/.halo2
    environment:
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://localhost:3306/halo
      - --spring.r2dbc.username=root
      - --spring.r2dbc.password=YOUR_PASSWORD
      - --spring.sql.init.platform=mysql
      - --halo.external-url=http://localhost:8090/
      - --server.port=8090

If using an external database, you must create the database manually before starting the container. For MySQL, use:

CREATE DATABASE halo CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

Configuration Parameters

Parameter Description
spring.r2dbc.url Database connection string (refer to the table below)
spring.r2dbc.username Database username
spring.r2dbc.password Database password
spring.sql.init.platform Database type: postgresql, mysql, mariadb, or h2
halo.external-url The public URL for the instance. Use your domain or IP

Database Connection Strings

Database URL Format spring.sql.init.platform
PostgreSQL r2dbc:pool:postgresql://{HOST}:{PORT}/{DATABASE} postgresql
MySQL r2dbc:pool:mysql://{HOST}:{PORT}/{DATABASE} mysql
MariaDB r2dbc:pool:mariadb://{HOST}:{PORT}/{DATABASE} mariadb
H2 r2dbc:h2:file:///${halo.work-dir}/db/halo-next?MODE=MySQL&DB_CLOSE_ON_EXIT=FALSE h2

For a full list of configuration options, please refer to the configuration documentation.


Start Halo

To launch the stack in detached mode:

docker-compose up -d

To monitor logs in real-time:

docker-compose logs -f

Once the container is running, navigate to http://your-ip:8090/console to begin the initialization process.

Note: If you intend to use a custom domain, configure your DNS and reverse proxy before running the initialization. If you cannot access the page via IP, ensure that port 8090 is open in your server's firewall and any cloud provider security groups.

Update the Stack

  1. Backup Data: We recommend performing a backup before any update. Refer to our backup and restore guide.
  2. Modify docker-compose.yaml: Update the image tag to the desired version:
services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
  1. Apply Changes:
docker-compose up -d

Reverse Proxy Examples

Ensure your reverse proxy software is already installed. For advanced configurations, refer to the documentation for Nginx Proxy Manager or Traefik.

Nginx Configuration

upstream halo {
  server 127.0.0.1:8090;
}
server {
  listen 80;
  listen [::]:80;
  server_name www.yourdomain.com;
  client_max_body_size 1024m;
  location / {
    proxy_pass http://halo;
    proxy_set_header HOST $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

Caddy 2 Configuration

www.yourdomain.com
encode gzip
reverse_proxy 127.0.0.1:8090

Traefik Configuration

To use Traefik, update your Halo stack configuration as follows (assuming an existing traefik network):

version: "3.8"
networks:
  traefik:
    external: true
  halo:
services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
    restart: on-failure:3
    volumes:
      - ./halo2:/root/.halo2
    networks:
      - traefik
      - halo
    command:
      - --halo.external-url=https://yourdomain.com
    labels:
      traefik.enable: "true"
      traefik.docker.network: traefik
      traefik.http.routers.halo.rule: Host(`yourdomain.com`)
      traefik.http.routers.halo.tls: "true"
      traefik.http.routers.halo.tls.certresolver: myresolver
      traefik.http.services.halo.loadbalancer.server.port: 8090