Ir para o conteúdo
Q
QuoteNode

Installation

Instalar num Servidor Público Ubuntu

Coloca o QuoteNode num servidor público Ubuntu com domínio, HTTPS, SMTP, backups e fundamentos de firewall.

Instalar num Servidor Público Ubuntu

Usa este caminho para um deployment em produção acessível por clientes através de um domínio público.

Quando usar

  • Clientes externos devem abrir links públicos de propostas.
  • As mensagens de email devem conter links funcionais.
  • Queres controlo direto sobre o servidor em vez de uma camada PaaS.

O que não vai funcionar sem configuração adequada

  • Links públicos falham se o DNS não apontar para o servidor.
  • Links públicos falham se o URL do browser diferir da configuração CORS.
  • A emissão do certificado HTTPS falha se os portos 80/443 estiverem bloqueados.
  • Links de email falham se o SMTP estiver em falta ou se as mensagens forem rejeitadas pelo provider de email do destinatário.
  • Deployments com IP doméstico dinâmico precisam de DDNS e port forwarding no router; um VPS é normalmente mais simples.

Pré-requisitos

  • Servidor Ubuntu LTS ou VPS.
  • Registo DNS público, por exemplo crm.example.com, a apontar para o servidor.
  • Portos 80 e 443 abertos a partir da internet.
  • Docker Engine 24.0+ e Docker Compose v2.
  • Conta SMTP para entrega de email.
  • Pelo menos 4 GB de RAM e 20 GB de espaço livre em disco (recomendados para produção).
  • Destino de backup e um procedimento de restore.

Verifica o Docker:

docker --version        # Should show 24.0+
docker compose version  # Should show v2.x

Passo 1 — Criar uma diretoria de projeto

mkdir quotenode && cd quotenode

Passo 2 — Criar o ficheiro de configuração

Cria um ficheiro chamado .env. Substitui crm.example.com pelo teu domínio real:

# Database
DB_URL=jdbc:postgresql://postgres:5432/quotenode
DB_USERNAME=quotenode
DB_PASSWORD=change-me-to-something-random-32-chars
DB_NAME=quotenode

# ============================================================
# SECURITY SECRETS — UNIQUE to this installation.
# SAVE THIS FILE and keep a secure backup.
# ============================================================
DB_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
TIMING_TOKEN_SECRET=change-me-timing-secret-min-32-chars
PUBLIC_LINK_PASSWORD_SESSION_SECRET=change-me-session-secret-min-32

# Public domain — replace with your real domain
CORS_ALLOWED_ORIGINS=https://crm.example.com
DOMAIN=crm.example.com

# Email delivery
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME[email protected]
SMTP_PASSWORD=your-smtp-password
SMTP_AUTH=true
SMTP_STARTTLS=true

# Notification preference links (must match your public domain)
NOTIFICATIONS_PUBLIC_PREFERENCES_URL=https://crm.example.com/notifications/preferences

# O IP do cliente é detetado automaticamente atrás de proxies internos e CDNs (incluindo Cloudflare) — deixe vazio.
# Defina apenas para um proxy invulgar cujo par de transporte seja um endereço PÚBLICO a confiar (IP/CIDR ou nome de host).
SECURITY_TRUSTED_PROXIES=

# Application
LOG_LEVEL=INFO
SPRING_PROFILES_ACTIVE=prod

Faz backup do teu ficheiro .env antes do primeiro uso em produção. Guarda-o num gestor de passwords ou num cofre físico. O DB_ENCRYPTION_KEY é crítico — perdê-lo significa que os dados cifrados ficam perdidos para sempre.

Alternativa SMTP: Podes omitir as variáveis SMTP_* do .env e configurar o email mais tarde em Definições > SMTP de email no QuoteNode. O painel de administração armazena a password SMTP cifrada com DB_ENCRYPTION_KEY, mantendo-a fora do teu ficheiro .env.

Passo 3 — Criar o ficheiro Docker Compose

Cria um ficheiro chamado docker-compose.yml:

services:
  postgres:
    image: postgres:18-alpine
    cpus: 4.0
    mem_limit: 512m
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      PGDATA: /var/lib/postgresql/data   # required for the postgres:18 image
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME}"]
      interval: 10s
      timeout: 5s
      retries: 10
    restart: unless-stopped

  gotenberg:
    image: gotenberg/gotenberg:8
    cpus: 2.0
    mem_limit: 448m
    environment:
      LOG_LEVEL: info
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:3000/health"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  backend:
    image: ghcr.io/lesisty7/quotenode/quotenode-api:latest
    cpus: 4.0
    mem_limit: 1792m
    depends_on:
      postgres: { condition: service_healthy }
      gotenberg: { condition: service_healthy }
    env_file: .env
    environment:
      SPRING_PROFILES_ACTIVE: prod
      JOBS_MODE: web
      PDF_ENABLED: "true"
      PDF_GOTENBERG_URL: http://gotenberg:3000
    volumes:
      - backend_uploads:/app/data/uploads
      - backend_pdfs:/app/data/pdfs
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 45s
    restart: unless-stopped

  frontend:
    image: ghcr.io/lesisty7/quotenode/quotenode-frontend:latest
    cpus: 2.0
    mem_limit: 192m
    depends_on:
      backend: { condition: service_healthy }
    ports:
      - "80:80"
      - "443:443"
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:80/"]
      interval: 15s
      timeout: 5s
      retries: 3
    restart: unless-stopped

volumes:
  postgres_data:
  backend_uploads:
  backend_pdfs:

Passo 4 — Configurar o firewall

Abre apenas o necessário:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Não expões o PostgreSQL publicamente. Fica na rede Docker.

Passo 5 — Iniciar o QuoteNode

docker compose up -d

Acompanha o arranque:

docker compose logs -f backend

Aguarda até ver Started QuoteNodeApplication. O container frontend (Caddy) obterá automaticamente um certificado Let’s Encrypt para o teu domínio.

Passo 6 — Abrir o QuoteNode

Navega para https://crm.example.com no teu browser.

Credenciais de acesso predefinidas:

CampoValor
Email[email protected]
PasswordAdmin123!

Altera a password predefinida imediatamente após iniciar sessão.

Verificações pós-deployment

  1. Iniciar sessão e alterar a password admin.
  2. Criar uma proposta de teste.
  3. Gerar um PDF.
  4. Criar e abrir um link público a partir de outro dispositivo.
  5. Se o SMTP estiver configurado, enviar uma notificação de teste e verificar que os links do email funcionam.

O que está a correr?

ContainerO que fazUso de RAM
postgresArmazena todos os teus dados~256 MB
backendServidor API Java, lógica de negócio~512 MB – 1,5 GB
gotenbergConverte HTML para PDF (baseado em Chromium)~200 MB
frontendServe a interface web + reverse proxy (Caddy com auto-HTTPS)~20 MB

Total: aproximadamente 1,5 – 2,5 GB de RAM.

Comandos habituais

# Check service status
docker compose ps

# View logs
docker compose logs -f backend

# Stop QuoteNode
docker compose down

# Update to the latest version
docker compose pull && docker compose up -d

Checklist de upgrade

Antes de cada upgrade:

  1. Confirma a versão atual da app na área de administração.
  2. Faz backup do .env.
  3. Corre ou verifica um backup fresco da base de dados.
  4. Faz pull das novas imagens e reinicia.
  5. Verifica health do backend, login, geração de PDF e um link público de proposta.

Manter os teus segredos seguros

SegredoO que protegeSe perdido
DB_PASSWORDAcesso à base de dadosRecuperável — reiniciar via ferramentas de administração PostgreSQL
DB_ENCRYPTION_KEYCódigos MFA, password SMTP, chave API FX, campos PIIPermanentemente ilegível
TIMING_TOKEN_SECRETTokens anti-timing-attackRegenerar — utilizadores re-autenticam-se
PUBLIC_LINK_PASSWORD_SESSION_SECRETSessões de links públicosRegenerar — as sessões ativas expiram

Guarda o .env num gestor de passwords (1Password, Bitwarden). Para máxima segurança, imprime os segredos e guarda a impressão numa caixa-forte física. Nunca faças commit do .env no controlo de versão.

Recuperação se .env for perdido

Se perderes o teu ficheiro .env mas tiveres uma cópia de segurança da base de dados não cifrada (o modo padrão):

  1. Cria um novo .env com novos segredos.
  2. Restaura a base de dados a partir da tua cópia de segurança.
  3. Todos os dados de negócio serão acessíveis.
  4. Perdidos: códigos MFA (utilizadores re-inscrevem-se), password SMTP (reinserir), chave API FX (reinserir). Se ENCRYPT_PII=true estava ativo, os dados de clientes cifrados também são perdidos.

Last reviewed: Recently