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 Railway | Na Zenifra |
|---|---|
| Project | Organização com vários projetos |
| Service com repositório ou imagem | Projeto HTTP |
| Service sem Public Networking (worker) | Projeto com Exposição Privado |
| Service com Cron Schedule | Job agendado |
| Railpack ou Nixpacks | Runtime e Versão (Node.js, Python, Bun, Go ou Java) |
| Builder Dockerfile | Imagem OCI |
| Variables e Shared Variables | Variáveis de Ambiente de cada projeto |
| Replicas | Instâncias Desejadas ou auto-scaling |
| Volume | Armazenamento persistente |
| Postgres, MySQL, Redis | PostgreSQL, MariaDB e Cache |
| PR Environments | Ambientes 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 Railway | Para que serve |
|---|---|
| Source | Repositório e branch do serviço, ou a imagem publicada |
| Root Directory | Pasta da aplicação dentro do repositório (monorepo). O padrão é / |
| Builder | Railpack (detecção automática) ou Dockerfile |
| Custom Build Command | Comando de build, se definido |
| Watch Paths | Pastas que disparam uma nova build. Não tem equivalente: toda mudança na branch publica |
Deploy
| Campo na Railway | Para que serve |
|---|---|
| Custom Start Command | Comando que inicia a aplicação |
| Pre-deploy command | Roda antes de cada deploy, normalmente migrations |
| Healthcheck path | Caminho verificado antes de liberar o deploy, como /health |
| Cron Schedule | Expressão cron, quando o serviço é uma tarefa agendada |
| Replicas | Quantidade 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.envO 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_DOMAINeRAILWAY_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 Railway | No console da Zenifra |
|---|---|
| Linguagem detectada pelo Railpack | Runtime e Versão |
| Root Directory | Diretório raiz. / na Railway equivale a . |
| Custom Build Command | Comando Build, sem a instalação de dependências |
| Pre-deploy command | Início do Comando Start; veja Pre-deploy |
| Custom Start Command | Comando Start |
| Healthcheck path | Caminho da verificação, em Editar › Healthcheck da aplicação (a partir do plano Premium) |
| Replicas | Instâncias Desejadas |
| Variables | Variáveis de Ambiente |
| Public Networking desligado | Exposiçã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 cie precisa de umpackage-lock.jsonversionado. Se o serviço usa pnpm ou Yarn, gere e versione umpackage-lock.jsonantes 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 umrequirements.txt, por exemplo comuv 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.sqlOs 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
- Abra a URL
*.clients.zenifra.comdo projeto e teste login, fluxos principais, e-mails, workers e webhooks. - Confira em Logs de build e nos logs da aplicação se não há erros.
- 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.
- Remova o Custom Domain do serviço na Railway depois que o DNS apontar para a Zenifra.
- Mantenha os serviços da Railway por alguns dias para rollback e só então remova o projeto.
Problemas comuns
| Sintoma | Causa provável | Correção |
|---|---|---|
npm ci falha | Serviço usa pnpm ou Yarn, sem package-lock.json | Gere e versione um package-lock.json |
| Build Python não instala dependências | Serviço usa Poetry, uv, pdm ou Pipenv | Exporte um requirements.txt |
| Aplicação não inicia | Comando Start vazio | Informe o comando que o Railpack usava |
Variável com ${{ ... }} literal | Variável de referência copiada sem resolver | Troque pelo valor real, como a URL do banco novo |
Erro ao conectar em *.railway.internal | A rede privada da Railway não existe na Zenifra | Use a URL do projeto ou do banco na Zenifra |
| Arquivos sumiram após publicar | Volume não foi recriado | Ative 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
Migrar do Render para a Zenifra
Passo a passo para trazer um Web Service do Render para a Zenifra: onde copiar Build Command, Start Command, Root Directory e variáveis no Render e onde colar cada valor no console da Zenifra.
Migrar do Fly.io para a Zenifra
Passo a passo para trazer um app do Fly.io para a Zenifra: como traduzir o fly.toml (internal_port, processes, release_command, mounts, checks), recuperar secrets, copiar Postgres, volumes e Tigris, e onde informar cada valor no console.