SoulFire LogoSoulFire

Run SoulFire with Docker Compose

Start a persistent local container, generate access, and add HTTPS for remote clients.

Install Docker Engine and Compose using the official installation guide. The official image contains the Java runtime and exposes the API on container port 38765. Persistent data belongs at /soulfire/data.

Start a local deployment

Create a deployment directory with this compose.yaml:

compose.yaml
services:
  app:
    image: ghcr.io/soulfiremc-com/soulfire:latest
    restart: unless-stopped
    stdin_open: true
    tty: true
    ports:
      - "127.0.0.1:38765:38765"
    volumes:
      - ./data:/soulfire/data

This publishes HTTP only on the host's loopback address. For a repeatable deployment, replace latest with the released tag or digest you choose. Record the image version with your test results.

Create the writable data directory on a Linux host:

mkdir -p data
sudo chown 1001:1001 data
docker compose up -d

The image runs as UID/GID 1001. Check the container and recent output:

docker compose ps
docker compose logs --tail=100 app
curl -f http://127.0.0.1:38765/health

Wait for startup to complete. A successful health response checks backend availability, not Minecraft connectivity.

Generate access

Attach to the backend console:

docker compose attach app

Run generate-token api in that console. Detach with Ctrl+P, Ctrl+Q to keep the container running. Connect a desktop client to http://127.0.0.1:38765 with that token from the same host.

For a bot target, remember that 127.0.0.1 inside the container refers to the container. Use a Minecraft address reachable from the container network. Then complete the first-bot tutorial.

Add a Cloudflare tunnel

Create a tunnel and route using Cloudflare's remote tunnel guide. Set its service target to http://app:38765. Save the tunnel token in your deployment's .env:

.env
TUNNEL_TOKEN=YOUR_TUNNEL_TOKEN

Add a service to the same Compose project:

  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run
    environment:
      TUNNEL_TOKEN: ${TUNNEL_TOKEN}

Run docker compose up -d after saving the change. Connect the client through the tunnel's HTTPS hostname. Keep the local API port bound to loopback, or remove the published port if only the tunnel needs access.

Use Traefik with a hostname

Point your hostname to this host and make port 443 reachable for the TLS challenge. Set these values in .env:

.env
DOMAIN=soulfire.example.com
EMAIL=admin@example.com

Use this Compose deployment instead of the local-only example:

compose.yaml
services:
  app:
    image: ghcr.io/soulfiremc-com/soulfire:latest
    restart: unless-stopped
    stdin_open: true
    tty: true
    volumes:
      - ./data:/soulfire/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.soulfire.rule=Host(`${DOMAIN}`)"
      - "traefik.http.routers.soulfire.entrypoints=websecure"
      - "traefik.http.routers.soulfire.tls.certresolver=soulfire"
      - "traefik.http.services.soulfire.loadbalancer.server.port=38765"
  traefik:
    image: traefik:v3
    restart: unless-stopped
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.soulfire.acme.tlschallenge=true"
      - "--certificatesresolvers.soulfire.acme.email=${EMAIL}"
      - "--certificatesresolvers.soulfire.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
volumes:
  letsencrypt:

Check the Traefik log for certificate errors before connecting the client. Preserve its letsencrypt volume across replacements. Use Traefik's ACME reference for challenge and renewal details. For IP-only HTTPS, use the automated setup or current upstream IP certificate instructions.

Panels and maintenance

For Pterodactyl or Pelican, use the official SoulFire egg. Preserve the panel's data mount and use the same access and HTTPS checks.

Read persistent data, backup and restore, and upgrade and rollback before replacing containers. Do not remove a data volume as a routine upgrade step.

How is this page?

Last updated on

On this page