Parte 3 - Reverse proxy, DNS, TLS
Cele trei piese care fac diferența între “rulează pe localhost” și “e accesibil pe internet la https://numele-vostru.dev”.
Reverse proxy: ce e și de ce
Un reverse proxy e un server care primește request-uri și le direcționează către alte servere din spate. Dintr-un singur punct de intrare (portul 443) gestionează:
- TLS termination - decriptează HTTPS, rulează HTTP intern către containere
- Routing -
/api/*la API,/*la frontend,/adminla alt serviciu - Rate limiting - blochează request-uri abuzive
- Headers manipulation - adaugă
X-Forwarded-For, security headers - Compression - gzip pentru text/css/js
- Static caching - servește singur fișiere statice frecvente
În stack-ul vostru, proxy-ul nginx primește tot traficul, decide unde să-l trimită:
Config nginx pentru proxy
nginx/nginx.conf (top-level config):
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off; # nu expune versiunea nginx
gzip on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
access_log /dev/stdout; # docker logs proxy va arata access log
error_log /dev/stderr warn;
include /etc/nginx/conf.d/*.conf;
}
nginx/conf.d/default.conf (regulile de proxy):
# HTTP -> redirectionare permanenta la HTTPS
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
# HTTPS - serve frontend + proxy /api/* la api
server {
listen 443 ssl;
http2 on;
server_name localhost;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location /api/ {
proxy_pass http://api:8080;
proxy_http_version 1.1;
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 /swagger {
proxy_pass http://api:8080;
proxy_set_header Host $host;
}
# Pagini MVC (Login/Register din Lab12 sunt servite tot de API container)
location /Auth/ {
proxy_pass http://api:8080;
proxy_set_header Host $host;
}
# Imagini din wwwroot/images servite de API
location /images/ {
proxy_pass http://api:8080;
proxy_set_header Host $host;
}
# Tot restul - frontend Angular static
location / {
proxy_pass http://frontend:80;
proxy_http_version 1.1;
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 se evaluează pe baza prefixului, în ordine de specificitate. location /api/ e mai specific decât location /, deci /api/articles se duce la API, nu la frontend.
proxy_pass http://api:8080 - aici api e numele serviciului din compose, rezolvat prin DNS-ul intern Docker. Ăsta e magia bridge-network: dintr-un container, alt container e accesibil prin nume.
TLS pe scurt
HTTPS = HTTP + TLS. TLS face două lucruri:
- Criptarea - tot ce trece între client și server e criptat. Nimeni în mijloc (ISP, sniffer wifi) nu poate citi.
- Autentificarea serverului - clientul verifică că site-ul e cine zice că e (printr-un certificat semnat de o autoritate de încredere - CA).
Un certificat TLS conține:
- Domeniul pentru care e valid (ex
*.example.com) - Cheia publică a serverului
- Semnătura unei autorități (CA) care garantează că cheia aparține domeniului
Browserele au pre-instalate ~150 CA-uri de încredere (Mozilla CA list). Dacă un cert e semnat de unul dintre ele, browserul acceptă. Altfel, warning “connection not private”.
Self-signed pentru dev local
Pentru dev local nu aveți nevoie de un cert “real” - merge unul self-signed (semnat de voi, nu de o CA). Browserul va da warning, dar pentru localhost e ok.
Generați cu OpenSSL:
openssl req -x509 -newkey rsa:4096 \
-keyout server.key \
-out server.crt \
-days 365 \
-nodes \
-subj "/CN=localhost"
Plasați server.crt și server.key în certs/. Compose-ul mountează ./certs:/etc/nginx/certs:ro -> nginx îl folosește.
Let’s Encrypt pentru producție
Pentru un domeniu real, folosiți Let’s Encrypt - o CA gratuită care emite certificate prin protocolul ACME. Tool-ul standard: certbot.
Two challenges:
- HTTP-01 - certbot pune un fișier la
http://yourdomain/.well-known/acme-challenge/..., Let’s Encrypt face GET, vede valoarea așteptată. Necesită ca domeniul să fie deja accesibil pe portul 80. - DNS-01 - certbot pune o înregistrare TXT în DNS-ul vostru. Mai complex, dar funcționează pentru wildcard certs (
*.example.com).
În producție, certbot rulează în container, într-un loop care reînnoiește certul la fiecare 12h:
certbot certonly --webroot -w /var/www/certbot -d yourdomain.com -m admin@yourdomain.com --agree-tos
# certificatele aterizeaza in /etc/letsencrypt/live/yourdomain.com/
VPS-ul cursului face asta automat - voi nu vă ocupați de cert. URL-ul https://<numele-vostru>.student-dev.ro are certificat valid emis de Let’s Encrypt, fără warning de browser.
DNS pe scurt
DNS = traducerea de la nume domeniu la IP. Când introduceți https://example.com, browserul întreabă un resolver: “ce IP are example.com?”. Resolver-ul întreabă autoritățile, se întoarce cu un IP, browserul deschide TCP la IP-ul ăla.
Tipuri de înregistrări (records)
| Tip | Ce face | Exemplu |
|---|---|---|
| A | Mapează nume -> IPv4 | example.com -> 1.2.3.4 |
| AAAA | Mapează nume -> IPv6 | example.com -> 2001:db8::1 |
| CNAME | Alias la alt nume | www.example.com -> example.com |
| MX | Server email | example.com -> mail.example.com priority=10 |
| TXT | Date arbitrare (SPF, verificări) | example.com -> "v=spf1 include:..." |
| NS | Care servere DNS sunt autoritate | example.com -> ns1.cloudflare.com |
Pentru proiect, aveți nevoie doar de A record: subdomeniul vostru -> IP-ul VPS-ului. În lab-ul nostru, toate subdomeniile *.student-dev.ro sunt deja mapate la 178.105.43.73 via wildcard (vedeți mai jos).
Wildcard records
Pentru *.example.com -> 1.2.3.4, orice subdomeniu se rezolvă la IP-ul respectiv. Ăsta e ce face VPS-ul cursului: un singur record *.student-dev.ro mapează toate <student-x>.student-dev.ro, <student-y>.student-dev.ro etc. la IP-ul serverului.
*.student-dev.ro 300 A 178.105.43.73
(300 = TTL în secunde - cât timp poate fi cached).
Tools utile
dig +short newsportal.student-dev.ro # ce IP rezolva
dig newsportal.student-dev.ro any # toate inregistrarile
nslookup newsportal.student-dev.ro # alt query DNS
whois student-dev.ro # cine e proprietar, cand expira
Cumpărat domeniu
Registrari uzuali:
- Spaceship - cei mai ieftini overall, panou OK
- Cloudflare Registrar - vinde la cost (renew identic cu price-ul wholesale), DNS gratis bun
- Namecheap - rezonabil, multe TLD-uri
- Evitați: GoDaddy (prețuri umflate la renew), domain parker (revând cu marjă)
TLD recomandate pentru proiecte tehnice (~$10-15/an):
.dev- HSTS preload (forțează HTTPS automat).app- similar.codes,.tech- mai “creative”.io- popular dar scump (~$30/an)
Evitați TLD-urile gratuite (.tk, .ml, .ga) - sunt instabile și reputației lor le pasă Google și email providers, multe ajung blocate.
Ce ați învățat
- Reverse proxy = single point of entry, TLS termination, routing
- nginx config: server blocks, location, proxy_pass, headers
- TLS: criptare + autentificare, CA-uri, self-signed pentru dev
- Let’s Encrypt + certbot pentru producție (cert real, gratuit, auto-renew)
- DNS: A/CNAME/MX/TXT, wildcard records, tools (
dig,nslookup) - Registrari: cum cumpărați un domeniu
În secțiunea următoare combinăm toate astea pentru un deploy real pe VPS.