Guia Pragmático: Gitea atrás do Traefik com HTTPS (Docker Compose)
Este é um guia objetivo para colocar o Gitea rodando atrás do Traefik, com TLS automático (Let’s Encrypt), usando Docker Compose. O domínio de exemplo usado aqui é caioperlin.dev; substitua pelo seu domínio.
Índice
- Introdução ao Serviço
- Visão Geral
- Arquitetura e Componentes
- Casos de Uso
- Pré-requisitos
- Estrutura de Diretórios
- Configuração do Traefik
- Docker Compose do Traefik
- Docker Compose do Gitea
- Criando o usuário
gite permissões - Configuração do Firewall (UFW)
- Criando o acme.json para Certificados HTTPS
- Inicialização e Validação
- Resolução de Problemas
- Comandos Úteis
Introdução ao Serviço
Este documento descreve um serviço composto por Traefik (proxy reverso + TLS) e Gitea (servidor Git autohospedado) empacotados via Docker Compose. O objetivo é oferecer um repositório Git privado/auto-hospedado com acesso HTTP(S) gerenciado automaticamente por certificados Let’s Encrypt, além de uma opção de acesso via SSH.
Público-alvo: administradores de servidores, desenvolvedores que querem hospedar seus próprios repositórios e times pequenos que precisam de controle total sobre seus dados.
Arquitetura e Componentes
Resumo da arquitetura (componentes principais):
- Traefik: proxy reverso responsável por expor serviços via HTTP/HTTPS, resolver certificados (ACME) e rotear para backends via labels do Docker.
- Gitea: aplicação web que fornece repositórios Git, UI de gerenciamento, autenticação e opcional serviço SSH para push/pull.
- Docker Engine / Docker Compose: orquestra os containers e monta volumes persistentes.
- Rede Docker
traefik: rede overlay (local) que conecta Traefik com serviços que devem ser roteados. - Volumes/Paths persistentes: diretórios no host mapeados para
/datado Gitea e paraacme.jsondo Traefik.
Fluxo de requisições (simplificado):
Client -> (80/443) -> Traefik -> Gitea (porta 3000 HTTP interna)
Pequeno diagrama ASCII:
Internet
|
80/443
|
[Traefik]
| (docker network: traefik)
|-> [Gitea:3000]
|-> (opcional) [Gitea SSH:22 -> host 2222]
Importante:
- Traefik faz apenas TLS/terminação e roteamento — a aplicação (Gitea) continua responsável por autenticação, permissões e armazenamento.
- O arquivo
acme.jsonarmazena os certificados TLS e precisa de proteção (permissões restritas).
Casos de falha comuns na arquitetura:
- Falha DNS apontando para IP errado -> ACME falha.
- Firewall bloqueando 80/443 -> ACME falha.
- Container Gitea não conectado à rede
traefik-> 504 Gateway.
Casos de Uso
- Time pequeno/empresa que quer hospedar código sem depender de serviços externos (GitHub/GitLab).
- Pessoal que precisa de repositórios privados mas com controle total de backup e acesso.
- Integração com pipelines CI que fazem push para repositórios internos.
- Ambientes de teste onde repositórios são criados automaticamente (ex.: laboratórios de ensino).
Cada caso de uso exige políticas extras (backups regulares, autenticação forte, monitoramento e auditoria de logs).
Pré-requisitos
- Sistema: servidor Linux (Ubuntu 22.04 recomendado, uma vez que os passos abaixo foram feitos numa VPS com essa versão).
- Um domínio apontando para o IP do servidor (‘A’ record).
- Portas: 80/tcp e 443/tcp abertas (8080 opcional para dashboard).
- Docker + Docker Compose instalados (instruções abaixo).
Instalação básica (Ubuntu/Debian):
# Atualiza pacotes
sudo apt update && sudo apt upgrade -y
# Instala pré-requisitos para adicionar repositórios HTTPS
sudo apt install -y ca-certificates curl gnupg lsb-release
# Adiciona chave e repositório oficial do Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Habilita e inicia o docker
sudo systemctl enable --now docker
# Confirme versão
docker --version
docker compose version
Observações:
- No Debian/Ubuntu modernos
docker composevia plugin é suficiente. Você também pode usar odocker-composev1 se preferir. - Se estiver em outra distro, use o instalador oficial do Docker.
Estrutura de Diretórios
Organize da seguinte forma:
~/traefik/
config/
traefik.yml
acme.json # (crie manualmente, ver abaixo)
compose.yml
~/gitea/
compose.yml
gitea/ # (diretório de dados persistente do Gitea)
Configuração do Traefik
Crie ~/traefik/config/traefik.yml:
global:
sendAnonymousUsage: false
log:
level: DEBUG
api:
dashboard: true
insecure: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
certificatesResolvers:
http:
acme:
email: "seu@email.com"
storage: "acme.json"
httpChallenge:
entrypoint: web
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
Comentários importantes neste arquivo:
insecure: truehabilita o dashboard sem autenticação; use apenas temporariamente para debug.certificatesResolvers.httpusa o desafio HTTP para obter certificados; se quiser usar DNS, troque paradnsChallenge.exposedByDefault: falseevita que todos containers sejam automaticamente expostos; preferível por segurança.
Docker Compose do Traefik
Salve como ~/traefik/compose.yml:
services:
traefik:
image: traefik:latest
container_name: traefik
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/traefik.yml:/etc/traefik/traefik.yml:ro
- ./config/acme.json:/etc/traefik/acme.json
networks:
- traefik
restart: unless-stopped
networks:
traefik:
external: true
Notas e comentários no compose:
- O
docker.socké necessário para o provider Docker; monta em modoropor segurança. acme.jsonprecisa existir e ter permissão600(veja seção abaixo).- A rede
traefiké externa: crie-a comdocker network create traefik.
Docker Compose do Gitea
Salve como ~/gitea/compose.yml:
services:
server:
image: docker.gitea.com/gitea:latest
container_name: gitea
environment:
- USER_UID=${USER_UID}
- USER_GID=${USER_GID}
restart: always
networks:
- gitea
- traefik
volumes:
- ./gitea:/data
- /home/git/.ssh/:/data/git/.ssh
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "2222:22" # Para SSH Git (opcional)
labels:
- "traefik.enable=true"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
- "traefik.http.services.gitea.loadbalancer.server.scheme=http"
- "traefik.http.routers.gitea.rule=Host(`gitea.caioperlin.dev`)"
- "traefik.http.routers.gitea.tls=true"
- "traefik.http.routers.gitea.tls.certresolver=http"
- "traefik.http.routers.gitea.entrypoints=websecure"
networks:
gitea:
external: false
traefik:
external: true
Comentários importantes:
- Usuário do sistema para Git (recomendado):
# Cria user 'git' sem shell e com diretório home em /home/git
sudo useradd --system --create-home --shell /usr/sbin/nologin git
# Opcional: defina UID/GID explícitos para persistência entre máquinas
id -u git # mostra UID (use este valor em USER_UID)
id -g git # mostra GID (use este valor em USER_GID)
# No .env do diretório do compose do Gitea, defina:
# USER_UID=1001
# USER_GID=1001
- Por que
USER_UID/USER_GID?
- Garante que arquivos criados pelo container tenham proprietários consistentes no host.
- Estrutura de dados do Gitea:
./gitea(no host) será mapeado para/datano container; é aqui que o Gitea guarda repositórios, config e banco.
- Labels do Traefik:
traefik.http.services.*.loadbalancer.server.port=3000diz ao Traefik a porta interna do Gitea.- A regra
Host(...)define o hostname público usado para roteamento.
- SSH para Git:
- Se quiser empurrar via SSH, ative a porta 22 do container (mapeando para 2222 como no exemplo) e configure chaves no admin do Gitea.
Observação: Use o domínio que você configurou (ex:
gitea.seudominio.com) nas labels do Gitea!
Configuração do Firewall (UFW)
Garanta que apenas portas necessárias estejam liberadas:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8080/tcp # Dashboard do Traefik (desative depois de conferir funcionamento)
sudo ufw enable
sudo ufw status
Criando o acme.json para Certificados HTTPS
O arquivo acme.json é crucial para Traefik salvar os certificados do Let’s Encrypt.
cd ~/traefik/config
touch acme.json
chmod 600 acme.json
Se estiver gerenciando com sudo/deploy automatizado, garanta que o arquivo seja acessível pelo usuário que executa o Docker (ou mantenha dono root com perm 600).
Inicialização e Validação
-
Crie a rede Docker externa traefik (apenas uma vez):
docker network create traefik -
Inicialize o Traefik:
cd ~/traefik docker compose up -d -
Inicialize o Gitea:
cd ~/gitea docker compose up -d -
Verifique se está rodando:
docker ps
Ambos containers devem aparecer como Up.
Checklist de verificação rápida:
docker logs traefik; ver se houve obtenção de certificados sem erros.curl -I http://localhost:8080; dashboard acessível (seinsecure: true).curl -vk https://gitea.caioperlin.dev/; ver redirecionamento e TLS.
Passo-a-passo detalhado com verificações (tutorial):
- Verificar que o Docker está funcionando:
sudo systemctl status docker --no-pager
docker info | head -n 5
O systemctl deve mostrar active (running); docker info deve retornar detalhes do daemon.
- Conferir que a rede
traefikexiste:
docker network ls --filter name=traefik
Deve aparecer uma entrada traefik na lista.
- Conferir
acme.jsone permissões antes de subir o Traefik:
ls -l ~/traefik/config/acme.json
# Esperado: -rw------- (600)
- Subir Traefik e conferir logs de ACME:
cd ~/traefik
docker compose up -d
docker compose logs -f traefik
Procure mensagens tipo Legally... obtained certificate ou acme: ... indicando que o ACME obteve/renovou certificados. Se houver erros, verifique DNS e portas 80/443.
- Subir Gitea e validar conectividade interna:
cd ~/gitea
docker compose up -d
docker ps --filter name=gitea
Teste de conectividade a partir do Traefik para o backend Gitea (executa curl dentro do container Traefik):
docker exec -it traefik curl -sS -o /dev/null -w "%{http_code}" http://gitea:3000/
Saída esperada: 200 (ou 302/301 se houver redirect para instalação). Qualquer 5xx pode indicar problema de aplicação.
- Verificar HTTPS externo e detalhes do certificado:
curl -vk https://gitea.caioperlin.dev/ 2>&1 | sed -n '1,40p'
Procure SSL connection using e verifique o subject / issuer do certificado — deve apontar para Let’s Encrypt.
- Verificação SSH (opcional):
# Tente conectar via SSH (pode pedir confirmação de chave)
ssh -p 2222 git@gitea.caioperlin.dev
Se a conexão for recusada, verifique se a porta está exposta e se o Gitea está rodando com o serviço SSH ativado.
- Validação final da aplicação:
- Acesse
https://gitea.caioperlin.devno navegador e confirme que a interface do Gitea carrega. Na primeira execução, o Gitea pode abrir uma página de instalação inicial — siga as instruções e guarde credenciais administrativas.
Se todos esses passos passarem, sua implantação básica está funcional.
Validação Básica
- Acesse o dashboard do Traefik:
http://<IP-do-servidor>:8080/ - Tente acessar o Gitea via HTTPS:
https://gitea.caioperlin.dev - Se tudo funcionou, a página deve carregar com cadeado de segurança!
Se você receber erros de acme ou timeout, confira os logs do Traefik e as regras do firewall/registro DNS.
Resolução de Problemas
Problema mais comum: Gateway Timeout (Erro 504)
Solução: Falta o arquivo
acme.jsonou ele não está com permissão 600. Crie e corriga como mostrado acima e reinicie Traefik.
Outros comandos de diagnóstico:
- Checar logs do Traefik:
docker logs traefik | grep acme - Testar conectividade backend:
docker exec -it traefik curl -vk http://gitea:3000/ - Checar rede Docker:
docker network inspect traefik
Problemas comuns e soluções rápidas:
- Certificado não gerado: verifique
acme.jsone se porta 80/443 apontam para o servidor. - 504 Gateway Timeout: confirme se o container do Gitea está na rede
traefike responde em:3000. - Permissão ao gravar em volumes: verifique UID/GID do usuário que criou os diretórios.
Comandos Úteis
- Reiniciar containers:
docker restart traefik docker restart gitea - Ver estado do firewall:
sudo ufw status - Inspecionar dashboard Traefik:
http://<IP-do-servidor>:8080/
(Desative ‘insecure’ na config após validação!)
Exemplo rápido de deploy (resumido):
# 1) Crie rede traefik (uma vez)
docker network create traefik
# 2) Prepare diretórios e permissões
sudo mkdir -p /srv/traefik/config /srv/gitea/gitea
sudo chown -R root:root /srv/traefik
sudo chown -R git:git /srv/gitea/gitea
# 3) Inicie Traefik
cd /srv/traefik && docker compose up -d
# 4) Inicie Gitea
cd /srv/gitea && docker compose up -d
# 5) Conferir logs
docker compose -f /srv/traefik/compose.yml logs -f traefik
Resumo Final
Seguindo estes passos, você terá o Gitea rodando atrás do Traefik, com HTTPS automático e seguro, usando Docker Compose.
Lembre-se de ajustar o domínio e o email para seus dados!
Depois de validar o funcionamento, considere:
- Ajustar
emailnotraefik.ymlpara receber alertas do Let’s Encrypt. - Trocar
insecure: trueporfalsenotraefik.ymlapós confirmar o dashboard. - Fazer backup periódico de
/datado Gitea (repositórios + banco).