Files
HODA/docker-compose.yml
TMCandClaude Opus 5.5 c58cc329b0 Deploy with root docker-compose files, like the other repos
docker-compose.yml runs HODA on the main host, published on one address
(10.20.30.10:10040 in .env.example) for the Pangolin resource. The agent
settings are optional, so a single host needs nothing else.
docker-compose.agent.yml is for a second Docker host. Both follow FiMa's
layout: required values fail with a clear message, pull_policy always,
memory limits, capped logs, a read-only root filesystem.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:55:06 +01:00

76 lines
2.7 KiB
YAML

# HODA — the main host: serves the dashboard of every labeled app on this host's Docker.
#
# Usage:
# cp .env.example .env # the defaults fit the main host
# docker compose pull # grab the latest image from the Gitea registry
# docker compose up -d
#
# Point the Pangolin resource for apps.mariosem.es at http://HODA_BIND_IP:HODA_PORT
# (http://10.20.30.10:10040 with .env.example) and turn SSO on: HODA has no login of its own.
#
# One host needs nothing else. A second Docker host runs docker-compose.agent.yml, and this
# host then gets HODA_AGENT_URL and HODA_PEER_TOKEN in .env to pull that host's apps.
#
# The image is built and published by .gitea/workflows/ci.yml.
name: hoda
x-logging: &logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
hoda:
image: git.mariosem.es/msemes/hoda:${HODA_TAG:-latest}
container_name: hoda
restart: unless-stopped
# `:latest` is mutable; `always` makes `docker compose up -d` check the registry for a newer
# image. If you pin HODA_TAG to a fixed tag, `missing` is enough.
pull_policy: always
depends_on:
- socket-proxy
environment:
MODE: primary
DOCKER_HOST: tcp://socket-proxy:2375
NODE_NAME: ${HODA_NODE_NAME:-host-1}
DASHBOARD_TITLE: ${HODA_TITLE:-apps.mariosem.es}
# Only with a second host: its agent's URL and the token both hosts share. HODA refuses to
# start with an agent URL but no token.
PEERS: ${HODA_AGENT_URL:-}
PEER_TOKEN: ${HODA_PEER_TOKEN:-}
LOG_LEVEL: ${HODA_LOG_LEVEL:-info}
ports:
# Published on one address only: loopback by default, or the LAN IP Pangolin reaches.
- "${HODA_BIND_IP:-127.0.0.1}:${HODA_PORT:-8090}:8080"
volumes:
# Icon cache. Set HODA_DATA_DIR to bind-mount a host directory instead of the named volume;
# it must be owned by the image's user first: sudo chown -R 65532:65532 /path/to/dir
- ${HODA_DATA_DIR:-hoda_data}:/data
# The binary only writes to /data, and needs no privileges.
read_only: true
cap_drop: [ALL]
security_opt: ["no-new-privileges:true"]
mem_limit: 128m
cpus: 0.5
logging: *logging
# Read-only Docker API for HODA: container lists and events, nothing else. No published port.
socket-proxy:
image: tecnativa/docker-socket-proxy:latest
container_name: hoda-socket-proxy
restart: unless-stopped
environment:
CONTAINERS: 1
EVENTS: 1
POST: 0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
mem_limit: 64m
logging: *logging
volumes:
# Fallback when HODA_DATA_DIR is unset; a no-op if /data is bind-mounted to a host path.
hoda_data: