Skip to main content

Diagnose Nginx, SSL, Docker, DNS, ports, and web app deployment problems from one CLI.

Project description

DeployDoctor

CI PyPI Python License: MIT Code style: Ruff Tests: pytest

When your site is down at 2 a.m., DeployDoctor is the one command that tells you what is actually broken.

deploydoctor is a small, no-magic CLI that runs the checks you would otherwise run by hand when a deployment goes sideways — DNS, HTTP/HTTPS, TLS certificates, port reachability, and the usual suspects on the host itself (nginx -t, ss -tulpn, docker ps, nginx error logs).

Output is a single readable Rich report with PASS / WARN / FAIL / SKIP markers, a summary, the most likely issue, and a set of copy-pasteable next commands.

Demo

DeployDoctor demo

Install

pip install deploydoctor

Or with pipx (recommended for CLI tools):

pipx install deploydoctor

Development (editable install with linter + tests):

git clone https://github.com/saidamiraslanli/deploydoctor.git
cd deploydoctor
pip install -e ".[dev]"

Python 3.11+.

Quick usage

deploydoctor check example.com       # full diagnosis: remote + local
deploydoctor remote example.com      # external-only: DNS, HTTP, HTTPS, SSL, ports
deploydoctor local                   # this host: nginx, docker, ss -tulpn
deploydoctor version
deploydoctor --help

# Also runnable as a module
python -m deploydoctor check example.com

A bare hostname (example.com) or a full URL (https://example.com/foo) both work — the host is extracted automatically.

Example output

─────────── DeployDoctor Report for example.com ───────────

╭─ DNS ─────────────────────────────────────────────────────╮
│ PASS  Resolved 1 A / 1 AAAA record(s)                     │
│       • A: 93.184.216.34                                  │
│       • AAAA: 2606:2800:220:1:248:1893:25c8:1946          │
╰───────────────────────────────────────────────────────────╯
╭─ HTTPS ───────────────────────────────────────────────────╮
│ FAIL  502 gateway error                                   │
│       → Possible cause: reverse proxy cannot reach        │
│         upstream app                                      │
│       → sudo systemctl status nginx                       │
│       → sudo tail -n 50 /var/log/nginx/error.log          │
│       → ss -tulpn                                         │
╰───────────────────────────────────────────────────────────╯
╭─ SSL ─────────────────────────────────────────────────────╮
│ WARN  Certificate expires in 12 day(s)                    │
│       • Subject CN: example.com                           │
│       • Issuer: Let's Encrypt R3                          │
│       → Schedule renewal (sudo certbot renew --dry-run)   │
╰───────────────────────────────────────────────────────────╯

                     Summary
┌────────┬──────────┬────────┬─────────┐
│ Passed │ Warnings │ Failed │ Skipped │
├────────┼──────────┼────────┼─────────┤
│   3    │    1     │   1    │    0    │
└────────┴──────────┴────────┴─────────┘

More worked examples in docs/examples/:

What problems it detects

Layer Detected
DNS NXDOMAIN, missing A/AAAA, resolver timeouts
HTTP / HTTPS connection refused, connect/read timeouts, too many redirects, SSL verification failures, 4xx, 5xx, 502 / 503 / 504 gateway errors, Cloudflare 525 SSL handshake failures, redirect chains
SSL / TLS expired certs, certs expiring within 30 days, verify failures, missing chain, hosts without TLS
Ports 80 / 443 closed, filtered, refused, or timing out from outside
Local host (Linux) nginx config syntax (nginx -t), listening sockets (ss -tulpn), nginx error log tail, running Docker containers, missing tools

Local vs remote mode

DeployDoctor exposes two scopes deliberately:

  • remote <domain>outside view. Everything runs over the network: DNS, HTTP, HTTPS, SSL, port probes. Safe to run from a laptop or from a monitoring host. Does not touch the deployment host.
  • localinside view. Inspects the host you run it on: is nginx installed, is its config valid, what is listening, what does the error log say, what Docker containers are running. Linux-only by design; cleanly SKIPs on Windows / macOS or when commands and permissions are missing.
  • check <domain> — runs both back-to-back, which is what you want when SSHed into the box that serves the domain.

This split exists so you can use the tool from anywhere without the local checks polluting the report with noise.

CI exit codes

Code Meaning
0 All checks passed
1 At least one WARN
2 At least one FAIL

Friendly for cron, CI, uptime scripts:

deploydoctor remote example.com || curl -X POST https://my-alert-hook
# GitHub Actions example
- name: Post-deploy smoke check
  run: deploydoctor remote example.com

Roadmap

  • HTTP/2 + HTTP/3 capability probe
  • TLS handshake details (protocol, cipher, OCSP stapling)
  • Configurable check timeouts via CLI flag
  • JSON output mode (--json) for piping into other tools
  • systemd unit health checks (is-active, is-failed)
  • Apache / Caddy parity for local config tests
  • deploydoctor watch for continuous monitoring

Troubleshooting

  • nginx -t reports permission denied — run with sudo; DeployDoctor will surface SKIP rather than fail.
  • All local checks SKIP — local checks are gated to Linux. Run on the deployment host.
  • SSL check is SKIP — port 443 refused; the domain likely doesn't serve TLS.
  • DNS timeout — typically a firewall blocking UDP/53 on the host running the CLI.

Contributing

Pull requests welcome. See CONTRIBUTING.md for setup, lint / test commands, and the rules every new check must follow.

Quick start:

git clone https://github.com/saidamiraslanli/deploydoctor.git
cd deploydoctor
pip install -e ".[dev]"
pytest
ruff check .

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deploydoctor-0.1.2.tar.gz (206.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deploydoctor-0.1.2-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file deploydoctor-0.1.2.tar.gz.

File metadata

  • Download URL: deploydoctor-0.1.2.tar.gz
  • Upload date:
  • Size: 206.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for deploydoctor-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b502f8234af71919d128b7de07468d1d6b2bb77adaf7bd61c4e83afa9fa52ed4
MD5 d42508c369f5f7cf60b50f1245467808
BLAKE2b-256 b8847139530ca794455d78ff0ece5eff148d2ee8cba567c66555f3677ef5c87d

See more details on using hashes here.

Provenance

The following attestation bundles were made for deploydoctor-0.1.2.tar.gz:

Publisher: workflow.yml on saidamiraslanli/deploydoctor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deploydoctor-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: deploydoctor-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for deploydoctor-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d9c174a8224f61343b7653f6fcf7961d77799ba510830e7d08562243bbe1f4ea
MD5 f4e2b3ef3416ce3bd6f06e8f8ef9a989
BLAKE2b-256 8d8e3ea6eaf4b51eee2e70231fda7dadf12df43dc4b349d584c0c1aa38b98879

See more details on using hashes here.

Provenance

The following attestation bundles were made for deploydoctor-0.1.2-py3-none-any.whl:

Publisher: workflow.yml on saidamiraslanli/deploydoctor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page