Guide
6 min read

The Hidden Prerequisites Docker Compose Setup Scripts Keep Missing

A Compose file isn't a full deployment. Setup scripts skip the kernel modules, sysctls, host directories, and permissions an app needs — and the failure shows up after 'it started'.

The Hidden Prerequisites Docker Compose Setup Scripts Keep Missing

docker compose up -d finishes, everything says Started, and ten minutes later the app is in a crash loop or silently broken. The Compose file did its job — it's the host that wasn't ready. A surprising number of self-hosted apps depend on prerequisites that live outside the YAML entirely, and the one-line setup scripts that promise "just run this" almost always skip them. This is the distinct sibling of Compose drift over time: drift is about the config changing under you; this is about what was never set on the host in the first place.

The prerequisites that aren't in the Compose file

Kernel parameters (sysctls). The classic is Elasticsearch/OpenSearch needing vm.max_map_count=262144 — without it the container exits immediately. Others need net.core.somaxconn raised, or vm.overcommit_memory for Redis. These are host settings; Compose can request some via sysctls: but many must be set on the host and made persistent in /etc/sysctl.d/.

Kernel modules. Apps doing networking or storage tricks (WireGuard, some VPN containers, ZFS tooling) need a module loaded on the host. If it's missing, the container starts and the feature just doesn't work.

Host directory ownership. Bind-mounted directories must be owned by the UID the container runs as. Create the dir as root, and the app — running as uid 1000 — can't write to its own data path. This is the quiet "it started but won't save anything" failure.

Ports already in use. A port the app wants is taken by another service, so it binds partially or not at all. On a multi-app box this is common enough to deserve its own treatment — see multi-app VPS port collisions.

Required environment / secrets. A missing .env value doesn't always stop startup; sometimes the app boots with an insecure default or a blank admin password. Worse than crashing, because it looks fine.

Run a preflight, not a post-mortem

The fix is to check these before up, not diagnose them after:

  • Required sysctls set on the host and persisted (vm.max_map_count, etc.).
  • Needed kernel modules loaded and set to load on boot.
  • Bind-mount directories created and chowned to the container's UID/GID.
  • Target ports confirmed free.
  • Every required env var present; no app left on a default password.
  • Disk headroom on the data volume.

A two-minute preflight turns "started but broken" into "actually working."

Templates encode the prerequisites

The reason a one-line script misses these is that it only knows about the container, not the host. A managed deployment that's built per-app can set the sysctls, create the directories with the right ownership, and pick free ports as part of bringing the app up.

ServerCompass reviewing generated settings before deploying an app Deploying from a per-app template in ServerCompass — host prerequisites, volumes, and ports are resolved as part of the deploy instead of being left to a generic script.

Takeaway

A Compose file describes containers; it doesn't describe the host they need. Most "it started and then broke" incidents are a missing sysctl, an unloaded module, a directory the app can't write to, or a port already taken. Run the preflight before you bring the stack up, and the app that "should just work" actually does.

docker-compose
preflight
self-hosted
permissions
sysctl

From across the StoicSoft network

Hand-curated reads on the same topic from sister sites in the StoicSoft family.

Keep reading

Guide
10 min

Docker Compose Drift: How to Catch Dev/Prod Differences Before They Break Your Deploy

Most "works on staging, broken on prod" deploys are docker-compose drift — a service name, env var, or network alias that diverged silently across files. A 30-line preflight catches nine in ten before the deploy runs.

Guide

Self-Hosted n8n: The OAuth Callback URL Checklist Before Your Credentials Fail

Your self-hosted n8n container is running, you add a Google credential, and OAuth dies with redirect_uri_mismatch. It is almost never the credential — it is the callback URL n8n hands the provider, and the env vars and reverse-proxy headers that decide what that URL says.

Guide
7 min

A Passthrough Preflight for Proxmox: IOMMU, Boot Order, and Hardware Isolation

Stacking GPU passthrough, an HBA to a TrueNAS VM, and LXC AI workloads on one Proxmox box works until a reboot reshuffles everything. A preflight for IOMMU groups, driver placement, and boot order.

Guide
6 min

Family Self-Hosters Need a Backup and Rollback Preflight Before Every App Upgrade

When the household depends on your server, a bad upgrade isn't a hobby setback — it's everyone's photos and files down. A two-minute backup-and-rollback preflight before you hit update.

Guide
6 min

Jellyfin on Linux: Choosing Between Docker Compose, Portainer, and a Template

Beginners stall on the first decision — how to actually deploy Jellyfin. Raw Compose, Portainer's UI, or a one-click template? A clear comparison so you pick once and move on.

Guide
6 min

Self-Hosted Operators Want Monitoring Beyond a Basic Uptime Check

A green 'it responds' check misses expired certs, broken logins, silent data staleness, and slow-but-up services. What real public-service monitoring looks like beyond a ping.