deeplo

Docker image

Set up deeplo as a Docker container and run your first deploy.

Prerequisites:

  • A host running Docker with the Compose plugin
  • At least one remote host running Docker with the Compose plugin
  • SSH access to those remote hosts

Create the compose file

Create compose.yml with the deeplo service:

services:
  deeplo:
    image: ghcr.io/jancernik/deeplo:latest
    container_name: deeplo
    restart: unless-stopped
    ports:
      - "8470:8470"
    environment:
      DEEPLO_SSH_PRIVATE_KEY_FILE: /run/secrets/deploy_key
      DEEPLO_SSH_USER: deploy
    volumes:
      - deeplo-data:/var/lib/deeplo
      - ./config.yml:/etc/deeplo/config.yml:ro
    secrets:
      - deploy_key

volumes:
  deeplo-data:

secrets:
  deploy_key:
    file: ./secrets/deploy_key

If you prefer to mount a host directory, create it with the same container ownership:

mkdir -p data
sudo chown 1000:1000 data

Then mount it instead of the named volume:

volumes:
  - ./data:/var/lib/deeplo

Generate a deploy key

mkdir -p secrets
ssh-keygen -t ed25519 -f secrets/deploy_key

Keys generated with the command above already have the right permissions. If you copy in an existing key or create one another way, make sure the container user owns it:

sudo chown 1000:1000 secrets/deploy_key
sudo chmod 600 secrets/deploy_key

Authorize the deploy key

Confirm DEEPLO_SSH_USER matches your deploy user. If you need to create one, see the deploy user. Then install the public key on each target before starting the daemon:

ssh-copy-id -i secrets/deploy_key.pub deploy@10.0.0.10

To do it manually, append the contents of secrets/deploy_key.pub to ~/.ssh/authorized_keys for the deploy user on each target.

The daemon uses the same key to fetch your repos over SSH. For private repos, grant that key read access. On GitHub, for example, you can add deploy_key.pub as a read-only deploy key.

Edit the config

Create config.yml beside compose.yml and replace the example values with your own:

hosts:
  - name: web-1
    address: 10.0.0.10 # your host IP or hostname
    deploy_dir: /srv/apps

repos:
  - name: myapp
    url: git@github.com:yourorg/myapp.git
    branch: main

projects:
  - name: myapp
    repo: myapp
    repo_subdir: deploy # directory in repo containing compose.yml
    persist_files:
      - .env
    targets:
      - web-1

The deploy directory is rebuilt each time

Each deploy rebuilds the project's remote directory from the commit and replaces the previous contents. A file that lives only on the host (a token you copied in, a runtime-generated file) won't survive the next deploy unless you persist it:

  • Keep specific files by listing them in persist_files (defaults to [".env"], [] keeps nothing).
  • Store data in a Docker named volume or a bind mount outside the deploy directory.

Then validate it:

docker compose run --rm deeplo config check

See Config file for the full schema.

Start the daemon

docker compose up -d
docker compose exec deeplo deeplo health  # confirm it's running and reachable

On start, the daemon reconciles your config and deploys every configured project at its current commit, so your first deploy begins right away.

Watch the first deploy

Follow it in the logs:

docker compose logs -f

Then check the result:

docker compose exec deeplo bash

deeplo deploys state          # latest state per project-host
deeplo deploys history        # recent runs
deeplo deploys logs <run-id>  # log for a run (id from history)

To see all available commands, use deeplo --help or browse the CLI reference.

You can create an alias to run CLI commands against the container as you would on a native install:

alias deeplo='docker exec deeplo deeplo'

Next steps

Upgrading

docker compose pull deeplo
docker compose up -d deeplo

This downloads the new image and recreates the container. In-flight deploys get up to DEEPLO_SHUTDOWN_GRACE (default 30s) to finish first.


On this page