Skip to content

Commit ccb5191

Browse files
committed
Aggiornato readme con dettagli installazione
1 parent afd1a75 commit ccb5191

1 file changed

Lines changed: 218 additions & 0 deletions

File tree

README.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,224 @@ sentinelcore/
292292

293293
---
294294

295+
296+
## 🚀 Binary Deployment
297+
298+
Pre-compiled binaries are distributed in the release package. No Rust toolchain is needed on the server.
299+
300+
**Release package contents:**
301+
```
302+
vulnerability-manager # backend binary (x86_64 Linux)
303+
migrations/ # SQL migration files (56 files)
304+
vulnerability-manager-frontend/build/ # React production build
305+
```
306+
307+
### System Requirements
308+
309+
- Debian 12/13 or Ubuntu 22.04+ (x86_64)
310+
- 2+ CPU cores, 4 GB+ RAM
311+
- PostgreSQL 15+, Nginx
312+
- `nmap`, `arp-scan` packages
313+
314+
### 1. Install Dependencies
315+
316+
```bash
317+
sudo apt update
318+
sudo apt install -y postgresql nginx nmap arp-scan libssl3
319+
```
320+
321+
---
322+
323+
### 2. PostgreSQL Setup
324+
325+
```bash
326+
sudo systemctl start postgresql
327+
sudo systemctl enable postgresql
328+
329+
sudo -u postgres psql -c "CREATE USER vlnman WITH PASSWORD 'your-strong-password';"
330+
sudo -u postgres psql -c "CREATE DATABASE vulnerability_manager OWNER vlnman;"
331+
```
332+
333+
> **Important:** The backend connects via TCP (`127.0.0.1:5432`), not via Unix socket.
334+
> Always use `127.0.0.1` (not `localhost`) in the connection URL — using `localhost`
335+
> can cause libpq to fall back to the Unix socket, triggering peer authentication
336+
> failure even though the pg_hba.conf allows scram-sha-256 for TCP connections.
337+
338+
---
339+
340+
### 3. Apply Database Migrations
341+
342+
Migrations are **not** applied automatically at startup. Run them manually before
343+
the first start, and again after any update that adds new migration files.
344+
345+
```bash
346+
# Copy migrations to the server first, then:
347+
for f in $(ls /opt/sentinelcore/migrations/*.sql | sort); do
348+
PGPASSWORD=your-password psql -h 127.0.0.1 -U vlnman -d vulnerability_manager -f "$f"
349+
done
350+
```
351+
352+
> The migrations directory contains 56 SQL files numbered sequentially.
353+
> They must be applied in alphabetical/numerical order.
354+
355+
---
356+
357+
### 4. Install Application Files
358+
359+
```bash
360+
sudo mkdir -p /opt/sentinelcore/{migrations,uploads}
361+
sudo chown -R $USER:$USER /opt/sentinelcore
362+
363+
# Backend binary
364+
cp vulnerability-manager /opt/sentinelcore/
365+
chmod +x /opt/sentinelcore/vulnerability-manager
366+
367+
# Migrations (keep for future upgrades)
368+
cp -r migrations/ /opt/sentinelcore/
369+
```
370+
371+
---
372+
373+
### 5. Environment Configuration
374+
375+
Create `/opt/sentinelcore/.env`:
376+
377+
```bash
378+
# Database — use 127.0.0.1, not localhost (see section 2)
379+
VULN_DATABASE_URL=postgresql://vlnman:your-password@127.0.0.1:5432/vulnerability_manager
380+
381+
# JWT secret — generate a strong random key (minimum 32 characters)
382+
JWT_SECRET_KEY=replace-with-a-long-random-secret-key
383+
384+
# Logging
385+
RUST_LOG=info,vulnerability_manager=info
386+
```
387+
388+
> **Config system note:** The default configuration is embedded in the binary at
389+
> compile time via `include_str!`. Runtime overrides require the `VULN_` prefix.
390+
> The separator is `_`, so `VULN_DATABASE_URL` maps to `database.url`,
391+
> `VULN_SERVER_PORT` maps to `server.port`, and so on.
392+
>
393+
> Alternatively, place a `config/development.yaml` (or `config/production.yaml`
394+
> with `APP_ENV=production`) in the working directory `/opt/sentinelcore/`.
395+
> This file is loaded at runtime and merged on top of compiled-in defaults.
396+
397+
---
398+
399+
### 6. Systemd Service
400+
401+
Create `/etc/systemd/system/sentinelcore.service`:
402+
403+
```ini
404+
[Unit]
405+
Description=SentinelCore Vulnerability Manager Backend
406+
After=network.target postgresql.service
407+
Requires=postgresql.service
408+
409+
[Service]
410+
Type=simple
411+
User=your-user
412+
WorkingDirectory=/opt/sentinelcore
413+
EnvironmentFile=/opt/sentinelcore/.env
414+
ExecStart=/opt/sentinelcore/vulnerability-manager
415+
Restart=on-failure
416+
RestartSec=5
417+
StandardOutput=journal
418+
StandardError=journal
419+
SyslogIdentifier=sentinelcore
420+
421+
[Install]
422+
WantedBy=multi-user.target
423+
```
424+
425+
```bash
426+
sudo systemctl daemon-reload
427+
sudo systemctl enable sentinelcore
428+
sudo systemctl start sentinelcore
429+
430+
# Verify
431+
sudo systemctl status sentinelcore
432+
sudo journalctl -u sentinelcore -f
433+
```
434+
435+
---
436+
437+
### 7. Nginx Configuration
438+
439+
Deploy the React build and install the site config:
440+
441+
```bash
442+
# Copy frontend static files
443+
sudo cp -r build/* /usr/share/nginx/html/
444+
```
445+
446+
Create `/etc/nginx/sites-available/sentinelcore`:
447+
448+
```nginx
449+
server {
450+
listen 80;
451+
listen [::]:80;
452+
server_name _;
453+
454+
root /usr/share/nginx/html;
455+
index index.html;
456+
457+
add_header X-Frame-Options "DENY" always;
458+
add_header X-Content-Type-Options "nosniff" always;
459+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
460+
461+
gzip on;
462+
gzip_vary on;
463+
gzip_min_length 1024;
464+
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript;
465+
466+
# Cache static assets (filenames are content-hashed by the build tool)
467+
location ~* \.(js|css|woff2?|ttf|eot|svg|ico|png|jpg)$ {
468+
expires 1y;
469+
add_header Cache-Control "public, immutable";
470+
}
471+
472+
# Proxy API requests to the backend
473+
location /api/ {
474+
proxy_pass http://127.0.0.1:8080;
475+
proxy_http_version 1.1;
476+
proxy_set_header Host $host;
477+
proxy_set_header X-Real-IP $remote_addr;
478+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
479+
proxy_set_header X-Forwarded-Proto $scheme;
480+
}
481+
482+
# Proxy file uploads served by the backend
483+
location /uploads/ {
484+
proxy_pass http://127.0.0.1:8080;
485+
proxy_set_header Host $host;
486+
proxy_set_header X-Real-IP $remote_addr;
487+
}
488+
489+
# SPA fallback — all unmatched routes return index.html
490+
location / {
491+
try_files $uri $uri/ /index.html;
492+
}
493+
494+
location ~ /\. {
495+
deny all;
496+
}
497+
}
498+
```
499+
500+
```bash
501+
sudo ln -sf /etc/nginx/sites-available/sentinelcore /etc/nginx/sites-enabled/sentinelcore
502+
sudo rm -f /etc/nginx/sites-enabled/default # remove default nginx page
503+
sudo nginx -t
504+
sudo systemctl reload nginx
505+
```
506+
507+
> **Why this nginx layout matters:** The frontend must be served as static files by
508+
> nginx, with only `/api/` and `/uploads/` proxied to the backend. Proxying
509+
> everything through the backend would bypass the React router (SPA fallback) and
510+
> break client-side navigation.
511+
512+
---
295513
## Development
296514

297515
```bash

0 commit comments

Comments
 (0)