π Deploy Playbook
TrueBalance Γ TrueCredits Hackathon Β· June 11β12, 2026 Β· all teams
hackathon-NN) and one public domain
(https://<team-slug>.hackathon.afinit.dev, TLS included).Run anything that listens on port
8080 of your EC2 β it is live on your domain immediately.
No load balancer config, no DNS, no tickets. Until then your domain shows your team's
"warming up" page; the moment something answers on :8080 it becomes your app.1 Β· Your kit
| EC2 | hackathon-NN (NN = your team number). Verify which box is yours: https://<slug>.hackathon.afinit.dev/__hk |
|---|---|
| Domain | https://<team-slug>.hackathon.afinit.dev β your EC2 port 8080. Find yours & watch it live: hackathon.afinit.dev/preview |
| Spec | 4 vCPU / 15 GB RAM / 50 GB disk Β· Amazon Linux 2023 Β· docker + compose + git preinstalled |
| SSH | ssh -i hackathon2026.pem ec2-user@<public-ip> β pem + IP list via Slack / your team room Β· #temp_hackathon_infra β EC2 inventory thread |
2 Β· Deploy β pick any recipe
A. Docker (recommended)
docker run -d --name app --restart unless-stopped -p 8080:8080 <your-image>
# app on another internal port? map it: -p 8080:3000 (Node), -p 8080:80 (nginx frontend)
B. docker compose β only ONE service publishes 8080 (the front door); internal services talk container-to-container, no ports: needed
services:
web: { build: ., ports: ["8080:3000"], restart: unless-stopped }
api: { build: ./api, restart: unless-stopped } # reach as http://api:<port>
C. Bare process
nohup python3 -m uvicorn main:app --host 0.0.0.0 --port 8080 > app.log 2>&1 &
# node/java: sudo dnf install -y nodejs / java-21-amazon-corretto
Getting code onto the box: github.com, Docker Hub, npm, pip, Maven all work.
β οΈ GHE (github.balancehero.cc) is NOT reachable from these hosts β
scp your code from your laptop, or mirror to github.com.
3 Β· Verify (60 seconds)
curl -s localhost:8080/ # 1. app answers locally
curl -s localhost/ # 2. through the on-host ingress
curl -s localhost/__hk # 3. confirms which team box you are on
If (1) works, https://<slug>.hackathon.afinit.dev works.
4 Β· Rules of the road
- Port 8080 is the only front door. Other published ports are blocked from the internet by the host firewall. Internal ports between your own containers are fine.
- Don't touch the plumbing: the
hk-ingresscontainer (port 80),komodo-periphery,vector(log collection, Β§7) and thehk-firewallservice keep your domain alive. Don't stop or "clean up" these. - HTTPS is terminated for you β your app sees plain HTTP on 8080 (
X-Forwarded-Proto: https). WebSockets work; single requests over ~60 s may be cut by proxy timeouts. - Database β pick the lightest option that fits:
- Team-private MySQL on your own box (recommended) β full freedom, zero cross-team conflicts, gone with the box:
docker run -d --name teamdb --restart unless-stopped -p 127.0.0.1:3306:3306 -e MYSQL_ROOT_PASSWORD=hackathon -e MYSQL_DATABASE=app -v ~/teamdb:/var/lib/mysql mysql:8.4
Reach it at127.0.0.1:3306(or as a composedbservice, noports:). The host firewall keeps it team-private by default. - Need existing TB/TC/MF/LG data in it? Seed from the hackathon RDS (endpoint in your team room), no client install needed:
docker run --rm mysql:8.4 mysqldump -h <rds-endpoint> -u <user> -p'<pw>' --single-transaction --set-gtid-purged=OFF <db> | docker exec -i teamdb mysql -uroot -phackathon app
Or use the db-stage-clone bundle from Slack: skipsetup.sh(laptop helper), rundocker compose up --build -dβ but first pointSTAGE_DB_HOST(+ user/password) in itsdocker-compose.ymlat the hackathon RDS; its default targets the real stage DB, which is cut during the event. TC only by default, port:3307. - Shared hackathon RDS β direct use only if you need a DB shared across machines. New tables with an
h_prefix; don't alter/drop what you didn't create. Discarded after the event.
- Team-private MySQL on your own box (recommended) β full freedom, zero cross-team conflicts, gone with the box:
- Vendor APIs (PayU Β· Razorpay Β· CIBIL Β· Experian): via mock-api-proxy β setup in your team room.
- Push your code to a remote you keep β EC2 and DB are reclaimed after the event.
5 Β· Slack login for your domain (optional, self-service)
Your domain is public by default. Want it gated behind company Slack? Flip it yourself at hackathon.afinit.dev/authctl β everyone in the workspace (participants, judges, ops) can still get in after signing in.
- Domain toggle: require Slack login β make public β takes effect in seconds.
- Path exceptions (max 5, wildcards
*/?) get the opposite of the domain setting β e.g. AUTH ON +/api/*= UI locked, API open for callbacks. - Machines (cron, other boxes, stage services) can always skip auth via port
:8443β same routing, no login, VPC/hackathon source IPs only. - Every change is logged with your Slack identity and announced β only touch your own
team's row. Use the
authtestsandbox row to try it out. Sign-in lasts 24 h per domain. - Path exceptions are convenience, not a security boundary β validate real secrets in your app.
6 Β· What you can (and can't) reach from your box
Verified from all 30 boxes β where a login exists, the network is open but you still sign in with your own account.
| β Reachable | Address | Note |
|---|---|---|
| Kibana β stage app logs | stage-applog-kibana.balancehero.cc | login required |
| Kibana β prod app logs | prod-applog-kibana.balancehero.cc | temporary routeΒΉ Β· prod β look, don't touch |
| JupyterHub | jupyterhub.balancehero.cc | temporary routeΒΉ Β· login required |
| Nexus (private Java deps) | nexus.truebalance.cc:443 | for building TB/TC backend services |
| stage infra services | memcached Β· egress-proxy etc. | VPC direct β for stage-stack replicas |
| mock-api-proxy | endpoint in your team room | PayU Β· Razorpay Β· CIBIL Β· Experian mocks |
| public internet (egress) | β | unrestricted β npm, pip, Docker Hub, github.com |
| β Not reachable (by design) | Why |
|---|---|
GHE (github.balancehero.cc) | IP allowlist β use github.com or scp (Β§2) |
| prod services / prod DB endpoints | Policy: stage only, no prod data (prod Kibana is the single read-only exception) |
ΒΉ Temporary route set up for the event β if these stop responding, don't debug it, ping
#temp_hackathon_infra (your domain, DB and stage Kibana are unaffected).
Stage DBs: directly reachable today, but use your team-private MySQL or the temporary
hackathon RDS (Β§4) β direct access to the real stage DBs is being cut intentionally; if a
direct DB connection stops working, switch to your team DB / the hackathon RDS endpoint,
don't file a bug.
7 Β· Logs & troubleshooting
Your logs β nearest first: β docker logs -f app on the box.
β‘ Central log search: everything your containers print to stdout/stderr is collected
automatically (nothing to set up) β open
stage Kibana, sign in with your own
account β Discover β data view "Hackathon team logs" β filter
team: <your-slug>. β’ Bare process? Log to ~/app.log (recipe C
already does) β collected too. JSON lines become searchable fields; bursts over ~200 lines/s per
container are dropped from central search only (docker logs keeps everything).
| Symptom | Fix |
|---|---|
| Domain still shows "warming up" page | Nothing on 8080: curl localhost:8080, docker ps, docker logs app |
| localhost:8080 works, domain doesn't | Wrong box β curl localhost/__hk must show your slug |
| App was live, team page is back | App crashed (the page is the automatic fallback) β docker logs app |
| "port already in use" on 8080 | Your own old process holds it: ss -tlnp | grep 8080. Port 80 busy is normal (ingress β leave it) |
| Long request dies ~60 s | Proxy timeout β stream, poll, or use WebSocket |
| Can't clone from GHE | Expected (blocked) β use github.com or scp |
Still stuck β Slack #temp_hackathon_infra (Neal Β· David Β· Dharmendra) Β· floor support: Sagar +1.