diff --git a/.env.example b/.env.example index e0a8902..dd789cf 100644 --- a/.env.example +++ b/.env.example @@ -19,6 +19,6 @@ POSTGRES_PASSWORD=CHANGE_ME_TO_A_STRONG_PASSWORD # Front-end URL used by CORS FRONTEND_PUBLIC_URL=https://seu-dominio.com -# Domain / HTTPS (docker-compose.prod.yml) +# Domain / HTTPS (docker-compose.prod.yml with Caddy) API_DOMAIN=api.seu-dominio.com ACME_EMAIL=seu-email@seu-dominio.com diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..f320404 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,8 @@ +{ + email {$ACME_EMAIL} +} + +{$API_DOMAIN} { + encode zstd gzip + reverse_proxy api:8080 +} diff --git a/DEPLOY.md b/DEPLOY.md index 9cd4a18..5a715fe 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -39,12 +39,14 @@ docker compose logs -f --tail=200 curl -I http://SEU_SERVIDOR:4000/health ``` -## Opção 2: subir já com domínio + HTTPS automático (Traefik) +## Opção 2: subir já com domínio + HTTPS automático (Caddy) ### Pré-requisitos - O DNS do domínio/subdomínio da API deve apontar para o IP do servidor (registro `A`). - Portas 80 e 443 abertas no firewall/security group. +> Se você viu erro do tipo `client version 1.24 is too old` no Traefik, use este modo com Caddy: ele não depende da API Docker para criar rotas e evita esse problema. + ### 1) Ajuste o `.env` Na pasta da API: @@ -60,7 +62,7 @@ Preencha obrigatoriamente: - `FRONTEND_PUBLIC_URL` (URL pública do front) - `JWT_KEY`, `SEED_ADMIN_*`, `POSTGRES_PASSWORD` -### 2) Suba em modo produção com Traefik +### 2) Suba em modo produção com Caddy ```bash docker compose -f docker-compose.prod.yml up -d --build @@ -116,5 +118,5 @@ docker compose -f docker-compose.prod.yml up -d --build ## Observações - O Postgres **não é exposto** para fora do Docker (sem `5432:5432`). - No modo IP, a API sobe na porta `4000` do host (`4000:8080`). -- No modo domínio, a API fica atrás do Traefik em `443` (HTTPS). +- No modo domínio, a API fica atrás do Caddy em `443` (HTTPS). - Defina valores fortes para `JWT_KEY`, `SEED_ADMIN_PASSWORD` e `POSTGRES_PASSWORD`. diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index ce15ba8..d347633 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,22 +1,21 @@ services: - traefik: - image: traefik:v3.3 - container_name: linegestao-traefik + caddy: + image: caddy:2.10-alpine + container_name: linegestao-caddy restart: unless-stopped - command: - - --providers.docker=true - - --providers.docker.exposedbydefault=false - - --entrypoints.web.address=:80 - - --entrypoints.websecure.address=:443 - - --certificatesresolvers.letsencrypt.acme.tlschallenge=true - - --certificatesresolvers.letsencrypt.acme.email=${ACME_EMAIL:?ACME_EMAIL is required} - - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json ports: - "80:80" - "443:443" + environment: + API_DOMAIN: ${API_DOMAIN:?API_DOMAIN is required} + ACME_EMAIL: ${ACME_EMAIL:?ACME_EMAIL is required} volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - traefik_letsencrypt:/letsencrypt + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data + - caddy_config:/config + depends_on: + api: + condition: service_healthy db: image: postgres:16-alpine @@ -59,13 +58,8 @@ services: timeout: 5s retries: 10 start_period: 20s - labels: - - traefik.enable=true - - traefik.http.routers.linegestao-api.rule=Host(`${API_DOMAIN:?API_DOMAIN is required}`) - - traefik.http.routers.linegestao-api.entrypoints=websecure - - traefik.http.routers.linegestao-api.tls.certresolver=letsencrypt - - traefik.http.services.linegestao-api.loadbalancer.server.port=8080 volumes: pg_data: - traefik_letsencrypt: + caddy_data: + caddy_config: