deeplo
Guides

GitHub reporting

Report deployment status to GitHub Deployments API and commit statuses. Includes run log serving.

When configured, deeplo reports deployment progress directly to GitHub using the Deployments API and Commit Statuses API.

This gives you:

  • Environment-level deployment history in GitHub's Environments tab
  • Red/green commit status indicators on commits and PRs
  • Clickable Details links that open the full plain-text run log (optional)

Reporting is entirely optional and additive — it never affects whether a deploy actually runs or succeeds.


What gets reported

For each (project, host) deploy target:

EventGitHub Deployment StatusGitHub Commit Status
Deploy startsin_progresspending
Deploy succeedssuccesssuccess
Deploy failsfailurefailure

Status descriptions are kept short and stable — concise phrases like "Preflight failed on vm-1", not raw docker/SSH error dumps. The full error detail lives in the run log, linked via the Details URL when log serving is enabled.


Environment naming

By default, the environment name is the project name. Use DEEPLO_GITHUB_ENVIRONMENT to add a prefix and DEEPLO_GITHUB_HOST_IN_ENV=true to include the host name.

ConfigurationEnvironment nameCommit context
Defaultnginxdeeplo/nginx
DEEPLO_GITHUB_ENVIRONMENT=homelabhomelab/nginxdeeplo/homelab/nginx
DEEPLO_GITHUB_HOST_IN_ENV=truevm-1/nginxdeeplo/vm-1/nginx
Both sethomelab/vm-1/nginxdeeplo/homelab/vm-1/nginx

Required permissions

Create a GitHub personal access token (classic or fine-grained) with:

  • Deployments: write — to create deployments and deployment statuses
  • Commit statuses: write — to create commit statuses

Configuration

GitHub reporting is configured entirely via environment variables.

Minimal setup

# docker-compose.yml
services:
  deeplo:
    environment:
      DEEPLO_GITHUB_WEBHOOK_SECRET_FILE: /run/secrets/github_webhook_secret
      DEEPLO_GITHUB_TOKEN_FILE: /run/secrets/github_token
    secrets:
      - github_webhook_secret
      - github_token

With run log serving

# docker-compose.yml
services:
  deeplo:
    environment:
      DEEPLO_GITHUB_WEBHOOK_SECRET_FILE: /run/secrets/github_webhook_secret
      DEEPLO_GITHUB_TOKEN_FILE: /run/secrets/github_token
      DEEPLO_GITHUB_ENVIRONMENT: homelab
      DEEPLO_LOGS_PORT: "8081"
      DEEPLO_LOGS_PUBLIC_URL: "https://logs.example.com"
      DEEPLO_LOG_RETENTION_DAYS: "14"
    secrets:
      - github_webhook_secret
      - github_token

Full env var reference

VariableDefaultDescription
DEEPLO_GITHUB_TOKEN_FILEPath to a file containing a GitHub PAT. Reporting is disabled if unset.
DEEPLO_GITHUB_WEBHOOK_SECRET_FILEPath to a file containing the webhook HMAC secret.
DEEPLO_GITHUB_ENVIRONMENTOptional prefix prepended to the environment name.
DEEPLO_GITHUB_HOST_IN_ENVfalseSet to true to include the host name in the environment (<host>/<project>).
DEEPLO_LOGS_PORTLog server port. Enables GET /runs/{id}/logs when set.
DEEPLO_LOGS_PUBLIC_URLExternally reachable base URL used for GitHub "Details" links.
DEEPLO_LOG_RETENTION_DAYS14Delete log files older than this many days. 0 = keep forever.

Run log endpoint

When DEEPLO_LOGS_PORT is set, each deployment writes a plain-text log to DEEPLO_DATA_DIR/runs/{run_id}.log and exposes it at:

GET /runs/{run_id}/logs
Content-Type: text/plain; charset=utf-8

Run logs are served on their own dedicated listener (DEEPLO_LOGS_PORT), completely separate from the main webhook/API server. This makes it straightforward to expose logs through a separate tunnel or reverse proxy while keeping the webhook port private.

If DEEPLO_LOGS_PUBLIC_URL is set, GitHub "Details" links are automatically populated pointing to {DEEPLO_LOGS_PUBLIC_URL}/runs/{run_id}/logs.

A run log contains:

  • Project, host, commit, branch, trigger source
  • Timestamped step entries (fetching repo, connecting, running compose)
  • Full error output when a step fails

Example:

=== Deploy Run 2026-04-14T18-05-17Z-a3f2bc91 ===
Project:  nginx
Host:     vm-1 (192.168.50.33)
Commit:   24e6285e31328431a674d314746d7aaf8fc80530
Branch:   main
Source:   webhook
Started:  2026-04-14T18:05:17Z

[18:05:17Z] Fetching repository git@github.com:org/repo.git
[18:05:18Z] Commit 24e6285e is available
[18:05:18Z] Extracting bundle from apps/nginx
[18:05:19Z] Connecting to vm-1 (deploy@192.168.50.33:22)
[18:05:19Z] Running docker compose up in /home/jan/deploys/nginx
[18:05:19Z] FAILED: docker compose up

--- Error detail ---
docker compose up: exit status 1 (stderr: invalid hostPort: 40dd82)

[18:05:19Z] Deploy FAILED in 2.047s — Preflight failed on vm-1

Security note

The run log endpoint is unauthenticated and serves plain text. Run logs may contain host addresses, project names, and partial error output.

Recommended approaches:

  • Run the daemon on a private network and only expose the webhook port externally
  • Place a reverse proxy in front that adds authentication to /runs/
  • If using a VPN or firewall, restrict access to the internal network

The endpoint validates all run IDs against a strict format to prevent path traversal and does not serve directory listings.


Failure behavior

Reporting failures never affect the actual deploy result:

  • If the GitHub API is unreachable, the deploy still runs normally.
  • Reporting errors are logged and stored in the deployment record (github_report_error field).
  • deeplo status shows error in the GH DEPLOY column when reporting failed.
  • A failure to write a run log is logged at WARN level; the deploy continues.

deeplo status with reporting enabled

PROJECT  HOST   STATUS   COMMIT   TRIGGER  GH ENV       GH DEPLOY  STARTED
-------  ----   ------   ------   -------  ------       ---------  -------
nginx    vm-1   success  24e6285e webhook  nginx        success    2026-04-14T18:07:20Z
whoami   vm-1   success  eecbbdc4 webhook  vm-1/whoami  success    2026-04-14T18:05:17Z
whoami   vm-2   failed   eecbbdc4 webhook  vm-2/whoami  failure    2026-04-14T18:05:17Z

Mounting the token in Docker Compose

services:
  deeplo:
    ports:
      - "8080:8080"
    secrets:
      - github_webhook_secret
      - github_token

secrets:
  github_webhook_secret:
    file: ./secrets/github_webhook_secret
  github_token:
    file: ./secrets/github_token

On this page