Cliente ── HTTP(S) ──► Servidor Web ──► Conteúdo │ (estático: ficheiros) (dinâmico: PHP/Python/Node) │ Base de dados
Stack clássica: LAMP (Linux+Apache+MySQL+PHP) / LEMP (Nginx).
sudo apt update sudo apt install nginx -y sudo systemctl enable --now nginx # Firewall sudo ufw allow 'Nginx Full' # Testar curl -I http://localhost
Conteúdo por defeito em /var/www/html. Configs em /etc/nginx/.
/var/www/html
/etc/nginx/
/etc/nginx/ ├── nginx.conf # principal ├── sites-available/ # sites definidos │ └── exemplo.conf └── sites-enabled/ # ativos (symlink)
sudo ln -s /etc/nginx/sites-available/site.conf \ /etc/nginx/sites-enabled/ sudo nginx -t # testar sintaxe sudo systemctl reload nginx
server { listen 80; server_name exemplo.pt www.exemplo.pt; root /var/www/exemplo; index index.html; location / { try_files $uri $uri/ =404; } }
Permite vários sites no mesmo servidor (por nome ou porta).
sudo apt install php-fpm -y
location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; }
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
A app (Gunicorn/Node) corre numa porta local; o Nginx é a "porta da frente" (TLS, estáticos, cache).
sudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d exemplo.pt -d www.exemplo.pt
sudo certbot renew --dry-run
server_tokens off
www-data
/var/log/nginx/
sudo nginx -t # sintaxe systemctl status nginx sudo tail -f /var/log/nginx/error.log curl -I https://exemplo.pt ss -tulpn | grep -E ':80|:443'
502/504 → backend (app) em baixo. 403 → permissões. 404 → root/try_files.