Linux: Projeto Final — Montando um Servidor Web Dev do Zero
Esse é o projeto final do curso. Você vai juntar tudo que aprendeu nas 25 aulas anteriores — começando de uma máquina zerada pra montar um servidor de desenvolvimento Web totalmente funcional.
📋 Pré-requisitos: Você já deve conhecer
- Aula 1: Introdução ao Linux
- Aula 2: Instalando o Linux
- Aula 3: Fundamentos do Terminal
- Aula 4: Navegação no Sistema de Arquivos
- Aula 5: Operações com Arquivos e Diretórios
- Aula 6: Configurando um Ambiente de Dev
- Aula 7: Editores de Texto
- Aula 8: Permissões de Arquivo
- Aula 9: Gerenciamento de Usuários e Grupos
- Aula 10: Variáveis de Ambiente e PATH
- Aula 11: Ambiente de Dev Multi-Usuário
- Aula 12: Streams Padrão e Redirecionamento
- Aula 13: Pipes e Filtros
- Aula 14: Busca em Texto
- Aula 15: Processamento de Texto
- Aula 16: Análise de Logs do Servidor
- Aula 17: Gerenciamento de Processos
- Aula 18: Gerenciamento de Pacotes
- Aula 19: Arquivos e Compactação
- Aula 20: Fundamentos de Script Bash
- Aula 21: Script Bash Avançado
- Aula 22: Script de Backup Automatizado
- Aula 23: Fundamentos de Rede
- Aula 24: Firewall e Segurança
- Aula 25: Automação de Tarefas
1. O Que Você Vai Aprender
- Fluxo completo de inicialização de servidor
- Setup do stack LEMP
- Deploy de aplicações Node.js/Python
- Configuração de certificado HTTPS
- Monitoramento e alertas
2. O Desafio "Vai Pra Produção Amanhã" do Xiaoming
(1) O Problema: Servidor Novo, Tem que Ir Pra Produção Amanhã
A empresa do Xiaoming comprou um servidor na nuvem. O chefe disse: "vai pra produção amanhã". Diante de uma máquina zerada com apenas um IP e a senha de root, o Xiaoming precisava aplicar tudo que tinha aprendido.
(2) 10 Passos Da Máquina Nua Até a Produção
O Xiaoming montou um plano:
1. Login SSH → 6. Deploy da app Node.js
2. Criação de usuário + hardening do SSH → 7. Configurar certificado HTTPS
3. Config do firewall → 8. Configurar o gerenciador de processos PM2
4. Instalar o Nginx → 9. Backup automatizado
5. Configurar proxy reverso → 10. Health check + alertas
(3) O Benefício: Entregue em 3 Horas
O Xiaoming começou às 14h, executou o plano passo a passo e terminou o deploy completo às 17h. O chefe testou e respondeu: "bom, tá pronto pra produção".
3. Pontos-Chave
(1) Checklist de Inicialização do Servidor
□ Login SSH (senha de root)
□ Atualizar o sistema (apt update && apt upgrade)
□ Criar usuário comum (useradd -m -s /bin/bash)
□ Configurar sudo (usermod -aG sudo)
□ Autenticação por chave SSH
□ Desabilitar login de root + por senha
□ Firewall (ufw: 22/80/443)
□ Proteção com fail2ban
□ Atualizações automáticas de segurança
(2) Stack LEMP (Linux + Nginx + MySQL + PHP/Node.js/Python)
# Nginx
sudo apt install nginx
sudo systemctl enable --now nginx
# Se for usar MySQL
sudo apt install mysql-server
sudo mysql_secure_installation
# Comparação de deploy de aplicação
| Método | Melhor Para | Prós | Contras |
|---|---|---|---|
| serviço systemd | Qualquer linguagem | Nativo, maduro, estável | Config um pouco mais complexa |
| PM2 | Node.js | Zero config, monitoramento embutido | Só Node.js |
| Gunicorn/uWSGI | Python | Boa performance, padrão WSGI | Precisa de Nginx |
| Docker Compose | Apps complexos | Ambiente consistente, fácil de escalar | Exige conhecimento de Docker |
(3) ▶ Exemplo: Deploy de uma App Node.js no Nginx
#!/bin/bash
# Faz o deploy de uma app Node.js em produção
# 1. Criar diretório da app
sudo mkdir -p /opt/webapp
sudo chown -R alice:alice /opt/webapp
# 2. Clonar os arquivos da app (assumindo que já foi desenvolvida)
git clone https://github.com/example/webapp.git /opt/webapp
# 3. Instalar dependências e build
cd /opt/webapp
npm install
npm run build
# 4. Configurar o PM2
npm install -g pm2
pm2 start server.js --name webapp -i max
pm2 save
pm2 startup
# 5. Configurar proxy reverso do Nginx
sudo tee /etc/nginx/sites-available/webapp << 'EOF'
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
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 /static/ {
alias /opt/webapp/public/;
expires 30d;
}
}
EOF
sudo ln -sf /etc/nginx/sites-available/webapp /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
Saída:
TEXTnpm WARN deprecated package@1.0.0 added 245 packages in 12s Building production bundle... [PM2] Process webapp started ┌────┬──────────┬─────────┬─────────┐ │ id │ name │ status │ cpu │ ├────┼──────────┼─────────┼─────────┤ │ 0 │ webapp │ online │ 0% │ └────┴──────────┴─────────┴─────────┘ nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
(4) ▶ Exemplo: HTTPS (Let's Encrypt + certbot)
sudo certbot renew --dry-run. Também vale colocar um lembrete no calendário pra verificar manualmente se a renovação deu certo uns 30 dias antes do vencimento (por volta do dia 60), caso alguma mudança de config tenha quebrado a renovação automática.
# Instalar o certbot
sudo apt install certbot python3-certbot-nginx -y
# Obter o certificado (modifica automaticamente a config do Nginx)
sudo certbot --nginx -d example.com -d www.example.com
# Ver os certificados
sudo certbot certificates
# Validar a renovação automática
sudo certbot renew --dry-run
# Renovação automática (o certbot adiciona um timer do systemd)
sudo systemctl list-timers | grep certbot
Saída:
TEXTSaving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for example.com and www.example.com Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem Found the following certs: Certificate Name: example.com Expiry Date: 2026-10-05 10:23:45+00:00 (VALID: 89 days) Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/example.com/fullchain.pem certbot.timer certbot.service Sat 2026-07-08 00:00:00 UTC 13h left
(5) ▶ Exemplo: Script de Health Check
#!/bin/bash
# health-check.sh - Health check multi-serviço
check_service() {
local name="$1"
local url="$2"
local expect="${3:-200}"
local status=$(curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null)
if [ "$status" = "$expect" ]; then
echo "[OK] $name: $status (saudavel)"
return 0
else
echo "[FAIL] $name: $status (com problema)"
return 1
fi
}
echo "=== Health Check do Sistema ==="
echo "Horario: $(date)"
echo ""
# Recursos do sistema
echo "CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}')%"
echo "Memoria: $(free -h | grep Mem | awk '{print $3 "/" $2}')"
echo "Disco: $(df -h / | tail -1 | awk '{print $3 "/" $2 " (" $5 ")"}')"
echo ""
# Serviços web
check_service "Nginx" "http://localhost/nginx_status" 200
check_service "WebApp" "http://localhost:3000/health" 200
check_service "HTTPS" "https://example.com/" 200
echo ""
echo "=== Check Concluido ==="
Saída:
TEXT=== Health Check do Sistema === Horario: Tue Jul 7 10:30:00 UTC 2026 CPU: 2.3% Memoria: 1.2Gi/3.9Gi Disco: 12G/50G (24%) [OK] Nginx: 200 (saudavel) [OK] WebApp: 200 (saudavel) [OK] HTTPS: 200 (saudavel) === Check Concluido ===
(6) ▶ Exemplo: Script Completo de Deploy
curl -fsSL URL | bash - executa um script remoto direto na sua máquina, o que traz risco de ataque na cadeia de suprimentos — se a fonte for comprometida ou o DNS for sequestrado, você pode executar código malicioso. Em produção, a abordagem mais segura é baixar e revisar o script antes, e depois executar: curl -fsSL URL -o setup.sh && less setup.sh && bash setup.sh.
#!/bin/bash
# setup-server.sh - Monta um servidor Web dev do zero
# Uso: sudo ./setup-server.sh example.com
set -euo pipefail
DOMAIN="${1:-example.com}"
APP_DIR="/opt/webapp"
APP_PORT=3000
ADMIN_USER="admin"
echo "========================================"
echo " Montando o Servidor Web Dev do Zero"
echo " Dominio: $DOMAIN"
echo "========================================"
# 1. Atualizar o sistema
echo ""
echo ">>> 1/10 Atualizando o sistema..."
apt update && apt upgrade -y
# 2. Criar usuário comum
echo ""
echo ">>> 2/10 Criando o usuario admin..."
if ! id "$ADMIN_USER" &>/dev/null; then
useradd -m -s /bin/bash "$ADMIN_USER"
usermod -aG sudo "$ADMIN_USER"
echo "Defina a senha para $ADMIN_USER:"
passwd "$ADMIN_USER"
# Obs: adicione manualmente sua chave SSH pública em /home/$ADMIN_USER/.ssh/authorized_keys
mkdir -p /home/$ADMIN_USER/.ssh
cp /root/.ssh/authorized_keys /home/$ADMIN_USER/.ssh/ 2>/dev/null || true
chown -R $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.ssh
chmod 700 /home/$ADMIN_USER/.ssh
chmod 600 /home/$ADMIN_USER/.ssh/authorized_keys
fi
# 3. Hardening do SSH
echo ""
echo ">>> 3/10 Fazendo o hardening do SSH..."
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
systemctl restart sshd
# 4. Firewall
echo ""
echo ">>> 4/10 Configurando o firewall..."
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
# 5. fail2ban
echo ""
echo ">>> 5/10 Instalando o fail2ban..."
apt install -y fail2ban
cat > /etc/fail2ban/jail.d/sshd.conf << EOF
[sshd]
enabled = true
maxretry = 3
bantime = 86400
findtime = 600
EOF
systemctl enable --now fail2ban
# 6. Instalar o Nginx
echo ""
echo ">>> 6/10 Instalando o Nginx..."
apt install -y nginx
systemctl enable --now nginx
# 7. Instalar o Node.js
echo ""
echo ">>> 7/10 Instalando o Node.js..."
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
npm install -g pm2
# 8. Configurar proxy reverso do Nginx
echo ""
echo ">>> 8/10 Configurando o Nginx..."
cat > /etc/nginx/sites-available/$DOMAIN << EOF
server {
listen 80;
server_name $DOMAIN www.$DOMAIN;
location / {
proxy_pass http://127.0.0.1:$APP_PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
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;
}
}
EOF
ln -sf /etc/nginx/sites-available/$DOMAIN /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx
# 9. Certificado HTTPS
echo ""
echo ">>> 9/10 Configurando HTTPS..."
apt install -y certbot python3-certbot-nginx
certbot --nginx --non-interactive --agree-tos \
--email admin@$DOMAIN \
-d $DOMAIN -d www.$DOMAIN \
|| echo "Atencao: certbot falhou, rode manualmente: sudo certbot --nginx -d $DOMAIN"
# 10. Script de health check
echo ""
echo ">>> 10/10 Configurando o health check..."
mkdir -p /opt/scripts
cat > /opt/scripts/health-check.sh << 'EOF'
#!/bin/bash
WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK"
for svc in nginx sshd fail2ban; do
if ! systemctl is-active --quiet "$svc"; then
echo "[$(date)] FAIL: $svc esta fora" >> /var/log/health.log
fi
done
DISK=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
[ "$DISK" -gt 85 ] && echo "[$(date)] WARNING: Uso de disco ${DISK}%" >> /var/log/health.log
EOF
chmod +x /opt/scripts/health-check.sh
# Adicionar ao cron
(crontab -l 2>/dev/null; echo "*/10 * * * * /opt/scripts/health-check.sh > /dev/null 2>&1") | crontab -
echo ""
echo "========================================"
echo "Setup do servidor concluido!"
echo ""
echo "Informacoes do deploy:"
echo " Usuario admin: $ADMIN_USER"
echo " Nginx: http://$DOMAIN"
echo " HTTPS: https://$DOMAIN (se o certbot deu certo)"
echo " Node.js: $(node --version)"
echo " PM2: $(pm2 --version)"
echo ""
echo "Proximos passos:"
echo " 1. Faca o deploy do codigo da sua aplicacao em $APP_DIR"
echo " 2. Inicie a aplicacao: pm2 start $APP_DIR/server.js --name webapp"
echo " 3. Faca login como $ADMIN_USER (login de root esta desabilitado)"
echo "========================================"
Saída:
TEXT======================================== Montando o Servidor Web Dev do Zero Dominio: example.com ======================================== >>> 1/10 Atualizando o sistema... ... ======================================== Setup do servidor concluido! Usuario admin: admin Nginx: http://example.com Node.js: v20.11.0 ========================================
(7) ▶ Exemplo Abrangente: Verificação Pós-Deploy
#!/bin/bash
# verify-deploy.sh - Verificação pós-deploy
echo "========================================"
echo " Verificacao do Deploy"
echo " Horario: $(date)"
echo "========================================"
echo ""
errors=0
check() {
local desc="$1"
shift
if "$@" &>/dev/null; then
echo " [OK] $desc"
else
echo " [FAIL] $desc"
errors=$((errors + 1))
fi
}
echo "1. Servicos do Sistema"
echo "-----------"
check "Nginx rodando" systemctl is-active nginx
check "SSH rodando" systemctl is-active sshd
check "fail2ban rodando" systemctl is-active fail2ban
echo ""
echo "2. Rede"
echo "--------"
check "Porta 80 em escuta" ss -tlnp grep -q ":80 "
check "Porta 443 em escuta" ss -tlnp grep -q ":443 "
check "ufw ativo" ufw status grep -q active
echo ""
echo "3. Servico HTTP"
echo "-------------"
check "Nginx local respondendo" curl -s -o /dev/null -w "%{http_code}" http://localhost grep -q 200
check "Processo da app rodando" pm2 list 2>/dev/null grep -q "online" || pgrep -f "node server" > /dev/null
echo ""
echo "4. Seguranca"
echo "--------"
check "SSH root desabilitado" grep "^PermitRootLogin" /etc/ssh/sshd_config grep -q "no"
check "Login por senha desabilitado" grep "^PasswordAuthentication" /etc/ssh/sshd_config grep -q "no"
echo ""
echo "5. Recursos"
echo "--------"
echo " CPU: $(top -bn1 | grep 'Cpu(s)' | awk '{print $2"%"}' )"
echo " Memoria: $(free -h | grep Mem | awk '{print $3"/"$2}')"
echo " Disco: $(df -h / | tail -1 | awk '{print $3"/"$2"("$5")"}')"
echo ""
echo "========================================"
if [ $errors -eq 0 ]; then
echo "Todas as verificacoes passaram!"
else
echo "$errors verificacao(oes) falhou(aram) - investigue"
fi
echo "========================================"
Saída:
TEXT======================================== Verificacao do Deploy Horario: Tue Jul 7 10:45:00 UTC 2026 ======================================== 1. Servicos do Sistema ----------- [OK] Nginx rodando [OK] SSH rodando [OK] fail2ban rodando 2. Rede -------- [OK] Porta 80 em escuta [OK] Porta 443 em escuta [OK] ufw ativo 3. Servico HTTP ------------- [OK] Nginx local respondendo [OK] Processo da app rodando 4. Seguranca -------- [OK] SSH root desabilitado [OK] Login por senha desabilitado 5. Recursos -------- CPU: 2.3% Memoria: 1.2Gi/3.9Gi Disco: 12G/50G(24%) ======================================== Todas as verificacoes passaram! ========================================
❓ Perguntas Frequentes
P: Qual é a primeira coisa a fazer ao colocar um servidor em produção? R: Atualizar o sistema (
apt update && apt upgrade), em seguida criar um usuário comum e configurar a autenticação por chave SSH. Nunca trabalhe como root por muito tempo.
P: Qual a relação entre o proxy reverso do Nginx e a aplicação? R: O Nginx é a "porta da frente" e a aplicação são "as pessoas lá dentro". Os usuários acessam o Nginx nas portas 80/443 → o Nginx decide pra qual app de backend encaminhar a requisição. O Nginx cuida dos arquivos estáticos, terminação SSL e balanceamento de carga; a app foca na lógica de negócio.
P: Os certificados HTTPS precisam de renovação periódica? R: Os certificados da Let's Encrypt têm validade de 90 dias. O certbot adiciona automaticamente um timer do systemd pra renovar. Verifique com:
systemctl list-timers | grep certbot. Renovação manual:sudo certbot renew.
P: Quais métricas devo monitorar num servidor? R: Métricas essenciais: uso de CPU, consumo de memória, espaço em disco (alerta em >80%), I/O de disco, tráfego de rede, status dos serviços e vencimento do certificado SSL.
P: Como verificar a segurança depois do deploy? R: Rode ferramentas de scan de segurança: 1)
sudo ufw statuspra conferir as portas. 2)ss -tlnppra ver os endereços de escuta dos serviços. 3)grep "Failed password" /var/log/auth.log | wc -lpra medir o volume de ataques. 4) Use https://www.ssllabs.com/ssltest/ pra testar a configuração SSL.
📖 Resumo
- Fluxo de 10 passos pra inicializar o servidor: atualizar → usuário → hardening SSH → firewall → fail2ban → Nginx → app → HTTPS → backup → monitoramento
- Proxy reverso do Nginx:
proxy_pass http://127.0.0.1:3000 - certbot:
--nginx -d example.compra HTTPS automático - PM2:
pm2 start app.js -i maxpra gerenciar múltiplos processos - Health check:
curl -o /dev/null -w "%{http_code}" http://localhost/health
📝 Exercícios
- Básico (⭐): Usando uma VM ou servidor na nuvem, execute o script
setup-server.shdo zero, faça deploy de uma app Web simples em Node.js ou Python e acesse ela através do proxy reverso do Nginx - Intermediário (⭐⭐): Configure um certificado HTTPS da Let's Encrypt (use
--dry-runpra testar), escreva e faça deploy de um script de health check e configure alertas (e-mail ou webhook) - Desafio (⭐⭐⭐⭐⭐): Configure uma estratégia completa de backup (cron + rsync remoto) e verifique se os backups podem ser restaurados, depois escreva um script automatizado de verificação de deploy que confira status de todos os serviços, configurações de segurança e métricas de performance, e gere um relatório de aceitação formatado