Repository: d4-platform-devops
Project: Healthcare Monitoring System
This repository contains the platform, security, deployment, logging, monitoring and integration work for Group D: Healthcare Monitoring System. The main purpose of D4 is to make sure the full healthcare monitoring system can run securely, connect with all other groups, and be monitored properly during testing and deployment.
D4 is not mainly responsible for collecting sensor data, building the AI model, or designing the doctor dashboard. Those parts are handled by D1, D2 and D3.
D4 is responsible for making the full system:
- Secure
- Deployable
- Connected
- Observable
- Maintainable
- Easy to test end-to-end
In simple terms:
D4 makes sure the whole healthcare monitoring system can be started, secured, connected, logged, monitored and tested as one working platform.
The full project is divided into four main groups.
| Group | Area | Main Responsibility |
|---|---|---|
| D1 | Device and Edge Systems | Collect vital signs from wearable or edge devices and send data securely |
| D2 | Data and Intelligence | Analyze time-series data, detect anomalies and generate risk scores |
| D3 | System Engineering and Interaction | Build doctor dashboard, patient interface and alert viewing interface |
| D4 | Platform, Security and Integration | Secure, deploy, monitor and integrate the whole system |
D4 should deliver the following main outputs:
- Dockerized system setup
- Keycloak authentication system
- JWT-based API protection
- Secure environment configuration
- Logging structure
- Prometheus metrics collection
- Grafana monitoring dashboard
- Integration testing with D1, D2 and D3
- Deployment documentation
- Final system run guide
Wearable / Edge Device
|
| Vital signs data
v
MQTT Broker / API Gateway
|
v
Backend API Service <------> Keycloak Authentication
|
v
PostgreSQL Database
|
v
Anomaly Detection Service
|
v
Doctor Dashboard / Patient Interface
Monitoring Layer:
Backend API + Database + Services
|
v
Prometheus
|
v
Grafana
| Area | Tool | Purpose |
|---|---|---|
| Containerization | Docker | Package services into containers |
| Multi-service setup | Docker Compose | Run backend, database, Keycloak, Prometheus and Grafana together |
| Authentication | Keycloak | Login, user management and role-based access control |
| API Security | JWT | Secure backend APIs using access tokens |
| Database | PostgreSQL | Store patient readings, users, alerts and system data |
| Metrics | Prometheus | Collect system and application metrics |
| Dashboards | Grafana | Visualize system health and metrics |
| Logging | Backend logger / Docker logs | Track important system events and errors |
| Deployment | Docker / optional Kubernetes | Run the system on another machine or server |
A recommended structure for this repository is shown below.
d4-platform-devops/
│
├── README.md
├── docker-compose.yml
├── .env.example
├── .gitignore
│
├── docs/
│ ├── architecture.md
│ ├── authentication.md
│ ├── deployment.md
│ ├── monitoring.md
│ ├── logging.md
│ ├── security.md
│ └── testing.md
│
├── keycloak/
│ ├── realm-export.json
│ └── README.md
│
├── prometheus/
│ ├── prometheus.yml
│ └── README.md
│
├── grafana/
│ ├── dashboards/
│ │ └── healthcare-monitoring-dashboard.json
│ ├── provisioning/
│ │ ├── dashboards/
│ │ └── datasources/
│ └── README.md
│
├── scripts/
│ ├── start.sh
│ ├── stop.sh
│ ├── reset.sh
│ └── test-health.sh
│
└── tests/
├── auth-test.md
├── integration-test.md
└── security-test.md
This exact structure can be changed later depending on how D1, D2 and D3 organize their repositories.
The full system may include these services.
| Service | Description | Owner |
|---|---|---|
| Backend API | Receives vitals, stores data and exposes APIs | D2 / D4 integration |
| Frontend Dashboard | Doctor or patient interface | D3 / D4 integration |
| PostgreSQL | Main database | D4 |
| Keycloak | Authentication and user roles | D4 |
| Prometheus | Metrics collector | D4 |
| Grafana | Monitoring dashboard | D4 |
| MQTT Broker | Receives device data from D1 | D1 / D4 integration |
| AI Service | Detects anomalies and risk level | D2 / D4 integration |
Dockerization means packaging each service so that the system can run without manually installing many dependencies.
Minimum required services:
backend
frontend
postgres
keycloak
prometheus
grafana
Optional services:
mqtt-broker
anomaly-detection-service
nginx-reverse-proxy
The final docker-compose.yml should follow a structure similar to this.
version: "3.9"
services:
postgres:
image: postgres:16
container_name: hms-postgres
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- hms-network
keycloak:
image: quay.io/keycloak/keycloak:latest
container_name: hms-keycloak
restart: unless-stopped
command: start-dev
environment:
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
ports:
- "8080:8080"
networks:
- hms-network
prometheus:
image: prom/prometheus:latest
container_name: hms-prometheus
restart: unless-stopped
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
- hms-network
grafana:
image: grafana/grafana:latest
container_name: hms-grafana
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER}
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD}
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
networks:
- hms-network
volumes:
postgres_data:
grafana_data:
networks:
hms-network:
driver: bridgeThis is a base structure. Backend, frontend, MQTT and AI services can be added after D1, D2 and D3 finalize their service details.
Create a .env.example file like this.
# PostgreSQL
POSTGRES_DB=healthcare_monitoring
POSTGRES_USER=hms_user
POSTGRES_PASSWORD=change_this_password
# Keycloak
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=change_this_password
KEYCLOAK_REALM=healthcare-monitoring
KEYCLOAK_CLIENT_BACKEND=hms-backend
KEYCLOAK_CLIENT_FRONTEND=hms-dashboard
# JWT
JWT_ISSUER=http://localhost:8080/realms/healthcare-monitoring
JWT_AUDIENCE=hms-backend
# Grafana
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=change_this_password
# Backend
BACKEND_PORT=5000
FRONTEND_PORT=3001Important rule:
Never commit the real
.envfile to GitHub.
Only commit .env.example.
Authentication means verifying who the user is.
Authorization means deciding what that user is allowed to do.
D4 should implement authentication using Keycloak.
Create one Keycloak realm:
healthcare-monitoring
A realm is like a separate authentication space for this project.
Create clients for the services that need login.
| Client | Purpose |
|---|---|
hms-backend |
Backend API token validation |
hms-dashboard |
Doctor or patient dashboard login |
hms-mobile-app |
Optional patient mobile app login |
Create the following roles:
| Role | Purpose |
|---|---|
PATIENT |
Can view only own health data |
DOCTOR |
Can view assigned patients and alerts |
ADMIN |
Can manage users and system settings |
| Feature | Patient | Doctor | Admin |
|---|---|---|---|
| View own vitals | Yes | No | Yes |
| View assigned patient vitals | No | Yes | Yes |
| View all system users | No | No | Yes |
| View alerts | Own only | Assigned patients | All |
| Manage users | No | No | Yes |
| View monitoring dashboard | No | Optional | Yes |
| Change system configuration | No | No | Yes |
The login and API access flow should work like this.
1. User opens dashboard
2. Dashboard redirects user to Keycloak login
3. User enters username and password
4. Keycloak returns an access token
5. Dashboard sends API requests with the access token
6. Backend validates the token
7. Backend checks the user role
8. Backend allows or blocks the request
Example API request:
GET /api/patients/P001/vitals
Authorization: Bearer <access_token>Backend must reject requests when:
- Token is missing
- Token is expired
- Token is invalid
- User role is not allowed
- User is trying to access another patient without permission
| Route | Allowed Role |
|---|---|
GET /api/patients/me |
PATIENT |
GET /api/patients/{id}/vitals |
DOCTOR, ADMIN, assigned PATIENT |
GET /api/alerts |
DOCTOR, ADMIN |
POST /api/vitals |
Authorized device or backend service |
POST /api/admin/users |
ADMIN |
GET /api/metrics-summary |
ADMIN |
GET /health |
Public or internal only |
GET /metrics |
Prometheus only |
Healthcare systems handle sensitive data. This project may be a university project, but the system should still follow good security practices.
patientId
patient name
age
deviceId
heart rate
temperature
SpO2 level
risk score
alert status
doctor notes
login details
access tokens
- Do not hardcode passwords
- Do not commit
.envfiles - Do not log passwords
- Do not log full JWT tokens
- Do not expose patient data to the wrong role
- Validate all incoming data
- Use HTTPS in production
- Use secure MQTT settings if MQTT is used
- Keep database credentials private
D4 should help define validation rules with D1 and D2.
Example vital sign payload:
{
"patientId": "P001",
"deviceId": "DEV001",
"heartRate": 96,
"temperature": 37.4,
"spo2": 98,
"timestamp": "2026-05-01T10:30:00Z"
}Suggested validation:
| Field | Rule |
|---|---|
patientId |
Required, must match known patient |
deviceId |
Required, must match registered device |
heartRate |
Must be within realistic range |
temperature |
Must be within realistic range |
spo2 |
Must be between 0 and 100 |
timestamp |
Required, valid date-time format |
Invalid data should be rejected before saving to the database.
If D1 uses MQTT, D4 should help secure it.
Recommended MQTT rules:
- Disable anonymous publishing
- Use username and password for devices
- Use separate topics for each patient or device
- Validate device ID in backend
- Do not trust incoming device data blindly
- Use TLS if possible
Example topics:
hms/devices/DEV001/vitals
hms/devices/DEV002/vitals
hms/patients/P001/alerts
Logging means recording important events so the team can debug problems.
The backend should log:
- Server started
- Database connected
- User login success or failure
- Unauthorized API access attempt
- New vital signs received
- Invalid data rejected
- Anomaly detected
- Alert generated
- Alert sent to dashboard
- API error
- Database error
[INFO] Backend server started on port 5000
[INFO] Database connected successfully
[INFO] Vitals received for patientId=P001 deviceId=DEV001
[WARN] Invalid temperature rejected for patientId=P001
[WARN] Unauthorized access attempt on /api/admin/users
[ERROR] Database insert failed for vitals record
[ERROR] Login failed for username=nimal password=123456
[INFO] JWT token = eyJhbGciOiJIUzI1NiIsInR5cCI...
Do not log passwords or full access tokens.
Prometheus collects system and application metrics.
The backend should expose a /metrics endpoint.
Example metrics:
http_requests_total
http_request_duration_seconds
backend_errors_total
vitals_received_total
invalid_vitals_total
alerts_generated_total
active_patients_total
anomalies_detected_total
Create prometheus/prometheus.yml.
global:
scrape_interval: 15s
scrape_configs:
- job_name: "hms-backend"
static_configs:
- targets: ["backend:5000"]
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]Update the target after the backend service name and port are finalized.
Each service should have a simple health check.
Recommended backend route:
GET /healthExample response:
{
"status": "ok",
"database": "connected",
"timestamp": "2026-05-01T10:30:00Z"
}Health checks help confirm whether the system is running correctly.
Grafana should be used to visualize metrics collected by Prometheus.
System-level panels:
- Backend status
- API request count
- API error count
- API response time
- Database connection status
- CPU usage
- Memory usage
Healthcare-specific panels:
- Total vital signs received
- Invalid data count
- Active patients
- Alerts generated
- Anomalies detected
- Device disconnection count
The actual medical alert logic belongs mostly to D2 and D3. However, D4 should support alert delivery, logging and security.
D4 responsibilities related to alerts:
- Secure alert APIs
- Log alert events
- Ensure only authorized users can view alerts
- Provide metrics for alert counts
- Support dashboard real-time alert delivery if needed
Example alert data:
{
"alertId": "A001",
"patientId": "P001",
"type": "HIGH_HEART_RATE",
"severity": "HIGH",
"message": "Heart rate is above the safe threshold",
"timestamp": "2026-05-01T10:40:00Z"
}D1 handles device and edge systems.
D4 must coordinate with D1 to finalize:
- Device ID format
- Patient ID format
- MQTT topic format
- Vital signs data format
- Device authentication method
- Data validation rules
- Test data generation method
Questions for D1:
1. What sensor values will be sent?
2. What is the exact JSON format?
3. Will data be sent through MQTT, HTTP or both?
4. How often will data be sent?
5. Will each device have a unique device ID?
6. How should invalid sensor readings be handled?
D2 handles data intelligence and anomaly detection.
D4 must coordinate with D2 to finalize:
- Database schema requirements
- Anomaly detection service endpoint
- Risk score format
- Alert generation format
- Metrics for anomaly detection
- Backend integration method
Questions for D2:
1. What input data does the model need?
2. What output does the model produce?
3. Will anomaly detection run as a separate service?
4. Should D2 service expose an API?
5. What fields should be stored in PostgreSQL?
6. How should risk scores be represented?
D3 handles dashboard and user interaction.
D4 must coordinate with D3 to finalize:
- Login flow
- Dashboard protected routes
- API endpoints needed by frontend
- User roles and permissions
- Real-time alert method
- Token handling in frontend
Questions for D3:
1. What pages require login?
2. What pages are for doctors?
3. What pages are for patients?
4. What pages are for admins?
5. Does the dashboard need real-time alerts?
6. How will the frontend store and send the access token?
| Test | Expected Result |
|---|---|
| Login as patient | Patient can access own data |
| Login as doctor | Doctor can access assigned patient data |
| Login as admin | Admin can access admin features |
| Call API without token | Request is rejected |
| Call API with invalid token | Request is rejected |
| Patient tries to access another patient | Request is rejected |
| Test | Expected Result |
|---|---|
| Send sample vitals from D1 | Backend receives data |
| Save vitals to PostgreSQL | Data appears in database |
| D2 analyzes vitals | Risk score or anomaly result is generated |
| Alert is generated | Alert appears in backend |
| D3 dashboard shows data | Doctor can view patient data |
| Prometheus collects metrics | Metrics appear in Prometheus |
| Grafana displays dashboard | Graphs update correctly |
| Test | Expected Result |
|---|---|
| Clone repository on new machine | Repo downloads correctly |
Create .env file |
Environment variables load correctly |
Run docker compose up |
Services start successfully |
| Open Keycloak | Login page works |
| Open Grafana | Dashboard works |
| Open Prometheus | Targets are visible |
| Stop services | Containers stop safely |
git clone https://github.com/Healthcare-Monitoring-System/d4-platform-devops.git
cd d4-platform-devopscp .env.example .envThen edit .env and replace default passwords.
docker compose up -ddocker psdocker compose downUse this only if you want to delete stored database and Grafana data.
docker compose down -v| Service | URL |
|---|---|
| Keycloak | http://localhost:8080 |
| Prometheus | http://localhost:9090 |
| Grafana | http://localhost:3000 |
| PostgreSQL | localhost:5432 |
| Backend API | http://localhost:5000 |
| Frontend | http://localhost:3001 |
Ports may change depending on final backend and frontend setup.
D4 should add these documents inside the docs/ folder.
| File | Purpose |
|---|---|
architecture.md |
Explain full system architecture |
authentication.md |
Explain Keycloak, roles and JWT flow |
deployment.md |
Explain Docker Compose setup |
monitoring.md |
Explain Prometheus and Grafana |
logging.md |
Explain logging rules |
security.md |
Explain secure data handling |
testing.md |
Explain final test cases |
Owner: Person 1
Tasks:
- Identify all services in the full system
- Define data flow between D1, D2, D3 and D4
- Create system architecture diagram
- Define API and MQTT communication points
- Define data ownership between groups
- Confirm integration assumptions with all teams
Owner: Person 1
Tasks:
- Define user roles
- Define role permissions
- Set up Keycloak realm
- Create Keycloak clients
- Create test users
- Configure role mapping
- Add JWT validation plan
- Test login for patient, doctor and admin
- Document authentication flow
Owner: Person 2
Tasks:
- Create base
docker-compose.yml - Add PostgreSQL container
- Add Keycloak container
- Add Prometheus container
- Add Grafana container
- Add backend container after backend is available
- Add frontend container after dashboard is available
- Add shared Docker network
- Add persistent volumes
- Test full startup
Owner: Person 2
Tasks:
- Define sensitive data
- Create
.env.example - Add
.envto.gitignore - Move secrets to environment variables
- Define input validation rules
- Define MQTT security rules
- Define database security rules
- Document secure handling practices
Owner: Person 3
Tasks:
- Define logging requirements
- Define log levels
- Add backend logging plan
- Add authentication event logs
- Add vital data event logs
- Add error logs
- Ensure sensitive data is not logged
- Document logging examples
Owner: Person 3 and Person 4
Tasks:
- Add Prometheus to Docker Compose
- Create
prometheus.yml - Define backend
/metricsendpoint requirements - Define metrics names
- Track API requests
- Track errors
- Track vitals received
- Track alerts generated
- Test Prometheus target status
Owner: Person 4
Tasks:
- Add Grafana to Docker Compose
- Connect Grafana to Prometheus
- Create system monitoring dashboard
- Create healthcare metrics dashboard
- Add API request panel
- Add error count panel
- Add vitals count panel
- Add alert count panel
- Export dashboard JSON
Owner: Person 5
Note: Medical alert logic is mainly D2 and D3. D4 only supports alert security, delivery, logging and monitoring.
Tasks:
- Define alert data format with D2 and D3
- Secure alert APIs
- Add alert metrics
- Add alert logs
- Test alert visibility by role
- Document alert integration flow
Owner: Person 5
Tasks:
- Test D1 to backend data flow
- Test backend to database flow
- Test D2 anomaly detection flow
- Test backend to D3 dashboard flow
- Test Keycloak login
- Test JWT protected APIs
- Test Prometheus metrics
- Test Grafana dashboard
- Record final test results
Owner: Person 5
Tasks:
- Write setup guide
- Write deployment guide
- Write authentication guide
- Write monitoring guide
- Write security guide
- Write integration testing guide
- Add screenshots where needed
- Prepare final presentation points for D4
Before final submission, confirm these points.
[ ] System starts using docker compose up
[ ] PostgreSQL container runs correctly
[ ] Keycloak login works
[ ] Patient, doctor and admin roles exist
[ ] Backend rejects invalid JWT tokens
[ ] Backend protects role-based API routes
[ ] Environment variables are used for secrets
[ ] Logs show important system events
[ ] Sensitive data is not exposed in logs
[ ] Prometheus collects metrics
[ ] Grafana displays dashboard panels
[ ] D1 sample data reaches backend
[ ] D2 anomaly result is received
[ ] D3 dashboard can show patient data or alerts
[ ] Final documentation is complete
Check logs:
docker compose logsCheck if ports are already used:
sudo lsof -i :8080
sudo lsof -i :3000
sudo lsof -i :5432Check whether the Keycloak container is running:
docker psCheck Keycloak logs:
docker compose logs keycloakInside Docker Compose, Grafana should use the service name:
http://prometheus:9090
Not:
http://localhost:9090
Inside Docker Compose, backend should connect using the service name:
postgres
Not:
localhost
Example database host:
DB_HOST=postgresRecommended workflow:
git pull origin main
git checkout -b feature/keycloak-setup
# Make changes
git add .
git commit -m "Add Keycloak setup documentation"
git push origin feature/keycloak-setupThen create a pull request to merge into main.
- Keep secrets out of GitHub
- Use clear commit messages
- Update documentation when configs change
- Test Docker Compose before pushing
- Use meaningful file names
- Do not break other teams' integration points
- Keep D1, D2 and D3 informed when changing ports, APIs or data formats
D4 is the platform backbone of the Healthcare Monitoring System.
The final D4 result should prove that:
The system can run using Docker, authenticate users using Keycloak, secure APIs using JWT, protect sensitive patient data, log important events, collect metrics using Prometheus, display monitoring dashboards using Grafana and support end-to-end integration with D1, D2 and D3.
This repository now includes a deployable D4 Keycloak image and Kubernetes manifests.
- Docker image:
ghcr.io/healthcare-monitoring-system/d4-platform-devops:latest - Workflow:
.github/workflows/docker-image.yml - Kubernetes base:
infra/k8s/base - Deployment guide:
docs/K3S_ARGOCD_DEPLOYMENT.md - Argo CD application:
d2-data-intelligence/infra/argocd/d4-platform-devops-application.yaml - Live Argo CD source path:
d2-data-intelligence/infra/k8s/d4-platform-devops
The Kubernetes service name is keycloak. Other pods in the d2 namespace can use:
http://keycloak:8080
For the droplet demo, Keycloak is exposed on NodePort 30080:
http://SERVER_IP:30080
- Docker documentation: https://docs.docker.com/
- Docker Compose documentation: https://docs.docker.com/compose/
- Keycloak documentation: https://www.keycloak.org/documentation
- Prometheus documentation: https://prometheus.io/docs/introduction/overview/
- Grafana documentation: https://grafana.com/docs/
- JWT introduction: https://jwt.io/introduction