Instalando e configurando Nginx

1. Introdução ao Nginx no Contexto DevOps

1.1. O papel do Nginx como proxy reverso e load balancer

No ecossistema DevOps, o Nginx se destaca como uma ferramenta essencial para gerenciar tráfego de rede em arquiteturas modernas. Atuando como proxy reverso, ele recebe requisições externas e as encaminha para servidores internos, ocultando a infraestrutura real. Como load balancer, distribui o tráfego entre múltiplos servidores, garantindo alta disponibilidade e escalabilidade.

1.2. Cenários de uso: servindo aplicações estáticas, APIs e microsserviços

O Nginx é versátil em diversos cenários:
- Aplicações estáticas: sites HTML/CSS/JS com alta performance de cache
- APIs REST: proxy reverso para backends como Node.js, Python ou Java
- Microsserviços: roteamento inteligente entre dezenas de serviços em clusters Kubernetes

1.3. Comparação com outras soluções

Característica Nginx Apache Caddy Traefik
Performance estática Excelente Boa Boa Média
Configuração Declarativa .htaccess Automática Dinâmica
HTTPS nativo Manual Manual Automático Automático
Docker/K8s Excelente Boa Boa Excelente

2. Instalação do Nginx

2.1. Instalação via gerenciador de pacotes

Ubuntu/Debian:

sudo apt update
sudo apt install nginx -y

CentOS/RHEL:

sudo yum install epel-release -y
sudo yum install nginx -y

2.2. Instalação via Docker

docker run --name nginx-server -d -p 80:80 nginx:alpine

Para configuração persistente:

docker run --name nginx-custom \
  -v /caminho/local/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v /caminho/local/html:/usr/share/nginx/html:ro \
  -d -p 80:80 nginx:alpine

2.3. Verificação da instalação

# Verificar versão
nginx -v

# Gerenciar serviço
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx

# Testar acesso
curl http://localhost

3. Estrutura de Diretórios e Arquivos de Configuração

3.1. Diretórios principais

/etc/nginx/           # Configurações principais
/var/log/nginx/      # Logs de acesso e erro
/var/www/html/       # Document root padrão
/usr/share/nginx/    # Arquivos estáticos do Nginx

3.2. Arquivo principal e inclusão de sites

O arquivo /etc/nginx/nginx.conf gerencia a configuração global:

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 768;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Inclusão de sites habilitados
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Para gerenciar sites:

sudo ln -s /etc/nginx/sites-available/meusite /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

3.3. Blocos de configuração

http {
    server {
        listen 80;
        server_name exemplo.com;

        location / {
            root /var/www/html;
            index index.html;
        }

        location /api/ {
            proxy_pass http://backend:3000;
        }
    }
}

4. Configuração Básica de um Servidor Web

4.1. Virtual host para arquivos estáticos

server {
    listen 80;
    server_name meusite.local;
    root /var/www/meusite;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    # Cache de arquivos estáticos
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

4.2. Configuração de logs customizados

http {
    log_format custom '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent" '
                      '$request_time';

    access_log /var/log/nginx/meusite_access.log custom;
    error_log /var/log/nginx/meusite_error.log warn;

    server {
        listen 80;
        server_name meusite.local;

        access_log /var/log/nginx/meusite_access.log custom;
        error_log /var/log/nginx/meusite_error.log;
    }
}

4.3. Habilitando compressão gzip

http {
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 256;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}

5. Configuração como Proxy Reverso

5.1. Proxy reverso para backend Node.js

server {
    listen 80;
    server_name api.exemplo.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

5.2. Cabeçalhos HTTP importantes

location / {
    proxy_pass http://backend:5000;

    # Preservar informações do cliente
    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;

    # Bufferização
    proxy_buffering off;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
}

5.3. Balanceamento de carga com upstream

upstream backend_pool {
    # Round-robin (padrão)
    server backend1:3000 weight=3;
    server backend2:3000 weight=2;
    server backend3:3000 backup;

    # Opções alternativas:
    # least_conn;
    # ip_hash;

    keepalive 32;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend_pool;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

6. Segurança e Boas Práticas

6.1. Restrição de acesso e rate limiting

# Restrição por IP
location /admin {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
}

# Rate limiting
http {
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        location /api/ {
            limit_req zone=api_limit burst=20 nodelay;
            proxy_pass http://backend;
        }
    }
}

6.2. Configuração HTTPS com Let's Encrypt

server {
    listen 443 ssl http2;
    server_name exemplo.com;

    ssl_certificate /etc/letsencrypt/live/exemplo.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exemplo.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Redirecionar HTTP para HTTPS
    if ($scheme != "https") {
        return 301 https://$server_name$request_uri;
    }
}

6.3. Headers de segurança

server {
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" always;
}

7. Monitoramento e Troubleshooting

7.1. Testando configurações

# Testar sintaxe
nginx -t

# Recarregar sem downtime
nginx -s reload

# Verificar processos
ps aux | grep nginx

7.2. Análise de logs

# Logs em tempo real
tail -f /var/log/nginx/access.log

# Filtrar erros 5xx
grep " 5[0-9][0-9] " /var/log/nginx/access.log

# Top 10 IPs mais frequentes
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# Usar GoAccess para análise visual
goaccess /var/log/nginx/access.log -o report.html --log-format=COMBINED

7.3. Métricas de performance

# Status das conexões
curl http://localhost/nginx_status

# Uso de memória
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | grep nginx

# Verificar conexões ativas
ss -tlnp | grep nginx

# Monitorar com netdata ou prometheus

8. Integração com Docker e Kubernetes

8.1. Dockerfile customizado com multi-stage builds

# Estágio 1: Build da aplicação
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Estágio 2: Nginx
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

8.2. Docker Compose: orquestrando Nginx com backend

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./static:/usr/share/nginx/html:ro
    depends_on:
      - backend
    networks:
      - app-network

  backend:
    build: ./backend
    expose:
      - "3000"
    environment:
      - NODE_ENV=production
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

8.3. Kubernetes: Deployment e Service para Nginx como Ingress Controller

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.exemplo.com
    secretName: tls-secret
  rules:
  - host: app.exemplo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: backend-service
            port:
              number: 3000

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer

Referências