CenĆ”rio: Servidor Oracle Cloud (Ubuntu 22.04 aarch64/ARM), Foundry VTT nativo em Node.js, atualização do v12 → v13, servindo via Caddy (HTTPS) e systemd (persistĆŖncia). Inclui solução para ERR_SSL_PROTOCOL_ERROR e erros comuns (ACME/Let’s Encrypt, DuckDNS, rate limit GitHub, etc.).


0) Pré‑requisitos

  • Acesso SSH como usuĆ”rio que roda o serviƧo (ex: ubuntu).
  • Foundry key vĆ”lida (licenƧa) e URL de download do pacote Node (ZIP) do v13.
  • DNS pĆŗblico resolvendo para o IP da instĆ¢ncia (ex.: foundry-pedro.duckdns.org → 134.65.24.217).
  • Portas 80/443 liberadas na VCN/NSG da Oracle (para HTTPS e ACME), e a porta do Foundry (ex.: 30000) se precisar de acesso direto por HTTP.

Checagens rƔpidas

curl -4 ifconfig.co                  # IP pĆŗblico da VM
sudo ss -lntp | grep 30000           # Foundry ouvindo localmente
sudo ss -lntlp | grep ":80\|:443"    # Caddy/HTTP(S) ouvindo

1) Node.js 20+ (requisito do v13)

node -v

Se for < 20, instale a partir do NodeSource (mƩtodo recomendado com keyring):

sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" \
  | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt update
sudo apt install -y nodejs
node -v

Dica: build-essential/python3 ajudam a compilar módulos nativos quando necessÔrio:

sudo apt install -y build-essential python3 make g++

2) Backup antes de atualizar

# pare o serviço se for copiar a instalação
sudo systemctl stop foundry || true
 
# backup do user data (mundos/módulos/config)
tar -czf ~/foundrydata-backup-$(date +%F).tgz -C /home/ubuntu foundrydata

3) Baixar e instalar o Foundry v13 (Node)

Crie um diretório temporÔrio, baixe o ZIP Node do v13 com sua URL licenciada e descompacte:

mkdir -p ~/foundry_v13 && cd ~/foundry_v13
# exemplo com curl (use sua URL de download licenciada)
curl -fSL -o foundry_node.zip "https://seu_link_licenciado/foundry_node_13.x.zip"
unzip foundry_node.zip

Observação: nomes baixados podem vir com ?verify=.... Remova o arquivo após unzip.

Mova a instalação para o caminho definitivo (mantendo a anterior como foundry_old):

cd ~
sudo mv /home/ubuntu/foundry /home/ubuntu/foundry_old 2>/dev/null || true
sudo mv ~/foundry_v13 /home/ubuntu/foundry
sudo chown -R ubuntu:ubuntu /home/ubuntu/foundry

Crie/garanta o User Data Path (separado da aplicação):

mkdir -p /home/ubuntu/foundrydata/Config

Teste manualmente (entrypoint mudou no v13: main.js na raiz):

node /home/ubuntu/foundry/main.js \
  --dataPath=/home/ubuntu/foundrydata \
  --port=30000 --hostname=0.0.0.0

Acesse: http://SEU-IP:30000 (HTTP puro) para checar se abre a tela de licenƧa.


4) Executar em segundo plano com systemd (persistĆŖncia)

Opção A — systemctl edit (boa prĆ”tica)

sudo systemctl edit --full --force foundry.service

Cole e salve:

[Unit]
Description=Foundry VTT (Node v13)
After=network.target
 
[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/foundry
ExecStart=/usr/bin/node /home/ubuntu/foundry/main.js --dataPath=/home/ubuntu/foundrydata --port=30000 --hostname=0.0.0.0
Environment=NODE_ENV=production
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target

Ative e inicie:

sudo systemctl daemon-reload
sudo systemctl enable --now foundry
sudo systemctl status foundry --no-pager -l

Opção B — heredoc com tee (sem editor)

sudo tee /etc/systemd/system/foundry.service >/dev/null <<'EOF'
[Unit]
Description=Foundry VTT (Node v13)
After=network.target
 
[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/foundry
ExecStart=/usr/bin/node /home/ubuntu/foundry/main.js --dataPath=/home/ubuntu/foundrydata --port=30000 --hostname=0.0.0.0
Environment=NODE_ENV=production
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target
EOF
 
sudo systemctl daemon-reload
sudo systemctl enable --now foundry
sudo systemctl status foundry --no-pager -l

Logs/manutenção:

journalctl -u foundry -f           # seguir logs
sudo systemctl restart foundry     # reiniciar após ajustes

5) HTTP direto (modo simples, sem proxy/SSL)

Se quiser acessar via IP/porta sem HTTPS:

// /home/ubuntu/foundrydata/Config/options.json
{
  "hostname": "0.0.0.0",
  "port": 30000,
  "routePrefix": null,
  "sslCert": null,
  "sslKey": null,
  "proxySSL": false,
  "proxyPort": null
}

Reinicie: sudo systemctl restart foundry

Acesse explicitamente por HTTP: http://SEU-IP:30000

ERR_SSL_PROTOCOL_ERROR ocorre quando vocĆŖ acessa https:// um servidor que estĆ” respondendo apenas http://. Use http:// ou configure o proxy TLS (Caddy) abaixo.


6) HTTPS com Caddy (reverse proxy recomendado)

6.1 Instale o Caddy

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
 | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
 | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy

6.2 Abra portas 80/443 na Oracle Cloud

  • Na VCN/NSG/SeguranƧa, libere TCP 80 e TCP 443 (ingress) para 0.0.0.0/0.

6.3 Configure o Caddyfile

sudo tee /etc/caddy/Caddyfile >/dev/null <<'EOF'
SEU-DOMINIO.duckdns.org {
  encode zstd gzip
  reverse_proxy 127.0.0.1:30000
}
EOF
 
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo systemctl reload caddy
journalctl -u caddy -n 50 --no-pager

Você deve ver logs de emissão de certificado. Se aparecer erro ACME (DNS/SERVFAIL), veja a seção Troubleshooting.

6.4 Ajuste o Foundry para ā€œatrĆ”s de proxy TLSā€

// /home/ubuntu/foundrydata/Config/options.json
{
  "hostname": "SEU-DOMINIO.duckdns.org",
  "port": 30000,
  "routePrefix": null,
  "sslCert": null,
  "sslKey": null,
  "proxySSL": true,
  "proxyPort": 443,
  "compressStatic": true,
  "language": "pt-BR",
  "upnp": false
}

Reinicie: sudo systemctl restart foundry

6.5 Testes

curl -I http://127.0.0.1:30000               # upstream local (302 /license ou 200)
curl -I https://SEU-DOMINIO.duckdns.org      # deve responder via Caddy (HTTP/2 302/200)

7) Ativação inicial e segurança

  • Entre em https://SEU-DOMINIO.duckdns.org → aceite a licenƧa → cole sua foundry.key → defina senha de admin.
  • Atualize módulos (compatĆ­veis com v13) e teste os mundos antes de ir pra sessĆ£o.

8) Troubleshooting — erros comuns e correƧƵes

8.1 ERR_SSL_PROTOCOL_ERROR

  • Causa: browser acessando https:// enquanto o servidor responde apenas http:// (ou proxySSL:true no Foundry sem um proxy HTTPS ativo).
  • Correção rĆ”pida:
    • HTTP direto: use http://IP:PORTA e deixe proxySSL:false, sslCert:null, sslKey:null.
    • Com Caddy: configure o Caddyfile com o host certo, libere 80/443, e no Foundry use proxySSL:true/proxyPort:443 + sslCert/sslKey:null.

8.2 ACME/Let’s Encrypt — DNS problem: SERVFAIL / falha no certificado

  • Confirme que o A de SEU-DOMINIO.duckdns.org estĆ” apontando para o IP pĆŗblico da VM:
    dig +short A SEU-DOMINIO.duckdns.org
    dig @1.1.1.1 +short A SEU-DOMINIO.duckdns.org
  • Libere 80/443 (ingress) na Oracle.
  • Aguarde propagação DNS (geralmente segundos/minutos no DuckDNS).
  • Se bater em rate limit, teste com ACME de staging temporariamente (Caddyfile):
    {
      acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
    }
    SEU-DOMINIO.duckdns.org {
      encode zstd gzip
      reverse_proxy 127.0.0.1:30000
    }
    Depois que passar, remova o bloco global para voltar ao ACME de produção e recarregue.

8.3 GitHub 429 (rate limit) ao baixar scripts (ex.: jarbas)

  • Nunca salve/execute HTML como se fosse script. Baixe do raw.githubusercontent.com com -L/--location e verifique:
    curl -fSL --retry 5 --retry-all-errors -o jarbas \
      https://raw.githubusercontent.com/brunocalado/mestre-digital/master/jarbas
    head -n5 jarbas   # deve mostrar shebang/comandos, não HTML
    chmod +x jarbas
  • Alternativa: git clone --depth 1 https://github.com/brunocalado/mestre-digital.git e use os scripts locais.

8.4 mv: cannot stat 'foundry_v13'

  • VocĆŖ estava dentro da pasta ao tentar movĆŖ-la. Use caminhos absolutos e rode a partir do ~.
    cd ~
    sudo mv ~/foundry_v13 /home/ubuntu/foundry

8.5 ā€œSoftware license requires signature.ā€

  • Mensagem normal na primeira execução. Acesse /license e cole a foundry.key.

8.6 UFW/Firewall local

sudo ufw status
sudo ufw allow 80,443/tcp
sudo ufw allow 30000/tcp

Na Oracle, alƩm do UFW, abra as portas na VCN/NSG.

8.7 Checagens Ćŗteis

# Foundry
journalctl -u foundry -n 50 --no-pager
sudo ss -lntp | grep 30000
curl -I http://127.0.0.1:30000
 
# Caddy/HTTPS
journalctl -u caddy -n 80 --no-pager
curl -I https://SEU-DOMINIO.duckdns.org

9) (Opcional) Unit systemd endurecido

[Service]
NoNewPrivileges=yes
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
# Liberar escrita apenas onde precisa
ReadWritePaths=/home/ubuntu/foundry /home/ubuntu/foundrydata /var/log

Atenção: se endurecer demais, o Node pode não conseguir ler/escrever onde precisa. Teste e ajuste ReadWritePaths.


10) (Opcional) Atualizador DuckDNS com systemd timer

sudo tee /usr/local/bin/duckdns-update.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
DOMAIN="SEU-SUBDOMINIO"   # ex.: foundry-pedro
TOKEN="SEU_TOKEN"
IP="$(curl -s -4 https://ifconfig.co)"
curl -s "https://www.duckdns.org/update?domains=${DOMAIN}&token=${TOKEN}&ip=${IP}"
EOF
sudo chmod +x /usr/local/bin/duckdns-update.sh
 
sudo tee /etc/systemd/system/duckdns.service >/dev/null <<'EOF'
[Unit]
Description=DuckDNS updater
[Service]
Type=oneshot
ExecStart=/usr/local/bin/duckdns-update.sh
EOF
 
sudo tee /etc/systemd/system/duckdns.timer >/dev/null <<'EOF'
[Unit]
Description=Run DuckDNS updater every 5 minutes
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Unit=duckdns.service
[Install]
WantedBy=timers.target
EOF
 
sudo systemctl daemon-reload
sudo systemctl enable --now duckdns.timer
systemctl list-timers duckdns.timer

11) Cheat sheet (cola & vai)

Atualização v12 → v13 (nĆŗcleo)

# Node 20+
sudo apt update && sudo apt install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt update && sudo apt install -y nodejs
 
# backup user data
tar -czf ~/foundrydata-backup-$(date +%F).tgz -C /home/ubuntu foundrydata
 
# instalar v13 (Node)
mkdir -p ~/foundry_v13 && cd ~/foundry_v13
curl -fSL -o foundry_node.zip "https://seu_link_licenciado/foundry_node_13.x.zip"
unzip foundry_node.zip
cd ~ && sudo mv /home/ubuntu/foundry /home/ubuntu/foundry_old 2>/dev/null || true
sudo mv ~/foundry_v13 /home/ubuntu/foundry
sudo chown -R ubuntu:ubuntu /home/ubuntu/foundry
mkdir -p /home/ubuntu/foundrydata/Config
 
# systemd
sudo systemctl edit --full --force foundry.service   # cole o unit
sudo systemctl daemon-reload
sudo systemctl enable --now foundry
 
# HTTP teste
curl -I http://127.0.0.1:30000

HTTPS com Caddy (reverse proxy)

# Caddy
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy
 
# Caddyfile (ajuste o domĆ­nio)
sudo tee /etc/caddy/Caddyfile >/dev/null <<'EOF'
SEU-DOMINIO.duckdns.org {
  encode zstd gzip
  reverse_proxy 127.0.0.1:30000
}
EOF
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo systemctl reload caddy
 
# options.json (proxy TLS)
sudo tee /home/ubuntu/foundrydata/Config/options.json >/dev/null <<'JSON'
{
  "hostname": "SEU-DOMINIO.duckdns.org",
  "port": 30000,
  "routePrefix": null,
  "sslCert": null,
  "sslKey": null,
  "proxySSL": true,
  "proxyPort": 443,
  "compressStatic": true,
  "language": "pt-BR",
  "upnp": false
}
JSON
sudo systemctl restart foundry
 
# testes
curl -I http://127.0.0.1:30000
curl -I https://SEU-DOMINIO.duckdns.org

Fim

Com isso, vocĆŖ tem um fluxo reprodutĆ­vel: atualização do nĆŗcleo, separação de dados, execução persistente, HTTPS automĆ”tico por proxy e um arsenal de checagens para diagnosticar ERR_SSL_PROTOCOL_ERROR ou erros de emissĆ£o de certificado. Guarde este guia; quando pintar o mesmo sintoma, siga direto para as seƧƵes 5/6 (HTTP vs HTTPS) e 8 (Troubleshooting). Boa mesa! šŸŽ²