Skip to content

Install via Docker

The universal path. Use Docker when you are on Fedora, Arch, Alpine, a NAS (Synology, TrueNAS), or just want a quick trial. For Debian/Ubuntu production servers, apt is still the recommended install.

  1. Create the host directories:

    Terminal window
    sudo mkdir -p /etc/simpledeploy /var/lib/simpledeploy
  2. Drop in a compose file at /etc/simpledeploy/docker-compose.yml:

    services:
    simpledeploy:
    image: ghcr.io/vazra/simpledeploy:latest
    restart: unless-stopped
    network_mode: host
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - /etc/simpledeploy:/etc/simpledeploy
    - /var/lib/simpledeploy:/var/lib/simpledeploy

    Also available as deploy/docker-compose.example.yml in the repo. network_mode: host lets Caddy bind host :80/:443 directly so TLS and reverse-proxy upstreams behave identically to the native install. The same-path bind mounts are required so docker compose -f /etc/simpledeploy/apps/<app>/docker-compose.yml resolves the same paths inside the container and on the host.

  3. Generate the config:

    Terminal window
    sudo docker run --rm \
    -v /etc/simpledeploy:/etc/simpledeploy \
    ghcr.io/vazra/simpledeploy:latest \
    init --config /etc/simpledeploy/config.yaml
    sudo vim /etc/simpledeploy/config.yaml

    Set domain, tls.email, and master_secret (generate via openssl rand -hex 32). See Configure SimpleDeploy for the full walkthrough.

  4. Start:

    Terminal window
    cd /etc/simpledeploy
    sudo docker compose up -d
  5. Tail the logs:

    Terminal window
    sudo docker compose logs -f simpledeploy

SimpleDeploy needs ports 80 and 443 reachable from the internet (Let’s Encrypt validates over 80, traffic flows over 443). Keep 22 open for SSH.

Terminal window
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

If you run a cloud firewall (AWS SG, Hetzner Cloud, DigitalOcean), open the same ports there too.

Hit the management UI:

https://manage.your-domain.com/

You should land on the setup wizard. If you get a TLS error, give Let’s Encrypt 30-60 seconds and reload.

Terminal window
cd /etc/simpledeploy
sudo docker compose pull
sudo docker compose up -d

If a release misbehaves, pin the image tag to the previous version and restart:

  1. Edit /etc/simpledeploy/docker-compose.yml and change the tag:

    image: ghcr.io/vazra/simpledeploy:<previous-version>
  2. Apply:

    Terminal window
    cd /etc/simpledeploy
    sudo docker compose up -d
  3. If the upgrade ran schema migrations, restore the pre-upgrade DB snapshot. See Disaster recovery for the procedure.

Use deploy/docker-compose.desktop.example.yml instead of the production compose file:

services:
simpledeploy:
image: ghcr.io/vazra/simpledeploy:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "8443:8443"
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
SIMPLEDEPLOY_UPSTREAM_HOST: host.docker.internal
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/simpledeploy:/etc/simpledeploy
- /var/lib/simpledeploy:/var/lib/simpledeploy

SIMPLEDEPLOY_UPSTREAM_HOST opts into an upstream rewrite: the proxy replaces localhost:<port> in resolved upstreams with host.docker.internal:<port> so Caddy inside the container can reach published app ports on the host.

The Desktop example also joins simpledeploy-public (see Shared network below) so Caddy can reach endpoint services over Docker DNS inside the VM, even when an app does not publish a host port.

If you are hacking on simpledeploy locally on a Mac and want endpoint-only apps to work end to end, use the containerized dev workflow:

Terminal window
make dev-docker # builds a linux binary + local image, starts the container
make dev-docker-down # stops and cleans up

This uses deploy/docker-compose.dev.yml, bind-mounts your repo at the same path inside the container (so docker compose -f <abs> resolves on both sides), reuses config.dev.yaml, and binds host :80/:443/:8500. Stop any native ./bin/simpledeploy on :443 before running it.

On first start simpledeploy auto-creates a bridge network called simpledeploy-public. Every deployed app’s endpoint-bearing services (any service with simpledeploy.endpoints.* or simpledeploy.domain labels) is auto-attached to it.

That is why endpoint services do not need to publish host ports to be reachable via their domain. Caddy resolves the upstream by container IP on the shared network.

For advanced app-to-app communication, you can reference simpledeploy-public as an external network on additional services. For most cross-app traffic, prefer exposing an endpoint and calling it over its domain.

Mounting /var/run/docker.sock into the container is root-equivalent on the host: anyone who can reach the container can control every container on the Docker daemon, including creating a privileged container that can escape to the host. Treat the SimpleDeploy container as sensitive and keep the management port firewalled to trusted networks.

Next: First deploy.