Saltar para o conteúdo principal
VPSGuia

Implementar uma aplicação local num VPS com o Claude Code: DNS e HTTPS

Passe uma aplicação Node.js local para um VPS Linux: revisão com o Claude Code, serviço sem root, configuração de DNS e HTTPS com Caddy.

7 min de leituraSharpHeberg
Implementar uma aplicação local num VPS com o Claude Code: DNS e HTTPS

A sua aplicação funciona em localhost. Agora quer partilhá-la através de um domínio real, sem deixar o portátil sempre ligado. As peças que faltam são um VPS, um processo de aplicação gerido, o DNS e um proxy inverso com HTTPS.

Este guia mostra esse percurso com uma pequena aplicação Node.js. O Claude Code pode ajudar a inspecionar o seu projeto e a preparar a configuração para revisão; a responsabilidade pelas alterações no servidor continua a ser sua. O modelo não é instalado no VPS, e o acesso e a faturação do Claude são independentes do alojamento.

De localhost a um VPS público: guia ilustrado de implementação

Guia animado. O dashboard é uma demonstração fictícia, não uma monitorização de infraestrutura em tempo real.

Veja a visão geral da implementação

Ver a apresentação da implementação (vídeo em inglês).

O que testámos na prática: um dashboard real, criado originalmente pelo Claude Code, foi implementado pelo nosso operador num VPS Linux descartável. Verificámos o DNS público, o HTTPS de confiança, o redirecionamento de HTTP para HTTPS, os processos da aplicação e do proxy sem privilégios de root e o acesso após reiniciar o serviço da aplicação. Não houve uma nova implementação autónoma feita pelo Claude. O prompt sugerido abaixo é didático, não uma resposta gravada.

Antes de começar

  • Um VPS Linux com systemd e uma conta SSH com acesso sudo. Utilize primeiro um VPS de teste; não substitua os serviços nem a configuração web de um site existente.
  • Um runtime Node.js LTS suportado, instalado no servidor, e o Caddy instalado como serviço do sistema. Instale estes pré-requisitos antes de seguir os passos de implementação.
  • Um domínio ou subdomínio cujos registos DNS possa editar.
  • Uma aplicação pequena e autónoma. O nosso exemplo serve index.html com server.mjs, sem dependências de pacotes nem base de dados.

As aplicações baseadas em frameworks precisam do seu próprio comando de build, comando de arranque, dependências e plano de armazenamento. Não presuma que um projeto Next.js, Python ou com base de dados possa usar este exemplo de dois ficheiros sem alterações.

1. Peça ao Claude Code que inspecione o projeto antes de o alterar

Comece no diretório do seu projeto local. Um bom primeiro pedido é:

code
Inspect this project without changing files. Identify its runtime,
build and start commands, configuration and secrets. Propose a Linux
VPS deployment using a non-root systemd service and Caddy HTTPS.
Bind the app to 127.0.0.1:3000. Explain each proposed file and
verification step. Do not connect to a server or edit DNS.

Os fluxos de trabalho documentados do Claude Code incluem o planeamento antes da edição. Reveja as alterações propostas em vez de aceitar cegamente os comandos de implementação. Mantenha chaves de API, credenciais de produção e chaves SSH privadas fora dos prompts e dos repositórios; o acesso só de leitura não torna confidenciais os ficheiros sensíveis.

2. Prepare e transfira a aplicação

Para este exemplo mínimo, guarde o seu HTML como index.html e utilize o servidor seguinte. Por predefinição, fica associado ao loopback e não expõe ficheiros arbitrários do projeto:

code
import {createServer} from 'node:http';
import {readFileSync} from 'node:fs';
import {fileURLToPath} from 'node:url';
const page=readFileSync(new URL('./index.html',import.meta.url));
export function createAppServer(){
 return createServer((req,res)=>{
  const pathname=new URL(req.url,'http://localhost').pathname;
  if(pathname!=='/' && pathname!=='/index.html'){
   res.writeHead(404,{'Content-Type':'text/plain; charset=utf-8'});res.end('Not found');return;
  }
  res.writeHead(200,{'Content-Type':'text/html; charset=utf-8','X-Content-Type-Options':'nosniff'});res.end(page);
 });
}
if(process.argv[1]===fileURLToPath(import.meta.url)){
 const host=process.env.HOST||'127.0.0.1';const port=Number(process.env.PORT||3000);
 const server=createAppServer();server.listen(port,host,()=>console.log(`Demo app listening on ${host}:${port}`));
 process.on('SIGTERM',()=>server.close(()=>process.exit(0)));
}

Execute-o localmente com node server.mjs, abra http://127.0.0.1:3000 e pare-o antes de continuar. Num VPS que já utilize a porta 3000, escolha outra porta privada e use-a de forma coerente no serviço e no proxy.

No diretório do seu projeto local, substitua deploy e VPS_IP pela sua conta SSH e pelo endereço real do servidor:

code
ssh deploy@VPS_IP 'mkdir -p ~/my-app'
scp index.html server.mjs deploy@VPS_IP:~/my-app/

No servidor, instale estes dois ficheiros não secretos num diretório de aplicação legível:

code
sudo install -d -m 0755 /opt/my-app
sudo install -m 0644 ~/my-app/index.html ~/my-app/server.mjs /opt/my-app/
command -v node

Anote o caminho absoluto do executável do Node. Tem de estar acessível fora da sua shell de login e do seu diretório pessoal. Uma instalação de gestor de versões apenas para o utilizador, em /home, não é adequada para o serviço reforçado abaixo. Nunca copie um .env de desenvolvimento, uma chave privada ou um dump de base de dados para um diretório web público.

3. Execute a aplicação como serviço systemd sem root

Utilize sudoedit /etc/systemd/system/my-app.service. Substitua /ABSOLUTE/PATH/TO/node pelo caminho real do executável, válido para todo o servidor, que acabou de verificar:

code
[Unit]
Description=My Node web app
After=network.target

[Service]
Type=simple
DynamicUser=true
WorkingDirectory=/opt/my-app
ExecStart=/ABSOLUTE/PATH/TO/node /opt/my-app/server.mjs
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=3000
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target

Os controlos de execução do systemd documentam a conta dinâmica e as definições de reforço de segurança. Este perfil serve a nossa aplicação só de leitura; as aplicações que escrevem uploads ou bases de dados exigem armazenamento persistente e permissões configurados de forma deliberada.

code
sudo systemctl daemon-reload
sudo systemctl enable --now my-app.service
sudo systemctl status my-app.service --no-pager
curl -fsS http://127.0.0.1:3000/

Resolva os erros da aplicação antes de mexer no DNS. Um serviço ativado fica configurado para arrancar com o sistema, mas isso não é prova de que um teste de reinício completo tenha sido feito.

4. Aponte um subdomínio para o VPS

Crie um registo A para o nome de anfitrião escolhido, como app.example.com, apontando para o endereço IPv4 público do seu VPS. Com a Cloudflare, a nossa demonstração com servidor direto utilizou apenas DNS e TTL automático. Não copie o IP da nossa demonstração para os registos do seu próprio site.

Verifique a resposta pública com dig +short A app.example.com. Inspecione também dig +short AAAA app.example.com: se existir um registo IPv6, este tem de chegar à mesma implementação funcional através de IPv6. O DNS apenas associa um endereço; não inicia a sua aplicação nem configura o HTTPS.

5. Coloque o Caddy à frente da aplicação privada

Mantenha o serviço Node em 127.0.0.1:3000. Torne as portas web públicas 80 e 443 acessíveis através da firewall do fornecedor e da firewall do anfitrião, sem remover o seu acesso SSH. Não exponha a porta 3000 à internet.

Adicione este bloco de site à configuração do serviço Caddy instalado, substituindo o nome de anfitrião de exemplo. Preserve os blocos de site não relacionados:

code
app.example.com {
    encode zstd gzip
    reverse_proxy 127.0.0.1:3000
}

A diretiva reverse_proxy reencaminha os pedidos públicos para a aplicação privada. Com um nome de anfitrião público elegível e condições de validação de certificados cumpridas, o HTTPS automático do Caddy obtém e renova os certificados e redireciona o HTTP para HTTPS.

Para o serviço de sistema e o caminho de configuração padrão do Caddy:

code
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy

O nosso VPS de filmagem utilizou um serviço Caddy dedicado e caminhos de configuração isolados, em vez do serviço partilhado padrão acima. O princípio de encaminhamento é o mesmo; estes caminhos e nomes de serviço destinados ao leitor são adaptações, não uma transcrição literal da instalação.

6. Verifique o resultado público e o reinício do serviço

code
curl -I http://app.example.com/
curl -I https://app.example.com/
sudo systemctl restart my-app.service
curl --retry 5 --retry-delay 1 --retry-connrefused -I https://app.example.com/

Confirme que existe um redirecionamento de HTTP para HTTPS, uma resposta HTTPS bem-sucedida e um certificado válido no navegador. Não utilize curl -k para esconder erros de confiança. Abra a página a partir de outra rede, e não apenas a partir do interior do VPS.

Uma verificação de reinício falhada exige investigação: consulte journalctl -u my-app.service -n 50 --no-pager e os registos do serviço do Caddy. Erros de DNS, IPv6 incorreto, uma aplicação parada, uma porta upstream errada e a validação de certificados bloqueada são problemas diferentes.

Verificámos o reinício do serviço da aplicação, não o reinício do VPS nem uma configuração de alta disponibilidade. Antes de alojar uma aplicação empresarial real, planeie também as atualizações, as cópias de segurança, a monitorização, a gestão de segredos e quaisquer dados persistentes.

Do projeto local a um endereço público

O percurso completo é simples: preparar o projeto, transferi-lo para o VPS, mantê-lo em execução como serviço gerido sem root, apontar o DNS para o servidor e terminar o HTTPS público no proxy inverso. O Claude Code pode ajudar a preparar e a explicar estas peças; a revisão e as verificações operacionais continuam a ser importantes.

Explore os planos VPS Linux da SharpHeberg quando estiver pronto para colocar um projeto local online. O alojamento fornece o ambiente de servidor, não uma subscrição do Claude incluída nem um modelo Claude alojado localmente.

Artigos relacionados

Continue a explorar a nossa base de conhecimento com estes artigos relacionados

Publicado em 28 de outubro de 2026 por SharpHeberg

Obrigado por ler as nossas análises técnicas e tutoriais

Voltar ao blog