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.
InSkillCoach
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ério | Nginx | Apache |
|---|---|---|
| Arquitetura | Orientada a eventos, assíncrona | Processos/threads por conexão (MPM event moderno) |
| Conteúdo estático | Excelente, uso de memória muito baixo | Bom |
| Conexões simultâneas em massa | Ponto forte histórico | Adequado com mpm_event |
| Reverse proxy / load balancing | Nativo e muito utilizado | Possível (mod_proxy) |
| Arquivos .htaccess | Não suportados | Suportados (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ção | Blocos concisos | Diretivas estilo XML, mais verbosas |
| Caso de uso típico | Reverse proxy, estático, aplicações modernas | Hospedagem 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 -touapachectl configtestantes de cada reload, idealmente na mesma linha de comando. - Prefira
reloadarestart: zero interrupção para seus visitantes. - HTTPS em todo lugar, redirecionamento de HTTP para HTTPS e um
certbot renew --dry-runapó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-ForeX-Forwarded-Protopara 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.
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+
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão