Skip to content

feat(deploy): EC2 deployment — Caddy, sslip.io TLS, deploy script, DEPLOYMENT.md - #4

Merged
DevSolex merged 1 commit into
mainfrom
feat/ec2-deployment
Sep 28, 2026
Merged

DevSolex merged 1 commit into
mainfrom
feat/ec2-deployment

Conversation

@devkryssie

Copy link
Copy Markdown
Collaborator

Summary

Replaces ngrok with a stable single-instance EC2 deployment using Caddy for automatic HTTPS.

Files

docker-compose.prod.yml — production overlay:

  • Adds Caddy service (auto-TLS via Let's Encrypt)
  • Removes direct host port bindings from checkout/messaging (Caddy handles public traffic)
  • Adds caddy_data and caddy_config volumes for certificate persistence

Caddyfile — path-based routing:

  • /webhooks/whatsapp* → messaging:8002
  • /webhooks/paystack → settlement-engine:8000
  • /* → checkout:8001
  • settlement-engine's internal endpoints (/merchants, /links, /internal/*) are never publicly routed (OQ-022 preserved)

deploy.sh — repeatable redeploy over SSH: git pull + build + up -d + health checks

scripts/ec2_setup.sh — one-shot instance provisioning: Docker install, repo clone, ufw rules (22/80/443 only)

DEPLOYMENT.md — complete step-by-step guide covering:

  • EC2 launch + security group config
  • sslip.io hostname derivation from IP
  • Elastic IP tradeoff (documented)
  • Permanent WhatsApp System User token (vs 24h temp token)
  • Stack startup, webhook URL update in Paystack + Meta dashboards
  • Redeploy procedure
  • What happens on instance restart without Elastic IP

.env.example — adds PUBLIC_HOSTNAME, RATE_LIMIT_* vars

Design choice: manual setup, not Terraform

Single instance that won't be replicated at this stage. Terraform adds ~200 lines and an init dependency for no benefit here. Document revisit when multi-instance is needed.

What 'done' looks like

Stack running on EC2, HTTPS working at sslip.io hostname, webhooks updated, full WhatsApp → Paystack → ledger loop verified over the real domain.

…PLOYMENT.md

Single-instance EC2 deployment that replaces ngrok for stable testing.

Files added:
  docker-compose.prod.yml — production overlay: adds Caddy service, removes
    direct host ports from checkout/messaging (Caddy handles public traffic)
  Caddyfile — routes by path: /webhooks/whatsapp → messaging,
    /webhooks/paystack → settlement-engine, /* → checkout.
    settlement-engine's internal endpoints (/merchants, /links) are never
    publicly routed (OQ-022 preserved).
  deploy.sh — git pull + build + up over SSH, with health checks
  scripts/ec2_setup.sh — one-shot instance provisioning: Docker install,
    repo clone, ufw rules (22/80/443 only)
  DEPLOYMENT.md — step-by-step: EC2 launch, sslip.io hostname derivation,
    Elastic IP tradeoff, .env setup (incl. permanent WhatsApp token note),
    stack start, webhook URL updates, redeploy, teardown
  .env.example — adds PUBLIC_HOSTNAME, RATE_LIMIT_* vars

Approach: documented manual setup (not Terraform). Reason: single instance
that won't be replicated; Terraform adds complexity without benefit here.
Revisit when multi-instance or IaC is needed.
@DevSolex
DevSolex merged commit eebda23 into main Sep 28, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants