Pular para o conteúdo

Guia passo a passo — Parte 1: Instalar

Parte 1 do guia passo a passo: instalar o TWS Panel numa VPS limpa, do zero até o assistente de configuração (wizard). O README tem a versão curta; este guia explica cada passo, o que aparece na tela e o que fazer quando algo dá errado.

Os passos são numerados de 1 a 8. Os scripts do painel (install.sh, uninstall.sh) citam esses números.

PassoOndeO que faz
1ProvedorContratar a VPS
2Seu computador → VPSEntrar como root e conferir o sistema
3VPSCriar o seu usuário não-root
4Seu computadorGerar a chave SSH e instalar na VPS
5VPSInstalar o git
6VPSClonar o repositório em /opt/tws-panel
7VPSRodar o instalador
8NavegadorAbrir o painel e seguir o wizard

Depois do Passo 8, a etapa de Segurança do wizard tem um guia próprio: Wizard de segurança. Em seguida, a Parte 2 continua a configuração.

Uma VPS (servidor virtual) com:

  • Ubuntu 22.04 ou 24.04 LTS, limpa (sem outros programas instalados). Na criação, prefira o 24.04.
  • Mínimo recomendado: 1 vCPU, 2 GB de RAM e 25 GB de disco.
  • Portas 80 e 443 abertas para a internet. O certificado HTTPS depende delas. Se o provedor tem um firewall no painel da hospedagem, libere as duas.
  • Para o e-mail: a porta 25 liberada pelo provedor. Muitos provedores a bloqueiam, principalmente em contas novas. Você confere isso na Etapa 4 da Parte 2.

Você vai precisar de duas coisas que o provedor entrega: o IP da VPS e a senha de root. Antes de seguir, procure no painel do provedor por “Console”, “VNC”, “Rescue” ou “Modo de recuperação” e confirme que ele existe: é o caminho de volta se você perder o acesso SSH. Veja Perdi o acesso.

Sem domínio, tudo funciona com endereços automáticos *.sslip.io (por exemplo, https://203-0-113-10.sslip.io). Com um domínio seu, você ganha:

  • um endereço próprio para o painel (painel.example.com), em vez de um com o IP no nome;
  • o e-mail profissional, que exige domínio;
  • endereços próprios para os seus projetos.

Você vai criar registros no DNS do domínio (no provedor onde ele está, ou no Cloudflare). Os exemplos da Parte 2 usam o Cloudflare. Pode deixar o domínio para depois: nada na Parte 1 depende dele.

ContaPara quêObrigatória?
GitHubPublicar projetos a partir de um repositório. Repositório privado pede um token somente leitura (a tela ensina a gerar).Só se o código está no GitHub
CloudflareO R2, o armazenamento externo dos backups (o plano gratuito cobre 10 GB por mês; ele pede um cartão). Também serve de DNS do domínio.Recomendada
TelegramReceber os avisos do painel no celular.Opcional

Nenhuma delas é usada na Parte 1; você só precisa delas na Parte 2.

⚠️ Deu erro ao conectar: "REMOTE HOST IDENTIFICATION HAS CHANGED!"

Se, ao tentar conectar, apareceu isto em letras garrafais e a conexão foi recusada:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
...
Host key verification failed.

O que aconteceu. O SSH guarda a “digital” de cada servidor em que você já entrou. A digital que o servidor apresentou agora é diferente da que está guardada no seu computador — e o SSH prefere recusar a conexão a te conectar num servidor que pode não ser o seu.

Quando isso é esperado: você reinstalou o sistema da VPS, trocou de VPS, ou o provedor reatribuiu aquele mesmo IP a outra máquina. Nesses casos o servidor é outro de verdade, e a digital antiga não vale mais.

A solução — apague a digital antiga daquele IP e conecte de novo. Rode no seu computador:

Janela do terminal
ssh-keygen -R SEU_IP
ssh root@SEU_IP

Ele vai perguntar se você confia na nova identidade — responda yes. Pronto, a conexão volta ao normal.

🔄 Já tinha o painel instalado e quer começar de novo?

Antes de reinstalar a máquina inteira, veja se o caso é mesmo esse — quase sempre não é.

Só quero refazer o assistente de configuração. Não precisa reinstalar nada. Na VPS:

Janela do terminal
cd /opt/tws-panel
sudo ./scripts/reset-setup.sh # o wizard volta ao passo 0
sudo ./scripts/show-token.sh # mostra o setup token de novo

Seus projetos, domínios, e-mail e histórico de segurança continuam intactos. Use --full no primeiro comando se quiser apagar também a conta de administrador do painel.

Quero remover o painel e instalar de novo, sem reinstalar o sistema. Serve para testar a instalação quantas vezes quiser. Na VPS:

Janela do terminal
cd /opt/tws-panel
./scripts/uninstall.sh --dry-run # só mostra o que seria apagado; não mexe em nada
./scripts/uninstall.sh # mostra de novo e pede para você digitar "remover"

Ele apaga tudo o que o painel criou: o painel e os containers dele, o proxy (Caddy), o servidor de e-mail, os projetos implantados com seus dados, a pasta /opt/tws-projects, os scripts de hardening copiados para a VPS e, por último, a própria pasta /opt/tws-panel. Antes de apagar, ele lista exatamente o que encontrou. Depois, entre em outra pasta (cd ~) e recomece pelo Passo 6 (clonar o repositório) — o git do Passo 5 continua instalado. Quer manter a pasta do repositório? Use --keep-repo e vá direto ao Passo 7.

Quero a máquina limpa de verdade. Aí sim é reinstalação do sistema operacional, e ela acontece em dois lugares:

1. No painel do seu provedor de VPS. Procure por “Reinstall”, “Reimage” ou “Reinstalar sistema” — o nome muda conforme o provedor. Escolha Ubuntu 24.04 LTS e anote a nova senha de root que ele gerar; a antiga deixa de valer.

2. No seu computador. Como o sistema é outro, o servidor passa a se identificar com uma chave diferente, e a sua próxima conexão vai ser recusada com o aviso REMOTE HOST IDENTIFICATION HAS CHANGED!. Isso é esperado, e a solução está no bloco logo acima:

⬆️ Deu erro ao conectar: “REMOTE HOST IDENTIFICATION HAS CHANGED!”

Depois disso é só seguir do Passo 1 em diante, como numa VPS nova — porque agora ela é uma.

Contrate uma VPS com Ubuntu 24.04 LTS (mínimo recomendado: 1 vCPU / 2 GB RAM / 25 GB de disco), conforme os requisitos de Antes de começar.

Entre na VPS e confirme a versão do SO:

Janela do terminal
ssh root@SEU_IP
cat /etc/os-release # esperado: PRETTY_NAME="Ubuntu 24.04.x LTS" (ou 22.04)
🔐 Primeira vez conectando via SSH? O que aparece e o que responder

Na primeira conexão com qualquer servidor novo, o SSH mostra este aviso:

The authenticity of host '203.0.113.10 (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:Xk9vN2mQpL7dR4wT8yB3cF6hJ1uA5sE0gH9zK2xW4vM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

O que responder: digite yes e pressione Enter.

O que é isso? O fingerprint é a “digital” do servidor — é assim que o seu computador reconhece a VPS nas próximas conexões. O aviso aparece só na primeira vez; depois o fingerprint fica salvo e a conexão é direta.

Erros comuns:

  • “Digito a senha e nada aparece” — é normal! O terminal não mostra nenhum caractere (nem *) enquanto você digita senhas. Digite com calma e pressione Enter.
  • Permission denied (publickey,password) — senha errada ou o provedor da VPS exige chave SSH. Confira a senha no painel do provedor e tente de novo.
  • O aviso de fingerprint aparece de novo depois de reinstalar a VPS — normal, a máquina mudou. Remova a entrada antiga com ssh-keygen -R SEU_IP e conecte novamente.

É ele quem vai operar a VPS daqui em diante:

Janela do terminal
adduser SEU_USUARIO # troque SEU_USUARIO pelo nome que quiser; você escolhe a senha na hora
usermod -aG sudo SEU_USUARIO # dá permissão de administrador (sudo)
# --- Errou a senha, desistiu no meio ou quer recomeçar? Escolha UMA das duas: ---
passwd SEU_USUARIO # define/redefine só a senha, mantendo o usuário
deluser --remove-home SEU_USUARIO # apaga o usuário e a pasta dele, para criar tudo de novo
👤 Travou no adduser? O que aparece e o que preencher

Ao rodar adduser SEU_USUARIO, o sistema faz uma série de perguntas. Nos exemplos abaixo usamos “kelvin” como nome de exemplo — no seu caso vai aparecer o nome de usuário que você escolheu. É assim que aparece:

Adding user `kelvin' ...
Adding new group `kelvin' (1000) ...
Adding new user `kelvin' (1000) with group `kelvin' ...
Creating home directory `/home/kelvin' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for kelvin
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]

O que preencher, passo a passo:

  1. New password: — crie uma senha forte que você vai lembrar (é a senha do seu usuário, usada no SSH e no sudo). Atenção: nada aparece enquanto você digita — nem *. É normal, a senha está sendo registrada. Digite e pressione Enter.
  2. Retype new password: — repita a mesma senha.
  3. Full Name, Room Number, Work Phone, Home Phone, Other — dados opcionais. Pode deixar tudo em branco: basta pressionar Enter em cada um.
  4. Is the information correct? [Y/n] — digite Y (ou só Enter) para confirmar.

Erros comuns:

  • Sorry, passwords do not match seguido de Try again? [y/N] — as duas senhas digitadas foram diferentes. Responda y para digitar de novo. Cuidado com o N maiúsculo: ele é o padrão, então só pressionar Enter é o mesmo que responder n.

    E se eu já respondi n? Aí o adduser desiste da senha mas continua e cria o usuário — você vai ver passwd: password unchanged e, no final, Adding new user .... O usuário existe, mas sem senha, e não consegue entrar por SSH. Não é perda: defina a senha agora, sem recriar nada.

    Janela do terminal
    passwd SEU_USUARIO

    Se preferir começar do zero, apague e rode o adduser de novo:

    Janela do terminal
    deluser --remove-home SEU_USUARIO
  • Digitei n (ou qualquer coisa) em Room Number / Work Phone — são campos puramente cosméticos, não afetam login nem permissão. Se quiser limpar: chfn SEU_USUARIO e pressione Enter em cada campo.

  • BAD PASSWORD: ... — aviso de senha fraca. O sistema aceita, mas prefira uma senha longa (frase com palavras + números, ex.: cavalo-bateria-42-janela).

  • “Acho que digitei errado porque não vi nada” — sem problemas: se errou, o adduser reclama (Sorry, try again.) e pede de novo.

Confira que deu certo antes de seguir:

Janela do terminal
id SEU_USUARIO

Tem que aparecer sudo na lista de grupos. Se não aparecer, o segundo comando não pegou.

Agora encerre a sessão de root. Não vamos reconectar ainda — o próximo passo acontece no seu computador, e o exit já te deixa lá:

Janela do terminal
exit # sai do root e fecha a conexão SSH

Você volta para o terminal do seu computador. É de lá que o Passo 4 continua.

🤔 E o su - SEU_USUARIO, não serve?

Serve, e é mais rápido — mas tem um efeito colateral que vale conhecer.

Com su - SEU_USUARIO você continua dentro da sessão do root — apenas com outra identidade por cima. Um exit te devolve ao root em vez de encerrar o acesso, e é fácil esquecer que aquele terminal ainda tem uma sessão de root aberta embaixo.

Entrando por SSH direto como o seu usuário, a sessão é dele do começo ao fim: exit encerra de verdade, e tudo que exigir privilégio vai passar por sudo — que pede senha e fica registrado no log do sistema. É a diferença entre “estou de root com outro chapéu” e “estou como usuário comum e peço permissão quando preciso”.

Isso vale ainda mais se você vai deixar a sessão aberta por um tempo: melhor que ela seja a do seu usuário, não a do root.

E por que não usamos esse atalho aqui? Além da sessão de root que fica aberta, ele te mantém dentro da VPS — e o Passo 4 acontece no seu computador. Você teria que sair de qualquer forma, então o exit resolve as duas coisas de uma vez.

⏱️ Quer controlar quanto tempo a sua sessão SSH sobrevive parada? (opcional — leia se a conexão cai sozinha quando você para de digitar)

Se você já percebeu a sessão fechando depois de alguns minutos parado, o culpado quase sempre é o provedor da VPS, não o servidor: firewalls de rede costumam descartar conexões que ficam um tempo sem tráfego. O seu computador pode resolver isso mandando um sinal de vida a cada minuto. Rode no seu computador, não na VPS:

Janela do terminal
# no SEU computador (Linux/macOS). No Windows com PuTTY, o campo equivalente é
# "Seconds between keepalives" em Connection.
printf 'Host *\n ServerAliveInterval 60\n ServerAliveCountMax 3\n' >> ~/.ssh/config

Depois disso, reconecte. Isso não enfraquece a segurança — a sessão continua sendo encerrada se a rede realmente cair; o que muda é que ela para de parecer abandonada enquanto você está trabalhando.

Faça isso antes de ir para o wizard.

A etapa de Segurança do wizard vai desligar o login por senha no SSH (fase 02 do hardening). A partir daí, a chave é a sua porta de entrada — e o wizard pede a chave pública já na primeira fase, com um rollback automático de 5 minutos correndo. Gerando agora, com o terminal já aberto, você não para no meio do processo para trocar de janela.

Você acabou de sair da VPS, então já está no lugar certo: os comandos abaixo rodam no seu computador. É nele que a chave precisa existir para você se autenticar depois — se ela fosse gerada na VPS, não serviria para entrar nela.

Primeiro, veja se você já tem uma chave. Se você já usa SSH para alguma coisa — GitHub, outro servidor, o trabalho — ela provavelmente já existe, e gerar outra por cima apaga a antiga. Rode:

Janela do terminal
ls -l ~/.ssh/*.pub

No Windows (PowerShell):

Janela do terminal
Get-ChildItem ~\.ssh\*.pub

Olhe só o nome dos arquivos que apareceram e siga a primeira linha da tabela que bate com o que você viu:

Se na lista aparece…Use esta chaveO que fazer agora
id_ed25519.pub (mesmo que apareçam outros arquivos junto)id_ed25519Não gere nada. Vá direto para ⬇️ Instale a chave na VPS (é um link — clique nele)
id_rsa.pub, mas não id_ed25519.pubid_rsaNão gere nada. Vá para ⬇️ Instale a chave na VPS e, lá, use os comandos com id_rsa
Só arquivos com outros nomes (ex.: github_deploy.pub, algum_servico_deploy.pub)nenhuma delasGere uma chave nova no próximo bloco
No such file or directory (ou nada)—Gere uma chave nova no próximo bloco

Por que essa regra, e não “escolha a que achar melhor”:

  • id_ed25519 e id_rsa são nomes que o ssh experimenta sozinho toda vez que você conecta. Usando uma delas, o login na VPS funciona sem nenhuma configuração extra no seu computador. A id_rsa é mais antiga, mas o servidor aceita do mesmo jeito.
  • Chaves com outros nomes foram criadas para um serviço específico (um deploy, uma empresa, uma ferramenta). Não reaproveite: além de o ssh não tentá-las sozinho, misturar acessos significa que quem tem aquela chave passa a entrar também na sua VPS.
  • Gerar uma id_ed25519 nova, nesses dois últimos casos, não apaga nada — ela ainda não existe, então não há o que sobrescrever.

Agora sim, gere o par de chaves (só se a tabela acima mandou gerar). É o mesmo comando no Linux, no macOS, no WSL e no PowerShell do Windows:

Janela do terminal
ssh-keygen -t ed25519

Ele faz três perguntas, nesta ordem:

O que apareceO que fazer
Enter file in which to save the key (...id_ed25519):Só Enter — aceita o local padrão
Enter passphrase (empty for no passphrase):Digite uma senha. Nada aparece na tela, nem asterisco
Enter same passphrase again:Repita a mesma

A passphrase é uma senha extra que protege a chave caso alguém tenha acesso ao seu computador. Ela é recomendada, e para não digitá-la a cada conexão você pode guardá-la na sessão:

Janela do terminal
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519

Quando o comando terminar, confira que a chave foi criada:

Janela do terminal
cat ~/.ssh/id_ed25519.pub

No Windows (PowerShell) o comando para exibir é outro:

Janela do terminal
Get-Content ~\.ssh\id_ed25519.pub

Vai aparecer uma única linha, longa, mais ou menos assim:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8k2p... seu-usuario@seu-computador

Se a linha apareceu, a chave está criada.

Instale a chave na VPS — agora, enquanto a senha ainda funciona. O comando sempre diz qual arquivo instalar; use a linha da chave que a tabela escolheu:

Janela do terminal
ssh-copy-id -i ~/.ssh/id_ed25519.pub SEU_USUARIO@SEU_IP

Se a tabela mandou usar a id_rsa, a linha é esta (em vez da de cima):

Janela do terminal
ssh-copy-id -i ~/.ssh/id_rsa.pub SEU_USUARIO@SEU_IP

Ele pede a senha do adduser uma última vez e grava a sua chave pública no servidor. No Windows (PowerShell), onde o ssh-copy-id não existe, o equivalente é:

Janela do terminal
Get-Content ~\.ssh\id_ed25519.pub | ssh SEU_USUARIO@SEU_IP "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Com a id_rsa, troque id_ed25519.pub por id_rsa.pub nessa linha. Daqui em diante, sempre que um comando citar id_ed25519 (o cat, o ssh-add), quem usa id_rsa faz a mesma troca.

Agora teste, e é o teste que importa:

Janela do terminal
ssh SEU_USUARIO@SEU_IP

Se você entrar sem que ele peça a senha da conta, está funcionando. Ele pode pedir a passphrase da chave — isso é outra coisa, é local, e não tem relação com o servidor.

🔑 E se eu perder, apagar ou corromper a chave privada?

Prevenção (faça isso antes de seguir em frente):

  • Guarde uma cópia da chave privada em lugar seguro, como um gerenciador de senhas. Quem tiver essa cópia acessa a VPS — trate-a como uma senha.

  • Alternativa mais robusta: tenha uma segunda chave, gerada num outro dispositivo (outro computador, ou o seu celular). O campo do wizard aceita uma chave por vez, então instale a segunda depois de concluir o wizard, enquanto a primeira ainda funciona.

    Pegue a chave pública do outro dispositivo (o conteúdo do .pub dele), conecte na VPS pelo computador que já tem acesso e acrescente a linha:

    Janela do terminal
    echo "COLE_AQUI_A_SEGUNDA_CHAVE_PUBLICA" >> ~/.ssh/authorized_keys

    Use >> e não > — um > sozinho apaga as chaves existentes e te tranca para fora na próxima conexão. Confira o resultado com cat ~/.ssh/authorized_keys: devem aparecer as duas linhas. Assim, perder um dispositivo não te deixa sem acesso.

Se você já perdeu a chave — ou a senha, ou o acesso ao painel — veja Perdi o acesso: e agora?, que cobre cada caso e o caminho de volta.

O teste acima já te deixou conectado na VPS. A partir daqui, todos os passos são feitos lá, com esse usuário — o que precisar de permissão de administrador vai pedir sudo e a sua senha.

Janela do terminal
sudo apt update && sudo apt install -y git
📦 O git já estava instalado. Isso é normal?

É normal, sim. “Ubuntu 24.04 LTS” no painel do seu provedor quase nunca é o sistema cru da Canonical: é um template montado pelo provedor, e git, curl, wget e vim costumam vir nesse pacote. Encontrar o git já pronto numa máquina recém-criada não indica que alguém entrou nela.

O comando do Passo 5 continua valendo: se o pacote já estiver lá, o apt responde git is already the newest version e não faz nada.

Quer confirmar em vez de confiar? São três verificações de leitura, nenhuma altera o sistema:

Janela do terminal
dpkg -V git # silêncio = arquivos idênticos aos do pacote oficial
apt-cache policy git # a origem deve ser archive.ubuntu.com ou security.ubuntu.com
last -a | head # só os seus próprios logins devem aparecer

O dpkg -V compara cada arquivo instalado com a assinatura oficial do pacote — nenhuma saída é o resultado bom. No apt-cache policy, o que importa é a origem: um repositório desconhecido aí, sim, seria motivo para parar e investigar.

🔑 Primeiro sudo: o aviso gigante e a senha que não aparece

Na primeira vez que você usa sudo com um usuário novo, aparece um aviso clássico:

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for kelvin:

O que fazer:

  1. O aviso é só cerimônia de boas-vindas (uma tradição do Linux) — não exige resposta.
  2. Em [sudo] password for kelvin: (no seu terminal vai aparecer o nome do usuário que você criou, não “kelvin”), digite a senha do SEU usuário (a que você criou no adduser), não a senha de root.
  3. Lembre-se: nada aparece na tela enquanto você digita — nem *. Digite e Enter.

Esse aviso longo só aparece uma vez. Depois disso o sudo pede a senha direto — e, por alguns minutos, nem isso (ele “lembra” que você se autenticou).

Erros comuns:

  • Sorry, try again. — senha errada. Você tem 3 tentativas antes de o comando falhar.

  • kelvin is not in the sudoers file — o usuário não tem permissão de administrador, porque o usermod do Passo 3 não chegou a rodar para este usuário. Como o próprio sudo está bloqueado, a correção tem que ser feita como root. No seu computador, abra a sessão de root, dê a permissão e confirme:

    Janela do terminal
    ssh root@SEU_IP
    usermod -aG sudo SEU_USUARIO
    id SEU_USUARIO # tem que listar "sudo"
    exit

    E agora o detalhe que engana todo mundo: volte ao terminal do seu usuário, feche a sessão com exit e conecte de novo. O Linux só lê os grupos de um usuário no momento em que a sessão abre — a sua foi aberta antes de o grupo existir, então ela continuaria recusando o comando mesmo com a correção já aplicada. Reconectado, teste com sudo whoami: deve responder root.

Clone em /opt e dê a propriedade da pasta ao seu usuário:

Janela do terminal
sudo git clone --branch main https://github.com/kelvindk9w/tws-panel.git /opt/tws-panel
sudo chown -R $USER:$USER /opt/tws-panel
cd /opt/tws-panel

O instalador instala o Docker se necessário, builda a imagem, sobe os containers e termina mostrando o endereço do seu painel, já com HTTPS: https://SEU-IP-COM-HÍFENS.sslip.io (ex.: https://203-0-113-10.sslip.io). Sem túnel e sem escolher porta.

Janela do terminal
./scripts/install.sh
🩺 Pré-flight: o que aparece na tela e o que fazer em cada cenário

Cenário 1 — VPS limpa (o esperado): o relatório sai todo verde e a instalação segue sozinha, sem pedir nada:

[tws-panel] Pré-flight: inspecionando a máquina (nada será alterado nesta etapa)…
✓ SO: Ubuntu 24.04.2 LTS (suportado)
✓ RAM: 1984 MB
✓ Disco livre em /: 23 GB
✓ Docker: ausente (será instalado por este script)
✓ Nenhum container Docker em execução
✓ Portas do proxy e do e-mail (80/443/25/465/587/143/993/8080) livres
[tws-panel] Máquina limpa detectada ✓ — prosseguindo com a instalação.

Não precisa fazer nada — só aguardar o build (leva alguns minutos na primeira vez).

Cenário 2 — VPS já em uso: o relatório mostra itens com ⚠ e o instalador para e espera sua decisão:

⚠ Portas em uso: 80 443
⚠ Serviço ativo: nginx
================================================================================
⚠️ ATENÇÃO: esta VPS NÃO parece estar limpa (2 ponto(s) acima).
O TWS Panel foi feito para uma VPS Ubuntu LIMPA. Continuar pode causar
conflitos (portas, serviços, recursos) com o que já existe na máquina.
Este instalador NUNCA remove ou para nada que já exista — mas os
serviços do painel podem falhar ao subir se as portas estiverem ocupadas.
Para prosseguir mesmo assim, digite "continuar" — ou rode com
--force (PAAS_FORCE=1) em automações.
================================================================================
Digite "continuar" para prosseguir:

O que fazer:

  • Recomendado: pressione Ctrl+C (ou simplesmente não digite nada e feche) para abortar — nada foi instalado nem alterado. Resolva os conflitos (ex.: desative o nginx se ele não é mais usado, ou contrate uma VPS limpa) e rode o instalador de novo.
  • Se você sabe o que está fazendo (ex.: o serviço listado não usa as portas do painel): digite continuar e pressione Enter. Ao digitar, você confirma que leu o relatório e aceita o risco de conflitos.

Erros comuns:

  • Digitou errado (continua, Continuar) — o instalador aborta com Instalação abortada. Nada foi instalado ou alterado. É só rodar de novo.
  • Não use --force no seu primeiro contato — ele pula exatamente a reflexão que este aviso quer provocar. O --force existe para automação, não para pressa.

Logo depois do pré-flight, o instalador faz duas perguntas. Elas decidem como o terminal ao vivo do painel trabalha — é nele que a varredura de segurança e o hardening rodam:

  1. Com qual usuário o terminal abre. Ele mostra os usuários da VPS que têm permissão de administrador, mas quem digita o nome é você — mesmo que só exista um. Digite o usuário que você criou no Passo 3. root também é aceito, mas não recomendamos: uma aba do navegador esquecida aberta daria acesso de root à VPS para quem sentasse na frente dela.
  2. Como rodar o que precisa de root. Responda 1 (senha) — é o recomendado: quando algo precisar de administrador, o painel usa o sudo dentro do terminal e você digita a sua senha ali, como faria por SSH. A outra opção, 2 (segundo-plano), não pede senha: esses comandos rodam como root por trás, e você confere depois na tela de Auditoria.

Se o usuário não servir (não existe, está sem senha, não tem sudo…), o instalador explica o que fazer e pergunta de novo. Nada é instalado antes de você responder. A porta do painel ele escolhe sozinho: ela é só interna, você nunca vai digitá-la.

🔑 Senha ou segundo plano? O que acontece em cada um, sem letras miúdas

Modo senha (recomendado). O terminal abre como o seu usuário. Quando uma varredura ou uma fase do hardening precisa de root, o painel roda o comando com sudo no próprio terminal, e o sudo pede a sua senha — a mesma do adduser. Nada roda como administrador sem você ver e autorizar.

  • O trade-off: a senha sai do seu navegador, passa pelo painel e chega ao terminal da VPS. Ela não é gravada, registrada nem enviada a lugar nenhum — o projeto é open source e isso pode ser conferido no código. No caminho entre o seu navegador e a VPS ela vai criptografada: o painel é aberto por HTTPS (ou pelo túnel SSH, se você escolher esse acesso).
  • Exige que o usuário tenha senha e esteja no grupo sudo — o que o Passo 3 já fez.

Modo segundo-plano. O terminal também abre como o seu usuário, mas os comandos que precisam de root rodam como root, por trás, pela mesma ponte que o painel já usa para falar com a VPS. A saída aparece no terminal só para você acompanhar.

  • O trade-off: não pede senha, então você não autoriza comando a comando. A conferência é depois: tudo fica registrado na tela de Auditoria do painel.
  • Não exige sudo — dá até para usar um usuário criado só para o painel. O instalador avisa se o usuário escolhido não tiver sudo, porque aí, entrando por SSH com ele, você não consegue fazer nada como administrador.

Nos dois modos, o monitoramento automático agendado — que roda sozinho, sem ninguém para digitar senha — continua executando como root em segundo plano, e cada execução fica registrada na Auditoria.

Condição para os dois modos protegerem de verdade: o usuário do terminal não pode estar no grupo docker. Quem está nesse grupo vira root sem senha com um único comando, então passaria por cima tanto do pedido de senha quanto da Auditoria. Se ele estiver, o instalador avisa e oferece remover — veja Por que o painel não te coloca no grupo docker.

Instalando por automação (sem ninguém para responder)? Passe as escolhas direto:

Janela do terminal
./scripts/install.sh --terminal-user=SEU_USUARIO --root-mode=senha

Sem essas opções, com --force ou sem terminal interativo, o instalador não adivinha: mantém o comportamento antigo (terminal como root) e avisa. Numa reinstalação, o que você escolheu da primeira vez é mantido sem perguntar de novo — para trocar, veja Trocar o usuário do terminal do painel.

🔐 Opcional — acesso só por túnel SSH (o painel fica invisível na internet)

Por padrão o painel abre em https://SEU-IP-COM-HÍFENS.sslip.io. Se você preferir que ele não tenha endereço nenhum na internet — só quem tem SSH na VPS chega nele —, instale com:

Janela do terminal
./scripts/install.sh --acesso=tunel

Nesse modo o instalador pergunta em qual porta da VPS o painel fica e termina mostrando o comando do túnel SSH e o endereço http://localhost:PORTA/?token=…. O navegador vai mostrar “Não seguro” por ser http://localhost — e aqui não tem problema: o tráfego viaja criptografado dentro do túnel SSH. Para trocar de modo depois, rode o instalador de novo com --acesso=https ou --acesso=tunel. Com o painel em HTTPS, a Fase 02 fecha também o túnel SSH (não é usado); ao trocar para --acesso=tunel, o instalador libera o túnel de novo sozinho.

Erros comuns ao abrir o túnel:

  • bind [127.0.0.1]:9000: Address already in use (ao abrir o túnel) — a porta ocupada é a do seu computador, não a da VPS: o número da esquerda no ssh -L. Algum programa seu já está usando a 9000 (é comum em quem programa). Troque só esse número e abra o navegador nele: ssh -L 9100:localhost:9000 SEU_USUARIO@SEU_IP, depois http://localhost:9100/?token=.... Qualquer número alto e livre serve — 9100, 9300, 12345. Entenda as duas portas do túnel. Na próxima instalação, esse erro nem aparece se você conferir antes qual porta está livre no seu computador e informar esse número ao instalador.
  • “Não é possível acessar esse site” no navegador, com o túnel aberto — o endereço está com o número errado. O que vai no navegador é sempre o número da esquerda do seu ssh -L, que é a porta do seu computador. Se o seu túnel é ssh -L 9100:localhost:9001, o endereço é http://localhost:9100/?token=... — a 9001 é a porta da VPS e nunca aparece no navegador. Confira qual número o seu túnel está escutando com ss -ltnH 'sport = :9100' (Linux/WSL).
  • channel 2: open failed: connect failed: Connection refused (o túnel abre, mas o navegador diz que não conseguiu conectar) — aí é o outro lado: o número da direita não bate com a porta em que o painel está na VPS. Confira com sudo ./scripts/show-token.sh, que imprime o comando já com a porta certa.

Abra o painel no endereço https://…sslip.io que o instalador mostrou no final (ele já leva o setup token no link; se precisar, o token também aparece em destaque no terminal) e siga o wizard. O assistente abre no idioma do seu navegador (veja Idioma da interface logo abaixo).

┌──────────────────────────────────────────────────────────────────────┐
│ Assistente — https://SEU-IP.sslip.io/?token=… │
├──────────────────────────────────────────────────────────────────────┤
│ 1. Boas-vindas e token → valida o setup token e libera o │
│ terminal ao vivo do servidor │
│ 2. Saúde da máquina → CPU, RAM, disco, rede — os checks │
│ rodam AO VIVO no terminal embutido │
│ 3. Segurança → scan Lynis → plano → hardening │
│ (com rollback automático em 5 min) │
│ 4. Conta de administrador → usuário + senha forte do painel │
└──────────────────────────────────────────────────────────────────────┘

Idioma da interface. O painel está disponível em português e em inglês. Na primeira visita, ele percorre a lista de idiomas do navegador e usa o primeiro que tem: português para qualquer variante de pt (como pt-BR), inglês para en; se nenhum combinar, inglês. Para mudar, use o seletor Idioma nas telas do assistente e de login, no cabeçalho do painel (ao lado do menu do usuário, sempre à vista depois do login; na disposição lateral, no rodapé da lateral, acima do menu do usuário) ou em Configurações → Aparência. A escolha fica guardada só nesse navegador (não faz parte da sua conta); outro navegador ou aparelho começa de novo pelo idioma dele. As mensagens que o próprio servidor escreve (veja o aviso no topo desta página) continuam em português.

A etapa Segurança é a que exige mais atenção: ela mexe em como você entra na VPS. Antes de aplicar as fases, leia o Wizard de segurança.

O instalador é idempotente: pode ser executado de novo sem quebrar nada (rebuild + restart). O painel roda 100% em Docker (docker compose up -d), com o estado persistido no volume paas_data e acesso ao socket do Docker para gerenciar Caddy, Stalwart e seus projetos.

🎫 Banner final do instalador — e como recuperar o token depois

Quando a instalação termina, o terminal toca um “bip” e mostra um banner assim:

██████████████████████████████████████████████████████████████████████████████
██ ██
██ ✅ TWS PANEL INSTALADO E RODANDO COM SUCESSO! ██
██ ██
██████████████████████████████████████████████████████████████████████████████
👉 PRÓXIMO PASSO: abra o painel no navegador
Abra no navegador (de qualquer computador — não precisa de túnel nem de porta):
https://203-0-113-10.sslip.io/?token=<seu-token-de-48-caracteres>
A conexão é criptografada (HTTPS, certificado Let's Encrypt): a senha de
administrador que você vai criar e a senha do sudo, se o terminal pedir,
trafegam protegidas. O sslip.io só traduz o nome para o IP desta VPS — o
tráfego vai direto do seu navegador para cá.
┌──────────────────────────────────────────────────────────────────────────┐
│ ⚑ SETUP TOKEN ⚑ │
│ │
│ <seu-token-de-48-caracteres> │
│ │
│ ⚠ Ele aparece SÓ AGORA em destaque. Guarde-o até concluir o wizard. │
│ ⚠ Após criar a conta admin no fim do wizard, ele é invalidado. │
└──────────────────────────────────────────────────────────────────────────┘

O que fazer: copie o link completo (https://…sslip.io/?token=...) e cole no navegador. Ele já leva o token embutido — não precisa digitar nada. Instalou com --acesso=tunel? O banner mostra, no lugar dele, o comando do túnel e o endereço http://localhost:… (veja Acesso por túnel SSH).

Fechou o terminal e perdeu o banner? Sem pânico. Na VPS, rode qualquer um dos dois:

Janela do terminal
sudo ./scripts/show-token.sh # reexibe o link completo + token
sudo docker exec tws-panel cat /data/setup-token # mostra só o token

Erros comuns:

  • O instalador disse que o endereço https://…sslip.io não respondeu em 3 minutos — o certificado não saiu. A causa mais comum são as portas 80 e 443 bloqueadas num firewall do provedor (no painel da hospedagem): libere as duas e reinicie o painel com sudo docker compose restart. Para ver o que o proxy diz: sudo docker logs paas-caddy --tail 50. Enquanto isso, o acesso por túnel funciona (o banner mostra o comando).
  • Erros ao abrir o túnel (só no acesso por túnel) — estão explicados em Acesso por túnel SSH.
  • permission denied while trying to connect to the Docker daemon socket — faltou o sudo na frente do comando. É de propósito: o painel não coloca ninguém no grupo docker (veja o porquê).
  • setup token não encontrado... — ou o show-token.sh foi rodado numa máquina sem o painel (rode-o na VPS certa, de dentro de /opt/tws-panel), ou o assistente já foi concluído e o token foi apagado de propósito: para reabri-lo com um token novo, sudo ./scripts/reset-setup.sh.
  • O token não funciona mais no navegador — depois que você cria a conta admin (última etapa do wizard), o token é invalidado para sempre. A partir daí o acesso é pela tela de login, com seu usuário e senha do painel.

No primeiro acesso, o Dashboard mostra o roteiro Deixe o painel pronto, com o que ainda falta configurar (proteções, verificação em duas etapas, domínio do painel, e-mail, notificações e backups). A Parte 2 percorre cada um deles, em ordem.

Para publicar um projeto: cadastre o projeto, aponte o DNS, e o painel cuida do build, do proxy e do SSL. Guia de produção em production.md. Comandos do dia a dia, pasta dos projetos e troca de porta ou de usuário do terminal estão em Operação.