Gids: moderne multi-service full-stack webapp
Met Nginx, een frontend-website en backends met Node.js en Rust.
Inhoud
Deze handleiding helpt u bij het opzetten van een webserver die het volgende host:
- Een frontend-website (HTML, CSS, PHP, JS)
- Een Node.js-backend (service)
- Een Roest-backend (service)
- Nginx als reverse proxy en frontend-server
Wat is er nieuw?
De browser communiceert alleen met Nginx en bepaalt wat er gebeurt:
- Frontend-verzoeken → HTML/CSS/PHP/JS-bestanden
- API-verzoeken → doorgestuurd naar Node.js of Rust-backend
Stap 1: Frontend-website
In dit voorbeeld bevinden de websitebestanden zich in:``` /var/www/testlab.computerbas.nl/public/
Bestanden:
- index.html
- stijlen.css
- app.js
### index.html```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My first Multi-Service Full-Stack Web App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Multi-Service Full-Stack App</h1>
<button id="nodeBtn">Get Data from Node.js</button>
<button id="rustBtn">Get Data from Rust</button>
<pre id="results"></pre>
<script src="app.js"></script>
</body>
</html>
app.js```javascript
document.addEventListener('DOMContentLoaded', () => { const nodeBtn = document.getElementById('nodeBtn'); const rustBtn = document.getElementById('rustBtn'); const resultsDiv = document.getElementById('results');
nodeBtn.addEventListener('click', async () => {
const response = await fetch('/api/nodejs/data');
const data = await response.json();
resultsDiv.textContent = JSON.stringify(data, null, 2);
});
rustBtn.addEventListener('click', async () => {
const response = await fetch('/api/rust/data');
const data = await response.json();
resultsDiv.textContent = JSON.stringify(data, null, 2);
});
});
## Stap 2: Backend-services
Deze backend-apps draaien lokaal (127.0.0.1) op verschillende poorten en zijn niet direct openbaar toegankelijk.
### A) Node.js-API
1. Maak een map, bijvoorbeeld `/home/bas/nodejs/`
2. Voer uit: `npm init -y` en `npm install express`
3. Maak een bestand `server.js`
#### server.js```javascript
const express = require('express');
const app = express();
const PORT = 3002;
app.get('/data', (req, res) => {
res.json({ service: 'Node.js', message: 'Hello from the Node API!' });
});
app.listen(PORT, '127.0.0.1', () => {
console.log(`Node.js API server listening on http://127.0.0.1:${PORT}`);
});
B) Roest-API
- Maak een nieuw project aan:
cargo new rust-app - Voeg Axum en Tokio toe:
cargo voeg axum tokio -F tokio/full toe
in src/main.rs```rust
use axum::{routing::get, Json, Router}; use serde_json::{json, Value};
async fn get_data_handler() -> Json
[tokio::main]
async fn main() { let app = Router::new().route("/data", get(get_data_handler));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3003")
.await
.unwrap();
println!("Rust API listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
## Stap 3: Beheer services met systemd
Maak systemd-services zodat de backends automatisch starten en opnieuw opstarten.
### nodejs.service```ini
[Unit]
Description=Node.js API Service
After=network.target
[Service]
User=bas
WorkingDirectory=/home/bas/nodejs/
ExecStart=/home/bas/nodejs/server.js
Restart=always
[Install]
WantedBy=multi-user.target
roestservice```ini
[Unit] Description=Rust API Service After=network.target
[Service] User=bas WorkingDirectory=/home/bas/rust ExecStart=/home/bas/rust/rust-app Restart=always
[Install] WantedBy=multi-user.target
## Stap 4: Configureer Nginx als reverse proxy
Maak een configuratiebestand:```bash
sudo nano /etc/nginx/sites-available/testlab.conf
in testlab.conf```nginx
server { listen 80; server_name testlab.computerbas.nl; return 301 https://$host$request_uri; }
server { listen 443 ssl http2; server_name testlab.computerbas.nl;
root /var/www/testlab.computerbas.nl/public;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location /api/nodejs/ {
proxy_pass http://127.0.0.1:3002/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/rust/ {
proxy_pass http://127.0.0.1:3003/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
## Resultaat
Een volledig functionele, multi-service webapplicatie.
- Frontend met Nginx
- Node.js en Rust-backends communiceren via API-routes
- Veilig, schaalbaar en eenvoudiger te onderhouden