0%
Montando um Servidor Web no Linux: Nginx e Apache

Montando um Servidor Web no Linux: Nginx e Apache

Guia completo para implantar um servidor web Linux: Nginx ou Apache, virtual hosts, HTTPS com Let's Encrypt, reverse proxy, segurança e otimizações.

I

InSkillCoach

· min

Montando um Servidor Web no Linux: Nginx e Apache

Hospedar um site ou uma aplicação web no seu próprio servidor Linux é um dos exercícios mais formativos da administração de sistemas: ele envolve gerenciamento de pacotes, serviços systemd, rede, certificados TLS e segurança. Neste guia, vamos montar um servidor web completo, da instalação ao HTTPS, passando pelo reverse proxy, cobrindo os dois servidores que dominam o mercado: Nginx e Apache. Os exemplos usam Ubuntu/Debian; as diferenças em relação à família Red Hat são indicadas quando existem.

1. Escolher entre Nginx e Apache

Os dois servidores são maduros, performáticos e perfeitamente capazes de hospedar qualquer site. No entanto, suas arquiteturas são diferentes, e certos contextos favorecem um ou outro.

CritérioNginxApache
ArquiteturaOrientada a eventos, assíncronaProcessos/threads por conexão (MPM event moderno)
Conteúdo estáticoExcelente, uso de memória muito baixoBom
Conexões simultâneas em massaPonto forte históricoAdequado com mpm_event
Reverse proxy / load balancingNativo e muito utilizadoPossível (mod_proxy)
Arquivos .htaccessNão suportadosSuportados (configuração por diretório)
Execução de código (PHP…)Sempre delegada (FastCGI/PHP-FPM)Módulos integrados possíveis (mod_php)
Sintaxe de configuraçãoBlocos concisosDiretivas estilo XML, mais verbosas
Caso de uso típicoReverse proxy, estático, aplicações modernasHospedagem compartilhada, legado, .htaccess necessário

Em 2026, a escolha padrão para um novo projeto costuma ser o Nginx: reverse proxy nativo, configuração compacta, consumo de memória estável sob carga alta. O Apache continua indispensável quando seus usuários precisam alterar a configuração por diretório (.htaccess) ou para aplicações legadas que dependem disso. O restante do guia privilegia o Nginx e apresenta os equivalentes do Apache nas etapas-chave.

2. Instalação

Nginx

# Debian / Ubuntu
sudo apt update
sudo apt install nginx

# RHEL / Rocky / Alma
sudo dnf install nginx
sudo systemctl enable --now nginx

# Verificar se o serviço está em execução
systemctl status nginx
curl -I http://localhost

Apache

# Debian / Ubuntu (o pacote e o serviço se chamam apache2)
sudo apt install apache2

# RHEL / Rocky / Alma (o pacote e o serviço se chamam httpd)
sudo dnf install httpd
sudo systemctl enable --now httpd

Não se esqueça de abrir o firewall:

# Ubuntu com ufw
sudo ufw allow "Nginx Full"

# RHEL com firewalld
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload

3. Estrutura de Configuração

Nginx

/etc/nginx/
├── nginx.conf              # configuração principal
├── conf.d/                 # arquivos .conf incluídos automaticamente
├── sites-available/        # seus vhosts (Debian/Ubuntu)
├── sites-enabled/          # links simbólicos para os vhosts ativos
└── snippets/               # fragmentos reutilizáveis (SSL, etc.)

No Debian/Ubuntu, cada site é escrito em sites-available/ e depois ativado por meio de um link simbólico em sites-enabled/. No RHEL, essa convenção não existe: coloque seus arquivos diretamente em conf.d/.

# Ativar um site (Debian/Ubuntu)
sudo ln -s /etc/nginx/sites-available/monsite.conf /etc/nginx/sites-enabled/

# Desativar um site: remova o link, nunca o arquivo de origem
sudo rm /etc/nginx/sites-enabled/monsite.conf

Apache

/etc/apache2/                     # Debian/Ubuntu (RHEL: /etc/httpd/)
├── apache2.conf                  # configuração principal
├── sites-available/              # vhosts disponíveis
├── sites-enabled/                # vhosts ativos
├── mods-available/               # módulos disponíveis
└── mods-enabled/                 # módulos ativos

O Apache fornece comandos dedicados para a ativação:

sudo a2ensite monsite.conf        # ativar um vhost
sudo a2dissite monsite.conf       # desativar
sudo a2enmod rewrite ssl headers  # ativar módulos

4. Virtual Hosts e Server Blocks

Um mesmo servidor pode hospedar vários sites, distinguidos pelo nome de domínio. O Nginx fala em “server blocks”, o Apache em “virtual hosts”.

Server block completo no Nginx

# /etc/nginx/sites-available/monsite.conf
server {
    listen 80;
    listen [::]:80;

    server_name monsite.example.com;

    root /var/www/monsite;
    index index.html index.htm;

    # Logs dedicados ao site
    access_log /var/log/nginx/monsite.access.log;
    error_log  /var/log/nginx/monsite.error.log;

    location / {
        # Servir o arquivo, senão o diretório, senão 404
        try_files $uri $uri/ =404;
    }

    # Bloquear o acesso a arquivos ocultos (.git, .env...)
    location ~ /\. {
        deny all;
    }
}
# Criar a raiz do site e uma página de teste
sudo mkdir -p /var/www/monsite
echo "<h1>Bienvenue sur monsite</h1>" | sudo tee /var/www/monsite/index.html
sudo chown -R www-data:www-data /var/www/monsite

# Ativar e recarregar
sudo ln -s /etc/nginx/sites-available/monsite.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Virtual host equivalente no Apache

# /etc/apache2/sites-available/monsite.conf
<VirtualHost *:80>
    ServerName monsite.example.com
    DocumentRoot /var/www/monsite

    ErrorLog ${APACHE_LOG_DIR}/monsite.error.log
    CustomLog ${APACHE_LOG_DIR}/monsite.access.log combined

    <Directory /var/www/monsite>
        Options -Indexes
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
sudo a2ensite monsite.conf
sudo apachectl configtest && sudo systemctl reload apache2

5. HTTPS com Let’s Encrypt

Um site sem HTTPS já não é aceitável: navegadores e mecanismos de busca penalizam o HTTP. O Let’s Encrypt fornece certificados gratuitos, e o certbot automatiza tudo, do desafio de validação à renovação.

# Instalação do certbot com o plugin do Nginx
sudo apt install certbot python3-certbot-nginx
# (Apache: python3-certbot-apache; RHEL: via EPEL)

# Obter o certificado E modificar a configuração automaticamente
sudo certbot --nginx -d monsite.example.com

# Verificar a renovação automática (timer systemd)
systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Pré-requisitos: o domínio deve apontar para o IP público do servidor (registro DNS A/AAAA) e a porta 80 deve estar acessível para o desafio HTTP-01. O certbot adiciona o redirecionamento de HTTP para HTTPS e configura os certificados no seu server block:

# Trecho adicionado pelo certbot no server block
listen 443 ssl;
ssl_certificate     /etc/letsencrypt/live/monsite.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/monsite.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;

Os certificados do Let’s Encrypt são válidos por 90 dias; o timer systemd instalado pelo pacote os renova automaticamente à medida que o vencimento se aproxima. Basta executar o --dry-run uma vez após a instalação.

6. Reverse Proxy para uma Aplicação

Caso extremamente comum: sua aplicação (Node.js, Python, Go…) escuta em uma porta local, e o Nginx a publica na porta 443, cuidando de TLS, compressão e logs.

# /etc/nginx/sites-available/app.conf
# Agrupamento dos backends (permite load balancing mais tarde)
upstream mon_app {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    listen 443 ssl;
    server_name app.example.com;

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

    location / {
        proxy_pass http://mon_app;

        # Transmitir as informações do cliente para a aplicação
        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;

        # Suporte a WebSockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Timeouts razoáveis
        proxy_connect_timeout 5s;
        proxy_read_timeout    60s;
    }
}

Os cabeçalhos X-Forwarded-* são essenciais: sem eles, sua aplicação vê todas as requisições vindo de 127.0.0.1 e acredita estar em HTTP. Na família Red Hat, lembre-se também do booleano SELinux que autoriza o Nginx a abrir conexões de saída:

sudo setsebool -P httpd_can_network_connect on

7. Cabeçalhos de Segurança

Alguns cabeçalhos HTTP protegem seus visitantes contra clickjacking, MIME sniffing e downgrades para HTTP. Coloque-os no server block (ou em um snippet incluído por todos os seus sites):

# /etc/nginx/snippets/security-headers.conf
# HSTS: força HTTPS por 2 anos (só ative quando o HTTPS estiver estável)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

# Proíbe a inclusão do site em um iframe de terceiros (clickjacking)
add_header X-Frame-Options "SAMEORIGIN" always;

# Proíbe o navegador de adivinhar os tipos MIME
add_header X-Content-Type-Options "nosniff" always;

# Limita as informações de origem transmitidas a sites de terceiros
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Em cada server block HTTPS
include snippets/security-headers.conf;

Adicione uma Content-Security-Policy adaptada ao seu site quando você conhecer com precisão as origens de seus scripts e estilos: é o cabeçalho mais eficaz, mas uma configuração rígida demais quebra o site. Teste sua configuração em securityheaders.com e a parte de TLS em ssllabs.com.

Oculte também a versão do servidor, uma informação inútil de oferecer a scanners:

# No bloco http {} de /etc/nginx/nginx.conf
server_tokens off;

8. Logs e Rotação

Ler os logs

# Acompanhar o tráfego em tempo real
sudo tail -f /var/log/nginx/access.log

# Acompanhar os erros
sudo tail -f /var/log/nginx/error.log

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

# Contar os códigos de resposta
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

Rotação com logrotate

Os pacotes Nginx e Apache já instalam uma configuração do logrotate; verifique-a e adapte a retenção às suas necessidades:

# /etc/logrotate.d/nginx (fornecido pelo pacote, trecho)
/var/log/nginx/*.log {
    daily              # rotação diária
    rotate 14          # manter 14 arquivos
    compress           # compactar os arquivos
    delaycompress      # exceto o mais recente
    notifempty
    sharedscripts
    postrotate
        invoke-rc.d nginx rotate >/dev/null 2>&1
    endscript
}

# Testar sem esperar a noite
sudo logrotate -d /etc/logrotate.d/nginx

Se você criar logs por site, como nos nossos exemplos, o padrão *.log os cobre automaticamente.

9. Testar e Recarregar sem Interrupção

Um reflexo que deve ser fixado definitivamente: nunca reinicie um servidor web sem ter validado a configuração, e prefira sempre o reload ao restart.

# 1. Validar a sintaxe e a coerência da configuração
sudo nginx -t
# Apache: sudo apachectl configtest

# 2. Recarregar: os workers terminam suas requisições em andamento,
#    novos workers iniciam com a nova configuração.
#    Nenhuma conexão é cortada.
sudo systemctl reload nginx

# Em uma linha, o reload condicionado ao teste
sudo nginx -t && sudo systemctl reload nginx

systemctl restart corta bruscamente as conexões em andamento; reserve-o para os casos em que o reload não basta (mudança de portas de escuta, atualização do binário).

10. Otimizações Básicas

Compressão gzip

# No bloco http {} de /etc/nginx/nginx.conf
gzip on;
gzip_comp_level 5;              # bom equilíbrio entre CPU e tamanho
gzip_min_length 256;            # inútil abaixo de 256 bytes
gzip_types text/plain text/css application/json application/javascript
           application/xml image/svg+xml;
# Imagens JPEG/PNG/WebP já são compactadas: não as liste

Cache de arquivos estáticos

Peça aos navegadores que mantenham por muito tempo os recursos que não mudam:

# No server block
location ~* \.(css|js|jpg|jpeg|png|webp|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;             # também alivia os logs
}

Essa estratégia pressupõe que seus arquivos mudem de nome a cada versão (hash no nome, o que todos os bundlers modernos fazem). Caso contrário, reduza a duração.

Processos workers

# Em /etc/nginx/nginx.conf
worker_processes auto;          # um worker por núcleo de CPU: o ajuste certo

events {
    worker_connections 1024;    # conexões simultâneas por worker
}

auto é o valor padrão dos pacotes recentes e atende a quase todos os casos. Só aumente worker_connections se seus logs mostrarem que o limite foi atingido, e pense então no limite de descritores de arquivo (worker_rlimit_nofile).

Boas Práticas

  • Um arquivo de configuração por site, ativado por link simbólico; não mexa nos arquivos fornecidos pelo pacote.
  • Valide com nginx -t ou apachectl configtest antes de cada reload, idealmente na mesma linha de comando.
  • Prefira reload a restart: zero interrupção para seus visitantes.
  • HTTPS em todo lugar, redirecionamento de HTTP para HTTPS e um certbot renew --dry-run após a instalação para validar a renovação automática.
  • Adicione os cabeçalhos de segurança em um snippet compartilhado e teste o resultado em securityheaders.com.
  • Logs dedicados por site, rotação verificada e uma olhada regular no error.log.
  • Atrás de um reverse proxy, transmita sempre Host, X-Forwarded-For e X-Forwarded-Proto para a aplicação.
  • Faça backup de /etc/nginx (ou /etc/apache2) e de /etc/letsencrypt: a configuração de um servidor web se reconstrói em minutos quando está versionada.

Conclusão

Agora você dispõe de um servidor web completo: vários sites em virtual hosts, HTTPS automático com Let’s Encrypt, reverse proxy para suas aplicações, cabeçalhos de segurança, logs sob controle e otimizações básicas. Nginx e Apache são softwares de confiabilidade notável: bem configurados, funcionam por anos sem intervenção. Os próximos passos da sua evolução: o load balancing entre vários backends, o cache com proxy_cache, a limitação de taxa (limit_req) contra abusos e a automatização de toda essa configuração com Ansible ou Terraform para reconstruir seu servidor com um único comando.

InSkillCoach

Sobre InSkillCoach

Especialista em treinamento e tecnologias

Coach especializado em tecnologias avançadas e IA, apoiado pela GNeurone Inc.

Certificações:

  • AWS Certified Solutions Architect – Professional
  • Certificações Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.3k
139

Comentários

Os comentários são alimentados pelo GitHub Discussions

Conecte-se com o GitHub para participar da discussão

Link copiado!