Migrar do Heroku para a Zenifra
Este guia mostra onde encontrar cada configuração de um app no Heroku e onde informar o mesmo valor no console da Zenifra. Ele cobre o Procfile, as Config Vars, os buildpacks, a release phase, o Heroku Scheduler, o Heroku Postgres e o Heroku Key-Value Store. Para o roteiro geral, com cópia de dados e troca de DNS, veja Migrar para a Zenifra.
Mantenha o app do Heroku no ar enquanto você sobe e valida a aplicação na Zenifra. Só desligue os dynos depois de trocar o DNS.
Como os conceitos se traduzem
| No Heroku | Na Zenifra |
|---|---|
| App | Projeto HTTP |
Processo web do Procfile | Comando Start do projeto |
Processo worker (ou outro nome) | Outro projeto com o mesmo repositório, Exposição Privado e o comando do worker |
Release phase (release:) | Início do Comando Start ou um passo manual; veja Release phase |
| Buildpack | Runtime e Versão (Node.js, Python, Bun, Go ou Java) ou Imagem OCI |
| Config Vars | Variáveis de Ambiente |
Quantidade de dynos web | Instâncias Desejadas ou auto-scaling |
| Heroku Scheduler | Jobs agendados |
| Heroku Postgres | PostgreSQL gerenciado |
| Heroku Key-Value Store | Cache gerenciado ou Chave-Valor |
| Review Apps | Ambientes de Preview |
heroku maintenance:on | Use no Heroku durante a cópia final dos dados |
1. Copie as configurações no Heroku
Os passos abaixo usam a CLI do Heroku. Troque meu-app pelo nome do app.
Config Vars
No painel do Heroku, as Config Vars ficam na aba Settings do app. Para exportar todas de uma vez:
heroku config --shell -a meu-app > heroku.envUse --json no lugar de --shell se preferir JSON. O arquivo tem segredos: não versione e apague depois da migração.
Ao revisar o arquivo:
DATABASE_URLeREDIS_URLforam criadas pelos add-ons e apontam para os bancos do Heroku. Na Zenifra, troque pelas URLs dos bancos novos.- Variáveis com prefixo
HEROKU_são da plataforma. Só copie se o seu código usa alguma delas, com um valor equivalente. - Variáveis de outros add-ons, como serviços de e-mail ou monitoramento, continuam valendo se você manter a conta no provedor do add-on.
Procfile
Abra o Procfile na raiz do repositório. Cada linha é tipo: comando:
release: bundle exec rails db:migrate
web: bundle exec puma -C config/puma.rb
worker: bundle exec sidekiqAnote o comando de cada tipo. Sem Procfile, o Heroku usa o padrão do buildpack, como o script start do package.json no Node.js.
Veja também quantos dynos de cada tipo estão ligados:
heroku ps -a meu-appBuildpacks e versão da linguagem
heroku buildpacks -a meu-appO buildpack da linguagem principal define o Runtime na Zenifra. A versão vem do próprio repositório:
| Linguagem | Onde o Heroku lê a versão |
|---|---|
| Node.js | engines.node no package.json |
| Python | .python-version (ou runtime.txt, que o Heroku considera obsoleto) |
| Go | Linha go do go.mod |
| Java | java.runtime.version no system.properties |
| Ruby | Entrada ruby no Gemfile |
Domínios, deploy e Scheduler
- Domínios:
heroku domains -a meu-applista os domínios e o destino DNS de cada um. - Deploy: na aba Deploy do app, veja se a integração com o GitHub está com Automatic deploys ligado e qual branch é publicada.
- Scheduler:
heroku addons:open scheduler -a meu-appabre a lista de tarefas agendadas. Anote o comando e a frequência de cada uma. - app.json: se o repositório tem um
app.json, ele lista variáveis, add-ons e scripts usados pelos Review Apps.
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 branch publicada no Heroku.
| No Heroku | No console da Zenifra |
|---|---|
| Buildpack da linguagem | Runtime |
| Versão no repositório | Versão, a mesma principal |
| Pasta do app no repositório | Diretório raiz. Use . para a raiz |
| Build automático do buildpack | Comando Build; veja a tabela abaixo |
Linha web: do Procfile | Comando Start |
$PORT | Porta e a variável PORT com o mesmo valor; veja Porta |
| Automatic deploys ligado | Modo de deploy Automático por branch |
| Automatic deploys desligado | Modo de deploy Manual |
| Config Vars | Variáveis de Ambiente |
Quantidade de dynos web | Instâncias Desejadas |
Comandos por linguagem
O Heroku roda alguns passos de build sozinho. Na Zenifra, cada passo fica explícito nos campos do projeto:
| Linguagem | Comando Build | Comando Start |
|---|---|---|
| Node.js | npm run build se o package.json tem script build; vazio se não tem | Linha web: do Procfile ou npm start |
| Python (Django) | python manage.py collectstatic --noinput | gunicorn projeto.wsgi --bind 0.0.0.0:8000 |
| Python (Flask, FastAPI) | vazio | Linha web: com --bind 0.0.0.0:8000 ou --host 0.0.0.0 --port 8000 |
| Go | go build -o app ./cmd/server (pasta do pacote main) | ./app |
| Java (Maven) | ./mvnw -B -DskipTests package ou mvn -B -DskipTests package | java -jar target/*.jar |
Detalhes de cada runtime estão em Runtimes, Python, Django e APIs Node.js.
Node.js: scripts do Heroku
- Scripts
heroku-prebuild,heroku-buildeheroku-postbuildnão rodam na Zenifra. Coloque o que eles faziam no Comando Pré-build ou no Comando Build. - A Zenifra instala com
npm cie precisa de umpackage-lock.jsonversionado. Se o app usa Yarn ou pnpm, gere e versione umpackage-lock.jsonantes de migrar. Veja Dependências Node.js. NPM_CONFIG_PRODUCTIONnão é necessária: asdevDependenciesficam disponíveis na build.
Python: Poetry, uv e Pipenv
A Zenifra instala dependências Python a partir do requirements.txt. Se o Heroku usava poetry.lock, uv.lock ou Pipfile.lock, exporte e versione um requirements.txt:
poetry export -f requirements.txt --output requirements.txt
uv export --format requirements-txt > requirements.txtRuby, PHP e outras linguagens
Ruby, PHP, .NET e outras linguagens fora dos runtimes acima são publicadas como Imagem Docker: construa a imagem a partir de um Dockerfile, envie para um registry e informe a imagem no projeto. Veja Dockerfiles prontos e Deploy via imagem OCI. A GitHub Action automatiza a build e o deploy a cada push.
3. Ajuste o que muda entre as plataformas
Porta
No Heroku, o processo web escuta na porta da variável PORT, escolhida pela plataforma. 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.
Release phase
No Heroku, a linha release: roda uma vez por release, antes de os dynos subirem. Na Zenifra não há uma etapa equivalente. Escolha uma destas opções:
- Junto do start:
npx prisma migrate deploy && npm startoupython manage.py migrate && gunicorn .... O comando roda a cada vez que uma instância inicia, então precisa ser idempotente, como as migrations da maioria dos frameworks. Com várias instâncias, todas executam o comando: prefira ferramentas que travam o banco durante a migration. - Manual: rode a migration a partir da sua máquina, apontando para o banco da Zenifra, antes de publicar a versão que depende dela. É o mais seguro para migrations longas.
Workers
Cada tipo de processo do Procfile além do web vira um projeto na Zenifra:
- Crie outro projeto HTTP com o mesmo repositório e a mesma branch.
- Em Exposição, escolha Privado - sem rota pública.
- Use o comando do worker no Comando Start, como
bundle exec sidekiqoucelery -A app worker. - Cadastre as mesmas variáveis do projeto web.
O processo clock, que agenda tarefas dentro de um dyno, pode virar um projeto privado do mesmo jeito ou ser trocado por Jobs agendados.
Heroku Scheduler
Cada tarefa do Scheduler vira um Job agendado. Crie o Job com Origem da tarefa Repositório GitHub, o mesmo Runtime, o comando da tarefa em Comando da tarefa e as variáveis de que ela precisa.
| Frequência no Scheduler | Expressão cron na Zenifra |
|---|---|
| A cada 10 minutos | */10 * * * * |
| A cada hora, no minuto 30 | 30 * * * * |
| Todo dia às 06:00 UTC | 0 6 * * * |
As duas plataformas usam UTC. Na Zenifra, a expressão cron aceita qualquer horário, como 0 9 * * 1-5 para dias úteis às 09:00 UTC.
Arquivos enviados por usuários
No Heroku, arquivos gravados no disco do dyno somem quando ele reinicia. Na Zenifra, você pode guardar arquivos no armazenamento persistente ou no Armazém, compatível com S3. Se o app já usa um bucket S3, ele continua funcionando com as mesmas variáveis.
HTTPS e proxy
Como no Heroku, a Zenifra encerra o HTTPS antes de encaminhar a requisição. Mantenha as configurações de proxy confiável do framework, como app.set('trust proxy', 1) no Express, config.force_ssl no Rails ou --proxy-headers no uvicorn.
4. Migre os bancos
Heroku Postgres
Crie o PostgreSQL gerenciado na Zenifra antes da aplicação. Para copiar os dados, você pode usar um backup do Heroku:
heroku pg:backups:capture -a meu-app
heroku pg:backups:download -a meu-app # gera latest.dump
pg_restore --list latest.dump > /dev/null && echo "dump ok"E restaurar na Zenifra com a URI do console:
pg_restore --no-owner --no-acl --jobs=4 \
--dbname="postgresql://usuario:senha@host:porta/banco?sslmode=verify-full&sslrootcert=system" \
latest.dumpO próprio Heroku recomenda os backups para bancos de até 20 GB. Para bancos maiores, ou para fazer a cópia direto, pegue a URL do banco do Heroku e use pg_dump:
heroku pg:credentials:url DATABASE -a meu-app
pg_dump --format=custom --no-owner --no-acl "URL_DO_HEROKU?sslmode=require" > dump.pgdumpUse um pg_dump da mesma versão principal do banco ou mais nova. Veja Migrar o banco de dados para validar a cópia.
Heroku Key-Value Store
Crie um cache gerenciado ou um banco Chave-Valor na Zenifra e troque a REDIS_URL. Dados de cache e de sessões costumam ser recriados pela aplicação. Se o Key-Value Store guarda filas, como as do Sidekiq ou do Celery, deixe os workers do Heroku esvaziarem a fila antes da troca.
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.
- No horário da troca, ligue o modo de manutenção do Heroku para congelar as escritas:
heroku maintenance:on -a meu-app. - Faça a cópia final do banco, adicione o domínio na Zenifra e atualize o DNS. Siga o checklist do dia da troca.
- Mantenha o app do Heroku por alguns dias para rollback. Depois, desligue os dynos e remova os add-ons para parar a cobrança.
Problemas comuns
| Sintoma | Causa provável | Correção |
|---|---|---|
npm ci falha | App usa Yarn ou pnpm, sem package-lock.json | Gere e versione um package-lock.json |
| Build Python não instala dependências | Projeto usa Poetry, uv ou Pipenv | Exporte um requirements.txt |
| URL pública não responde | App escuta em localhost ou em outra porta | Escute em 0.0.0.0, na porta do campo Porta, e defina PORT |
| Tabelas não existem | A release phase não roda na Zenifra | Rode as migrations; veja Release phase |
| Tarefas em segundo plano paradas | Worker não foi criado | Crie um projeto privado para cada processo além do web |
assets ou staticfiles faltando | O buildpack fazia esse passo sozinho | Coloque o comando, como collectstatic ou assets:precompile, no Comando Build |
Precisa de ajuda?
Escreva para [email protected] com o seu Procfile e a lista de add-ons ou fale pelo WhatsApp +55 (11) 5199-3013.
Última atualização em
Migrar da Vercel para a Zenifra
Passo a passo para trazer um projeto da Vercel para a Zenifra: onde copiar Build Command, Output Directory, Root Directory e variáveis na Vercel, como traduzir o vercel.json, Functions e Cron Jobs e onde informar cada valor no console.
Migrar da Netlify para a Zenifra
Passo a passo para trazer um site da Netlify para a Zenifra: onde copiar Build command, Publish directory e variáveis, como traduzir netlify.toml, _redirects e _headers, Functions, Forms e DNS, e onde informar cada valor no console.