Skip to content

About

REST API for tracking habits — built to learn Docker, CI/CD, and AWS deployment end to end.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

DevTrack API

A backend API for a habit-tracking app to create habits, mark them complete, track streaks and stats.

The app logic is intentionally simple: a handful of CRUD endpoints. The actual point of this project was learning how software gets deployed and kept running in production — containers, CI/CD, a real cloud server, and the operational systems (migrations, backups, secrets, dynamic firewalls, health checks) that most tutorials skip.

Live: https://devtrack.vishwajitmohol.me/docs
(Note: To optimize AWS billing, this EC2 instance is run ephemerally and is not kept online 24/7. The deployment engine and infrastructure code detailed below serve as the primary proof of execution.)

Stack

Layer Choice
API FastAPI + Pydantic
Database PostgreSQL 15, SQLAlchemy ORM, Alembic migrations
Auth JWT (stateless), bcrypt password hashing
Containers Docker, multi-stage build
Host Single AWS EC2 instance (Ubuntu), Docker Compose
Reverse Proxy Nginx, TLS via Let's Encrypt (Certbot)
CI/CD GitHub Actions

Note on infrastructure: Deploying to a single EC2 instance, rather than a cluster, was a deliberate constraint. The goal was to actually understand container orchestration and Linux server administration from first principles before reaching for higher-level abstractions.

Architecture

flowchart LR
    Client -->|HTTPS| Nginx[Nginx\nTLS termination]
    Nginx --> API[FastAPI container]
    API --> DB[(PostgreSQL)]

    GH[GitHub Actions] -->|build + push, tag = git SHA| GHCR[(GHCR)]
    GH -->|SSH deploy trigger| EC2[EC2 host]
    GHCR -->|pull| EC2
    EC2 -.contains.-> Nginx
    EC2 -.contains.-> API
    EC2 -.contains.-> DB
Loading

The application logic is a straightforward CRUD implementation for users, habits, and completions.

Interactive Swagger documentation (auto-generated by FastAPI) is available at: https://devtrack.vishwajitmohol.me/docs


The Deployment Engine (CI/CD)

On push to main:

  1. Gate: Lint (ruff) and tests run.
  2. Artifact: If green, the Docker image is built (multi-stage), tagged with the git commit SHA, and pushed to GHCR.
  3. Firewall: Deploy job whitelists the GitHub runner's IP in the EC2 security group (runner IPs are ephemeral, so this is executed dynamically per run).
  4. Pre-Deployment Backup: A pg_dump snapshot is taken and shipped to S3, ensuring a bad schema migration doesn't destroy live data.
  5. State Mutation: SSH into the server, run the Alembic migration against the live DB, pull the new image, and execute docker compose up -d.
  6. Telemetry: Health check is polled after restart — the deploy pipeline fails loudly if the system doesn't come back healthy.
  7. Perimeter Seal: Runner's IP is revoked from the security group, regardless of whether the deployment succeeded or failed.

Getting Started

Prerequisites: Docker and Docker Compose.

# 1. Clone the repository
git clone https://github.com/Vishwajit1610/DevTrack-API.git
cd DevTrack-API

# 2. Configure environment variables
cp .env.example .env

# 3. Boot the environment
docker compose up --build

# 4. Apply database migrations
docker compose run --rm api alembic upgrade head

The API base URL is http://localhost:8000 (e.g., http://localhost:8000/api/v1/habits). Interactive Swagger docs are at http://localhost:8000/docs.

Environment Variables

Variable Purpose
DATABASE_URL Postgres connection string
POSTGRES_PASSWORD Local Postgres container password
JWT_SECRET_KEY Signs auth tokens — generate your own, do not reuse the example

(See .env.example for the full list.)

Known Limitations / What's Next

Being upfront about what this system doesn't do yet:

  • Downtime Deploys: Deploys aren't zero-downtime. Container restarts mean a short gap. Blue-green routing (two containers + traffic switch) would fix this and is planned.
  • Manual Rollbacks: If a deploy goes bad, rollback requires manually re-running the workflow against the previous image tag. It works, but it isn't automatic.
  • Test Depth: CI runs pytest against an in-memory SQLite DB, which is fast but misses Postgres-specific behaviors. Integration tests against a real Postgres container are required ahead of any new feature.
  • No Caching Layer: Redis is scoped (cache /stats and /streak, invalidate on completion) but not yet built.
  • No Observability: Prometheus + Grafana is the next infrastructure piece after test coverage.
  • CORS Restrictions: CORS is currently scoped to local dev origins only (localhost:3000/5173) and needs updating once a frontend is deployed.

About

REST API for tracking habits — built to learn Docker, CI/CD, and AWS deployment end to end.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages