Chirp is a Twitter-like blogging platform built as part of the ITU BSc Software Development & DevDevOps, Software Evolution and Software Maintenance courses .
The app is deployed on DigitalOcean using Docker Swarm and is live at https://itu-minitwit.duckdns.org.
- Post, view, and delete cheeps (messages up to 160 characters)
- Follow / unfollow other users with a personalised timeline
- OAuth sign-in via GitHub, Google, Facebook, and Microsoft Account
- Simulator-compatible REST API (
/register,/msgs,/fllws,/latest) - Real-time metrics with Prometheus + Grafana dashboards
- Centralised log aggregation with Loki and Grafana Alloy
- Horizontal scaling via Docker Swarm (2 app replicas)
| Layer | Technology |
|---|---|
| Web framework | ASP.NET Core 8 (Razor Pages) |
| Language | C# (.NET 8) |
| Database | PostgreSQL 16 |
| Cache / session store | Redis 7 |
| ORM | Entity Framework Core 8 (Npgsql) |
| Containerisation | Docker + Docker Swarm |
| Monitoring | Prometheus, Grafana, Loki, Grafana Alloy |
| CI/CD | GitHub Actions |
| Hosting | DigitalOcean (Docker Swarm) |
ITU-MiniTwit/
├── src/
│ ├── Chirp.Core/ # Domain models and interfaces
│ ├── Chirp.Infrastructure/ # EF Core repositories and services
│ └── Chirp.Web/ # ASP.NET Razor Pages app + REST API
├── test/
│ ├── UnitTests/
│ ├── IntegrationTests/
│ └── End2End/ # Playwright browser tests
├── scripts/
│ ├── provision_itu_minitwit.sh # Spin up a DigitalOcean droplet
│ ├── bootstrap.sh # Install Docker on a fresh droplet
│ └── deploy.sh # Pull and restart containers
├── monitoring/ # Prometheus, Loki, Grafana, Alloy configs
├── docker-compose.yml # Local development compose file
├── docker-stack.yml # Production Swarm stack (app + Redis)
├── docker-stack.monitoring.yml # Production Swarm stack (monitoring)
└── Dockerfile # Multi-stage build for the web app
The production system runs on DigitalOcean as a Docker Swarm cluster.
Internet → itu-minitwit.duckdns.org
│
Docker Swarm manager
├── minitwit stack
│ ├── itu-minitwit (2 replicas, port 5001)
│ ├── redis (session store)
│ └── node-exporter
└── monitoring stack
├── prometheus (port 9090)
├── grafana (port 3000)
├── loki (port 3100)
└── alloy (log collector, global mode)
All automation lives in .github/workflows/.
| Workflow | Trigger | What it does |
|---|---|---|
CI.yml |
Push to main, PRs |
Build → unit/integration tests → E2E tests → SonarCloud → Trivy image scan |
CD.yml |
CI passes on main |
Build & push Docker image → deploy Swarm stack → deploy monitoring stack |
WeeklyRelease.yml |
week* tags |
Tag-based release automation |
WeeklyHostUpdate.yml |
Schedule | Automated host OS updates |
The CD pipeline:
- Builds and pushes a Docker image tagged with the git SHA to Docker Hub.
- SSHs into the swarm manager and writes the production
.env(from GitHub secrets). - Deploys
docker-stack.yml(app + Redis) anddocker-stack.monitoring.yml. - Performs a health check against
https://itu-minitwit.duckdns.org.
Required GitHub secrets: DOCKER_USERNAME, DOCKER_PASSWORD, SSH_HOST_APP2, SSH_USER, SSH_KEY_APP2, DO_CONNECTION_STRING, DO_REDIS_CONNECTION_STRING, SONAR_TOKEN.
Can be found on http://165.245.209.232:3000/.
| Service | URL (production) | Purpose |
|---|---|---|
| Grafana | :3000 |
Dashboards for app metrics and logs |
| Prometheus | :9090 |
Metrics scraping and storage |
| Loki | :3100 |
Log aggregation |
| Grafana Alloy | — | Ships container logs to Loki |
The app exposes a /metrics endpoint (Prometheus format) and a /health endpoint used by the Swarm healthcheck.
This project is licensed under the MIT License — see LICENSE.md for details.



