Graduado em Análise de Sistemas (Estácio), MBA em IA & Analytics (Cruzeiro do Sul), Técnico em Redes (EEEP Ícaro).
Atuação como Analista de Sistemas em hospitais, desenvolvendo APIs, sistemas e liderando equipes.
Python, Django, React, APIs REST, GitHub Actions, Docker, Zabbix, Linux, PostgreSQL, Oracle Cloud, entre outras.
Liderança técnica, automações, suporte estratégico, foco em performance e entrega de valor real com tecnologia.
Tutoriais, dicas e comandos úteis para desenvolvimento, deploy e automações.
Guia passo a passo para colocar seu projeto Django em produção no Ubuntu.
Aprenda a instalar e renovar certificados SSL grátis com Certbot.
Automatize testes e deploys com GitHub Actions de forma simples.
Aprenda a criar imagens Docker para seus projetos Python.
Automatize tarefas com o agendador cron no seu servidor.
Passo a passo para criar e publicar uma API com Django Rest Framework.
Configure e use o Zabbix para monitorar seus servidores.
Suba e gerencie bancos PostgreSQL usando containers Docker.
Dicas práticas para proteger seu servidor contra acessos indevidos.
Coloque seu projeto Django em produção com Gunicorn (via socket) e Nginx no Ubuntu.
sudo apt update
sudo apt install python3-pip python3-venv nginx
git clone https://github.com/seuuser/projeto.git
cd projeto
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
sudo nano /etc/systemd/system/projeto.service
[Unit]
Description=Gunicorn App
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/caminho/para/seu/projeto
ExecStart=/caminho/para/seu/projeto/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
projeto.wsgi:application
[Install]
WantedBy=multi-user.target
sudo nano /etc/nginx/sites-available/projeto
server {
listen 80;
server_name exemplo.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /caminho/para/seu/projeto;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
sudo ln -s /etc/nginx/sites-available/projeto /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl daemon-reexec
sudo systemctl start projeto
sudo systemctl enable projeto
Adicione HTTPS ao seu site com certificado gratuito da Let's Encrypt usando o Certbot.
sudo apt update
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d exemplo.com -d www.exemplo.com
sudo certbot renew --dry-run
Crie um pipeline de CI/CD para testar, construir e publicar sua aplicação automaticamente a cada push ou PR.
Crie o workflow no repositório:
.github/workflows/ci.yml
Workflow com gatilhos em push e pull_request, cache de dependências e matriz de versões:
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- name: Install
run: npm ci
- name: Lint
run: npm run lint --if-present
- name: Test
run: npm test -- --ci --reporters=default
- name: Build
run: npm run build --if-present
deploy:
needs: build-and-test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: "npm"
- run: npm ci
- run: npm run build --if-present
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: dist
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v4
Para projetos Python, incluindo cache de pip
e execução de testes:
name: CI-Python
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.10", "3.11" ]
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Lint (ruff/flake8) - opcional
run: |
pip install ruff
ruff check .
- name: Test (pytest)
run: |
pip install pytest
pytest -q
Defina credenciais em Settings > Secrets and variables > Actions e consuma no workflow:
- name: Login no Registro Docker
run: echo "${{ secrets.DOCKER_TOKEN }}" | docker login -u "${{ secrets.DOCKER_USER }}" --password-stdin
- name: Deploy com SSH
run: ssh -o StrictHostKeyChecking=no user@server "bash deploy.sh"
env:
APP_ENV: production
name: Build Docker
on:
push:
branches: [ "main" ]
jobs:
docker:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
Crie imagens leves, reproduzíveis e seguras para seus serviços Python, com cache eficiente e boas práticas.
.
├── app.py
├── requirements.txt
└── Dockerfile
# Dockerfile
FROM python:3.12-slim
# Evita prompts interativos
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
# Instala dependências do sistema (se precisar compilar libs)
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Diretório da app
WORKDIR /app
# Dependências primeiro para aproveitar cache
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Código da aplicação
COPY . .
# Usuário não-root para segurança
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
# Exemplo: app Flask em 0.0.0.0:8000
EXPOSE 8000
CMD ["python", "app.py"]
CMD
conforme sua stack (Flask, FastAPI, Django, etc.).# Dockerfile (multi-stage)
# 1) Builder: compila wheels e dependências
FROM python:3.12-slim AS builder
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential gcc \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY requirements.txt .
RUN pip wheel --no-cache-dir --wheel-dir /build/wheels -r requirements.txt
# 2) Runner: imagem final minimalista
FROM python:3.12-slim AS runner
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
# Copia apenas wheels já prontos (rápido e cacheável)
COPY --from=builder /build/wheels /wheels
RUN pip install --no-cache-dir /wheels/*
# Copia o código da aplicação
COPY . .
# Segurança
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
# Ex.: uvicorn para FastAPI (ajuste conforme app)
# CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
CMD ["python", "app.py"]
# .dockerignore
__pycache__/
*.pyc
*.pyo
*.pyd
.env
.venv
.git
.gitignore
dist/
build/
.coverage
.pytest_cache/
node_modules/
# Build (nomeie sua imagem)
docker build -t seuuser/minha-api:latest .
# Rodar expondo a porta 8000
docker run --rm -p 8000:8000 seuuser/minha-api:latest
# Com variáveis de ambiente (ex.: Flask)
docker run --rm -p 8000:8000 -e FLASK_ENV=production seuuser/minha-api:latest
# docker-compose.yml
services:
web:
build: .
image: seuuser/minha-api:latest
ports:
- "8000:8000"
environment:
- APP_ENV=production
volumes:
- .:/app:rw
command: python app.py
# app.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"ok": True, "msg": "Hello from container!"}
# requirements.txt
# fastapi
# uvicorn[standard]
# Ajuste CMD no Dockerfile para Uvicorn:
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
# Exemplo de Dockerfile (trecho) com healthcheck
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -fsS http://localhost:8000/health || exit 1
# Para Django (Gunicorn):
# requirements.txt inclui: gunicorn
# CMD ["gunicorn", "projeto.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]
USER
não-root (já aplicado).-slim
e remova caches de APT.requirements.txt
para reprodutibilidade.docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image seuuser/minha-api:latest
# GHCR (GitHub Container Registry)
echo <TOKEN> | docker login ghcr.io -u <SEU_USUARIO> --password-stdin
docker tag suaimg:latest ghcr.io/<SEU_USUARIO>/suaimg:latest
docker push ghcr.io/<SEU_USUARIO>/suaimg:latest
Use o cron
para automatizar tarefas recorrentes no Linux, como backups, limpeza de logs ou execução de scripts.
O cron
é um serviço que executa comandos agendados em intervalos definidos.
As configurações ficam na crontab
(tabela de agendamento).
# min hora dia_mes mes dia_semana comando
* * * * * comando-a-executar
*
→ qualquer valor# Editar crontab do usuário atual
crontab -e
# Listar agendamentos
crontab -l
# Editar crontab de outro usuário (root)
sudo crontab -u usuario -e
# Rodar backup.sh todo dia às 2h da manhã
0 2 * * * /home/user/scripts/backup.sh
# Limpar logs toda segunda às 5h30
30 5 * * 1 /home/user/scripts/limpar_logs.sh
# Sincronizar arquivos a cada 15 minutos
*/15 * * * * rsync -av /origem /destino
# Reiniciar serviço nginx todo dia às 3h
0 3 * * * systemctl restart nginx
# Registrar saída e erros em arquivo
0 2 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1
# Ver logs no journal (para cron jobs)
journalctl -u cron
# Para cron do root:
sudo journalctl -u cron
/usr/bin/python3
).# Script Python (backup.py)
import datetime
print(f"Backup executado em {datetime.datetime.now()}")
# Crontab: roda todo dia às 1h
0 1 * * * /usr/bin/python3 /home/user/scripts/backup.py >> /var/log/backup.log 2>&1
Crie, documente e publique uma API com Django REST Framework (DRF), com autenticação JWT, CORS e documentação OpenAPI prontos para produção.
# Requisitos
python -m venv venv && source venv/bin/activate
pip install django djangorestframework djangorestframework-simplejwt django-cors-headers drf-spectacular
# Projeto e app
django-admin startproject api .
python manage.py startapp core
# Migrar e criar superusuário
python manage.py migrate
python manage.py createsuperuser
settings.py
# settings.py (trechos)
INSTALLED_APPS = [
"django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes",
"django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles",
"rest_framework", "corsheaders", "drf_spectacular", "core",
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": (
"rest_framework.permissions.IsAuthenticatedOrReadOnly",
),
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}
SPECTACULAR_SETTINGS = {
"TITLE": "Minha API",
"DESCRIPTION": "API de exemplo com DRF + JWT",
"VERSION": "1.0.0",
}
# CORS (ajuste para o seu domínio frontend)
CORS_ALLOWED_ORIGINS = [
"https://meu-frontend.com",
"http://localhost:3000",
]
# Em produção:
ALLOWED_HOSTS = ["exemplo.com", "api.exemplo.com", "localhost"]
# core/models.py
from django.db import models
class Produto(models.Model):
nome = models.CharField(max_length=120)
preco = models.DecimalField(max_digits=10, decimal_places=2)
criado_em = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.nome
# Após criar o modelo
python manage.py makemigrations
python manage.py migrate
# core/serializers.py
from rest_framework import serializers
from .models import Produto
class ProdutoSerializer(serializers.ModelSerializer):
class Meta:
model = Produto
fields = ["id", "nome", "preco", "criado_em"]
# core/views.py
from rest_framework.viewsets import ModelViewSet
from .models import Produto
from .serializers import ProdutoSerializer
class ProdutoViewSet(ModelViewSet):
queryset = Produto.objects.all().order_by("-criado_em")
serializer_class = ProdutoSerializer
# api/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import SimpleRouter
from core.views import ProdutoViewSet
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
router = SimpleRouter()
router.register("produtos", ProdutoViewSet, basename="produtos")
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include(router.urls)),
# JWT
path("api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
# OpenAPI + Swagger UI
path("api/schema/", SpectacularAPIView.as_view(), name="schema"),
path("api/docs/", SpectacularSwaggerView.as_view(url_name="schema"), name="swagger-ui"),
]
/api/produtos/
, /api/token/
, /api/docs/
.
# Obter token (use o superusuário criado)
curl -X POST http://localhost:8000/api/token/ -H "Content-Type: application/json" \
-d '{"username":"admin","password":"sua_senha"}'
# Listar produtos (sem token = leitura pública se IsAuthenticatedOrReadOnly)
curl http://localhost:8000/api/produtos/
# Criar produto (requer token)
TOKEN="<Bearer_Token>"
curl -X POST http://localhost:8000/api/produtos/ \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"nome":"Teclado","preco":"199.90"}'
DEBUG = False
, defina ALLOWED_HOSTS
e configure SECURE_*
(HTTPS).gunicorn
(WSGI) ou uvicorn
(ASGI) por trás do Nginx.collectstatic
+ Nginx/Storage (ou WhiteNoise para apps simples).# Execução com Gunicorn (exemplo)
pip install gunicorn
gunicorn api.wsgi:application --bind 0.0.0.0:8000 --workers 3
REST_FRAMEWORK["DEFAULT_PAGINATION_CLASS"]
e PAGE_SIZE
.django-filter
e use filter_backends
no ViewSet.IsAuthenticated
, IsAdminUser
, ou crie permissions customizadas./api/v1/
) para evoluir sem quebrar consumidores./api/docs/
, pronta para publicar.
Configure um ambiente de monitoramento completo com Zabbix (Server + Web + DB + Agent), com discovery, alertas e integração com Grafana — ideal para demonstrar habilidades DevOps/SRE no portfólio.
# docker-compose.yml
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: zabbix
POSTGRES_DB: zabbix
volumes:
- db_data:/var/lib/postgresql/data
restart: unless-stopped
zabbix-server:
image: zabbix/zabbix-server-pgsql:alpine-latest
environment:
DB_SERVER_HOST: db
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: zabbix
POSTGRES_DB: zabbix
depends_on: [db]
ports:
- "10051:10051"
restart: unless-stopped
zabbix-web:
image: zabbix/zabbix-web-nginx-pgsql:alpine-latest
environment:
DB_SERVER_HOST: db
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: zabbix
POSTGRES_DB: zabbix
PHP_TZ: America/Fortaleza
depends_on: [db, zabbix-server]
ports:
- "8080:8080"
restart: unless-stopped
agent:
image: zabbix/zabbix-agent2:alpine-latest
environment:
ZBX_SERVER_HOST: zabbix-server
depends_on: [zabbix-server]
restart: unless-stopped
volumes:
db_data:
# Subir o stack
docker compose up -d
# Acessar a interface
# http://SEU_HOST:8080 (user: Admin | pass padrão: zabbix)
# (exemplo) instalar server + frontend + agente
sudo apt update
# Siga a doc oficial para adicionar o repositório da sua versão
# https://www.zabbix.com/download
# Depois:
sudo apt install zabbix-server-pgsql zabbix-frontend-php zabbix-apache-conf \
zabbix-sql-scripts zabbix-agent2 postgresql
# Crie o banco, configure /etc/zabbix/zabbix_server.conf e start/enable os serviços.
Admin
e crie um usuário read‑only para a demo.# No host monitorado (Ubuntu/Debian):
sudo apt update
sudo apt install zabbix-agent2
sudo sed -i 's/^Server=.*/Server=SEU_IP_OU_DNS_DO_SERVER/' /etc/zabbix/zabbix_agent2.conf
sudo sed -i 's/^ServerActive=.*/ServerActive=SEU_IP_OU_DNS_DO_SERVER/' /etc/zabbix/zabbix_agent2.conf
sudo sed -i 's/^Hostname=.*/Hostname=host-demo-01/' /etc/zabbix/zabbix_agent2.conf
sudo systemctl enable --now zabbix-agent2
Linux by Zabbix agent
.
# Exemplo (container do agente)
docker run -d --name zbx-agent2 --restart unless-stopped \
-e ZBX_SERVER_HOST=SEU_ZABBIX \
-v /var/run/docker.sock:/var/run/docker.sock \
zabbix/zabbix-agent2:alpine-latest
Em seguida, aplique um template de Docker apropriado (ou itens/LLD custom).
Adicione a interface SNMP no host e aplique templates como Template Net Network Generic
ou específicos do fabricante.
# Exemplo no Linux para expor SNMP (apenas laboratório!)
sudo apt install snmpd
sudo sed -i 's/^agentAddress.*/agentAddress udp:161,udp6:[::1]:161/' /etc/snmp/snmpd.conf
sudo systemctl restart snmpd
# Exemplo de condição de ação
Trigger severity: High e acima
Host group: Linux-Servers
Operations: Send message via Telegram to "SRE On-Call"
# playbook.yml (trecho)
- hosts: linux
become: true
tasks:
- name: Instalar zabbix-agent2
apt:
name: zabbix-agent2
state: present
update_cache: yes
- name: Configurar agent
lineinfile:
path: /etc/zabbix/zabbix_agent2.conf
regexp: '^Server=|^ServerActive=|^Hostname='
line: "{{ item }}"
with_items:
- "Server={{ zabbix_server }}"
- "ServerActive={{ zabbix_server }}"
- "Hostname={{ inventory_hostname }}"
- name: Habilitar e iniciar
service:
name: zabbix-agent2
state: started
enabled: yes
# Testar conectividade do agente
zabbix_get -s HOST_IP -k agent.ping
# Ver logs
docker logs zabbix-server
docker logs zabbix-web
sudo journalctl -u zabbix-agent2 -f
Suba um PostgreSQL com persistência, ferramenta de administração, backups e boas práticas — ideal para desenvolvimento e demos.
# docker-compose.yml
services:
db:
image: postgres:16-alpine
container_name: pg
environment:
POSTGRES_DB: appdb
POSTGRES_USER: appuser
POSTGRES_PASSWORD: supersecret
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
- ./init:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
interval: 10s
timeout: 3s
retries: 5
restart: unless-stopped
pgadmin:
image: dpage/pgadmin4:8
container_name: pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: admin123
ports:
- "8081:80"
depends_on:
- db
restart: unless-stopped
volumes:
pg_data:
./init
(opcional) carrega scripts .sql
e .sh
na criação do banco.# Subir
docker compose up -d
# Conectar no container e abrir psql
docker exec -it pg psql -U appuser -d appdb
# Dentro do psql, teste:
-- SQL:
CREATE TABLE healthcheck (id serial PRIMARY KEY, ts timestamptz default now());
INSERT INTO healthcheck DEFAULT VALUES;
SELECT * FROM healthcheck;
http://SEU_HOST:8081
→ Add New Server → Host db
, User appuser
, Password supersecret
.POSTGRES_DB
, POSTGRES_USER
, POSTGRES_PASSWORD
criam DB/usuário iniciais./docker-entrypoint-initdb.d
rodam só na primeira inicialização do volume.# init/001-schema.sql (exemplo)
CREATE SCHEMA IF NOT EXISTS app AUTHORIZATION appuser;
CREATE TABLE IF NOT EXISTS app.items (
id serial PRIMARY KEY,
name text NOT NULL,
created_at timestamptz DEFAULT now()
);
# Backup lógico (dump custom)
docker exec -t pg pg_dump -U appuser -d appdb -F c -f /tmp/appdb.dump
docker cp pg:/tmp/appdb.dump ./backup/appdb_$(date +%F).dump
# Restore
docker cp ./backup/appdb_2025-01-01.dump pg:/tmp/restore.dump
docker exec -it pg pg_restore -U appuser -d appdb --clean --if-exists /tmp/restore.dump
# Export CSV de uma tabela
docker exec -it pg psql -U appuser -d appdb -c \
"\copy app.items TO '/tmp/items.csv' with csv header"
docker cp pg:/tmp/items.csv ./backup/items.csv
.env
(não comite no Git).postgres:alpine
para leveza; fixe a versão (ex.: 16-alpine
).ANALYZE
e VACUUM
automáticos.shared_buffers
, work_mem
, maintenance_work_mem
via arquivo postgresql.conf
montado no volume.# Exemplo: montar um postgresql.conf custom
# docker-compose.yml (trecho)
volumes:
- pg_data:/var/lib/postgresql/data
- ./conf/postgresql.conf:/etc/postgresql/postgresql.conf:ro
command: ["-c", "config_file=/etc/postgresql/postgresql.conf"]
# Django settings.py (trecho)
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "appdb",
"USER": "appuser",
"PASSWORD": "supersecret",
"HOST": "localhost", # ou 'db' se a app estiver no mesmo compose
"PORT": "5432",
}
}
# SQLAlchemy (Python)
from sqlalchemy import create_engine
ENGINE = create_engine("postgresql+psycopg2://appuser:supersecret@localhost:5432/appdb", echo=False)
# docker-compose.yml (trecho adicional)
web:
build: .
depends_on:
- db
environment:
DATABASE_URL: postgresql://appuser:supersecret@db:5432/appdb
ports:
- "8000:8000"
command: python app.py
db:5432
entre containers; para acesso externo, exponha portas no serviço certo.Para demonstrar escala/HA, você pode incluir um read‑replica usando imagens com suporte a replication (ex.: bitnami/postgresql) e exibir no portfólio.
Guia prático para endurecer (hardening) um servidor Linux: atualizações, usuários/SSH, firewall, proteção contra brute force, logs/auditoria e boas práticas para produção.
sudo
, use chaves SSH e desabilite senha/RootLogin.ufw
(ou nftables
) e permita só o necessário.sysctl
e ajuste permissões de arquivos sensíveis.journald
, auditd
, alertas e backups.# Ubuntu/Debian
sudo apt update && sudo apt full-upgrade -y
# Atualizações automáticas (Ubuntu/Debian)
sudo apt install -y unattended-upgrades apt-listchanges
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Crie usuário "deploy" e adicione ao sudo
sudo adduser deploy
sudo usermod -aG sudo deploy
# Configure chaves SSH (no seu computador)
ssh-keygen -t ed25519 -C "deploy@seu-servidor"
ssh-copy-id deploy@SEU_IP
# Endurecer o SSH (edite /etc/ssh/sshd_config)
sudo nano /etc/ssh/sshd_config
# Ajustes recomendados:
# PermitRootLogin no
# PasswordAuthentication no
# PubkeyAuthentication yes
# ChallengeResponseAuthentication no
# AllowUsers deploy
# (opcional) Port 2222
sudo systemctl restart ssh
# Abrir somente o necessário (ex.: SSH 22/2222, HTTP 80, HTTPS 443)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
# sudo ufw allow 2222/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
# Instalação e configuração base
sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
# Arquivo local (não edite o .conf padrão)
sudo nano /etc/fail2ban/jail.local
# Exemplo mínimo:
# [sshd]
# enabled = true
# port = 22
# filter = sshd
# maxretry = 5
# bantime = 1h
# findtime = 10m
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
# Home segura e .ssh protegido
chmod 700 /home/deploy
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
# Proteja /etc/shadow e chaves privadas
sudo chown root:root /etc/shadow
sudo chmod 640 /etc/shadow
# /etc/sysctl.d/99-hardening.conf (exemplo)
net.ipv4.ip_forward = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv6.conf.all.accept_redirects = 0
kernel.kptr_restrict = 2
kernel.randomize_va_space = 2
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
# Aplicar
sudo sysctl --system
# Ver logs do sistema
journalctl -p 3 -xb # erros do último boot
journalctl -u ssh -f # seguir logs do SSH
# auditd (rastreamento de eventos sensíveis)
sudo apt install -y auditd audispd-plugins
sudo systemctl enable --now auditd
sudo auditctl -l # regras ativas
ss -tulpen # serviços escutando
sudo lsof -i # sockets de rede por processo
sudo systemctl list-unit-files --type=service | grep enabled
# ClamAV (opcional, útil em servidores de arquivos)
sudo apt install -y clamav
sudo freshclam
clamscan -r /home
# Lynis (benchmark de hardening)
sudo apt install -y lynis
sudo lynis audit system
# Exemplo simples com tar + data
sudo tar -czf /backup/etc_$(date +%F).tar.gz /etc
# Recomendações:
# - Rotacionar backups (retenção)
# - Criptografar (gpg/age)
# - Testar restauração periodicamente
sudo
só quando necessário.Entre em contato pelo e-mail:
ou mande uma mensagem no WhatsApp