This document presents the security measures applied to the FirstBreath infrastructure, following system and network administration best practices.
Security Layers Overview
1. Network Security
VPS Access Security
| Measure | Configuration | Details |
|---|
| SSH key-only | PasswordAuthentication no | Password login disabled, only public key authentication allowed |
| Fail2ban | sshd jail active | Automatic IP banning after repeated failed login attempts |
| Exposed ports | 22 (SSH), 80 (HTTP), 443 (HTTPS) | All other ports are closed by firewall |
Docker Network Isolation
| Network | External Access | Role |
|---|
dokploy-network | Via Traefik only | Services exposed to the reverse proxy |
monitor-net | No | Vision ↔ Backend ↔ Monitoring communication |
internal | No | Private network for the Control-Hub stack |
Principle: databases (MySQL, Redis) and internal services are never exposed to the Internet. Only Traefik is publicly accessible.
TLS / HTTPS
- Certificates: Let's Encrypt (automatic generation and renewal via Certbot + Traefik)
- Redirect: all HTTP traffic is redirected to HTTPS (
redirect-to-https@file)
- Protected domains:
api.firstbreath.fr — REST API and WebSocket
db.firstbreath.fr — CloudBeaver (DB admin)
sonar.firstbreath.fr — SonarQube
Exposed Ports
Only ports 80 (HTTP → redirect) and 443 (HTTPS) are publicly exposed via Traefik. Internal ports (3306 MySQL, 6379 Redis, 9090 Prometheus, etc.) are not accessible from the Internet.
2. Container Security
Non-root Users
Application containers run with non-root users where applicable:
| Service | User | UID:GID |
|---|
| REST API (AdonisJS) | nodejs | 1001:1001 |
| Frontend (my-app) | nextjs | 1001:1001 |
| Showcase | nextjs | via addgroup/adduser |
| Redis Worker | appuser | dynamic |
| Camera Manager | root | GPU driver requirement |
| Batch Inference | root | GPU driver requirement |
Resource Limits
Each container has CPU and memory limits defined (see Global Architecture), preventing a compromised service from consuming all server resources.
Minimal Base Images
| Image | Usage | Security Advantage |
|---|
node:20-alpine | Backend (API) | Reduced attack surface (minimal Alpine) |
node:22-alpine | Frontend, Showcase | Reduced attack surface (minimal Alpine) |
python:3.11-slim-bookworm | Redis Worker | Lightweight image without unnecessary tools |
nginx:alpine | Documentation | Minimal static server |
ultralytics/ultralytics | Batch Inference | GPU-specialized image (heavier, required for YOLO) |
ghcr.io/firstbreath/opencv-cuda | Camera Manager | Custom GPU image (CUDA + OpenCV, heavier) |
Multi-stage Builds
Application Dockerfiles (API, Frontend, Showcase, Redis Worker, Documentation) use multi-stage builds: only compiled artifacts are copied into the final image. Build tools (gcc, make, python-dev) are not present in production. Vision service Dockerfiles (Camera Manager, Batch Inference) use single-stage builds due to GPU-specific base images.
3. Application Security
Dependency Auditing (CI)
| Ecosystem | Tool | Execution |
|---|
| Node.js (npm/pnpm/yarn) | pnpm audit / npm audit | Every CI pipeline |
| Python (pip) | safety check | Every CI pipeline (Vision) |
CI pipelines fail if critical vulnerabilities are detected in dependencies.
Static Analysis (SonarQube)
SonarQube automatically detects:
- Security Hotspots: code points requiring manual security review
- Vulnerabilities: known security flaws (SQL injection, XSS, etc.)
- Code smells: patterns that may lead to security issues
Code Review
- Every Pull Request requires at least one peer review
- Reviewer checks: business logic, test coverage, standards compliance, security
main branch is protected: direct merge is forbidden
4. Data Security
Database
| Measure | Details |
|---|
| Network access | MySQL accessible only via the internal Docker network |
| Authentication | Passwords via environment variables (.env) |
| Persistent volumes | MySQL data stored in a named Docker volume (mysql_data) |
| Administration | CloudBeaver accessible only via HTTPS with authentication |
Redis
| Measure | Details |
|---|
| Authentication | requirepass mandatory |
| Memory | Limited to 256 MB with allkeys-lru eviction policy |
| Network access | Not publicly exposed |
Secrets and Environment Variables
- Secrets (passwords, API tokens, keys) are stored in
.env files on the server
.env files are excluded from version control (.gitignore)
- Sensitive variables are injected via Dokploy or Docker environment
5. Attack Protection
Denial of Service (DDoS) Attacks
| Measure | Details |
|---|
| Rate limiting | Configurable via Traefik middleware |
| Resource limits | CPU/RAM caps on each container |
| Redis LRU | Eviction policy to prevent memory exhaustion |
| Healthchecks | Automatic restart of failing services |
Intrusions
| Measure | Details |
|---|
| Network isolation | Internal services not accessible from the Internet |
| Non-root users | Privilege limitation in case of compromise |
| Minimal images | Reduced attack surface |
| Mandatory TLS | Encryption of all communications |
| CI audits | Proactive vulnerability detection |
Secure Container Registry
Custom Docker images are hosted on GitHub Container Registry (GHCR):
- Authentication required (GitHub token)
- Private images by default
- Access restricted to organization members
6. Compliance and Best Practices
| Practice | Implementation |
|---|
| Least privilege | Non-root users, resource limits |
| Encryption in transit | TLS/HTTPS on all external communications |
| Defense in depth | Isolated network + limited containers + CI audits + code review |
| Patch management | Dependabot / regular Docker image updates |
| Environment separation | Separate Docker Compose files (dev / prod) |
| Logging | Docker logs accessible via docker compose logs and Grafana |
| Monitoring | Prometheus/Grafana stack for anomaly detection |