A Django-based infrastructure monitoring project with:
- server registration
- metric ingestion for CPU, memory, and disk usage
- websocket-based live dashboard updates
- alert generation for sustained high CPU
- API activity logging with request IP visibility
- a lightweight Python agent for pushing host metrics
This README focuses on getting the project running cleanly on an AWS EC2 instance.
observability/Django project and monitoring appagent/agent.pymetric collection agentrequirements.txtPython dependencies
- Register monitored servers through
/api/register/ - Push infrastructure metrics through
/api/ingest/ - View charts and alerts in
/api/dashboard/ - See recent API hits, endpoints, and IP addresses in the dashboard
- Track server status as online or offline
- Python
- Django
- Django REST Framework
- Django Channels
- Redis
- Celery
- PostgreSQL or SQLite for local fallback
- Chart.js
This guide assumes:
- Ubuntu 22.04 or 24.04 EC2
- one EC2 instance for the app
- Redis installed on the same instance
- PostgreSQL either on the same instance or on Amazon RDS
- Nginx as reverse proxy
- Daphne as the ASGI app server
- Celery worker running as a background service
Recommended instance for a small demo:
t3.smallort3.medium
Security group:
- allow
22from your IP - allow
80from the internet - allow
443from the internet if you plan to add HTTPS
If PostgreSQL is on another machine or RDS:
- allow the PostgreSQL port
5432between the app host and database
ssh -i /path/to/key.pem ubuntu@YOUR_EC2_PUBLIC_IPsudo apt update
sudo apt install -y python3 python3-venv python3-pip git nginx redis-server postgresql-client libpq-dev build-essentialEnable Redis and Nginx:
sudo systemctl enable redis-server
sudo systemctl start redis-server
sudo systemctl enable nginx
sudo systemctl start nginxChoose an app directory:
sudo mkdir -p /srv/monitoring
sudo chown ubuntu:ubuntu /srv/monitoring
cd /srv/monitoring
git clone <YOUR_REPOSITORY_URL> .python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txtCreate observability/.env:
SECRET_KEY=replace-with-a-long-random-secret
DEBUG=False
ALLOWED_HOSTS=YOUR_EC2_PUBLIC_IP,YOUR_DOMAIN,localhost,127.0.0.1
DB_ENGINE=django.db.backends.postgresql
DB_NAME=observability_db
DB_USER=observability_user
DB_PASSWORD=replace-with-db-password
DB_HOST=127.0.0.1
DB_PORT=5432
REDIS_URL=redis://127.0.0.1:6379/0
CELERY_BROKER_URL=redis://127.0.0.1:6379/0
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=your-email@example.com
EMAIL_HOST_PASSWORD=your-email-passwordNotes:
ALLOWED_HOSTSshould include your EC2 public IP and domain if you use one.- If you do not want PostgreSQL immediately, you can omit the
DB_*values and Django will fall back to SQLite. - For production, PostgreSQL is strongly recommended.
If you are using PostgreSQL, create the database and user first.
Example:
CREATE DATABASE observability_db;
CREATE USER observability_user WITH PASSWORD 'replace-with-db-password';
GRANT ALL PRIVILEGES ON DATABASE observability_db TO observability_user;If you use Amazon RDS instead:
- create a PostgreSQL RDS instance
- allow access from the EC2 security group
- set
DB_HOSTto the RDS endpoint
cd /srv/monitoring
source venv/bin/activate
python observability/manage.py migrateOptional admin user:
python observability/manage.py createsuperuserCollect static files:
python observability/manage.py collectstatic --noinputStart Daphne:
cd /srv/monitoring
source venv/bin/activate
daphne -b 0.0.0.0 -p 8001 observability.asgi:applicationIf import resolution fails, run it from the Django project directory:
cd /srv/monitoring/observability
source ../venv/bin/activate
daphne -b 0.0.0.0 -p 8001 observability.asgi:applicationThen open:
http://YOUR_EC2_PUBLIC_IP/api/dashboard/
Create /etc/systemd/system/monitoring-daphne.service:
[Unit]
Description=Monitoring Daphne Service
After=network.target redis-server.service
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/srv/monitoring/observability
Environment="DJANGO_SETTINGS_MODULE=observability.settings"
ExecStart=/srv/monitoring/venv/bin/daphne -b 127.0.0.1 -p 8001 observability.asgi:application
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetEnable it:
sudo systemctl daemon-reload
sudo systemctl enable monitoring-daphne
sudo systemctl start monitoring-daphne
sudo systemctl status monitoring-daphneCreate /etc/systemd/system/monitoring-celery.service:
[Unit]
Description=Monitoring Celery Worker
After=network.target redis-server.service
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/srv/monitoring/observability
Environment="DJANGO_SETTINGS_MODULE=observability.settings"
ExecStart=/srv/monitoring/venv/bin/celery -A observability worker --loglevel=info
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetEnable it:
sudo systemctl daemon-reload
sudo systemctl enable monitoring-celery
sudo systemctl start monitoring-celery
sudo systemctl status monitoring-celeryNote:
- The project contains a Celery task file, but no periodic beat schedule is configured in code yet.
- If you later add scheduled tasks, also create a
celery beatservice.
Create /etc/nginx/sites-available/monitoring:
server {
listen 80;
server_name YOUR_EC2_PUBLIC_IP YOUR_DOMAIN;
location /static/ {
alias /srv/monitoring/observability/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}Enable the site:
sudo ln -s /etc/nginx/sites-available/monitoring /etc/nginx/sites-enabled/monitoring
sudo nginx -t
sudo systemctl reload nginxRemove the default site if needed:
sudo rm -f /etc/nginx/sites-enabled/default
sudo systemctl reload nginxOnce Nginx and Daphne are running:
http://YOUR_EC2_PUBLIC_IP/api/dashboard/
You should see:
- system summary cards
- server selector
- metric charts
- alert history
- API hit summary with IP addresses
- recent API activity table
The agent can run on the same EC2 instance or on another machine.
Before running the agent, update agent/agent.py:
URL_BASE = "http://YOUR_EC2_PUBLIC_IP/api"Then run:
cd /srv/monitoring
source venv/bin/activate
python agent/agent.pyWhat the agent does:
- registers the server if no API key exists locally
- stores the API key in
api_key.txt - sends CPU, memory, and disk usage every 5 seconds
Check Django:
cd /srv/monitoring
source venv/bin/activate
python observability/manage.py checkCheck tests:
python observability/manage.py test monitoring --settings=observability.test_settingsCheck services:
sudo systemctl status monitoring-daphne
sudo systemctl status monitoring-celery
sudo systemctl status nginx
sudo systemctl status redis-serverCheck logs:
journalctl -u monitoring-daphne -f
journalctl -u monitoring-celery -f
sudo tail -f /var/log/nginx/error.logIf you are using a Cloudflare Tunnel (using cloudflared) to expose your server via a subdomain (e.g., server.example.com), you can completely skip the Nginx configuration.
- Skip Nginx: Do not install or configure Nginx (Skip Step 12).
- Run Daphne: Set up the Daphne systemd service exactly as shown in Step 10, ensuring it runs on a local port like
8001. - Configure Tunnel: In your Cloudflare Zero Trust dashboard (or
cloudflaredconfig), create a Public Hostname routing your subdomain tohttp://127.0.0.1:8001. Cloudflare Tunnel supports WebSockets natively, so the real-time dashboard updates (Django Channels) will work out of the box. - Update
.env: Ensure your subdomain is included in theALLOWED_HOSTSlist in yourobservability/.envfile.ALLOWED_HOSTS=server.example.com,127.0.0.1,localhost
- CSRF Settings (If Needed): If you encounter
403 CSRF verification failederrors when submitting forms (because Cloudflare provides HTTPS but proxies HTTP to your server), add the following toobservability/observability/settings.py:CSRF_TRUSTED_ORIGINS = ['https://server.example.com'] SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
This project now works well as an EC2-hosted MVP, but for stronger production readiness you should still add:
- HTTPS with Let’s Encrypt
- database backups
- a proper domain name
- stricter dashboard/API authentication
- log rotation and centralized monitoring
- alert notification channels like email, Slack, or SMS
- metric retention cleanup for old
InfrastructureMetricandAPIRequestLogrows
Check:
ALLOWED_HOSTS- Nginx config
- Daphne service status
- whether port
80is open in the EC2 security group
Check:
- Redis is running
REDIS_URLis set- Nginx includes
UpgradeandConnectionheaders - Daphne is running successfully
Run:
cd /srv/monitoring
source venv/bin/activate
python observability/manage.py collectstatic --noinputThen reload Nginx.
Check:
DB_HOST,DB_NAME,DB_USER,DB_PASSWORD,DB_PORT- PostgreSQL or RDS security group rules
- local firewall rules if using self-hosted PostgreSQL
git clone <YOUR_REPOSITORY_URL>
cd Monitoring
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp observability/.env observability/.env.local.backup
python observability/manage.py migrate
python observability/manage.py runserverOpen:
http://127.0.0.1:8000/api/dashboard/
POST /api/register/POST /api/ingest/GET /api/metrics/?server=<id>&minutes=<n>GET /api/servers/GET /api/system-summary/GET /api/api-activity/GET /api/dashboard-data/?server=<id>&minutes=<n>GET /api/dashboard/
This repository is now suitable for:
- local development
- project demonstration
- EC2 deployment for MVP use
It is not yet a fully hardened enterprise monitoring platform, but this README gives you a proper path to install and run it on AWS EC2 cleanly.