Production-ready Docker Compose templates for self-hosting open-source applications. Every template is hardened to a uniform baseline — cap_drop: ALL with the minimum verified cap_add, no-new-privileges, ipc: private, internal-only Docker networks for database tiers, pinned image versions, healthchecks, and per-container resource limits. The current CVE state of every image is published in AUDIT.md.
- Available Templates
- Prerequisites
- Quick Start
- Directory Structure
- Common Configuration
- Security Features
- Security Audit
- Releases & Verification
- About Webnestify
- Contributing
- Support
- License
| Template | Description |
|---|---|
| n8n | Workflow automation (Zapier alternative). Postgres 18, Redis, dedicated task runner |
| Baserow | No-code database (Airtable alternative). Postgres 18 |
| DocuSeal | Document signing and forms. Postgres 18, bundled Gotenberg |
| Nextcloud | File sync + collaboration. Postgres 18, Redis, FPM + nginx, cron |
| Template | Description |
|---|---|
| Jellyfin | Free media server for movies, TV, and music |
| Navidrome | Self-hosted music server (Subsonic/Airsonic compatible) |
| qBittorrent | BitTorrent client with web UI |
| Template | Description |
|---|---|
| Dockhand | Docker management UI with free SSO (Portainer alternative). Postgres + docker-socket-proxy |
| Uptime Kuma | Self-hosted monitoring + status pages. MariaDB backend |
| MeshCentral | Remote monitoring & management (RMM). Vanilla MongoDB 8.0 |
| WireGuard + AdGuard | WireGuard VPN (wg-easy) with AdGuard Home DNS filtering |
| Template | Description |
|---|---|
| Authentik | Identity provider with SSO, OAuth2, SAML, LDAP. Postgres 18 (Redis dropped in 2025.10+) |
| Template | Description |
|---|---|
| Stoat | Self-hosted Discord alternative with voice/video (formerly Revolt) |
| Zulip | Threaded team chat (Slack alternative). Postgres 18, Memcached, RabbitMQ, Redis |
| Open WebUI | Web interface for LLMs (ChatGPT alternative) |
| Template | Description |
|---|---|
| FreshRSS | Self-hosted RSS feed aggregator |
| SerpBear | SEO rank tracking |
- Docker v20.10 or higher
- Docker Compose v2.0 or higher
- A reverse proxy with TLS termination — Caddy or Pangolin is recommended. Every template's web UI binds to
127.0.0.1and is intended to be fronted by the proxy. - For each template: one or more external Docker networks that the compose file references. Each template's
README.mddocuments the exactdocker network createcommands it needs (commonly one front-of-house network and one--internalnetwork for the database tier).
-
Clone the repository
git clone https://github.com/wnstify/docker.git cd docker -
Pick a template and read its README
cd n8n && cat README.md
Every template's README documents the exact Docker networks it needs, the required
.envvalues, and any host-side prep (e.g.,modprobe wireguardfor the VPN stack). -
Create the networks the template needs
# Example (n8n): two networks, db tier internal-only docker network create n8n-front docker network create --internal n8n-db -
Configure environment
cp .env.example .env $EDITOR .env.env.examplefiles includeopensslrecipes next to every secret. Generate strong values — most templates:?on missing required vars and refuse to start with placeholders. -
Deploy
docker compose up -d
-
Front it with the reverse proxy — every template binds to
127.0.0.1, so the proxy is the only thing serving the web UI publicly.
docker/
├── README.md # this file
├── SECURITY.md # vulnerability reporting + security policy
├── AUDIT.md # latest CVE scan of every image (Trivy)
├── LICENSE
│
├── authentik/ # SSO / IdP
├── baserow/ # no-code DB
├── dockhand/ # Docker management UI
├── docuseal/ # document signing
├── freshrss/ # RSS aggregator
├── jellyfin/ # media server
├── meshcentral/ # RMM
├── n8n/ # workflow automation
├── navidrome/ # music server
├── nextcloud/ # files + collab (5-service vanilla stack)
├── openwebui/ # LLM web UI
├── qbittorrent/ # BitTorrent client
├── serpbear/ # SEO rank tracking
├── stoat/ # Discord-alternative chat
├── uptime-kuma/ # monitoring + status pages
├── wg-adguard/ # WireGuard VPN + AdGuard DNS
└── zulip/ # team chat
Every template directory contains at least docker-compose.yml, .env.example, and README.md. Some also ship an init-data.sh for non-root DB user creation or other small helpers — see each template's own README.
Every template ships a tracked .env.example and an untracked .env. The example file has openssl recipes next to every secret it expects. Never commit .env — the repo's .gitignore already excludes it, but generate strong unique values and don't reuse the placeholders.
All web UIs bind to 127.0.0.1 only — the reverse proxy is the only thing that serves them publicly. Caddy example:
your-domain.com {
reverse_proxy http://127.0.0.1:5678
}
Pangolin is the other recommended option if you want central auth + tunnels in front of multiple services.
We use Dockhand (with the tecnativa/docker-socket-proxy sidecar limiting socket exposure) for ongoing container management. Image updates are handled by docker compose pull && docker compose up -d against the pinned tags in each template's compose file — there's no Watchtower or other auto-pull mechanism in this repo.
Templates that run their own Postgres (n8n, Baserow, DocuSeal, Nextcloud, authentik, zulip) ship an init-data.sh that creates a non-root application user on first boot. The compose's POSTGRES_PASSWORD is the superuser; the application connects as POSTGRES_NON_ROOT_USER. SCRAM-SHA-256 is forced via POSTGRES_HOST_AUTH_METHOD.
Every template ships with the same hardened baseline:
| Layer | Setting | Effect |
|---|---|---|
| Capabilities | cap_drop: ALL with a minimum verified cap_add per role |
Each capability earned its place via cap-trim testing. Most database/cache containers run with zero caps. |
| Privileges | security_opt: no-new-privileges:true |
Setuid binaries can't gain caps mid-process |
| IPC | ipc: private |
Isolated SysV / POSIX IPC namespace per container |
| Image tags | Specific patch versions, never :latest or floating major tags |
Reproducible deploys; supply-chain pin |
| Network split | App tier on a regular bridge; DB / cache tier on an --internal bridge |
Postgres / Redis / MongoDB / MariaDB have no internet egress |
| Public exposure | 127.0.0.1:<port> bindings on every web UI |
Only the reverse proxy can reach the admin endpoints |
| Resources | deploy.resources.limits for memory / cpus / pids on every service |
DoS-class CVEs in any one container can't take down the host |
| Ephemeral writes | tmpfs for /tmp, /var/cache/nginx, etc. with size= caps |
No persistence required; race-condition gadgets neutered |
| Auth | Postgres uses SCRAM-SHA-256; Redis uses --requirepass + REDISCLI_AUTH; non-root app DB user |
Stronger than upstream defaults; credentials never appear in process list |
| Lifecycle | Healthchecks on every service with start_period matched to the slowest first-boot |
docker compose ps is a true signal |
| Secrets | .env.example tracked, .env ignored; required vars use ${VAR:?error} |
Service fails fast if a secret is missing |
For security concerns or vulnerability reports, see our Security Policy.
AUDIT.md is a Trivy CVE scan of every image referenced in every compose file in this repo, triaged against the hardened configuration above. The audit is timestamped (image tags + scanner DB version + scan date), distinguishes findings that are exploitable in production from those neutered by the hardening, and lists exactly which CVE patterns were filtered as noise and why. It's regenerated each time the templates change materially.
Re-running it locally:
# Install Trivy (if not already installed)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin
# Scan a single image
trivy image --severity CRITICAL,HIGH,MEDIUM,LOW --scanners vuln <image>:<tag>Releases are tagged with Calendar Versioning (YYYY.MM.DD) and signed end-to-end:
- Source archive (
.tar.gz+.zip) built from tracked files viagit archive. SHA256SUMScovering both archives.- Sigstore keyless signature (
SHA256SUMS.sigstore.json) — bound to this repo's release workflow via short-lived OIDC certs (no long-lived private key to leak). - SLSA build-provenance attestation for each archive — verifiable with
gh attestation verify.
Notable changes appear on the Releases page, auto-generated from merged PRs. Each release tarball also includes a CHANGELOG.md snapshot. Copy-paste verification commands (cosign + gh attestation verify) are in VERIFICATION.md. The release workflow itself: .github/workflows/release.yml.
Webnestify empowers businesses and developers with tools for managing web infrastructure. We believe in:
- Saving Money — Reduce reliance on costly SaaS tools
- Owning Your Data — Privacy-focused, self-hosted solutions
- Simplifying Management — Intuitive tools and educational resources
- Managed Services — Email servers, Cloudflare configuration, dedicated hosting
- Educational Content — Tutorials, livestreams, and courses on YouTube
- Open-Source Advocacy — Tailored solutions that give you full control
Learn more at webnestify.cloud
Contributions are welcome! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-template) - Commit your changes (
git commit -m 'Add new template') - Push to the branch (
git push origin feature/new-template) - Open a Pull Request
New templates must match the hardening baseline (see Security Features). Concretely, each new template should include:
docker-compose.ymlwith, for every service:- Pinned image tag (no
:latest, no floating major) cap_drop: ALL+ the minimumcap_addthat you've verified by trim-and-retestsecurity_opt: [no-new-privileges:true]andipc: privatedeploy.resources.limitscoveringmemory,cpus, andpids- A working
healthcheckwith astart_periodmatched to the slowest first-boot - Web UIs bound to
127.0.0.1only - Database / cache tier on an external
--internalDocker network
- Pinned image tag (no
.env.exampletracked, real.envgit-ignored. Required vars use${VAR:?error}so the stack fails fast if you forget one.README.mddocumenting the exact networks todocker network create, the required.envvalues, and any host-side prep.- Optional but recommended:
init-data.shfor non-root DB user.
- YouTube Tutorials: @webnestify
- Discord Community: Join Discord
- Contact: webnestify.cloud/contact
This project is licensed under the MIT License — see the LICENSE file for details.
Webnestify – Your partner in simplifying web infrastructure.
