Migrar para a Zenifra

Migrar da Railway para a Zenifra

Este guia mostra onde encontrar cada configuração de um serviço na Railway e onde informar o mesmo valor no console da Zenifra. Ele cobre serviços com repositório Git ou Dockerfile, variáveis e variáveis de referência, pre-deploy, cron, volumes e os bancos da Railway. Para o roteiro geral, com cópia de dados e troca de DNS, veja Migrar para a Zenifra.

Mantenha o projeto da Railway no ar enquanto você sobe e valida a aplicação na Zenifra. Só remova os serviços depois de trocar o DNS.

Como os conceitos se traduzem

Na RailwayNa Zenifra
ProjectOrganização com vários projetos
Service com repositório ou imagemProjeto HTTP
Service sem Public Networking (worker)Projeto com Exposição Privado
Service com Cron ScheduleJob agendado
Railpack ou NixpacksRuntime e Versão (Node.js, Python, Bun, Go ou Java)
Builder DockerfileImagem OCI
Variables e Shared VariablesVariáveis de Ambiente de cada projeto
ReplicasInstâncias Desejadas ou auto-scaling
VolumeArmazenamento persistente
Postgres, MySQL, RedisPostgreSQL, MariaDB e Cache
PR EnvironmentsAmbientes de Preview

1. Copie as configurações na Railway

No painel da Railway, abra o projeto, clique no serviço e abra a aba Settings.

Source e build

Campo na RailwayPara que serve
SourceRepositório e branch do serviço, ou a imagem publicada
Root DirectoryPasta da aplicação dentro do repositório (monorepo). O padrão é /
BuilderRailpack (detecção automática) ou Dockerfile
Custom Build CommandComando de build, se definido
Watch PathsPastas que disparam uma nova build. Não tem equivalente: toda mudança na branch publica

Deploy

Campo na RailwayPara que serve
Custom Start CommandComando que inicia a aplicação
Pre-deploy commandRoda antes de cada deploy, normalmente migrations
Healthcheck pathCaminho verificado antes de liberar o deploy, como /health
Cron ScheduleExpressão cron, quando o serviço é uma tarefa agendada
ReplicasQuantidade de instâncias

Se o Custom Build Command ou o Custom Start Command estão vazios, o Railpack escolheu os comandos sozinho. Nesse caso, veja nos logs da última build e do último deploy os comandos usados, ou use os scripts build e start do package.json.

Networking

Em Settings › Networking, veja se o serviço tem Public Networking, o domínio gerado pela Railway e os Custom Domains. Serviços sem rede pública são workers ou serviços internos.

Variáveis

Abra a aba Variables do serviço e clique em Raw Editor para ver todas as variáveis em formato .env ou JSON e copiar de uma vez. Pela CLI da Railway, na pasta do projeto vinculado:

railway variable list --service meu-servico --kv > railway.env

O arquivo tem segredos: não versione e apague depois da migração. Ao revisar:

  • Variáveis de referência, como ${{ Postgres.DATABASE_URL }} ou ${{ shared.API_KEY }}, aparecem resolvidas na CLI. Na Zenifra, cada projeto tem as próprias variáveis, então troque as URLs de banco pelas dos bancos novos e cadastre as compartilhadas em cada projeto que as usa.
  • Variáveis da Railway, como RAILWAY_PUBLIC_DOMAIN, RAILWAY_PRIVATE_DOMAIN e RAILWAY_ENVIRONMENT_NAME, não existem na Zenifra. Se o código usa alguma, crie uma variável sua com o valor equivalente.
  • PORT: a Railway define a porta. Veja Porta.

railway.json ou railway.toml

Se o repositório tem um railway.json ou railway.toml, os valores do arquivo valem mais que os do painel. Anote build.buildCommand, build.dockerfilePath, deploy.startCommand, deploy.preDeployCommand, deploy.healthcheckPath e deploy.cronSchedule.

2. Crie o projeto na Zenifra

No console, clique em + Criar projeto, escolha Aplicação HTTP e o plano. Em Configurações Avançadas, escolha Repositório Git em Origem do Projeto, o Provedor Git GitHub (ou Forgejo), o mesmo repositório e a mesma branch. Depois preencha:

Na RailwayNo console da Zenifra
Linguagem detectada pelo RailpackRuntime e Versão
Root DirectoryDiretório raiz. / na Railway equivale a .
Custom Build CommandComando Build, sem a instalação de dependências
Pre-deploy commandInício do Comando Start; veja Pre-deploy
Custom Start CommandComando Start
Healthcheck pathCaminho da verificação, em Editar › Healthcheck da aplicação (a partir do plano Premium)
ReplicasInstâncias Desejadas
VariablesVariáveis de Ambiente
Public Networking desligadoExposição Privado - sem rota pública

A Zenifra não detecta a linguagem: você escolhe o Runtime e a Versão na criação. Use a mesma versão principal que o Railpack usava, que ele lê de engines.node, .nvmrc ou .node-version no Node.js e de .python-version ou runtime.txt no Python.

Diferenças na instalação de dependências

O Railpack detecta o gerenciador de pacotes sozinho. Na Zenifra:

  • Node.js instala com npm ci e precisa de um package-lock.json versionado. Se o serviço usa pnpm ou Yarn, gere e versione um package-lock.json antes de migrar.
  • Bun instala com bun install --frozen-lockfile.
  • Python instala a partir do requirements.txt. Se o serviço usa Poetry, uv, pdm ou Pipenv, exporte um requirements.txt, por exemplo com uv export --format requirements-txt > requirements.txt.

Veja Runtimes para os detalhes de cada linguagem.

Serviços com Dockerfile ou imagem

Serviços com o builder Dockerfile, ou que publicam uma imagem pronta, entram como Imagem Docker: construa a imagem, envie para um registry e informe a imagem no projeto. Veja Deploy via imagem OCI e Registry privado. A GitHub Action automatiza a build e o deploy a cada push.

3. Ajuste o que muda entre as plataformas

Porta

A Railway define a variável PORT e espera que a aplicação escute nela. Na Zenifra, a porta é o campo Porta do projeto. Como o código já lê PORT, defina os dois com o mesmo valor, por exemplo Porta 3000 e a variável PORT=3000. A aplicação precisa escutar em 0.0.0.0.

Pre-deploy

Na Railway, o pre-deploy roda uma vez, em um container separado, antes de liberar o deploy. Na Zenifra, coloque o comando no início do Comando Start, como npm run migrate && npm start. Ele passa a rodar sempre que uma instância inicia, então precisa ser idempotente. Para migrations longas ou com várias instâncias, rode a migration manualmente antes de publicar.

Rede privada entre serviços

Na Railway, serviços se falam por nome-do-servico.railway.internal. Na Zenifra, troque esses endereços pela URL do projeto de destino, *.clients.zenifra.com ou o domínio dele, e proteja as rotas internas com autenticação. Bancos e serviços gerenciados da Zenifra já têm as próprias URLs de conexão, mostradas no console.

Cron

Um serviço com Cron Schedule vira um Job agendado. Crie o Job com Origem da tarefa Repositório GitHub, o mesmo Runtime, o start command do serviço em Comando da tarefa e a mesma Expressão cron: as duas plataformas usam UTC. Como na Railway, o comando precisa terminar sozinho quando a tarefa acaba.

Workers

Serviços sem rede pública, como filas e bots, viram projetos com Exposição Privado - sem rota pública e o mesmo Comando Start.

4. Migre bancos e volumes

Postgres e MySQL

Os bancos da Railway são privados por padrão. Para copiar os dados a partir da sua máquina, ative o acesso público do banco em Settings › Networking. A Railway cria então a variável DATABASE_PUBLIC_URL (Postgres) ou MYSQL_PUBLIC_URL (MySQL). Esse tráfego é cobrado pela Railway como saída de rede.

Crie o banco na Zenifra antes e copie os dados:

# PostgreSQL
pg_dump --format=custom --no-owner --no-acl "$DATABASE_PUBLIC_URL" > dump.pgdump
pg_restore --no-owner --no-acl --jobs=4 \
  --dbname="postgresql://usuario:senha@host:porta/banco?sslmode=verify-full&sslrootcert=system" \
  dump.pgdump

# MySQL para MariaDB
mysqldump --single-transaction --routines --triggers -h HOST -P PORTA -u USUARIO -p BANCO > dump.sql
mariadb --ssl -h HOST_ZENIFRA -P PORTA -u USUARIO -p BANCO < dump.sql

Os dados de host, porta e usuário do MySQL estão na MYSQL_PUBLIC_URL. Depois da cópia, desative o acesso público do banco na Railway. Veja Migrar o banco de dados para validar a cópia.

Redis

Crie um cache gerenciado ou um banco Chave-Valor e troque a REDIS_URL. Dados de cache e de sessões costumam ser recriados pela aplicação. Se o Redis guarda filas, deixe os workers da Railway esvaziarem a fila antes da troca.

MongoDB

A Zenifra não oferece MongoDB gerenciado. Mantenha o banco em um provedor de MongoDB e aponte a variável MONGO_URL do projeto para ele.

Volumes

Na Railway, cada serviço pode ter um volume montado em um caminho. Na Zenifra, ative o armazenamento persistente na criação do projeto e use o mesmo caminho em Diretório para Persistir. Esse caminho não pode ser alterado depois.

Para copiar os arquivos, baixe-os do volume com a CLI da Railway e envie para o novo projeto, por exemplo por uma rota de importação temporária protegida por senha. Arquivos que servem como mídia ou uploads podem ir para o Armazém, compatível com S3.

5. Valide e troque o DNS

  1. Abra a URL *.clients.zenifra.com do projeto e teste login, fluxos principais, e-mails, workers e webhooks.
  2. Confira em Logs de build e nos logs da aplicação se não há erros.
  3. Siga o checklist do dia da troca: reduza o TTL do DNS, faça a cópia final dos dados, adicione o domínio na Zenifra e atualize o DNS.
  4. Remova o Custom Domain do serviço na Railway depois que o DNS apontar para a Zenifra.
  5. Mantenha os serviços da Railway por alguns dias para rollback e só então remova o projeto.

Problemas comuns

SintomaCausa provávelCorreção
npm ci falhaServiço usa pnpm ou Yarn, sem package-lock.jsonGere e versione um package-lock.json
Build Python não instala dependênciasServiço usa Poetry, uv, pdm ou PipenvExporte um requirements.txt
Aplicação não iniciaComando Start vazioInforme o comando que o Railpack usava
Variável com ${{ ... }} literalVariável de referência copiada sem resolverTroque pelo valor real, como a URL do banco novo
Erro ao conectar em *.railway.internalA rede privada da Railway não existe na ZenifraUse a URL do projeto ou do banco na Zenifra
Arquivos sumiram após publicarVolume não foi recriadoAtive o armazenamento persistente com o mesmo caminho

Precisa de ajuda?

Escreva para [email protected] com a lista de serviços do projeto na Railway ou fale pelo WhatsApp +55 (11) 5199-3013.

Última atualização em

Nessa página