ferrum-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env.example +90 -0
- data/CHANGELOG.md +229 -0
- data/CONTRIBUTING.md +469 -0
- data/LICENSE +21 -0
- data/README.md +334 -0
- data/SECURITY.md +286 -0
- data/bin/ferrum-mcp +66 -0
- data/bin/lint +10 -0
- data/bin/serve +3 -0
- data/bin/test +4 -0
- data/docs/API_REFERENCE.md +1410 -0
- data/docs/CONFIGURATION.md +254 -0
- data/docs/DEPLOYMENT.md +846 -0
- data/docs/DOCKER.md +836 -0
- data/docs/DOCKER_BOTBROWSER.md +455 -0
- data/docs/GETTING_STARTED.md +249 -0
- data/docs/TROUBLESHOOTING.md +677 -0
- data/lib/ferrum_mcp/browser_manager.rb +101 -0
- data/lib/ferrum_mcp/cli/command_handler.rb +99 -0
- data/lib/ferrum_mcp/cli/server_runner.rb +166 -0
- data/lib/ferrum_mcp/configuration.rb +229 -0
- data/lib/ferrum_mcp/resource_manager.rb +223 -0
- data/lib/ferrum_mcp/server.rb +254 -0
- data/lib/ferrum_mcp/session.rb +227 -0
- data/lib/ferrum_mcp/session_manager.rb +183 -0
- data/lib/ferrum_mcp/tools/accept_cookies_tool.rb +458 -0
- data/lib/ferrum_mcp/tools/base_tool.rb +114 -0
- data/lib/ferrum_mcp/tools/clear_cookies_tool.rb +66 -0
- data/lib/ferrum_mcp/tools/click_tool.rb +218 -0
- data/lib/ferrum_mcp/tools/close_session_tool.rb +49 -0
- data/lib/ferrum_mcp/tools/create_session_tool.rb +146 -0
- data/lib/ferrum_mcp/tools/drag_and_drop_tool.rb +171 -0
- data/lib/ferrum_mcp/tools/evaluate_js_tool.rb +46 -0
- data/lib/ferrum_mcp/tools/execute_script_tool.rb +48 -0
- data/lib/ferrum_mcp/tools/fill_form_tool.rb +78 -0
- data/lib/ferrum_mcp/tools/find_by_text_tool.rb +153 -0
- data/lib/ferrum_mcp/tools/get_attribute_tool.rb +56 -0
- data/lib/ferrum_mcp/tools/get_cookies_tool.rb +70 -0
- data/lib/ferrum_mcp/tools/get_html_tool.rb +52 -0
- data/lib/ferrum_mcp/tools/get_session_info_tool.rb +40 -0
- data/lib/ferrum_mcp/tools/get_text_tool.rb +67 -0
- data/lib/ferrum_mcp/tools/get_title_tool.rb +42 -0
- data/lib/ferrum_mcp/tools/get_url_tool.rb +39 -0
- data/lib/ferrum_mcp/tools/go_back_tool.rb +49 -0
- data/lib/ferrum_mcp/tools/go_forward_tool.rb +49 -0
- data/lib/ferrum_mcp/tools/hover_tool.rb +76 -0
- data/lib/ferrum_mcp/tools/list_sessions_tool.rb +33 -0
- data/lib/ferrum_mcp/tools/navigate_tool.rb +59 -0
- data/lib/ferrum_mcp/tools/press_key_tool.rb +91 -0
- data/lib/ferrum_mcp/tools/query_shadow_dom_tool.rb +225 -0
- data/lib/ferrum_mcp/tools/refresh_tool.rb +49 -0
- data/lib/ferrum_mcp/tools/screenshot_tool.rb +121 -0
- data/lib/ferrum_mcp/tools/session_tool.rb +37 -0
- data/lib/ferrum_mcp/tools/set_cookie_tool.rb +77 -0
- data/lib/ferrum_mcp/tools/solve_captcha_tool.rb +528 -0
- data/lib/ferrum_mcp/transport/http_server.rb +93 -0
- data/lib/ferrum_mcp/transport/rate_limiter.rb +79 -0
- data/lib/ferrum_mcp/transport/stdio_server.rb +63 -0
- data/lib/ferrum_mcp/version.rb +5 -0
- data/lib/ferrum_mcp/whisper_service.rb +222 -0
- data/lib/ferrum_mcp.rb +35 -0
- metadata +248 -0
data/docs/DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,846 @@
|
|
|
1
|
+
# Production Deployment Guide
|
|
2
|
+
|
|
3
|
+
This guide covers deploying FerrumMCP in production environments.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Prerequisites](#prerequisites)
|
|
8
|
+
- [Deployment Options](#deployment-options)
|
|
9
|
+
- [Docker Deployment](#docker-deployment)
|
|
10
|
+
- [Kubernetes Deployment](#kubernetes-deployment)
|
|
11
|
+
- [Systemd Service](#systemd-service)
|
|
12
|
+
- [Reverse Proxy Setup](#reverse-proxy-setup)
|
|
13
|
+
- [Security Hardening](#security-hardening)
|
|
14
|
+
- [Monitoring](#monitoring)
|
|
15
|
+
- [Performance Tuning](#performance-tuning)
|
|
16
|
+
- [Backup and Recovery](#backup-and-recovery)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
### System Requirements
|
|
23
|
+
|
|
24
|
+
**Minimum**:
|
|
25
|
+
- CPU: 2 cores
|
|
26
|
+
- RAM: 2 GB
|
|
27
|
+
- Disk: 5 GB
|
|
28
|
+
- OS: Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)
|
|
29
|
+
|
|
30
|
+
**Recommended**:
|
|
31
|
+
- CPU: 4+ cores
|
|
32
|
+
- RAM: 4+ GB (add 500MB per concurrent session)
|
|
33
|
+
- Disk: 10+ GB SSD
|
|
34
|
+
- OS: Ubuntu 22.04 LTS
|
|
35
|
+
|
|
36
|
+
### Software Requirements
|
|
37
|
+
|
|
38
|
+
- Ruby 3.2 or higher
|
|
39
|
+
- Chrome/Chromium browser
|
|
40
|
+
- (Optional) BotBrowser for anti-detection
|
|
41
|
+
- (Optional) whisper-cli for CAPTCHA solving
|
|
42
|
+
- (Optional) nginx or Apache for reverse proxy
|
|
43
|
+
|
|
44
|
+
### Network Requirements
|
|
45
|
+
|
|
46
|
+
- **Inbound**: Port 3000 (HTTP) or custom port
|
|
47
|
+
- **Outbound**: Port 443 (HTTPS) for browsing
|
|
48
|
+
- **Internal**: PostgreSQL, Redis (if adding persistence)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Deployment Options
|
|
53
|
+
|
|
54
|
+
### Option 1: Docker (Recommended)
|
|
55
|
+
|
|
56
|
+
**Pros**:
|
|
57
|
+
- ✅ Isolated environment
|
|
58
|
+
- ✅ Easy to update
|
|
59
|
+
- ✅ Consistent across platforms
|
|
60
|
+
- ✅ Built-in Chrome
|
|
61
|
+
|
|
62
|
+
**Cons**:
|
|
63
|
+
- ❌ Slight overhead
|
|
64
|
+
- ❌ Requires Docker knowledge
|
|
65
|
+
|
|
66
|
+
**Best for**: Most production deployments
|
|
67
|
+
|
|
68
|
+
### Option 2: Systemd Service
|
|
69
|
+
|
|
70
|
+
**Pros**:
|
|
71
|
+
- ✅ Native performance
|
|
72
|
+
- ✅ System integration
|
|
73
|
+
- ✅ Easy log management
|
|
74
|
+
|
|
75
|
+
**Cons**:
|
|
76
|
+
- ❌ Manual dependency management
|
|
77
|
+
- ❌ Platform-specific setup
|
|
78
|
+
|
|
79
|
+
**Best for**: Dedicated servers
|
|
80
|
+
|
|
81
|
+
### Option 3: Kubernetes
|
|
82
|
+
|
|
83
|
+
**Pros**:
|
|
84
|
+
- ✅ Auto-scaling
|
|
85
|
+
- ✅ High availability
|
|
86
|
+
- ✅ Rolling updates
|
|
87
|
+
|
|
88
|
+
**Cons**:
|
|
89
|
+
- ❌ Complex setup
|
|
90
|
+
- ❌ Requires K8s cluster
|
|
91
|
+
|
|
92
|
+
**Best for**: Large-scale deployments
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Docker Deployment
|
|
97
|
+
|
|
98
|
+
### Basic Docker Deployment
|
|
99
|
+
|
|
100
|
+
1. **Pull the image**:
|
|
101
|
+
```bash
|
|
102
|
+
docker pull eth3rnit3/ferrum-mcp:latest
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
2. **Create environment file**:
|
|
106
|
+
```bash
|
|
107
|
+
cat > .env << EOF
|
|
108
|
+
MCP_SERVER_HOST=0.0.0.0
|
|
109
|
+
MCP_SERVER_PORT=3000
|
|
110
|
+
BROWSER_HEADLESS=true
|
|
111
|
+
LOG_LEVEL=info
|
|
112
|
+
MAX_CONCURRENT_SESSIONS=10
|
|
113
|
+
EOF
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
3. **Run container**:
|
|
117
|
+
```bash
|
|
118
|
+
docker run -d \
|
|
119
|
+
--name ferrum-mcp \
|
|
120
|
+
--env-file .env \
|
|
121
|
+
--shm-size=2g \
|
|
122
|
+
-p 3000:3000 \
|
|
123
|
+
--restart unless-stopped \
|
|
124
|
+
eth3rnit3/ferrum-mcp:latest
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
4. **Verify deployment**:
|
|
128
|
+
```bash
|
|
129
|
+
curl http://localhost:3000/health
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Docker Compose Deployment
|
|
133
|
+
|
|
134
|
+
Create `docker-compose.yml`:
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
version: '3.8'
|
|
138
|
+
|
|
139
|
+
services:
|
|
140
|
+
ferrum-mcp:
|
|
141
|
+
image: eth3rnit3/ferrum-mcp:latest
|
|
142
|
+
container_name: ferrum-mcp
|
|
143
|
+
restart: unless-stopped
|
|
144
|
+
shm_size: 2g
|
|
145
|
+
ports:
|
|
146
|
+
- "3000:3000"
|
|
147
|
+
environment:
|
|
148
|
+
- MCP_SERVER_HOST=0.0.0.0
|
|
149
|
+
- MCP_SERVER_PORT=3000
|
|
150
|
+
- BROWSER_HEADLESS=true
|
|
151
|
+
- LOG_LEVEL=info
|
|
152
|
+
- MAX_CONCURRENT_SESSIONS=10
|
|
153
|
+
- MAX_REQUESTS_PER_MINUTE=100
|
|
154
|
+
volumes:
|
|
155
|
+
- ./logs:/app/logs
|
|
156
|
+
- ./config:/app/config # For BotBrowser profiles
|
|
157
|
+
healthcheck:
|
|
158
|
+
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
159
|
+
interval: 30s
|
|
160
|
+
timeout: 10s
|
|
161
|
+
retries: 3
|
|
162
|
+
start_period: 40s
|
|
163
|
+
deploy:
|
|
164
|
+
resources:
|
|
165
|
+
limits:
|
|
166
|
+
cpus: '2.0'
|
|
167
|
+
memory: 4G
|
|
168
|
+
reservations:
|
|
169
|
+
cpus: '1.0'
|
|
170
|
+
memory: 2G
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Deploy:
|
|
174
|
+
```bash
|
|
175
|
+
docker-compose up -d
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Multi-Container Setup with Nginx
|
|
179
|
+
|
|
180
|
+
`docker-compose.yml`:
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
version: '3.8'
|
|
184
|
+
|
|
185
|
+
services:
|
|
186
|
+
ferrum-mcp:
|
|
187
|
+
image: eth3rnit3/ferrum-mcp:latest
|
|
188
|
+
container_name: ferrum-mcp
|
|
189
|
+
restart: unless-stopped
|
|
190
|
+
shm_size: 2g
|
|
191
|
+
environment:
|
|
192
|
+
- MCP_SERVER_HOST=0.0.0.0
|
|
193
|
+
- MCP_SERVER_PORT=3000
|
|
194
|
+
- BROWSER_HEADLESS=true
|
|
195
|
+
- LOG_LEVEL=info
|
|
196
|
+
volumes:
|
|
197
|
+
- ./logs:/app/logs
|
|
198
|
+
healthcheck:
|
|
199
|
+
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
|
200
|
+
interval: 30s
|
|
201
|
+
timeout: 10s
|
|
202
|
+
retries: 3
|
|
203
|
+
networks:
|
|
204
|
+
- ferrum-net
|
|
205
|
+
|
|
206
|
+
nginx:
|
|
207
|
+
image: nginx:alpine
|
|
208
|
+
container_name: ferrum-nginx
|
|
209
|
+
restart: unless-stopped
|
|
210
|
+
ports:
|
|
211
|
+
- "80:80"
|
|
212
|
+
- "443:443"
|
|
213
|
+
volumes:
|
|
214
|
+
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
|
215
|
+
- ./ssl:/etc/nginx/ssl:ro
|
|
216
|
+
depends_on:
|
|
217
|
+
- ferrum-mcp
|
|
218
|
+
networks:
|
|
219
|
+
- ferrum-net
|
|
220
|
+
|
|
221
|
+
networks:
|
|
222
|
+
ferrum-net:
|
|
223
|
+
driver: bridge
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Kubernetes Deployment
|
|
229
|
+
|
|
230
|
+
### Deployment Manifest
|
|
231
|
+
|
|
232
|
+
`k8s/deployment.yaml`:
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
apiVersion: apps/v1
|
|
236
|
+
kind: Deployment
|
|
237
|
+
metadata:
|
|
238
|
+
name: ferrum-mcp
|
|
239
|
+
namespace: default
|
|
240
|
+
spec:
|
|
241
|
+
replicas: 3
|
|
242
|
+
selector:
|
|
243
|
+
matchLabels:
|
|
244
|
+
app: ferrum-mcp
|
|
245
|
+
template:
|
|
246
|
+
metadata:
|
|
247
|
+
labels:
|
|
248
|
+
app: ferrum-mcp
|
|
249
|
+
spec:
|
|
250
|
+
containers:
|
|
251
|
+
- name: ferrum-mcp
|
|
252
|
+
image: eth3rnit3/ferrum-mcp:latest
|
|
253
|
+
ports:
|
|
254
|
+
- containerPort: 3000
|
|
255
|
+
name: http
|
|
256
|
+
env:
|
|
257
|
+
- name: MCP_SERVER_HOST
|
|
258
|
+
value: "0.0.0.0"
|
|
259
|
+
- name: MCP_SERVER_PORT
|
|
260
|
+
value: "3000"
|
|
261
|
+
- name: BROWSER_HEADLESS
|
|
262
|
+
value: "true"
|
|
263
|
+
- name: LOG_LEVEL
|
|
264
|
+
value: "info"
|
|
265
|
+
- name: MAX_CONCURRENT_SESSIONS
|
|
266
|
+
valueFrom:
|
|
267
|
+
configMapKeyRef:
|
|
268
|
+
name: ferrum-config
|
|
269
|
+
key: max_sessions
|
|
270
|
+
resources:
|
|
271
|
+
requests:
|
|
272
|
+
memory: "2Gi"
|
|
273
|
+
cpu: "1000m"
|
|
274
|
+
limits:
|
|
275
|
+
memory: "4Gi"
|
|
276
|
+
cpu: "2000m"
|
|
277
|
+
volumeMounts:
|
|
278
|
+
- name: shm
|
|
279
|
+
mountPath: /dev/shm
|
|
280
|
+
- name: logs
|
|
281
|
+
mountPath: /app/logs
|
|
282
|
+
livenessProbe:
|
|
283
|
+
httpGet:
|
|
284
|
+
path: /health
|
|
285
|
+
port: 3000
|
|
286
|
+
initialDelaySeconds: 30
|
|
287
|
+
periodSeconds: 10
|
|
288
|
+
readinessProbe:
|
|
289
|
+
httpGet:
|
|
290
|
+
path: /health
|
|
291
|
+
port: 3000
|
|
292
|
+
initialDelaySeconds: 10
|
|
293
|
+
periodSeconds: 5
|
|
294
|
+
volumes:
|
|
295
|
+
- name: shm
|
|
296
|
+
emptyDir:
|
|
297
|
+
medium: Memory
|
|
298
|
+
sizeLimit: 2Gi
|
|
299
|
+
- name: logs
|
|
300
|
+
emptyDir: {}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Service Manifest
|
|
304
|
+
|
|
305
|
+
`k8s/service.yaml`:
|
|
306
|
+
|
|
307
|
+
```yaml
|
|
308
|
+
apiVersion: v1
|
|
309
|
+
kind: Service
|
|
310
|
+
metadata:
|
|
311
|
+
name: ferrum-mcp
|
|
312
|
+
namespace: default
|
|
313
|
+
spec:
|
|
314
|
+
selector:
|
|
315
|
+
app: ferrum-mcp
|
|
316
|
+
ports:
|
|
317
|
+
- protocol: TCP
|
|
318
|
+
port: 80
|
|
319
|
+
targetPort: 3000
|
|
320
|
+
type: LoadBalancer
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### ConfigMap
|
|
324
|
+
|
|
325
|
+
`k8s/configmap.yaml`:
|
|
326
|
+
|
|
327
|
+
```yaml
|
|
328
|
+
apiVersion: v1
|
|
329
|
+
kind: ConfigMap
|
|
330
|
+
metadata:
|
|
331
|
+
name: ferrum-config
|
|
332
|
+
namespace: default
|
|
333
|
+
data:
|
|
334
|
+
max_sessions: "10"
|
|
335
|
+
max_requests_per_minute: "100"
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Deploy to Kubernetes
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
kubectl apply -f k8s/configmap.yaml
|
|
342
|
+
kubectl apply -f k8s/deployment.yaml
|
|
343
|
+
kubectl apply -f k8s/service.yaml
|
|
344
|
+
|
|
345
|
+
# Check status
|
|
346
|
+
kubectl get pods -l app=ferrum-mcp
|
|
347
|
+
kubectl get svc ferrum-mcp
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Systemd Service
|
|
353
|
+
|
|
354
|
+
### Service File
|
|
355
|
+
|
|
356
|
+
Create `/etc/systemd/system/ferrum-mcp.service`:
|
|
357
|
+
|
|
358
|
+
```ini
|
|
359
|
+
[Unit]
|
|
360
|
+
Description=FerrumMCP Browser Automation Server
|
|
361
|
+
After=network.target
|
|
362
|
+
|
|
363
|
+
[Service]
|
|
364
|
+
Type=simple
|
|
365
|
+
User=ferrum
|
|
366
|
+
Group=ferrum
|
|
367
|
+
WorkingDirectory=/opt/ferrum-mcp
|
|
368
|
+
Environment="PATH=/home/ferrum/.rbenv/shims:/home/ferrum/.rbenv/bin:/usr/local/bin:/usr/bin:/bin"
|
|
369
|
+
EnvironmentFile=/opt/ferrum-mcp/.env
|
|
370
|
+
ExecStart=/home/ferrum/.rbenv/shims/ruby /opt/ferrum-mcp/bin/ferrum-mcp --transport http
|
|
371
|
+
Restart=on-failure
|
|
372
|
+
RestartSec=10
|
|
373
|
+
StandardOutput=journal
|
|
374
|
+
StandardError=journal
|
|
375
|
+
SyslogIdentifier=ferrum-mcp
|
|
376
|
+
|
|
377
|
+
# Security
|
|
378
|
+
NoNewPrivileges=true
|
|
379
|
+
PrivateTmp=true
|
|
380
|
+
ProtectSystem=strict
|
|
381
|
+
ProtectHome=true
|
|
382
|
+
ReadWritePaths=/opt/ferrum-mcp/logs
|
|
383
|
+
|
|
384
|
+
# Resource limits
|
|
385
|
+
LimitNOFILE=65536
|
|
386
|
+
LimitNPROC=4096
|
|
387
|
+
|
|
388
|
+
[Install]
|
|
389
|
+
WantedBy=multi-user.target
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Setup Steps
|
|
393
|
+
|
|
394
|
+
1. **Create user**:
|
|
395
|
+
```bash
|
|
396
|
+
sudo useradd -r -s /bin/bash -d /opt/ferrum-mcp ferrum
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
2. **Install FerrumMCP**:
|
|
400
|
+
```bash
|
|
401
|
+
sudo mkdir -p /opt/ferrum-mcp
|
|
402
|
+
sudo chown ferrum:ferrum /opt/ferrum-mcp
|
|
403
|
+
|
|
404
|
+
# As ferrum user
|
|
405
|
+
sudo -u ferrum -i
|
|
406
|
+
cd /opt/ferrum-mcp
|
|
407
|
+
git clone https://github.com/Eth3rnit3/FerrumMCP.git .
|
|
408
|
+
bundle install --deployment --without development test
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
3. **Configure environment**:
|
|
412
|
+
```bash
|
|
413
|
+
sudo -u ferrum cp /opt/ferrum-mcp/.env.example /opt/ferrum-mcp/.env
|
|
414
|
+
sudo -u ferrum nano /opt/ferrum-mcp/.env
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
4. **Enable and start service**:
|
|
418
|
+
```bash
|
|
419
|
+
sudo systemctl daemon-reload
|
|
420
|
+
sudo systemctl enable ferrum-mcp
|
|
421
|
+
sudo systemctl start ferrum-mcp
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
5. **Check status**:
|
|
425
|
+
```bash
|
|
426
|
+
sudo systemctl status ferrum-mcp
|
|
427
|
+
sudo journalctl -u ferrum-mcp -f
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Reverse Proxy Setup
|
|
433
|
+
|
|
434
|
+
### Nginx Configuration
|
|
435
|
+
|
|
436
|
+
`/etc/nginx/sites-available/ferrum-mcp`:
|
|
437
|
+
|
|
438
|
+
```nginx
|
|
439
|
+
upstream ferrum_backend {
|
|
440
|
+
server 127.0.0.1:3000 fail_timeout=0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
# Rate limiting
|
|
444
|
+
limit_req_zone $binary_remote_addr zone=ferrum_limit:10m rate=10r/s;
|
|
445
|
+
|
|
446
|
+
server {
|
|
447
|
+
listen 80;
|
|
448
|
+
server_name ferrum.example.com;
|
|
449
|
+
|
|
450
|
+
# Redirect to HTTPS
|
|
451
|
+
return 301 https://$host$request_uri;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
server {
|
|
455
|
+
listen 443 ssl http2;
|
|
456
|
+
server_name ferrum.example.com;
|
|
457
|
+
|
|
458
|
+
# SSL Configuration
|
|
459
|
+
ssl_certificate /etc/letsencrypt/live/ferrum.example.com/fullchain.pem;
|
|
460
|
+
ssl_certificate_key /etc/letsencrypt/live/ferrum.example.com/privkey.pem;
|
|
461
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
|
462
|
+
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
463
|
+
ssl_prefer_server_ciphers on;
|
|
464
|
+
|
|
465
|
+
# Security Headers
|
|
466
|
+
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
467
|
+
add_header X-Frame-Options "DENY" always;
|
|
468
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
469
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
470
|
+
|
|
471
|
+
# Logging
|
|
472
|
+
access_log /var/log/nginx/ferrum_access.log;
|
|
473
|
+
error_log /var/log/nginx/ferrum_error.log;
|
|
474
|
+
|
|
475
|
+
# Health check (no rate limit)
|
|
476
|
+
location /health {
|
|
477
|
+
proxy_pass http://ferrum_backend;
|
|
478
|
+
access_log off;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
# MCP endpoint
|
|
482
|
+
location /mcp {
|
|
483
|
+
# Rate limiting
|
|
484
|
+
limit_req zone=ferrum_limit burst=20 nodelay;
|
|
485
|
+
|
|
486
|
+
# Proxy settings
|
|
487
|
+
proxy_pass http://ferrum_backend;
|
|
488
|
+
proxy_set_header Host $host;
|
|
489
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
490
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
491
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
492
|
+
|
|
493
|
+
# Timeouts
|
|
494
|
+
proxy_connect_timeout 60s;
|
|
495
|
+
proxy_send_timeout 120s;
|
|
496
|
+
proxy_read_timeout 120s;
|
|
497
|
+
|
|
498
|
+
# Buffering
|
|
499
|
+
proxy_buffering off;
|
|
500
|
+
proxy_request_buffering off;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
# Block all other paths
|
|
504
|
+
location / {
|
|
505
|
+
return 404;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
Enable and reload:
|
|
511
|
+
```bash
|
|
512
|
+
sudo ln -s /etc/nginx/sites-available/ferrum-mcp /etc/nginx/sites-enabled/
|
|
513
|
+
sudo nginx -t
|
|
514
|
+
sudo systemctl reload nginx
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Apache Configuration
|
|
518
|
+
|
|
519
|
+
`/etc/apache2/sites-available/ferrum-mcp.conf`:
|
|
520
|
+
|
|
521
|
+
```apache
|
|
522
|
+
<VirtualHost *:80>
|
|
523
|
+
ServerName ferrum.example.com
|
|
524
|
+
Redirect permanent / https://ferrum.example.com/
|
|
525
|
+
</VirtualHost>
|
|
526
|
+
|
|
527
|
+
<VirtualHost *:443>
|
|
528
|
+
ServerName ferrum.example.com
|
|
529
|
+
|
|
530
|
+
# SSL Configuration
|
|
531
|
+
SSLEngine on
|
|
532
|
+
SSLCertificateFile /etc/letsencrypt/live/ferrum.example.com/fullchain.pem
|
|
533
|
+
SSLCertificateKeyFile /etc/letsencrypt/live/ferrum.example.com/privkey.pem
|
|
534
|
+
|
|
535
|
+
# Security Headers
|
|
536
|
+
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
|
537
|
+
Header always set X-Frame-Options "DENY"
|
|
538
|
+
Header always set X-Content-Type-Options "nosniff"
|
|
539
|
+
|
|
540
|
+
# Logging
|
|
541
|
+
ErrorLog ${APACHE_LOG_DIR}/ferrum_error.log
|
|
542
|
+
CustomLog ${APACHE_LOG_DIR}/ferrum_access.log combined
|
|
543
|
+
|
|
544
|
+
# Proxy
|
|
545
|
+
ProxyRequests Off
|
|
546
|
+
ProxyPreserveHost On
|
|
547
|
+
|
|
548
|
+
<Location /mcp>
|
|
549
|
+
ProxyPass http://localhost:3000/mcp
|
|
550
|
+
ProxyPassReverse http://localhost:3000/mcp
|
|
551
|
+
ProxyTimeout 120
|
|
552
|
+
</Location>
|
|
553
|
+
|
|
554
|
+
<Location /health>
|
|
555
|
+
ProxyPass http://localhost:3000/health
|
|
556
|
+
ProxyPassReverse http://localhost:3000/health
|
|
557
|
+
</Location>
|
|
558
|
+
</VirtualHost>
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Enable and reload:
|
|
562
|
+
```bash
|
|
563
|
+
sudo a2enmod ssl proxy proxy_http headers
|
|
564
|
+
sudo a2ensite ferrum-mcp
|
|
565
|
+
sudo apachectl configtest
|
|
566
|
+
sudo systemctl reload apache2
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## Security Hardening
|
|
572
|
+
|
|
573
|
+
### 1. Network Security
|
|
574
|
+
|
|
575
|
+
**Firewall (UFW)**:
|
|
576
|
+
```bash
|
|
577
|
+
sudo ufw default deny incoming
|
|
578
|
+
sudo ufw default allow outgoing
|
|
579
|
+
sudo ufw allow 22/tcp # SSH
|
|
580
|
+
sudo ufw allow 80/tcp # HTTP
|
|
581
|
+
sudo ufw allow 443/tcp # HTTPS
|
|
582
|
+
sudo ufw enable
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
**Firewall (iptables)**:
|
|
586
|
+
```bash
|
|
587
|
+
# Allow established connections
|
|
588
|
+
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
589
|
+
|
|
590
|
+
# Allow SSH
|
|
591
|
+
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
|
592
|
+
|
|
593
|
+
# Allow HTTP/HTTPS
|
|
594
|
+
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
|
595
|
+
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
|
596
|
+
|
|
597
|
+
# Allow localhost
|
|
598
|
+
iptables -A INPUT -i lo -j ACCEPT
|
|
599
|
+
|
|
600
|
+
# Drop everything else
|
|
601
|
+
iptables -P INPUT DROP
|
|
602
|
+
iptables -P FORWARD DROP
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### 2. Application Security
|
|
606
|
+
|
|
607
|
+
**Environment Variables**:
|
|
608
|
+
```bash
|
|
609
|
+
# Use strong configurations
|
|
610
|
+
MAX_CONCURRENT_SESSIONS=10
|
|
611
|
+
SESSION_IDLE_TIMEOUT=1800
|
|
612
|
+
MAX_REQUESTS_PER_MINUTE=100
|
|
613
|
+
|
|
614
|
+
# Bind to localhost if using reverse proxy
|
|
615
|
+
MCP_SERVER_HOST=127.0.0.1
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**File Permissions**:
|
|
619
|
+
```bash
|
|
620
|
+
# Restrict .env file
|
|
621
|
+
chmod 600 .env
|
|
622
|
+
chown ferrum:ferrum .env
|
|
623
|
+
|
|
624
|
+
# Logs directory
|
|
625
|
+
chmod 750 logs/
|
|
626
|
+
chown -R ferrum:ferrum logs/
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### 3. Docker Security
|
|
630
|
+
|
|
631
|
+
```bash
|
|
632
|
+
docker run -d \
|
|
633
|
+
--name ferrum-mcp \
|
|
634
|
+
--user 1000:1000 \ # Non-root user
|
|
635
|
+
--read-only \ # Read-only filesystem
|
|
636
|
+
--tmpfs /tmp:rw,noexec,nosuid \ # Writable tmp
|
|
637
|
+
--security-opt no-new-privileges \ # No privilege escalation
|
|
638
|
+
--cap-drop ALL \ # Drop all capabilities
|
|
639
|
+
--cap-add NET_BIND_SERVICE \ # Only needed capabilities
|
|
640
|
+
--env-file .env \
|
|
641
|
+
-p 127.0.0.1:3000:3000 \ # Bind to localhost only
|
|
642
|
+
eth3rnit3/ferrum-mcp:latest
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### 4. SSL/TLS
|
|
646
|
+
|
|
647
|
+
**Let's Encrypt**:
|
|
648
|
+
```bash
|
|
649
|
+
sudo apt install certbot python3-certbot-nginx
|
|
650
|
+
sudo certbot --nginx -d ferrum.example.com
|
|
651
|
+
sudo systemctl reload nginx
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
**Auto-renewal**:
|
|
655
|
+
```bash
|
|
656
|
+
sudo systemctl enable certbot.timer
|
|
657
|
+
sudo systemctl start certbot.timer
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## Monitoring
|
|
663
|
+
|
|
664
|
+
### Health Checks
|
|
665
|
+
|
|
666
|
+
```bash
|
|
667
|
+
# Basic health check
|
|
668
|
+
curl http://localhost:3000/health
|
|
669
|
+
|
|
670
|
+
# Response
|
|
671
|
+
{
|
|
672
|
+
"status": "ok",
|
|
673
|
+
"version": "1.0.0",
|
|
674
|
+
"active_sessions": 3,
|
|
675
|
+
"uptime": 3600
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### Logging
|
|
680
|
+
|
|
681
|
+
**Structured logging** (planned v1.1):
|
|
682
|
+
```bash
|
|
683
|
+
# Current: Plain text
|
|
684
|
+
tail -f logs/ferrum_mcp.log
|
|
685
|
+
|
|
686
|
+
# Future: JSON logs
|
|
687
|
+
tail -f logs/ferrum_mcp.log | jq .
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
### Metrics (Prometheus)
|
|
691
|
+
|
|
692
|
+
**Planned for v1.2**:
|
|
693
|
+
```yaml
|
|
694
|
+
# prometheus.yml
|
|
695
|
+
scrape_configs:
|
|
696
|
+
- job_name: 'ferrum-mcp'
|
|
697
|
+
static_configs:
|
|
698
|
+
- targets: ['localhost:3000']
|
|
699
|
+
metrics_path: '/metrics'
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### Alerting
|
|
703
|
+
|
|
704
|
+
**Example Grafana alerts**:
|
|
705
|
+
- Active sessions > 8
|
|
706
|
+
- Memory usage > 80%
|
|
707
|
+
- Error rate > 1%
|
|
708
|
+
- Response time > 5s
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## Performance Tuning
|
|
713
|
+
|
|
714
|
+
### System Tuning
|
|
715
|
+
|
|
716
|
+
**Increase file descriptors**:
|
|
717
|
+
```bash
|
|
718
|
+
# /etc/security/limits.conf
|
|
719
|
+
ferrum soft nofile 65536
|
|
720
|
+
ferrum hard nofile 65536
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
**Shared memory**:
|
|
724
|
+
```bash
|
|
725
|
+
# For Docker
|
|
726
|
+
--shm-size=2g
|
|
727
|
+
|
|
728
|
+
# For systemd
|
|
729
|
+
# Add tmpfs mount in service file
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
### Application Tuning
|
|
733
|
+
|
|
734
|
+
**Session limits**:
|
|
735
|
+
```bash
|
|
736
|
+
# Conservative (low-resource server)
|
|
737
|
+
MAX_CONCURRENT_SESSIONS=5
|
|
738
|
+
|
|
739
|
+
# Moderate (4GB RAM)
|
|
740
|
+
MAX_CONCURRENT_SESSIONS=10
|
|
741
|
+
|
|
742
|
+
# Aggressive (8GB+ RAM)
|
|
743
|
+
MAX_CONCURRENT_SESSIONS=20
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
**Browser options**:
|
|
747
|
+
```ruby
|
|
748
|
+
# Faster but less stable
|
|
749
|
+
create_session(
|
|
750
|
+
headless: true,
|
|
751
|
+
browser_options: {
|
|
752
|
+
'--disable-dev-shm-usage': nil,
|
|
753
|
+
'--disable-gpu': nil,
|
|
754
|
+
'--no-sandbox': nil,
|
|
755
|
+
'--disable-setuid-sandbox': nil
|
|
756
|
+
}
|
|
757
|
+
)
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
### Resource Estimates
|
|
761
|
+
|
|
762
|
+
| Sessions | CPU | RAM | Notes |
|
|
763
|
+
|----------|-----|-----|-------|
|
|
764
|
+
| 1-3 | 1 core | 2 GB | Light usage |
|
|
765
|
+
| 4-10 | 2 cores | 4 GB | Moderate usage |
|
|
766
|
+
| 11-20 | 4 cores | 8 GB | Heavy usage |
|
|
767
|
+
| 21+ | 8 cores | 16 GB | Enterprise |
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## Backup and Recovery
|
|
772
|
+
|
|
773
|
+
### What to Backup
|
|
774
|
+
|
|
775
|
+
- **Configuration**: `.env`, browser configs
|
|
776
|
+
- **Logs**: `logs/` directory (optional)
|
|
777
|
+
- **BotBrowser Profiles**: `config/` directory
|
|
778
|
+
|
|
779
|
+
### Backup Script
|
|
780
|
+
|
|
781
|
+
```bash
|
|
782
|
+
#!/bin/bash
|
|
783
|
+
# backup.sh
|
|
784
|
+
|
|
785
|
+
BACKUP_DIR="/backups/ferrum-mcp"
|
|
786
|
+
DATE=$(date +%Y%m%d_%H%M%S)
|
|
787
|
+
|
|
788
|
+
mkdir -p $BACKUP_DIR
|
|
789
|
+
|
|
790
|
+
# Backup configuration
|
|
791
|
+
tar -czf $BACKUP_DIR/config_$DATE.tar.gz \
|
|
792
|
+
.env \
|
|
793
|
+
config/
|
|
794
|
+
|
|
795
|
+
# Backup logs (last 7 days)
|
|
796
|
+
find logs/ -name "*.log" -mtime -7 | \
|
|
797
|
+
tar -czf $BACKUP_DIR/logs_$DATE.tar.gz -T -
|
|
798
|
+
|
|
799
|
+
# Keep last 30 days of backups
|
|
800
|
+
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
|
|
801
|
+
|
|
802
|
+
echo "Backup completed: $BACKUP_DIR"
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
### Recovery
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
# Restore configuration
|
|
809
|
+
cd /opt/ferrum-mcp
|
|
810
|
+
tar -xzf /backups/ferrum-mcp/config_20241122_120000.tar.gz
|
|
811
|
+
|
|
812
|
+
# Restart service
|
|
813
|
+
sudo systemctl restart ferrum-mcp
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
---
|
|
817
|
+
|
|
818
|
+
## Checklist for Production
|
|
819
|
+
|
|
820
|
+
- [ ] Ruby 3.2+ installed
|
|
821
|
+
- [ ] Chrome/Chromium installed
|
|
822
|
+
- [ ] FerrumMCP deployed (Docker/systemd/K8s)
|
|
823
|
+
- [ ] Environment variables configured
|
|
824
|
+
- [ ] Session limits set (`MAX_CONCURRENT_SESSIONS`)
|
|
825
|
+
- [ ] Rate limiting configured
|
|
826
|
+
- [ ] Reverse proxy setup (nginx/Apache)
|
|
827
|
+
- [ ] SSL/TLS certificates configured
|
|
828
|
+
- [ ] Firewall rules applied
|
|
829
|
+
- [ ] Health checks working
|
|
830
|
+
- [ ] Logging configured and rotating
|
|
831
|
+
- [ ] Monitoring setup (metrics, alerts)
|
|
832
|
+
- [ ] Backup script scheduled
|
|
833
|
+
- [ ] Security hardening applied
|
|
834
|
+
- [ ] Documentation updated
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
## Getting Help
|
|
839
|
+
|
|
840
|
+
- Read [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
|
|
841
|
+
- Check [GitHub Issues](https://github.com/Eth3rnit3/FerrumMCP/issues)
|
|
842
|
+
- Email: [eth3rnit3@gmail.com](mailto:eth3rnit3@gmail.com)
|
|
843
|
+
|
|
844
|
+
---
|
|
845
|
+
|
|
846
|
+
**Last Updated**: 2024-11-22
|