mirror of
https://github.com/mblanke/Dashboard.git
synced 2026-03-01 04:00:22 -05:00
7.9 KiB
7.9 KiB
Security & Best Practices
Credential Management
⚠️ Critical Security Rules
-
Never commit
.env.localto Git- It contains passwords and API keys
- Use
.env.examplefor template only - Add to
.gitignore(already configured)
-
Rotate credentials regularly
- Change Synology password every 90 days
- Rotate UniFi credentials quarterly
- Update Grafana API keys if compromised
-
Use strong passwords
- Minimum 16 characters
- Mix of uppercase, lowercase, numbers, special characters
- Unique per service
Credential Storage
Best Practice: Use a secrets manager
Option 1: HashiCorp Vault
# Store credentials in Vault
vault kv put secret/dashboard/atlas \
unifi_password="..." \
synology_password="..."
# Load in container startup script
export UNIFI_PASSWORD=$(vault kv get -field=unifi_password secret/dashboard/atlas)
Option 2: AWS Secrets Manager
# Store and retrieve
aws secretsmanager get-secret-value --secret-id dashboard/credentials
Option 3: GitHub Actions Secrets (for automation)
env:
UNIFI_PASSWORD: ${{ secrets.UNIFI_PASSWORD }}
Network Security
Docker API Security
⚠️ Current Setup: Docker API exposed to internal network only
# Verify Docker API is not publicly exposed
curl http://100.104.196.38:2375/containers/json
# Should NOT be accessible from external networks
# If it is, restrict with firewall:
sudo ufw allow from 100.104.196.0/24 to any port 2375
sudo ufw deny from any to any port 2375
HTTPS/SSL Configuration
Recommended: Use reverse proxy with SSL
# Nginx example
server {
listen 443 ssl http2;
server_name dashboard.yourdomain.com;
ssl_certificate /etc/ssl/certs/your_cert.crt;
ssl_certificate_key /etc/ssl/private/your_key.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
VPN/Network Access
Recommended Setup:
- Dashboard accessible only via VPN
- Or restrict to specific IP ranges:
# UFW firewall rules
sudo ufw allow from 100.104.196.0/24 to any port 3001
sudo ufw deny from any to any port 3001
Authentication & Authorization
Basic Auth (Simple)
Add basic authentication with Nginx/Traefik:
# Traefik example
labels:
- "traefik.http.middlewares.auth.basicauth.users=admin:your_hashed_password"
- "traefik.http.routers.dashboard.middlewares=auth"
Generate hashed password:
echo $(htpasswd -nB admin) | sed -r 's/:.*//'
# Use output in Traefik config
OAuth2 (Advanced)
Using Oauth2-proxy:
# docker-compose.yml addition
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy:v7.4.0
environment:
OAUTH2_PROXY_PROVIDER: github
OAUTH2_PROXY_CLIENT_ID: your_client_id
OAUTH2_PROXY_CLIENT_SECRET: your_client_secret
OAUTH2_PROXY_COOKIE_SECRET: your_secret
ports:
- "4180:4180"
API Security
Rate Limiting
Add rate limiting to API endpoints:
// src/app/api/containers/route.ts
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 100, // 100 requests per minute
});
export const GET = limiter(async (req) => {
// ... existing code
});
Input Validation
Always validate external inputs:
// Validate environment variables
function validateEnv() {
const required = ['DOCKER_HOST', 'UNIFI_HOST', 'SYNOLOGY_HOST'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing env vars: ${missing.join(', ')}`);
}
}
API Key Rotation
For Grafana API key:
# Generate new key in Grafana UI
# Update in .env.local
# Revoke old key in Grafana
# Script to automate
#!/bin/bash
NEW_KEY=$(curl -X POST https://grafana/api/auth/keys \
-H "Authorization: Bearer $OLD_KEY" \
-d '{"name": "dashboard", "role": "Viewer"}')
# Update .env.local
sed -i "s/GRAFANA_API_KEY=.*/GRAFANA_API_KEY=$NEW_KEY/" /opt/dashboard/.env.local
Logging & Monitoring
Enable Audit Logging
# Docker daemon audit log
echo '{"log-driver": "json-file"}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker
Monitor Access Logs
# View nginx/reverse proxy logs
tail -f /var/log/nginx/access.log | grep dashboard
# Monitor failed authentication attempts
grep "401\|403" /var/log/nginx/access.log
Alert on Anomalies
# Example: Alert on excessive API errors
docker logs atlas-dashboard | grep -c "error" | awk '{if ($1 > 10) print "ALERT: High error rate"}'
Vulnerability Management
Scan for CVEs
# Scan Docker image
trivy image atlas-dashboard:latest
# Scan dependencies
npm audit
# Fix vulnerabilities
npm audit fix
Keep Images Updated
# Update base image
docker-compose build --pull
# Update Node.js version regularly
# Edit Dockerfile to latest LTS version
Monitor for Vulnerabilities
# GitHub Dependabot - enabled by default
# Review and merge dependabot PRs regularly
# Manual check
npm outdated
Data Privacy
GDPR/Data Protection
The dashboard:
- ✅ Does NOT store personal data
- ✅ Does NOT use cookies or tracking
- ✅ Does NOT collect user information
- ⚠️ Logs contain IP addresses
To anonymize logs:
# Redact IPs from logs
docker logs atlas-dashboard | sed 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/[REDACTED]/g'
Compliance Checklist
- All credentials use strong passwords
- .env.local is NOT committed to Git
- Docker API is not publicly exposed
- HTTPS/SSL configured for production
- Authentication layer in place
- Audit logs are enabled
- Dependencies are up-to-date
- Security scanning (trivy) runs regularly
- Access is restricted by firewall/VPN
- Backup strategy is documented
- Incident response plan is prepared
- Regular security reviews scheduled
Incident Response
If Credentials Are Compromised
-
Immediately change passwords:
# Synology # UniFi # Any API keys -
Update in .env.local:
ssh soadmin@100.104.196.38 nano /opt/dashboard/.env.local -
Restart container:
docker-compose restart dashboard -
Check logs for unauthorized access:
docker logs atlas-dashboard | grep error -
Review API call history in Synology/UniFi
If Container Is Compromised
-
Isolate the container:
docker-compose down -
Rebuild from source:
cd /opt/dashboard git fetch origin git reset --hard origin/main docker-compose build --no-cache -
Verify integrity:
git log -1 docker images atlas-dashboard -
Redeploy:
docker-compose up -d
If Server Is Compromised
- Migrate to new server (see MONITORING.md - Disaster Recovery)
- Rotate ALL credentials
- Conduct security audit of infrastructure
- Review access logs from before incident