Voltar para o blog
BunSelf-hostingDevOpsOpen Source

Self-host com Bun: o que vale rodar no seu próprio servidor

17 de outubro de 2026·7 min de leitura·Diego Horvatti

Toda vez que eu abro a fatura do cartão aparece mais uma assinatura de 5 dólares que eu nem lembrava que existia. Por isso o post What I self-host, do viceconsole.fyi, me pegou. O autor mostra o que roda na própria infraestrutura e explica o porquê de cada escolha. Eu li e fui direto revisar a minha lista. Este artigo é a minha versão do assunto, com um recorte específico: self-host com Bun, que hoje é o jeito mais curto que eu conheço de sair do "vou subir um servicinho" e chegar no "está rodando".

Por que self-host voltou a ser assunto

Durante uns dez anos a resposta padrão foi "joga num SaaS". Fazia sentido. Servidor dava trabalho, e o tempo do dev custa caro.

Três coisas mudaram:

  • VPS ficou barata. Com uns 5 dólares por mês você tem 2 vCPUs e 4 GB de RAM, o suficiente para uma dúzia de serviços pequenos.
  • SaaS ficou caro. Muita ferramenta que era grátis virou "free tier com 1 projeto" e o resto passou a ser pago.
  • O runtime ficou simples. Esse é o ponto que me interessa. Rodar JavaScript no servidor antes exigia Node, um gerenciador de pacotes, um bundler, às vezes um transpiler e um process manager. Com Bun boa parte disso vem num executável só.

O post original vai por um caminho mais amplo: fala de serviços prontos, de hardware, do prazer de ser dono dos próprios dados. Eu concordo com o espírito. Mas como dev, o que eu mais tenho para hospedar não é software dos outros. É a minha própria tralha: bots, webhooks, dashboards internos, scripts que precisam rodar de hora em hora.

O que faz sentido hospedar você mesmo

Antes de falar de código, vale separar. Nem tudo merece ir para o seu servidor.

O que eu hospedo sem medo:

  • Ferramentas internas. Painel de métricas do blog, encurtador de links, um formulário que manda notificação no Telegram.
  • Webhooks e automações. Coisa que recebe um POST do GitHub ou da Stripe e faz alguma tarefa.
  • Jobs agendados. Backup, scraping leve, relatório semanal por e-mail.
  • Protótipos. Aquela ideia que pode virar projeto ou morrer em duas semanas.

O que eu não hospedo:

  • E-mail. Entregabilidade é um buraco sem fundo. Deixe com quem vive disso.
  • Autenticação de produto com usuário pagante. Dá para fazer, mas o custo de errar é alto demais.
  • Banco de dados de cliente sem backup testado. Se você nunca restaurou um backup, você não tem backup. Tem um arquivo.

Self-host é ótimo até a hora em que você vira o plantão de si mesmo.

Essa frase resume a regra que eu uso: se cair às 3 da manhã e eu só descobrir no almoço, tudo bem? Então pode ir para casa. Se não pode, paga o SaaS e dorme.

Como um servidor com Bun fica enxuto

O motivo de eu gostar tanto de Bun para isso é que ele já traz quase tudo de que um serviço pequeno precisa. Servidor HTTP, SQLite, hash de senha, leitura de arquivo, cliente S3 e cliente Postgres estão na caixa.

Um encurtador de links completo, com persistência, cabe nisto:

import { Database } from "bun:sqlite";

const db = new Database("links.db", { create: true });
db.run("CREATE TABLE IF NOT EXISTS links (slug TEXT PRIMARY KEY, url TEXT NOT NULL)");

const find = db.query<{ url: string }, [string]>("SELECT url FROM links WHERE slug = ?");

Bun.serve({
  port: 3000,
  routes: {
    "/:slug": (req) => {
      const row = find.get(req.params.slug);
      return row ? Response.redirect(row.url, 302) : new Response("Não achei", { status: 404 });
    },
  },
});

Zero dependências. Sem express, sem better-sqlite3 compilando binding nativo na VPS, sem dotenv (o Bun lê o .env sozinho). O package.json desse projeto praticamente só tem o nome.

Isso parece detalhe, mas não é. Cada dependência é uma coisa que pode quebrar num npm install daqui a oito meses, quando você nem lembra mais como o projeto funciona. Em self-host, o inimigo não é a performance. É o esquecimento.

Binário único: o truque que muda o deploy

A parte que realmente mudou meu fluxo é o bun build --compile. Ele empacota o seu código e o runtime num executável só.

bun build ./src/index.ts --compile --minify --target=bun-linux-x64 --outfile encurtador
scp encurtador vps:/opt/encurtador/

Pronto. Na VPS não precisa ter Bun, Node, nada instalado. O arquivo fica com algumas dezenas de megabytes, porque carrega o runtime junto, mas em troca você ganha um deploy que é literalmente copiar um arquivo.

Para manter rodando, eu uso o que o Linux já tem. Nada de PM2:

# /etc/systemd/system/encurtador.service
[Service]
ExecStart=/opt/encurtador/encurtador
WorkingDirectory=/opt/encurtador
Restart=always
User=apps

[Install]
WantedBy=multi-user.target

Um systemctl enable --now encurtador e o serviço sobe no boot e reinicia se cair. Na frente eu coloco um Caddy, que resolve HTTPS sozinho com duas linhas de config por domínio.

Docker? Uso quando o serviço é software de terceiro, tipo um Postgres ou uma ferramenta open source que já vem com imagem pronta. Para código meu, em Bun, o binário + systemd é mais leve e tem menos peça móvel. Opinião forte da casa: container para um script de 40 linhas é fantasia de infraestrutura. Se o seu docker-compose é maior que o seu código, algo deu errado.

E o banco de dados?

Para quase tudo que é pessoal, SQLite resolve. Sério. Um arquivo, sem processo separado, sem senha, sem porta aberta. O bun:sqlite é rápido o bastante para um volume que um projeto pessoal nunca vai alcançar.

Quando preciso de Postgres (porque o projeto pode crescer, ou porque quero usar jsonb e full text search direito), o Bun também tem cliente nativo:

import { sql } from "bun";

const posts = await sql`SELECT slug, title FROM posts WHERE published = true LIMIT 10`;

Ele lê a DATABASE_URL do ambiente e usa template literal com parâmetros escapados. Dá para trocar o driver pg em muito projeto sem mexer em quase nada.

O backup é a parte que ninguém gosta e todo mundo deveria fazer. O meu é um job em Bun que roda de madrugada, gera o dump e manda para um bucket S3 compatível usando o Bun.s3 que já vem embutido. Uma vez por mês eu baixo um desses arquivos e restauro numa máquina local. Leva dez minutos e já me salvou uma vez.

Quanto custa e quanto dá de trabalho

Números da minha realidade, para você ter referência:

  • VPS: cerca de 5 dólares por mês, rodando 9 serviços.
  • Uso de RAM: cada serviço Bun parado fica na casa de 30 a 50 MB. O Postgres é quem mais come.
  • Tempo de manutenção: uns 30 minutos por mês, quase tudo atualizando o sistema e conferindo backup.

Comparando com o que eu pagaria em SaaS equivalente (encurtador, analytics simples, cron gerenciado, um banco pequeno), a conta passa fácil de 40 dólares. Mas a economia não é o argumento principal. O argumento é que eu entendo cada peça. Quando algo quebra, eu sei onde olhar.

O lado ruim existe e precisa ser dito. Atualização de segurança é responsabilidade sua. Se a VPS for invadida porque você deixou SSH com senha, a culpa é sua e de mais ninguém. Configure chave SSH, desligue login por senha, ligue o firewall e ative atualização automática de pacotes de segurança. Isso leva vinte minutos na primeira vez e evita muita dor de cabeça.

Vale a pena para você?

Se você é dev e tem meia dúzia de projetos pequenos espalhados em free tiers que vivem mudando de regra, vale. Comece pequeno: pegue um único serviço, reescreva em Bun sem dependências, compile, suba numa VPS com systemd e Caddy. Se depois de um mês ele não tiver te dado trabalho, mova o próximo.

O post do viceconsole.fyi me lembrou que ser dono da própria infraestrutura é mais uma questão de hábito do que de talento. O Bun só deixou esse hábito bem mais barato de manter. Hoje boa parte do que eu rodo em produção pessoal é um arquivo executável e um .service. Se quiser ver alguns dos projetos que nasceram assim, estão aqui no portfólio.

Resumo para o LinkedIn

Toda fatura do cartão traz mais uma assinatura de 5 dólares que eu nem lembrava que existia.

Hoje uma VPS de 5 dólares roda 9 serviços meus, e a manutenção não passa de 30 minutos por mês.

O segredo é o Bun: servidor HTTP, SQLite e cliente S3 já vêm na caixa, sem nenhuma dependência.

Um `bun build --compile` gera um binário único. O deploy virou copiar um arquivo, com systemd e Caddy na frente.

Minha regra: se cair às 3 da manhã e eu só descobrir no almoço, pode ir para o meu servidor. Se não pode, eu pago o SaaS e durmo.

Escrevi no blog o que vale hospedar você mesmo e o que eu deixo de fora. O link está nos comentários.

#Bun #SelfHosting #DevOps #JavaScript #Programação