Skip to content

Commit 42891f3

Browse files
authored
Merge pull request #162 from PoCInnovation/156-provide-nginx-config
feat(docs): provide nginx config and guidance for deployment, firewal…
2 parents 8343b1a + 3daf461 commit 42891f3

2 files changed

Lines changed: 115 additions & 6 deletions

File tree

README.md

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ When an event reaches its deadline, the share link stops working, all VM credent
125125

126126
```bash
127127
bash setup.sh
128+
129+
cp .env.example .env
130+
128131
docker compose --profile master up -d --build
129132
```
130133

@@ -136,12 +139,7 @@ For development with hot-reloading:
136139
docker compose --profile dev up --build
137140
```
138141

139-
To run a slave node on another machine:
140-
141-
```bash
142-
bash setup.sh
143-
docker compose --profile slave up -d --build
144-
```
142+
To run a slave node on another machine, use the `slave` and follow the guide on the frontend:
145143

146144
## Configuration
147145

@@ -158,6 +156,77 @@ Copy `.env.example` to `.env` and adjust as needed. Key variables:
158156
| `BACKEND_PORT` | `8080` | Backend API port |
159157
| `VITE_PORT` | `3000` | Frontend port |
160158

159+
## Deployment
160+
161+
### Reverse Proxy (nginx)
162+
163+
In production, you should place nginx in front of the application to serve both the frontend and backend on a single port. A ready-to-use configuration is provided in [`nginx.conf`](./nginx.conf).
164+
165+
Install it:
166+
167+
```bash
168+
sudo cp nginx.conf /etc/nginx/sites-available/distribox
169+
sudo ln -s /etc/nginx/sites-available/distribox /etc/nginx/sites-enabled/
170+
sudo nginx -t && sudo systemctl reload nginx
171+
```
172+
173+
This configuration:
174+
- Listens on port **80** and routes traffic to the frontend (port 3000) and backend (port 8080)
175+
- Proxies WebSocket connections for VM streaming (`/tunnel`)
176+
- All other backend routes (`/auth`, `/vms`, `/images`, etc.) are forwarded to the API
177+
178+
> Note: If you change port configuration for the deployment, we trust you will update the reverse proxy configuration accordingly.
179+
180+
After enabling the reverse proxy, update your `.env` so the frontend calls the backend through nginx instead of directly:
181+
182+
```env
183+
VITE_API_DOMAIN=http://your-domain.com
184+
FRONTEND_URL=http://your-domain.com
185+
```
186+
187+
### Firewall
188+
189+
VNC servers listen on ports 5900-5999 on the host. These must **not** be exposed to the network -- VM streaming is handled securely through the Guacamole WebSocket tunnel. Block external access with your firewall:
190+
191+
```bash
192+
# ufw
193+
sudo ufw deny 5900:5999/tcp
194+
195+
# or iptables
196+
sudo iptables -A INPUT -p tcp --dport 5900:5999 -j DROP
197+
```
198+
199+
### SSL is STRONGLY RECOMMENDED
200+
201+
Distribox should be served over HTTPS. Without SSL:
202+
203+
- **Clipboard will not work.** The browser Clipboard API (`navigator.clipboard`) is only available in [secure contexts](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API#security_considerations) (HTTPS). Copying VM credentials, event links, or any other data from the dashboard will silently fail on plain HTTP.
204+
- **Pasting into VMs will not work.** The Guacamole client uses the Clipboard API to sync your clipboard with the remote VM. Without HTTPS, you will not be able to paste text into a VM session from your browser.
205+
206+
The easiest way to set up SSL is with [Certbot](https://certbot.eff.org/) (Let's Encrypt):
207+
208+
```bash
209+
sudo apt install certbot python3-certbot-nginx
210+
sudo certbot --nginx -d your-domain.com
211+
```
212+
213+
Certbot will automatically modify your nginx configuration to:
214+
- Redirect HTTP (port 80) to HTTPS (port 443)
215+
- Install and renew your TLS certificate
216+
217+
After running Certbot, update your `.env`:
218+
219+
```env
220+
VITE_API_DOMAIN=https://your-domain.com
221+
FRONTEND_URL=https://your-domain.com
222+
```
223+
224+
Certbot sets up automatic renewal via a systemd timer. You can verify it with:
225+
226+
```bash
227+
sudo certbot renew --dry-run
228+
```
229+
161230
## Tech Stack
162231

163232
- **Backend:** FastAPI, SQLModel, PostgreSQL, libvirt, KVM/QEMU

nginx.conf

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
server {
2+
listen 80;
3+
server_name _;
4+
5+
# Backend API routes (FastAPI on port 8080)
6+
location ~ ^/(auth|vms|images|host|events|slaves|policies|users|docs|openapi\.json|redoc) {
7+
proxy_pass http://127.0.0.1:8080;
8+
proxy_http_version 1.1;
9+
proxy_set_header Host $host;
10+
proxy_set_header X-Real-IP $remote_addr;
11+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
12+
proxy_set_header X-Forwarded-Proto $scheme;
13+
}
14+
15+
# WebSocket tunnel for Guacamole VNC streaming
16+
location /tunnel {
17+
proxy_pass http://127.0.0.1:8080;
18+
proxy_http_version 1.1;
19+
proxy_set_header Upgrade $http_upgrade;
20+
proxy_set_header Connection "upgrade";
21+
proxy_set_header Host $host;
22+
proxy_set_header X-Real-IP $remote_addr;
23+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
24+
proxy_set_header X-Forwarded-Proto $scheme;
25+
26+
# WebSocket connections can be long-lived
27+
proxy_read_timeout 86400s;
28+
proxy_send_timeout 86400s;
29+
}
30+
31+
# Frontend (React app on port 3000) — catch-all
32+
location / {
33+
proxy_pass http://127.0.0.1:3000;
34+
proxy_http_version 1.1;
35+
proxy_set_header Host $host;
36+
proxy_set_header X-Real-IP $remote_addr;
37+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
38+
proxy_set_header X-Forwarded-Proto $scheme;
39+
}
40+
}

0 commit comments

Comments
 (0)