Docker Deployment

Deploy from GHCR with Compose, port binding, and optional reverse proxy examples.

Docker Deployment

BoxBox builds into one container: Bun compiles the SvelteKit frontend, Go embeds those static files, and the runtime image starts one HTTP server on port 80.

Prerequisites

  • Docker 24+ or a recent Docker Engine.
  • Docker Compose v2 if using docker-compose.yml.
  • A Linux host if you want accurate system drive discovery and mount propagation.

Preferred Deployment

Deploy BoxBox with Docker Compose using the published GitHub Container Registry image. This is the recommended path for servers because it does not require cloning the repository and keeps updates simple.

Download the deployment files, edit the environment, then start the published image:

mkdir -p boxbox
cd boxbox
curl -fsSLO https://raw.githubusercontent.com/jR4dh3y/BoxBox/master/docker-compose.yml
curl -fsSLO https://raw.githubusercontent.com/jR4dh3y/BoxBox/master/.env.example
mkdir -p backend
curl -fsSL https://raw.githubusercontent.com/jR4dh3y/BoxBox/master/backend/config.yaml -o backend/config.yaml
cp .env.example .env
$EDITOR .env
docker compose pull
docker compose up -d

Set these values in .env before starting:

FM_JWT_SECRET=generate-a-long-random-secret
FM_USERS_admin=replace-this-password
HOST_PORT=8080
HOME_PATH=/home/your-user
BOXBOX_IMAGE=ghcr.io/jr4dh3y/boxbox:latest

Open http://localhost:8080, or use the host and port you configured with HOST_PORT.

Published Images

Release images are published to GitHub Container Registry:

docker pull ghcr.io/jr4dh3y/boxbox:latest

The publish workflow runs when a v* git tag is pushed. It publishes the tag name and updates latest.

git tag v0.1.0
git push origin v0.1.0

Optional: Reverse Proxy or Traefik

The default compose file uses normal host port binding and does not require Traefik. If you want to put BoxBox behind Traefik, remove the ports entry, attach the service to your Traefik network, and add labels for your router.

services:
  filemanager:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.boxbox.rule=Host(`boxbox.example.test`)"
      - "traefik.http.routers.boxbox.entrypoints=web"
      - "traefik.http.services.boxbox.loadbalancer.server.port=80"
    networks:
      - proxy

networks:
  proxy:
    external: true

For public or semi-public access, put TLS and access controls on your reverse proxy before exposing BoxBox beyond a trusted network.

Alternative: Simple Local Container

Use this path when you want a quick local test without Compose. It still uses the published GHCR image.

mkdir -p boxbox
cd boxbox

cat > config.yaml <<'EOF'
port: 80
host: "0.0.0.0"
jwt_secret: "replace-this-with-a-long-random-secret"
mount_points:
  - name: "home"
    path: "/home/user"
    read_only: false
EOF

docker pull ghcr.io/jr4dh3y/boxbox:latest

docker run -d \
  --name boxbox \
  -p 8080:80 \
  -e FM_JWT_SECRET="$(openssl rand -base64 32)" \
  -e FM_USERS_admin="replace-this-password" \
  -v "$PWD/config.yaml:/app/config.yaml:ro" \
  -v "$HOME:/home/user" \
  -v boxbox-data:/data \
  -v boxbox-temp:/tmp/filemanager \
  ghcr.io/jr4dh3y/boxbox:latest

Open http://localhost:8080 and sign in as admin with the password you set in FM_USERS_admin.

Alternative: Local Source Builds

Cloning the repository is supported, but it is not the preferred deployment method. Use this path only when you want to build the image from source instead of pulling the published GHCR image.

git clone https://github.com/jR4dh3y/BoxBox.git
cd BoxBox
docker build -t boxbox:local .

For compose, set BOXBOX_IMAGE=boxbox:local in .env, then run docker compose up -d.

Volumes

The default compose file mounts:

Host path Container path Why
./backend/config.yaml /app/config.yaml Runtime configuration.
/media/devmon /media/devmon Auto-discovered removable drives.
/ /host_root Host root browsing. High blast radius.
${HOME_PATH} /home/user User home directory browsing.
filemanager-temp /tmp/filemanager Chunked upload assembly.
filemanager-data /data Persistent app data, including custom drive names.

Use :ro on a volume or read_only: true in config.yaml when a path should never be modified through BoxBox.

Mount Propagation

The compose file uses rslave for host mount paths so new host mounts can appear inside the container. This matters for removable drives and some NAS/rclone mounts.

volumes:
  - /media/devmon:/media/devmon:rslave
  - /:/host_root:rslave

Updating

docker compose pull
docker compose up -d

For local source builds:

git pull
docker build --no-cache -t boxbox:local .
docker compose up -d

For a docker run deployment:

docker pull ghcr.io/jr4dh3y/boxbox:latest
docker stop boxbox
docker rm boxbox
# Re-run the docker run command with the same volumes and env values.

Health and Logs

curl http://localhost:8080/health
docker compose ps
docker compose logs -f filemanager

The health response is:

{"status":"ok"}

Permission Notes

The container runs with a small set of Linux capabilities in compose so it can read and manage a variety of host-owned files without full privileged mode. If a path still returns permission errors, check the host path permissions and consider narrowing BoxBox to directories owned by a consistent user or group.