O que há de novo
Cada funcionalidade, correção e melhoria entregue no sh0. 29 fases, 2 auditorias de segurança, mais de 90 sessões de engenharia — construído do zero em Rust.
v1.10.0: a porta que você escolhe chega à sua aplicação
Duas versões desde a v1.8.0. A que importa: a porta digitada no formulário de implantação enfim chega à própria aplicação. Um campo preenchido de antemão com 80 neutralizava em silêncio duas correções já entregues, e nenhum teste unitário conseguia vê-lo — cada camada estava correta isoladamente. Além disso, uma rede de proteção sob o segundo fator, uma página de acesso 99,5 % mais leve no retorno, e um domínio próprio para o painel.
Endpoints API
Ferramentas MCP
Testes passando
Templates de deploy
Linha do tempo de desenvolvimento
Do primeiro commit até pronto para produção — o histórico completo de construção
v1.10.0: a porta que você escolhe chega à sua aplicação
- A porta que você digita agora chega à sua aplicação. Um formulário de implantação preenchido com 80 fazia todas as aplicações declararem uma porta explícita, o que neutralizava de uma vez duas correções já entregues: o valor chegava ao `EXPOSE`, à porta publicada e à sonda de saúde, mas nunca ao processo. O campo agora começa vazio nos quatro caminhos — envio de arquivo, git, Dockerfile, imagem Docker —, doze modelos a mais escrevem `ENV PORT`, os modelos Java escrevem `ENV SERVER_PORT` para o Spring Boot, e quando você não diz nada é o `EXPOSE` da imagem que decide.
- Uma sonda de saúde que falha nomeia a porta realmente aberta: “Nothing answers on port 3000; the container listens on 9091”. Um Dockerfile que não declara nenhum `EXPOSE` diz para qual porta recorreu, em vez de fazê-lo em silêncio, e uma porta que contradiz o `EXPOSE` da imagem é sinalizada antes da implantação, não depois.
- O segundo fator ganha uma rede de proteção e uma memória. Os códigos de recuperação sobrevivem ao recarregamento do perfil que os apagava, podem ser regenerados pelo painel mediante um código novo do autenticador, e cada acesso protegido — por senha ou pelo Google — grava uma linha datada no registro de auditoria, recusas incluídas.
- O peso. Um visitante baixa um idioma em vez de cinco, e os recursos estáticos são armazenados em cache, revalidados por ETag e pré-comprimidos em brotli e gzip. A página de acesso passou de 1106 KB para 168 KB na primeira visita, e para 763 bytes na seguinte.
- A ligação com a nuvem passa a ser própria de cada instância. Cada instalação carrega agora a sua credencial e um canal cifrado até o proxy, em vez de uma chave partilhada por todos, e o painel pode mudar-se para um domínio seu — anunciado no painel, com o endereço antigo nomeado no momento em que deixa de responder.
- E o resto: onze laços de falha em modelos lidos e classificados — oito corrigidos, dois retirados —, um nome de host de serviço que já não serve o conteúdo do contêiner principal, uma troca de senha que revoga de verdade as outras sessões, e as origens do Google Identity autorizadas pela política de segurança de conteúdo. Cada correção aqui carrega uma observação datada em uma máquina real; o contador de “corrigido no código, nunca visto funcionar” continua em zero.
v1.9.0: um domínio para o painel, e falhas que se distinguem
- O painel recebe um caminho de adoção para o seu próprio domínio. Defini-lo ou removê-lo nomeia o endereço que vai deixar de responder, uma remoção que falha aparece em vermelho em vez de um falso sucesso, e a troca só é oferecida quando o certificado já está ativo.
- Três falhas diferentes do proxy devolviam o mesmo 404. Agora devolvem três códigos distintos, e um domínio conhecido cujo destino está ausente já não se declara desconhecido.
- Os três selos de estado do painel falam o idioma do painel, em vez de responder sempre em inglês.
- O documento OpenAPI anuncia a versão do binário que realmente o serve, em vez de um número fixado no código.
v1.8.0: projetos multisserviço, backup da instância, atualização autônoma
- Os serviços de um projeto se alcançam pelo nome. Um alias interno estável (`<app>.internal`) acompanha o contêiner quando seu endereço muda: ao reimplantar, o IP passa de 172.20.0.4 para 172.20.0.5, o nome continua respondendo e nenhuma URL precisa ser editada. Variáveis compartilhadas no nível do projeto, ordem de inicialização e importação de Compose de ponta a ponta.
- O sh0 faz backup de si mesmo. `sh0 instance backup` tira um instantâneo coerente do próprio banco de dados via `VACUUM INTO` — nunca uma cópia de arquivo, pois o banco roda em WAL —, mantém a chave mestra fora do artefato mas registra sua impressão digital, e `sh0 instance restore` o recoloca em uma máquina nova. Além da importação de projetos entre instâncias e da rotação da chave de criptografia dos segredos.
- O diagnóstico chega durante a espera, não depois dela. Os logs do contêiner aparecem enquanto a sonda de saúde roda, cada etapa de build informa quanto custou, uma linha de contexto abre o log de build, o estado do disco é legível pela API, a coleta de camadas pendentes fica registrada e um alerta precede a saturação em vez de constatá-la.
- A via de arquivo, para quem implanta o próprio código sem repositório git. O tipo de aplicação é aceito no envio, o comando de inicialização é configurável, uma falha de build mostra sua linha de contexto e sua causa, e um worker sem porta não retém mais o envio por 300 segundos deixando um contêiner para trás. Node, Python, Go e Rust implantados pelas duas vias, arquivo e Dockerfile.
- Uma instalação se repara e se atualiza sem SSH. `sh0 update` escolhe seu canal — estável ou preliminar —, verifica a soma de verificação do binário baixado e volta atrás nos dois sentidos; uma atualização não interrompe mais as aplicações implantadas. `sh0 doctor` verifica Docker, portas, disco, certificados e relógio, e termina com erro quando algo falta. Desinstalação limpa e unidade systemd endurecida.
- O correio e o armazenamento de arquivos tornam-se utilizáveis: Stalwart v0.16 controlado por JMAP, as rotações automáticas de DKIM refletidas no DNS, uma credencial recusada que o diz em vez de silenciar. E quarenta e oito correções, cada uma com uma observação datada em uma máquina real: não um teste unitário, uma máquina.
v1.7.1: licenças com data, renovação automática
- Uma licença passa a ter uma data de expiração alinhada com a assinatura que a pagou. As assinaturas mensais emitiam licenças perpétuas: um mês pago dava acesso vitalício.
- Uma passagem diária recupera a chave renovada, verifica a assinatura e substitui a armazenada — nada a fazer quando uma assinatura é renovada. Uma assinatura cancelada revoga a chave e o plano cai na passagem seguinte.
- Desafio DNS-01 por domínio: um servidor atrás de um CDN que termina o TLS (nuvem laranja da Cloudflare) obtém agora um certificado sem desativar a proteção, em vez de queimar o seu orçamento Let’s Encrypt em ciclo.
- Roteamento e ciclo de vida: um reinício que muda a porta publicada atualiza a rota do Caddy; uma aplicação que não escuta na porta configurada deixa de ser declarada saudável enquanto devolve 502; uma reimplantação já não deixa o contentor antigo vivo ao lado do novo.
- Os limites de recursos seguem o hardware e não a licença numa instalação auto-hospedada, e os atualizadores de estado SSL já sabem rebaixar um certificado, e não apenas promovê-lo.
- A v1.7.1 é necessária para qualquer licença comprada depois de 9 de setembro de 2026. As versões anteriores não sabem recuperar uma renovação e param no fim do primeiro período.
v1.7.0: uma licença é um documento assinado
- Uma chave de licença é agora um documento assinado em Ed25519 que carrega o seu próprio plano, e não uma cadeia cujo prefixo era acreditado. Qualquer cadeia não reconhecida ativava o plano Pro.
- A verificação é offline: a chave pública viaja dentro do binário, portanto um servidor isolado da rede valida a sua licença sem chamar nada.
v1.6.29: correções do dogfooding -- paridade .dockerignore, loops de falha nomeados, aplicações worker sem porta
- O contexto de build aplicava um padrão .dockerignore sem barra a qualquer profundidade (semântica gitignore); o Docker ancora cada padrão na raiz e só **/ desce. Um projeto que ignorava *.md e importava src/lib/resources/x.md compilava no Easypanel e falhava no sh0. O sh0 aplica agora as regras do Docker; a sua própria lista gerada escreve **/ explicitamente.
- O ciclo de saúde só lia State.Running. Um contentor que sai ao arrancar sob unless-stopped é reiniciado em menos de um segundo: parecia em execução, a sonda TCP falhava 300 s e o registo concluía tempo esgotado. O ciclo lê agora RestartCount e Restarting, falha em segundos com "crashed N times (exit code X)", para o loop e nomeia um OOM-kill. v1.6.30, no mesmo dia: o código de saída e o indicador OOM são lidos numa captura parada, porque o Docker os repõe a zero assim que reinicia o contentor -- um OOM-kill era anunciado como "exit code 0".
- Os builds de imagem usavam rm=true, que só remove os contentores intermédios em caso de sucesso; cada build falhado deixava um contentor Exited (1) com nome aleatório que nenhuma limpeza via. forcerm=true remove-o em ambos os casos.
- As aplicações têm um tipo: web (inalterado) ou worker. Um worker não resolve nem publica porta, não recebe rota Caddy nem domínio de pré-visualização, e está saudável quando permanece em execução 15 s sem reinício. Celery, BullMQ e processos tipo cron implantam-se sem serem mortos por uma sonda a que nada podia responder. Os formulários do painel expõem a escolha.
Correção v1.6.28: a API congelava após duas reimplantações, e o Sinatra respondia 403
- O proxy de pré-visualização dos endereços *.sh0.app mantinha vivo um guard de leitura do DashMap durante todo o pedido reencaminhado, horas num WebSocket. A limpeza da cache adicionada na reimplantação bloqueava então uma thread do runtime, um escritor em espera bloqueava os novos leitores, e duas reimplantações com tráfego congelaram a API com centenas de ligações em fila. A entrada da cache é agora copiada antes de qualquer await. Não instale a v1.6.27 em produção.
- O modelo Ruby nunca definia RACK_ENV: o Puma arrancava em desenvolvimento e a autorização de host do Sinatra 4 devolvia 403 a todos os hosts públicos, enquanto a sonda em localhost passava. A etapa de produção define agora RACK_ENV e RAILS_ENV como production.
Dezenove correções antes da produção: contexto de build, login em claro, modelos quebrados e um instalador que traz o Docker
- Contexto de build: um único caminho com mais de 100 bytes fazia falhar o arquivo tar (o cabeçalho GNU não tem campo prefix); os caminhos longos passam agora como ligações longas GNU. O sh0 também substituía o .dockerignore do projeto pela sua própria lista, que excluía todos os *.md: o ficheiro do projeto é agora lido e completado, nada é imposto quando traz o seu Dockerfile, e o número de ficheiros excluídos é registado.
- Autenticação: os cookies de sessão e de renovação levam Secure sempre que o pedido chegou por HTTPS, a porta 80 responde um 308 para https:// em cada host gerido (os desafios ACME continuam a passar), o instalador avisa que o primeiro login por IP vai em claro e mostra como pôr um domínio TLS no painel, e as credenciais fictícias [email protected] desaparecem do instalador, do painel e do banner do servidor.
- Stacks: o Go compila qualquer versão de go.mod (GOTOOLCHAIN=auto numa imagem atual) e encontra a raiz do módulo quando o binário vive em cmd/<nome>; a configuração do Bundler em Ruby chega à etapa de produção e o Puma liga-se uma só vez; o .NET deduz o assembly de entrada na construção, inclui o curl para a sua sonda e corre em .NET 10 com roll-forward. Uma reimplantação ou um escalonamento já não serve 502 em *.sh0.app enquanto a cache expira.
- Plataforma: uma cadeia de licença desconhecida é recusada em vez de ativar o Pro, a mensagem de quota nomeia o projeto que ocupa a vaga, `sh0 users list` lê a base local na máquina servidor, o proxy na nuvem encaminha /api/* para a sua aplicação em vez de responder por ela, o cartão Active Servers do site lê batimentos reais, e o get.sh0.dev instala o Docker (ou falha cedo com o comando exato) antes de escrever a unidade systemd.
Duas correções antes do dogfooding: contêineres parados sobrevivem à limpeza, certificados sob demanda já não exigem e-mail
- A limpeza horária do Docker removia todos os contêineres parados geridos pelo sh0, incluindo o de uma aplicação que acabara de falhar: código de saída, logs e o botão Iniciar desapareciam com ele. Um contêiner parado é agora mantido enquanto uma linha da base de dados o referenciar; só os verdadeiros órfãos são removidos, e a etapa é ignorada em vez de executada às cegas se a base não puder ser lida.
- A emissão de certificados sob demanda só era armada com um e-mail ACME configurado, embora o log a anunciasse armada em todos os casos -- numa instalação padrão, o Caddy continuava a emitir ao carregar a rota. A política abrangente sob demanda é agora emitida com ou sem e-mail; o e-mail é simplesmente omitido do emissor quando não existe.
Quatro lotes saem juntos: bloqueio de instância, certificados sob demanda e um estado SSL honesto
- `sh0 serve --port 9001` ao lado de uma instância em execução instalava pacotes, migrava a base de dados e parava o Caddy em execução antes de descobrir que não conseguia arrancar. Um `flock` consultivo sobre `sh0.pid` recusa agora a segunda instância de imediato, indica o PID que ocupa o diretório e não toca em nada. Uma falha deixa o ficheiro sem consequências: o bloqueio morre com o processo, e o arranque seguinte prossegue.
- Os certificados são emitidos sob demanda, no primeiro aperto de mão TLS, em vez de ao carregar a rota -- um domínio cujo DNS ainda não chegou deixa de consumir uma tentativa do Let's Encrypt. Um domínio fica `pending` até alguém se ligar, e o selo diz agora porquê (`ssl_pending_reason`). `ssl_expiry` era sempre `null`; agora é lido do certificado em disco. Um domínio `active` cujo certificado desaparece volta a `pending` após duas verificações consecutivas.
- Um contentor em ciclo de falhas dizia-se `running` porque só o estado do Docker era lido; o contador de reinícios e o código de saída fazem agora parte do veredicto. Os caminhos de streaming do Docker tinham buffers em memória sem limite -- o sh0 foi morto por OOM aos 7,3 GB em isolamento -- e estão agora limitados. O serviço de uma pilha Compose que recebia a rota pública era escolhido pela ordem de iteração de uma tabela hash e podia mudar entre implantações; agora é determinístico.
- As subscrições da página de estado estavam mortas por construção: o e-mail de confirmação nunca era enviado enquanto a API afirmava o contrário. O formulário só aparece agora se o SMTP estiver configurado, as subscrições não confirmadas são limitadas a 200 por domínio, e as linhas não confirmadas são purgadas após 48 horas em vez de 7 dias.
- «Executar agora» num agendamento de cópias lançava uma cópia pontual cujos arquivos escapavam a toda a retenção; agora executa o próprio agendamento. `restore-external` recusava um servidor de base de dados nunca aprovisionado mas aceitava um parado; um servidor parado também é recusado de forma síncrona.
- O importador Compose exigia `image:` e ignorava `build:` em silêncio; agora recusa um serviço `build:` com uma mensagem que diz o que fazer. `--acme-email` é persistido como `--panel-domain`, por isso as renovações deixam de depender de um valor de recurso não verificado. E a API já não anuncia `panel_domain_ssl: "provisioning"` quando nenhum aprovisionamento está a decorrer.
Laravel implanta, o Compose fala a forma longa e a porta para de se perder
- Toda aplicação Laravel era construída como Node. O detector parava no primeiro `package.json`, e um Laravel moderno sempre traz um porque é assim que o Vite compila os assets, então o contêiner morria em `npm start`, um script que nenhum `package.json` do Laravel contém. Agora o PHP vence esse empate quando o projeto apresenta provas: um framework em `composer.json`, um `artisan` ou um `public/index.php`. Um projeto Node que apenas embarca uma biblioteca PHP continua sendo Node.
- Detectar o Laravel não era fazê-lo funcionar. O `package.json` passa a ser uma etapa de assets dentro da imagem PHP, o Composer instala em duas passagens porque o `artisan` ainda não existe na primeira, uma `APP_KEY` é cunhada no primeiro deploy e guardada cifrada em vez de embutida na imagem, e os drivers de sessão, cache e fila passam a usar por padrão os que não exigem banco de dados. Esse último apareceu ao implantar na máquina de demonstração e receber um 500, não lendo código.
- Arquivos Compose escritos na forma longa para `ports` e `volumes` falhavam na leitura — `invalid type: map, expected a string`. As duas chaves aceitam agora qualquer das formas, inteiros nus incluídos, e `read_only: true` vira um monte realmente somente-leitura. Um caminho do host na forma longa continua recusado, mas a recusa agora nomeia a política em vez de devolver um erro de tipo.
- Na via de imagem Docker, a porta resolvida servia para publicar o contêiner e depois era descartada: uma aplicação implantada sem porta devolvia `port: null`, e qualquer domínio associado roteava para 3000 enquanto o contêiner escutava em outro lugar. Agora a porta é gravada em todas as vias, e o teste acrescentado não verifica a função e sim quem a chama, de modo que uma sexta via que esquecer fará a suíte falhar.
- O branch padrão era a string `main`, fixa no código. O sh0 nunca consultava o remoto: `laravel/laravel` (em `13.x`) e todo repositório ainda em `master` falhavam no primeiro passo com uma mensagem do libgit2. Um branch vazio significa agora «o do repositório»: o clone resolve o HEAD remoto, grava o nome encontrado na aplicação, e um branch inexistente é reportado nomeando os que existem.
Guardas que nunca corriam: CSRF, limitação de débito e dez comandos da CLI avariados
- O `sh0 push` não conseguia implantar de todo. Onze isenções de CSRF estavam escritas com um prefixo `/api/v1/` que o axum já tinha retirado: a guarda não correspondia a nada e `/apps/upload` e `/auth/logout` respondiam 415. As isenções correspondem agora aos caminhos que a camada vê realmente; uma implantação através do `sh0 push` foi medida em 25,7 s.
- O `sh0 login` falhava com `Unexpected response format`. O comando ainda desserializava um token que a API já não devolve -- ela coloca cookies HttpOnly e entrega apenas o token CSRF. O início de sessão agora autentica, ultrapassa o segundo fator quando está configurado, cunha uma chave de API e persiste-a; a chave leva o nome do utilizador, o da máquina e a data.
- O limitador de débito global estava inerte, e o defeito foi medido na própria instância de demonstração pública antes da correção: 1100 leituras, 1100 respostas, nem um único 429, contra as 1000 leituras e 500 escritas por minuto anunciadas. Mesma causa raiz -- a camada está montada dentro do ninho `/api/v1`, pelo que os seus caminhos `/api/v1/...` nunca correspondiam. É uma correção de segurança.
- O `X-Forwarded-For` só é acreditado quando o pedido chega de um par loopback ou privado, que é o que o próprio processo filho Caddy do sh0 é. Nota de compatibilidade: uma instalação por trás de um proxy com endereço público -- Cloudflare e afins -- passa a contar todo o seu tráfego num único compartimento, por falta de uma lista de proxies declarados.
- Oito comandos `list` estavam avariados -- `database-servers`, `auth-servers`, `realtime-servers`, `function-servers`, `mail`, `file-storage`, `uptime` e `nodes` morriam todos em `Failed to parse paginated response`. O `sh0 templates info` e o `sh0 db connection-info` falhavam em nomes de campo que tinham derivado do lado do servidor. O banner de arranque anunciava também systemd no macOS, onde o instalador não regista serviço algum desses; passa a nomear o launchd e cala-se quando o servidor já corre sob um LaunchAgent.
Oito casos de implantação jogados numa máquina real, três muros encontrados
- Esta versão vem de uma matriz de fumo da implantação jogada por inteiro numa máquina real -- oito casos, não uma releitura de código. Seis passam: Node genérico, Next com pnpm, site estático, Dockerfile arbitrário, e os modelos PostgreSQL e Redis. Dois falhavam e continuam abertos: Laravel e docker-compose.
- O falso verde, e o pior dos três. A verificação de saúde sondava o `docker-proxy`, que completa o aperto de mão TCP seja qual for a saúde do contentor: uma aplicação morta era declarada saudável. A sonda devolve agora um estado de três valores, e é o seu desfecho que decide, não a sua falha. Medido: um `nginx:alpine` sem HEALTHCHECK numa porta deliberadamente errada falha agora ao fim de 304 738 ms, ali onde a v1.6.20 o declarava verde em menos de um minuto.
- Sites estáticos: o nginx morria em ciclo por causa do seu pidfile. O `chown` não tinha acompanhado a mudança do pidfile para `/tmp/nginx`. Corrigido, mais um teste que verifica cada caminho gravável individualmente -- o teste existente procurava apenas a subcadeia `chown` e manteve-se verde durante todo o episódio.
- A porta introduzida sobrepunha-se em silêncio ao `EXPOSE` da imagem. O sh0 lê agora o `EXPOSE` quando nenhuma porta é indicada, e avisa em caso de desacordo, nas cinco vias de implantação.
- pnpm. As dependências com scripts de compilação já não eram construídas, e a poda do pnpm falhava duas vezes. Critério de aceitação atingido: o `ts-nextjs-tailwind-starter` compila em 211 s e serve um 200.
- 804 testes passados, `clippy --workspace --all-targets -- -D warnings` verde.
Uma retenção que poupa as cópias manuais e restauros que alcançam servidores autónomos
- A retenção deixa de tocar nas cópias manuais. Um agendamento só conta e remove as cópias que criou; tudo o que for lançado à mão fica imune por construção. A migração 057 liga cada cópia ao seu agendamento e só adota as linhas existentes quando a atribuição é certa -- uma origem com vários agendamentos mantém as linhas antigas intactas em vez de adivinhar. É a alteração de motor anunciada como futura na v1.6.19.
- O modal de agendamento lista os servidores de base de dados autónomos. O cartão Base de dados contava-os, a lista de seleção não: um servidor visível na contagem não podia ser agendado. Ambos mostram agora a mesma população -- bases de aplicações, serviços com base embebida e servidores autónomos com um distintivo «DB Server» -- e o passo para trás regressa à lista correta.
- Um restauro externo pode visar um servidor de base de dados autónomo, servidor inteiro ou base única. A via de servidor inteiro preserva as bases já presentes no destino, a garantia introduzida na v1.6.19. Três casos passam a ser recusados com uma mensagem clara em vez de falharem em silêncio: um servidor sem contentor iniciado, um nome de base começado por hífen e um destino desconhecido.
- O estado de restauro de uma cópia é gravado no momento em que a sua linha é criada. Os restauros externos mostravam um estado vazio até à primeira atualização -- uma lacuna presente desde a inserção original, revelada pelos testes novos. A confirmação de edição de um agendamento está também traduzida nas cinco línguas do painel, em vez de mostrar a chave por traduzir.
Segurança de restauro, reparação de linhas e um contrato de retenção coerente
- Restaurar uma cópia de servidor PostgreSQL completo já não destrói o destino. O restauro da v1.6.18 apagava todas as bases do servidor de destino e depois não restaurava nada -- uma regressão publicada com a correção do pg_dumpall. O restauro filtra agora o script no momento de restaurar: os arquivos já produzidos pela v1.6.18 continuam restauráveis.
- As cópias MongoDB autenticam-se. O mongodump e o mongorestore eram lançados sem credenciais: nenhuma cópia MongoDB de um servidor gerido tinha alguma vez produzido um arquivo -- cada tentativa morria no muro de autenticação. A palavra-passe chega agora às ferramentas pelo ambiente de execução do contentor.
- As cópias de servidor completo CockroachDB são recusadas com uma mensagem clara em vez de fingir. A imagem não inclui ferramentas cliente PostgreSQL, portanto a função não pode funcionar; o ramo morto que sugeria o contrário foi removido.
- A migração 056 repara as linhas de cópia danificadas por versões anteriores: restauros externos registados como arquivos (um caminho sem tamanho) e linhas presas em « restoring » pelo antigo caminho de restauro. Dois invariantes medidos em todo o histórico de versões tornam a reparação segura; as linhas inclassificáveis ficam intactas e documentadas.
- A retenção passa a ter um único contrato: 7 por omissão em todo o lado, 0 significa ilimitado. O formulário dizia 30 enquanto a API dizia 7, e escrever 0 tornava-se silenciosamente 30 porque zero é falsy. Limites 0-365, com rótulos atualizados nas cinco línguas do painel.
- A retenção conta todas as cópias de uma origem -- agendadas e manuais por igual. A documentação prometia que as manuais nunca eram contadas: era falso face ao motor, e a documentação diz agora o que acontece realmente. Tornar as cópias manuais imunes é uma alteração futura do motor, seguida à parte.
Retenção de cópias e dumps de servidor completo
- A retenção de cópias de segurança finalmente corre. A função de purga existia, não era chamada de lado nenhum e nunca tinha corrido desde a v1.0.0: o campo «Retenção» do painel não controlava nada e os repositórios cresciam sem limite. Corre agora após cada cópia agendada bem-sucedida, com uma varredura horária de recuperação para os repositórios já transbordados.
- Uma cópia de um servidor PostgreSQL completo já contém os seus dados. O agendador passava «postgres» como nome da base de dados, pelo que despejava a base de arranque, vazia: o arquivo estava bem formado, era restaurável e estava vazio. As cópias de servidor completo usam agora pg_dumpall, e o restauro já não corre numa transação única, porque criar bases de dados o proíbe.
- As cópias de um servidor MySQL completo funcionam, pura e simplesmente. Nunca tinham chegado a correr: o agendador passava «--all-databases» como nome de base de dados, que a validação rejeitava pelo travessão inicial. Mesma causa da falha do PostgreSQL, sintoma oposto: esta falhava ruidosamente em vez de mentir em silêncio.
- O painel dizia «Retenção (dias)» para aquilo que sempre foi um número de cópias. Corrigido nas cinco línguas do painel.
- Estas duas correções estão verificadas por testes, ainda não num servidor real. Nenhum teste da suite toca numa instância PostgreSQL verdadeira: verificam o comando construído, nunca a sua saída. Considere esta versão corrigida-mas-não-provada nos dumps de servidor completo até ter corrido na sua própria máquina.
Cópias de segurança de bases geridas -- acionamento, agendamento, restauro
- Uma base de dados criada num servidor de bases gerido já pode ser copiada: o acionador consultava apenas a tabela das bases autónomas, pelo que uma base gerida respondia «origem de cópia não encontrada». Verificado num servidor real abrindo o artefacto -- contém a tabela e as suas linhas.
- As cópias de um servidor de bases inteiro já podem ser restauradas. O acionador aceitava um tipo de origem que o restauro desconhecia, por isso cada restauro desse tipo era aceite e falhava depois em segundo plano; os destinos inválidos passam a ser recusados à partida.
- Um restauro externo deixa de provocar a purga de cópias verdadeiras. O registo de um restauro era escrito com o mesmo estado «concluído» de um arquivo, pelo que a retenção o contava e apagava cópias autênticas -- linhas e objetos armazenados -- para respeitar a quota. Cópias e operações de restauro são agora registos de natureza distinta.
- As bases geridas podem entrar num agendamento de cópias, e não apenas ser copiadas a pedido.
- Os projetos Python com Pipfile passam a incluir as suas dependências na imagem de produção. Confirmado abrindo a imagem construída e não por uma resposta HTTP correta: a correção anterior passava nos testes e entregava mesmo assim uma imagem sem elas.
- Os projetos com pnpm voltam a compilar: a imagem gerada instala exatamente a versão do pnpm que produziu o ficheiro de bloqueio, sobre uma base Node suficientemente recente para a executar. Fica um caso em aberto -- um projeto pnpm cujas dependências executam scripts de instalação falha na construção; correção em curso.
Correções de build nos deploys Git -- gestores de pacotes, Django, verificações de saúde
- Projetos com yarn ou bun voltam a compilar: a imagem gerada instala o gestor de pacotes em vez de invocar um que nunca esteve presente. Os projetos com pnpm continuam bloqueados -- a verificação em condições reais mostrou que a imagem base do Node é demasiado antiga para a versão do pnpm que é descarregada; corrigido em 1.6.17.
- Deploys Django executam o collectstatic na etapa de produção, onde as dependências realmente estão -- o passo falhava em silêncio e os ficheiros estáticos devolviam erro 500
- Os projetos Python com Pipfile ainda não estão corrigidos: a verificação em condições reais mostrou que a correção incluída aqui é incompleta -- as dependências continuam a não chegar à imagem final. Corrigido e verificado num servidor real em 1.6.17.
- As verificações de saúde em imagens Alpine consultam 127.0.0.1 com recurso a IPv6 -- o busybox wget resolvia ::1 primeiro, pelo que servidores apenas IPv4 eram reiniciados como não saudáveis
- Projetos Rust compilam com uma toolchain atual (rust:1-alpine) -- a imagem fixada em 1.77 já nem conseguia ler um Cargo.lock moderno
Reforço de alertas e monitoramento -- RBAC, SSRF, servidores de autenticação
- As regras de alerta e os canais de notificação agora aplicam as permissões de função -- os visualizadores do projeto não podem mais criar ou editar alertas, nem ler os segredos das rotas de notificação
- As verificações de uptime e de alerta foram reforçadas contra SSRF -- as requisições de saída não podem mais ser direcionadas a endereços internos ou privados
- O DNS rebinding é neutralizado fixando o IP resolvido durante toda a requisição, e o monitoramento agora falha de forma explícita se o seu cliente HTTP reforçado contra SSRF não puder ser construído, em vez de recorrer silenciosamente a um inseguro
- O provisionamento de servidores de autenticação (Logto) agora concede apenas as funções necessárias e falha de forma explícita em caso de criação parcial, em vez de deixar um servidor meio criado marcado como pronto
- Rotas de notificação mortas foram removidas e as entradas de configuração de alertas e uptime são validadas de forma mais rigorosa
Correções dos hubs BaaS -- segredos, domínios, funções edge
- As restaurações de banco de dados agora substituem o banco de destino e revertem de forma atômica em caso de erro, em vez de mesclar silenciosamente linhas com os dados existentes
- As credenciais dos servidores realtime só são retornadas a desenvolvedores e acima -- visualizadores do projeto não recebem mais os segredos de conexão
- Os servidores realtime, auth e de funções agora são acessíveis nos seus domínios públicos *.sh0.app
- Os servidores de funções Deno iniciam de forma confiável -- uma falha na inicialização é informada imediatamente em vez de um falso status de execução
- Os servidores de funções recebem um domínio público funcional com HTTPS automático na criação
Paridade de execução de contêineres -- correções de confiabilidade
- Restauração externa corrigida -- restaurar um backup armazenado em um destino externo (S3, R2) agora lê corretamente o artefato enviado
- Paridade de previews -- os contêineres de preview agora executam com o mesmo usuário da produção, de modo que aplicações que exigem privilégios elevados não falham mais em loop nas previews
- Paridade de escalonamento -- as réplicas agora herdam o usuário do contêiner principal, de modo que escalar uma aplicação cuja imagem executa como root não produz mais réplicas falhando em loop
- Correções de templates -- Garage, Logto e Plane agora iniciam corretamente logo após a instalação
Reforço de backups e armazenamento
- Restauração corrigida -- restaurar um backup de banco de dados ou de volume pelo painel ou pela API agora é concluído corretamente
- Controle de acesso de backups -- listar, acionar, baixar, restaurar e excluir backups agora exige as permissões adequadas do projeto
- Credenciais protegidas -- os endpoints de armazenamento de arquivos não retornam mais credenciais de administrador compartilhadas, e os destinos de backup só podem ser gerenciados por seus proprietários
- Listagens restritas -- os domínios de armazenamento e as chaves de acesso só são visíveis e gerenciáveis dentro dos seus próprios projetos e instâncias
- Limpeza completa -- excluir um backup remove seu artefato armazenado, e excluir uma instância de armazenamento desfaz suas rotas de proxy e sua configuração TLS
Confiabilidade de implantações -- correções complementares
- Implantações Git acessíveis -- a porta detectada de uma aplicação passa a ser memorizada, de modo que projetos Next.js, Django, FastAPI e Rust respondem na sua URL de pré-visualização sem configuração manual
- TLS mais limpo -- o servidor de origem não tenta mais obter certificados impossíveis para os domínios proxy *.sh0.app, liberando a cota de certificados compartilhada
- Plausible Analytics -- o modelo agora cria o papel e o banco de dados PostgreSQL, de forma que a pilha inicia corretamente
- Zitadel -- o modelo agora fornece uma tela de login funcional por padrão
- Convex -- o backend agora inicia (marcado como experimental enquanto o suporte multiporta é concluído)
- Limpeza aprimorada -- implantações com falha não deixam mais contêineres ou imagens órfãos
Reforço de produção -- lote de correções da auditoria
- As stacks populares são implantadas corretamente -- as aplicações recebem o seu cabeçalho Host real, de modo que WordPress, Laravel e Django funcionam atrás dos domínios *.sh0.app
- Estado de implantação confiável -- contêineres em loop de reinicialização são detectados e relatados como falhos em vez de aparecerem como em execução
- Indicador SSL preciso -- os domínios mostram o estado real do seu certificado e os links usam HTTPS
- Padrões mais seguros -- painéis de administração secundários (consoles de banco de dados, armazenamento de objetos, provedores de identidade) não são mais expostos publicamente por padrão
- Next.js e Rust -- projetos padrão do create-next-app e projetos Rust reais agora são implantados sem configuração manual
- Reparos no catálogo de modelos -- correção do tratamento de credenciais para Zitadel, Chatwoot, Langfuse, SurrealDB e Convex; remoção de modelos cujas imagens de origem não estão mais disponíveis
sh0 Manager: gestão da frota pelo celular
- Aplicativo móvel sh0 Manager: gerencie todas as suas instâncias sh0 pelo celular (iOS e Android)
- Vinculação por código QR: escaneie no painel para vincular instâncias, com tokens seguros de duração limitada
- Visão da frota: todas as instâncias, status on-line ou off-line, número de aplicações e plano, de relance
- Autenticação por token Bearer: o aplicativo móvel usa autenticação de sessão pelo cabeçalho Authorization
- Seção Manager no painel: gere tokens de vinculação, veja as informações da instância e gerencie a propriedade
Logs de construção ao vivo, variáveis de ambiente no envio e confiabilidade
- Logs de construção ao vivo: acompanhe as construções Docker em tempo real, com rolagem automática
- Corrigida a condição de corrida no envio de variáveis de ambiente: elas são salvas atomicamente antes de o pipeline de implantação começar
- Tempo limite de construção ampliado para 30 minutos: atende Rust e outros projetos de compilação longa
- Maior precisão da pontuação de saúde: teto de penalidade por regra, regras de segurança deixam de ser bloqueantes
- 0cron.dev implantado com sucesso no sh0 (backend em Rust e frontend SvelteKit): o primeiro aplicativo Rust real
- Ruído dos registros de sinal de vida eliminado: rotina em nível de depuração, informação apenas na troca de IP
Domínios de pré-visualização: uma URL imediata para cada aplicação
- Cada instância sh0 se registra no proxy em nuvem ao iniciar, sem nenhuma configuração
- Formato de subdomínio plano: undefined-undefined.sh0.app — um único certificado curinga, sustentável acima de 100 000 instalações
- Proxy reverso dos domínios de pré-visualização: um middleware Axum roteia o tráfego para o contêiner Docker correto
- Nenhum registro DNS na Cloudflare é necessário: o curinga *.sh0.app resolve tudo
- O painel exibe um selo “Pré-visualização” e links HTTPS clicáveis para todos esses domínios
- Funciona no plano gratuito: os domínios de pré-visualização não exigem licença
Rodada de QA 1: correções e acabamento
- Corrigido o selo de status SSL que exibia “pendente” com o HTTPS já ativo
- DNS do e-mail: o registro PTR passa a ser opcional (um IP compartilhado não permite DNS reverso)
- URLs do e-mail: portas Docker aleatórias removidas, endereços HTTPS limpos através do proxy Caddy
- Adicionados os redirecionamentos /webmail e /admin no estilo cPanel para os nomes de host do e-mail
- Corrigido o laço infinito de recarregamento do navegador na aba Fila do e-mail
- As credenciais de administração do e-mail aparecem na aba Visão geral, com alternância de exibição
- Tarefas agendadas: os redirecionamentos de shell (> /dev/null 2>&1) são removidos automaticamente dos comandos
- O histórico de execução das tarefas mostra a saída padrão e a de erro em um visualizador expansível
- Disparo de uma tarefa: janela em tempo real com sondagem, em vez de um aviso silencioso
- Corrigido o servidor de autenticação: imagem Docker correta (svhd/logto), ponto de entrada adequado, banco de dados inicializado na primeira execução
- Autenticação, tempo real e funções: estados vazios com explicações e pré-requisitos
- Os erros internos agora retornam a mensagem real (produto auto-hospedado, o usuário é administrador)
- Terminal do servidor e navegador de arquivos nas Configurações, para acesso direto à máquina
- Abas Arquivos e Volumes adicionadas às páginas de detalhe dos servidores de funções e de tempo real
- Corrigida a restrição de domínio sobre service_id (migração 049)
- 475 novas chaves de internacionalização e 4 páginas do site convertidas para o Paraglide
Segurança, Polimento e Feature-Complete
- Recursos avançados de e-mail: configuração de filtro de spam, resposta automática de férias, regras de filtro Sieve, monitoramento da fila de e-mails
- Rotação de chave DKIM e streaming de logs de contêiner para servidores de e-mail
- Controle de licença: todos os serviços BaaS restritos ao Pro+ com popups de UpgradePrompt em 12 páginas
- Integração com Trustpilot como aba fixa em todas as páginas do dashboard
- Estatísticas rápidas de BaaS na página inicial do dashboard
- 8 novas páginas de alternativas SEO: Vercel, Supabase, Firebase, Netlify, cPanel, Render, Railway, Fly.io
- Redesign da página inicial com hero de BaaS, seção de capacidades e faixa de preços
- Matriz de comparação de recursos na página de preços com 27 linhas
- Página de relações com investidores com white paper e PDFs de apresentação
- Prompts de sistema de IA atualizados com recursos e capacidades atuais
- 979 chaves i18n para páginas de SEO em 5 idiomas
- 5 correções de segurança críticas: injeção Sieve, perda de dados em resposta automática de férias, bypass de escopo MCP em 92 ferramentas, travessia de caminho em backups, sobrescrita de estado do Cloudflare
- 10 correções de segurança importantes: validação de entrada, limpeza de DNS, validação de alvo de sandbox, prompts de confirmação no CLI
Armazenamento de Arquivos, Servidores de Banco de Dados e E-mail
- Armazenamento de objetos S3-compatível gerenciado com MinIO — buckets, chaves de acesso, monitoramento de uso
- Servidores de banco de dados standalone: PostgreSQL, MySQL, MariaDB, MongoDB, Redis com gerenciamento de usuários e permissões
- Hospedagem de e-mail gerenciada via Stalwart com configuração automática de DKIM, SPF e DMARC
- Assistente de configuração DNS em 4 etapas para e-mail com suporte a autoconfiguração do Cloudflare
- Caixas de entrada, aliases, regras catch-all e monitoramento de entregabilidade
- Integração de UI de administração de banco de dados: dbGate, phpMyAdmin, Mongo Express
- Acesso externo ao banco de dados com lista de IPs permitidos para conexões remotas seguras
- Página global de domínios: visão central de todas as URLs de serviço em cada app
- Mais de 50 novos endpoints de API para armazenamento de arquivos, servidores de banco de dados e e-mail
- Funciona nativamente com AWS SDK, Laravel, WordPress e qualquer cliente S3-compatível
Infraestrutura Core
- Cargo workspace com 10 crates Rust, gerenciamento de dependências compartilhado
- sh0-db: SQLite com modo WAL, pool r2d2, 30 migrações
- sh0-docker: Cliente completo da API Docker Engine sobre Unix socket (hyper 1.x)
- sh0-api: Servidor REST Axum com CRUD, paginação, streaming de logs via WebSocket
- sh0-git: Git clone/pull (libgit2), parsing de webhooks GitHub/GitLab/Bitbucket com HMAC-SHA256
- sh0-builder: 19 detectores de stack, 15 templates Dockerfile, builds multi-stage
- Motor de Verificação de Saúde do Código: 34 regras em Rust puro em 8 categorias
Proxy Reverso & Pipeline de Deploy Completo
- sh0-proxy: gerenciamento de processo filho Caddy com API admin JSON
- Auto-SSL via Let's Encrypt com e-mail ACME configurável
- Pipeline de deploy ponta a ponta: git pull -> analisar -> construir -> deploy -> verificação de saúde -> rotear
- Troca de container blue-green com deploy sem downtime
- Sistema de limpeza Docker: imagens penduradas, imagens antigas de apps, limpeza de cache de build
- Verificação de espaço em disco pré-deploy (falha em >90%, avisa em >80%)
- Rollback via reutilização de imagem em cache
Autenticação & Monitoramento
- Hashing de senha Argon2id, JWT HS256 (1h access + rotação de refresh de 30d)
- 2FA TOTP com códigos de backup com hash e URI de provisionamento
- Sistema de chaves API: hash SHA-256, prefixo sh0_, comparação em tempo constante
- Chave mestra de criptografia AES-256-GCM (PBKDF2, 100K iterações)
- Coleta de métricas em tempo real: CPU, memória, I/O de rede por container
- Avaliação de alertas: high_cpu, high_memory, app_down com cooldown de 5 min
Motor de Backup & Dashboard
- Dumps de banco via Docker exec: pg_dump, mysqldump, mongodump
- Backup de volume (tar + gzip) com criptografia AES-256-GCM
- Agendamento de backup via cron com limpeza por retenção
- SvelteKit 2 + Svelte 5 runes SPA com TailwindCSS 4
- Tema claro/escuro, i18n em 5 idiomas (EN, FR, ES, PT, SW)
- Cliente API com Bearer token automático, WebSocket com reconexão automática
- Dashboard embarcado no binário Rust via include_dir + build.rs
Dashboard Core & Páginas Estendidas
- Página de detalhe de app com layout de 6 abas: Visão Geral, Deploys, Logs, Domínios, Ambiente, Configurações
- Visualizador de logs em tempo real: WebSocket, estilo terminal, auto-scroll, buffer de 1000 linhas
- Editor de variáveis de ambiente com toggle de criptografia/revelação AES-256-GCM
- Página de gerenciamento de banco de dados com seletor de engine (postgres, mysql, mongodb, redis, mariadb)
- Gerenciador de backup: acionar, restaurar, excluir, criação de agendamento com cron
- Página de monitoramento: medidores de CPU/memória, CRUD de alertas, atualização automática
- Configurações: info do servidor, configuração/desativação 2FA TOTP, gerenciamento de chaves API
CLI, Templates, Alertas & Compose
- Cliente CLI: 7 comandos (apps, deploy, logs, env, check, ssh, status)
- Verificação de Saúde do Código local via sh0 check com saída colorida no terminal
- 170 templates YAML com um clique em 15 categorias (WordPress ao Ollama)
- Motor de substituição de variáveis com geração automática para secrets/senhas
- 5 canais de despacho de alertas: e-mail (SMTP), Slack, Discord, Telegram, webhook
- Parser Docker Compose v3 com deploy multi-serviço
RBAC, Exportação, Cron, Previews & Hooks
- RBAC de 4 níveis: Owner > Admin > Developer > Viewer (global + escopo por projeto)
- Log de auditoria em todos os handlers (assíncrono fire-and-forget)
- 7 formatos de exportação: Docker Compose, Kubernetes, AWS ECS, GCP Cloud Run, Vercel, Railway, Render
- Agendador de cron jobs com execução baseada em ticks, captura de stdout/stderr, histórico de execuções
- Ambientes de preview: auto-deploy baseado em PR com subdomínios únicos e limpeza TTL
- Hooks de deploy: pre_build, post_build, pre_deploy, post_deploy com enforcement de timeout
- sh0.yaml Infraestrutura como Código: defina stacks inteiras em um arquivo
Scaling & Monitoramento de Uptime
- Scaling horizontal: 1-50 réplicas com balanceamento de carga (round_robin, least_conn, random)
- Autoscaling por limites de CPU/memória com cooldowns configuráveis
- Monitoramento de uptime: verificações de saúde HTTP com detecção e ciclo de vida de incidentes
- Páginas de status públicas com histórico de uptime por domínio
- Sistema de assinatura por e-mail para notificações da página de status
51 Problemas Encontrados & Corrigidos
- 2 auditorias de segurança abrangentes em todas as 103 fases
- 13 correções críticas: comparação de chave API em tempo constante, auth JWT WebSocket, hashing de código de backup, lock de deploy por app
- 20 correções altas: validação de domínio, prevenção de path traversal, redação de secrets em logs de build, args Docker codificados em URL
- Expiração JWT reduzida (7d -> 1h) com rotação de refresh token de 30 dias
- Proteção CSRF (enforcement de Content-Type + padrão double-submit)
- Rate limiting: login (10/15min), TOTP (5/5min), global (1000/500s)
- Headers de segurança: HSTS, CSP, X-Frame-Options, X-Content-Type-Options
Arquitetura Baseada em Stacks & Polimento
- Barra lateral somente ícones de 56px com tooltips + barra lateral contextual de 240px para navegação de projetos
- Arquitetura baseada em stacks: agrupar serviços por projeto (frontend + backend + db + cache)
- Deploy Hub: wizard unificado com 183 opções de deploy, abas por categoria, seção em destaque
- 7 componentes de formulário de deploy: FormGit, FormUpload, FormDockerImage, FormDockerfile, FormCompose, FormService, FormFramework
- Paleta de comandos Cmd+K: busque páginas, stacks e serviços instantaneamente
- Barra lateral contextual responsiva para mobile com drawer + botão hamburger
- Redesign da página inicial com estatísticas do servidor, grade de stacks, ações rápidas
- Visualização de detalhe de app com 16 abas: Visão Geral, Deploys, Logs, Terminal, Arquivos, Armazenamento, Domínios & SSL, Ambiente, Redirecionamentos, Previews, Hooks, Scaling, Uptime, Cron, Serviços, Configurações
Imagem Docker, Dockerfile, ZIP & PHP/Ruby/.NET
- Deploy direto de Imagem Docker: baixar imagem, pular pipeline git/build
- Deploy somente Dockerfile: colar conteúdo, construir localmente
- Deploy por upload de arquivo ZIP com limite de 500MB e prevenção de path traversal
- Templates Dockerfile para PHP, Ruby e .NET adicionados
- Nomes de apps com escopo por projeto (índice único composto)
- Nomenclatura de container com prefixo de projeto: sh0-undefined-undefined
- 45 novos testes (scaling, compose, YAML)
Templates, Terminal, Navegador de Arquivos, Volumes
- Página Deploy Hub com catálogo de 183 opções de deploy
- Barra de progresso de deploy com rastreamento de etapas nos logs
- 170 templates: bancos de dados (33), CMS (18), analytics (7), auth (6), IA/ML (8), DevTools (12) e mais
- Gerenciamento de sub-serviços (containers MySQL, phpMyAdmin, dbGate)
- URLs de acesso a serviços: endpoints interno/local/externo com toggle externo
- Terminal web: xterm.js com seletor de shell (sh/bash/ash), suporte SSH TTY
- Navegador de arquivos: explorador de dois painéis estilo Docker Desktop com editor inline
- Armazenamento persistente: gerenciamento de volumes Docker, bind mounts, file mounts
- Página de documentação da API com playground interativo (26 grupos de endpoints)
URLs de Conexão, Credenciais, Vars de Ambiente em Lote
- URLs de conexão de banco de dados: interna e externa, calculadas automaticamente a partir da configuração do container
- Card de credenciais do banco: usuário, senha, strings de conexão
- Operações em lote de vars de ambiente com modo editor .env
- Persistência de credenciais de template (vars de ambiente armazenadas no DB)
Certificados SSL, Confiabilidade Caddy, Provedores de Armazenamento
- Migração de cookie HTTP-only com padrão CSRF double-submit (SameSite=Strict)
- Geração automática de chave mestra (derivada do secret JWT na primeira execução)
- Certificados SSL personalizados: geração CSR (rcgen), upload PEM (x509-parser), ssl_mode por domínio
- Criptografia de chave privada (AES-256-GCM) com permissões de arquivo restritas (0o600)
- Confiabilidade do proxy Caddy: matar processos obsoletos, retentar cargas de config, sincronizar rotas do DB
- 13 provedores de armazenamento via OpenDAL: S3, R2, Wasabi, Backblaze B2, SFTP, FTP/FTPS, Dropbox, Google Drive e mais
- Correção de IPv6 FTP/FTPS (modo EPSV, cliente suppaftp direto)
- Alinhamento de planos/preços: Free ($0), Pro ($19/mês), Business ($97/mês)
CronBuilder, Redirecionamentos, Restauração de Backup, Refatoração do Monitoramento
- Componente CronBuilder com 18 presets e sincronização bidirecional
- Regras de redirecionamento de URL: correspondência exata, prefixo, regex com códigos de status 301/302/307/308
- Restauração de backup: Fluxo A (backups sh0) e Fluxo B (upload de fonte externa)
- Refatoração da página de monitoramento: dashboard com 4 abas (Visão Geral, Apps, Uptime, Alertas)
- Redução de falsos positivos na verificação de saúde (mais de 80 novos testes, pular arquivos env/lock/doc)
- Modal de configuração DNS com IP real do servidor e orientação para Cloudflare
- Configuração de e-mail ACME (armazenado no DB, atualizações em runtime)
Multi-Servidor BYOS
- Registro de nó remoto com gerenciamento de túnel SSH (russh)
- SSH TOFU (Trust on First Use) com verificação de fingerprint de chave do host
- Transferência de imagem Docker via save/load por túneis SSH
- Pipeline de deploy com reconhecimento de nó, despachando builds para servidores remotos
- Dashboard de gerenciamento de nós com indicadores de status e monitoramento de saúde
- Hardening de nós: tratamento de erros, validação de conexão, limpeza graceful
Servidor MCP & Assistente IA
- Servidor MCP com 103 ferramentas: transporte Streamable HTTP em /mcp (JSON-RPC 2.0)
- Geração de ferramentas baseada em OpenAPI via utoipa com extensões x-mcp-*
- Segurança em 3 camadas: escopos de chave API (read/standard/admin), classificação de risco por ferramenta, tokens de confirmação para operações destrutivas
- Gateway de IA: roteamento de chat em 3 vias (conector MCP, legacy, especialista em docs)
- AI Sandbox: container sidecar Alpine 3.19 por app com shell root, instalação de pacotes, volumes graváveis
- Integração Claude MCP Connector para execução agêntica de ferramentas no servidor
- Chat IA no dashboard com seletor de modelo, histórico de conversas, timeline de etapas de processamento
- Modal de capacidades: 24 capacidades em 5 categorias, traduzidas em 5 idiomas
- Cobrança por carteira pré-paga com precificação por token (Haiku, Sonnet, Opus)
- Suporte BYOK no plano Business (chaves API Anthropic ou OpenRouter)
- 10 rodadas de auditoria em 5 fases — 0 problemas críticos chegaram à produção
Plano Free, Docker e Distribuição
- Backups liberados para o plano Free (armazenamento local); armazenamento em nuvem restrito ao Pro+
- Imagem Docker publicada no Docker Hub (zerosuiteinc/sh0) e GHCR
- Sistema de autoatualização: sh0 update verifica o GitHub Releases e atualiza automaticamente
- Configuração automática de serviço systemd no Linux (sh0 serve instala e ativa a unit)
- Bloqueios de página inteira para upgrade substituídos por banners inline em monitoramento, backups e equipe
- Matriz de recursos de licença refinada: backups granulares (local/nuvem) e monitoramento (métricas/alertas/uptime)
- Comando de desinstalação: sh0 uninstall remove o binário, a unit systemd e os dados de forma limpa
- Banner de inicialização com versão, URL do dashboard e dica de systemd
Tudo na v1.0.0
Motor de Deploy
- 5 pipelines de deploy: Git, Imagem Docker, Dockerfile, upload ZIP, Template/Compose
- Autodetecção de 19 stacks com 15 templates Dockerfile otimizados
- Deploys blue-green com troca sem downtime e rollback
- 183 opções de deploy no Deploy Hub
- Parser Docker Compose v3 com deploy multi-serviço
Loja de Templates
- 170 templates com um clique em 15 categorias
- Bancos de dados, CMS, IA/ML, DevTools, analytics, auth, e-mail, filas, busca
- Substituição de variáveis com geração automática (secrets, senhas)
- Deploy multi-serviço com ordenação topológica
Domínios & SSL
- Auto-SSL via Let's Encrypt com Caddy ACME
- Upload de certificado SSL personalizado com geração de CSR
- Regras de redirecionamento de URL (prefixo, exato, regex)
- Balanceamento de carga: round_robin, least_conn, random
Monitoramento & Alertas
- Métricas de CPU, memória e rede em tempo real com gráficos sparkline
- 5 canais de alerta: E-mail, Slack, Discord, Telegram, Webhook
- Monitoramento de uptime com páginas de status públicas
- Autoscaling por limites de CPU/memória (1-50 réplicas)
Backup & Armazenamento
- Dumps de banco (pg_dump, mysqldump, mongodump) + backups de volume
- Criptografia AES-256-GCM com backups agendados via cron
- 13 provedores de armazenamento via OpenDAL (S3, R2, SFTP, Dropbox, Google Drive)
- Restauração a partir de backup ou armazenamento externo
Segurança
- 51 problemas de segurança encontrados e corrigidos em 2 auditorias
- Senhas Argon2id, JWT + rotação de refresh, 2FA TOTP, Google OAuth
- Criptografia AES-256-GCM para todos os secrets (vars de ambiente, tokens, chaves)
- Prevenção CSRF, SSRF, rate limiting, hardening de containers
Experiência do Desenvolvedor
- Terminal no navegador (xterm.js) com seleção de shell
- Navegador de arquivos com editor inline, mkdir, delete
- Verificação de Saúde do Código: mais de 34 regras verificadas antes de cada build
- Exportação para 7 plataformas: K8s, AWS, GCP, Vercel, Railway, Render, Compose
Dashboard
- 22 páginas, mais de 70 componentes, visualização de detalhe de app com 16 abas
- Paleta de comandos Cmd+K, tema claro/escuro, 5 idiomas
- Arquitetura baseada em stacks com barra lateral dupla
- Documentação da API com playground interativo (26 grupos de endpoints)
Automação
- Cron jobs com CronBuilder (18 presets, 50 jobs/app)
- Hooks de deploy: pre_build, post_build, pre_deploy, post_deploy
- Ambientes de preview a partir de webhooks de PR com limpeza TTL
- Infraestrutura como Código via sh0.yaml
Equipe & RBAC
- 4 níveis de papéis: Owner, Admin, Developer, Viewer
- Controle de acesso por escopo de projeto
- Log de auditoria em todas as operações
- Sistema de licenças: Free, Pro ($19/mês), Business ($97/mês)
Assistente IA
- Servidor MCP com 103 ferramentas (37 leitura, 44 escrita, 16 destrutivas, 5 sandbox, 1 confirmação)
- AI Sandbox: container Alpine por app para depuração e desenvolvimento
- Conecte do Claude Desktop, Cursor ou qualquer cliente MCP
- Gateway de IA com chat web, seleção de modelo, histórico de conversas
- Carteira pré-paga com opção BYOK no plano Business
Em números
Crates Rust
Migrações
Endpoints API
Páginas do dashboard
Componentes UI
Idiomas
Templates de deploy
Ferramentas MCP
Regras de saúde
Formatos de exportação
Provedores de armazenamento
Canais de alerta
Testes passando
Protótipo Legacy (Python/FastAPI)
O sh0 original, construído em Python. Arquitetura baseada em agentes com detecção de stack, verificações de saúde e geração de Dockerfile. Serviu como blueprint para a reescrita em Rust.
Por que Rust? Reescrito em Rust por: ~30MB de memória ociosa (vs ~500MB Python), distribuição em binário único, API Docker socket direto (sem shell CLI), zero pausas de GC sob carga.
Pronto para fazer deploy?
Instale sh0 em menos de 60 segundos e faça deploy do seu primeiro app.