You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- [] **Review and update user security guide**: Review `docs/user-guide/security.md` and verify it aligns with the new Docker/UFW security strategy - update any outdated assumptions about UFW protecting Docker ports
502
-
- [] Update user guide with security strategy explanation
503
-
- [] Document deployment security best practices
504
-
- [] Add warnings about Docker port binding risks
501
+
- [x] **Review and update user security guide**: Review `docs/user-guide/security.md` and verify it aligns with the new Docker/UFW security strategy - update any outdated assumptions about UFW protecting Docker ports
502
+
- [x] Update user guide with security strategy explanation
503
+
- [x] Document deployment security best practices
504
+
- [x] Add warnings about Docker port binding risks
505
505
- [ ] Create troubleshooting guide for firewall issues
506
506
- [ ] Review all documentation for accuracy and completeness
@@ -8,97 +8,219 @@ Security is a critical aspect of production deployments. The Torrust Tracker Dep
8
8
9
9
## Firewall Configuration
10
10
11
-
### Automatic Firewall Setup
11
+
### Layered Security Approach
12
+
13
+
**CRITICAL**: The deployer uses a **layered security approach** combining UFW firewall and Docker networking to protect your deployment. Understanding how these layers work together is essential for secure deployments.
14
+
15
+
#### Security Architecture
16
+
17
+
The deployer implements security at two levels:
18
+
19
+
1.**Instance-Level Security (UFW)** - Protects the VM itself
20
+
21
+
- Denies all incoming traffic by default
22
+
- Allows only SSH access for administration
23
+
-**Does NOT control Docker container ports** (Docker bypasses UFW)
24
+
25
+
2.**Service-Level Security (Docker)** - Controls service exposure
26
+
- Public services have explicit port bindings (Tracker, Grafana)
27
+
- Internal services have NO port bindings (MySQL)
28
+
- Localhost-only services bind to `127.0.0.1` (Prometheus)
29
+
- Docker network segmentation isolates service communication
30
+
31
+
#### Why UFW Cannot Protect Docker Ports
32
+
33
+
**Important**: Docker manipulates iptables directly and **bypasses UFW rules** for published container ports. This is documented behavior (see [Docker documentation](https://docs.docker.com/engine/network/packet-filtering-firewalls/)).
**CRITICAL**: The `configure` command automatically configures UFW (Uncomplicated Firewall) on virtual machines to protect internal services from unauthorized external access.
43
+
Docker routes container traffic in the NAT table, meaning packets are diverted before reaching the INPUT and OUTPUT chains that UFW uses. Therefore:
4.**Allows tracker services** - Opens only necessary tracker ports:
21
-
- UDP tracker ports (configured in environment)
22
-
- HTTP tracker ports (configured in environment)
23
-
- HTTP API port (configured in environment)
24
-
5.**Enables the firewall** - Activates rules to protect the system
56
+
4. **Enables the firewall** - Activates rules to protect SSH access
57
+
58
+
**Note**: UFW only controls SSH access. Application ports are controlled by Docker port bindings in the docker-compose configuration.
25
59
26
-
###Why Firewall Configuration Matters
60
+
###Service Exposure Strategy
27
61
28
-
The Docker Compose configuration (`templates/docker-compose/docker-compose.yml.tera`) exposes several service ports that should **NOT** be publicly accessible:
62
+
### Service Exposure Strategy
29
63
30
-
**Exposed Ports in Docker Compose**:
64
+
The Docker Compose configuration (`templates/docker-compose/docker-compose.yml.tera`) controls which services are accessible from the internet through **explicit port bindings**:
65
+
66
+
**Service Exposure Levels**:
31
67
32
68
```yaml
33
69
services:
34
-
#Tracker - Public ports (UDP/HTTP tracker, HTTP API)
70
+
# ✅ PUBLIC SERVICES - Explicit port bindings
35
71
tracker:
36
72
ports:
37
-
- "6969:6969/udp"# ✅ Public - UDP tracker
38
-
- "7070:7070"# ✅ Public - HTTP tracker
39
-
- "1212:1212"# ✅ Public - HTTP API
73
+
- "6969:6969/udp" # Public - UDP tracker
74
+
- "7070:7070" # Public - HTTP tracker
75
+
- "1212:1212" # Public - REST API
76
+
77
+
grafana:
78
+
ports:
79
+
- "3100:3000" # Public - Monitoring UI (authenticated)
40
80
41
-
#Prometheus - INTERNAL ONLY
81
+
# 🔒 LOCALHOST-ONLY SERVICES - Bound to 127.0.0.1
42
82
prometheus:
43
83
ports:
44
-
- "9090:9090"#⚠️ INTERNAL - Metrics UI
84
+
- "127.0.0.1:9090:9090" # Accessible only from VM host
45
85
46
-
# MySQL - INTERNAL ONLY
86
+
# 🔒 INTERNAL-ONLY SERVICES - No port bindings
87
+
mysql:
88
+
# No ports section - completely internal
89
+
# Accessed via Docker network: mysql:3306
90
+
```
91
+
92
+
**Security Properties**:
93
+
94
+
- **Public Services** - Have `ports:` section binding to `0.0.0.0` (accessible externally)
95
+
- **Localhost Services** - Bind to `127.0.0.1` (accessible only from VM host via SSH)
96
+
- **Internal Services** - No port bindings (accessible only via Docker internal networks)
97
+
98
+
### Network Segmentation
99
+
100
+
The deployer implements **three isolated Docker networks** for defense-in-depth security:
101
+
102
+
```yaml
103
+
networks:
104
+
database_network: # Tracker ↔ MySQL only
105
+
metrics_network: # Tracker ↔ Prometheus only
106
+
visualization_network: # Prometheus ↔ Grafana only
107
+
108
+
services:
109
+
tracker:
110
+
networks:
111
+
- database_network # Can access MySQL
112
+
- metrics_network # Can be scraped by Prometheus
113
+
114
+
mysql:
115
+
networks:
116
+
- database_network # Isolated - only Tracker can access
117
+
118
+
prometheus:
119
+
networks:
120
+
- metrics_network # Can scrape Tracker metrics
121
+
- visualization_network # Can be queried by Grafana
122
+
123
+
grafana:
124
+
networks:
125
+
- visualization_network # Can query Prometheus only
126
+
```
127
+
128
+
**Security Benefits**:
129
+
130
+
1. **Reduced Attack Surface**: MySQL accessible from 1 service (Tracker) instead of 3 services
131
+
2. **Lateral Movement Prevention**: Compromised Grafana cannot access MySQL or Tracker
132
+
3. **Principle of Least Privilege**: Services can only communicate where necessary
# INSECURE - All services on one network with public port bindings
141
+
services:
47
142
mysql:
48
143
ports:
49
-
- "3306:3306"# ⚠️ INTERNAL - Database
144
+
- "3306:3306" # ⚠️ MySQL publicly accessible!
145
+
networks:
146
+
- backend_network
50
147
```
51
148
52
-
**Without firewall protection**, services like Prometheus (port 9090) and MySQL (port 3306) would be accessible from the internet, potentially exposing:
149
+
- ❌ Internal services exposed to internet
150
+
- ❌ All services can communicate (no segmentation)
151
+
- ❌ Docker bypasses UFW firewall rules
152
+
- ❌ High attack surface
53
153
54
-
- **Prometheus** - Internal metrics, performance data, system topology
55
-
- **MySQL** - Database access (even with authentication, this is a security risk)
154
+
**With deployer configuration** ✅:
56
155
57
-
**With firewall protection** (UFW configured by `configure` command):
156
+
```yaml
157
+
# SECURE - Network segmentation + no public port bindings
**Note**: Application ports (Tracker, Grafana, Prometheus, MySQL) are **not** managed by UFW. They are controlled by Docker port bindings in the docker-compose.yml configuration.
202
+
203
+
### Security Best Practices
204
+
205
+
**DO**:
206
+
207
+
- ✅ Use the deployer's default docker-compose template (network segmentation included)
208
+
- ✅ Review port bindings before deploying (`build/{env}/docker-compose/docker-compose.yml`)
209
+
- ✅ Keep internal services without port bindings (MySQL)
210
+
- ✅ Use `127.0.0.1` bindings for localhost-only access (Prometheus)
211
+
- ✅ Apply security updates to the VM regularly
212
+
- ✅ Use strong SSH keys and disable password authentication
213
+
- ✅ Monitor logs for suspicious activity
214
+
215
+
**DON'T**:
216
+
217
+
- ❌ Add port bindings to internal services (e.g., `3306:3306` for MySQL)
218
+
- ❌ Disable UFW firewall on production VMs
219
+
- ❌ Remove network segmentation from docker-compose.yml
220
+
- ❌ Assume UFW protects Docker-published ports
221
+
- ❌ Expose Prometheus/MySQL publicly
222
+
- ❌ Use default passwords for services
223
+
102
224
### Verifying Firewall Configuration
103
225
104
226
After running the `configure` command, verify firewall rules:
0 commit comments