Skip to content

Advanced configuration

Everyday setup happens in the web UI. Nothing on this page is required for a normal install. These are deployment concerns: how the container is reached, what it may reach, and how it identifies clients.

Every variable is optional. The defaults are what the container ships with.

VariableDefaultWhat it does
ALLOW_PRIVATE_IPSunsetTurns the SSRF guard off, so badges and widgets may reach private, LAN and loopback addresses. Most homelab installs need it.
SOCKET_PROXY_URLunsetA Docker socket proxy, for container health monitoring.
TRUST_PROXYunsetBelieve X-Forwarded-Proto, so a request through a TLS-terminating proxy gets a Secure cookie.
TRUSTED_PROXYunsetWhere a front proxy sits, so nginx can resolve the real client for rate limiting.
SESSION_MAX_AGE_DAYS12hIdle session lifetime before re-login. Accepts a fraction. A session in use is extended.
PASSWORD_HASH_MEMORY16mibMemory per password hash. One of 8mib, 16mib, 32mib, 64mib, 128mib.
LOG_LEVELinfodebug, info, warn or error. warn and error behave the same. The General settings page also sets this, and that wins once the config has loaded.
DEMO_MODEunsetRun as a read-only public showcase.
CONFIG_PATH/data/apps.jsonWhere the config file lives.
ICONS_PATH/iconsWhere uploaded icons are written.
WIDGETS_PATH/usr/share/nginx/html/widgetsWhere widget folders are read from. A wrong path loads an empty registry and every widget reports as unknown.
PORT3000The port the API listens on. Nginx proxies to it, so changing it means changing the nginx config too.

The repo’s docker-compose.yml carries each of these as a commented line.

The SSRF guard blocks requests to private, loopback and link-local addresses. Most homelab services live on private IPs, so most installs need the guard off:

environment:
- ALLOW_PRIVATE_IPS=true

Read Security before setting it. Two things work without it: dotless hostnames such as Docker container names, and the host IP you set in General settings.

On Linux a container cannot reach the host’s LAN IP by default. Add:

extra_hosts:
- "host.docker.internal:host-gateway"

host-gateway is a Docker built-in that resolves to the host machine’s IP.

Two variables apply, and they do different things.

TRUST_PROXY=true makes Stackyard believe X-Forwarded-Proto: https, so the session cookie gets its Secure flag. Set it only when a proxy you control is actually in front of the app.

TRUSTED_PROXY tells nginx where the front proxy sits, so it can resolve the real client address for rate limiting:

TRUSTED_PROXY=172.18.0.0/16
TRUSTED_PROXY="172.18.0.0/16 10.0.0.5"

Without it, every request through the proxy counts as the same client and rate limiting becomes one shared bucket.

Rate-limit counters are held in memory and are not shared across replicas. Run a single instance behind any proxy.

The health-check badge can read a container’s state from the Docker daemon. This needs a Docker socket proxy, a separate container that exposes a narrowed read-only view of the socket.

tecnativa/docker-socket-proxy is the usual choice:

services:
socket-proxy:
image: tecnativa/docker-socket-proxy
environment:
- CONTAINERS=1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket_proxy
restart: unless-stopped
stackyard:
environment:
- SOCKET_PROXY_URL=http://socket-proxy:2375
networks:
- socket_proxy
networks:
socket_proxy:

Then turn on Docker Container Health Checks in General.

Ping-based health checks need none of this. See Badges.

Two mounts extend what the System Summary widget can read when its source is This Machine:

volumes:
# CPU temperature sensors
- /sys/class/thermal:/sys/class/thermal:ro
# Disk usage for a mount path
- /mnt/your-drive:/mnt/your-drive:ro

Stackyard does not terminate TLS and serves plain HTTP only. Put it behind a reverse proxy that terminates TLS. See Security.