Como fazer Deploy em Servidor do zero (Next.js + Github + PM2 + Nginx + SSL + DigitalOcean)
Passo a passo completo para colocar uma aplicação Next.js no ar em uma VPS do zero, com banco de dados PostgreSQL, PM2 para manter o processo rodando, Nginx como proxy reverso e certificado SSL gratuito com o Certbot.
Esse é um passo a passo completo de como pegar uma aplicação Next.js e colocar no ar em uma VPS, do zero absoluto até o site funcionando com domínio, banco de dados e HTTPS.
A ideia aqui é configurar tudo, literalmente tudo. Vamos criar um servidor novo, instalar o banco de dados, clonar o projeto, configurar o processo para rodar em segundo plano, apontar o domínio e emitir o certificado SSL. No final, qualquer alteração no código vai poder ser publicada com um único comando.
Para esse tutorial eu criei uma VPS do zero na DigitalOcean, sem nunca ter logado nela antes, apenas associei um subdomínio a ela. A partir daqui, vamos fazer tudo juntos, desde o primeiro contato com o servidor.
Conectando no servidor via SSH
O primeiro passo é acessar o servidor a partir do seu computador. O comando é o mesmo em qualquer sistema operacional, muda só onde você abre o terminal.
Ubuntu ou outra distribuição Linux
Abra o terminal padrão do sistema e rode:
ssh root@SEU_IP_AQUIMac
Abra o aplicativo Terminal (ou o iTerm, se você usar) e rode o mesmo comando, já que o macOS também é baseado em Unix:
ssh root@SEU_IP_AQUIWindows
Desde o Windows 10, o cliente SSH já vem instalado por padrão. Basta abrir o Prompt de Comando (cmd) ou o PowerShell e rodar o mesmo comando:
ssh root@SEU_IP_AQUISe por algum motivo o comando não for reconhecido, ative o recurso em Configurações, em Aplicativos, Recursos Opcionais, Adicionar um Recurso, procurando por "Cliente OpenSSH". Outra alternativa é usar um programa como o PuTTY, que oferece uma interface gráfica para a mesma conexão.
Em qualquer um dos três sistemas, o servidor vai pedir para confirmar a conexão na primeira vez, e depois vai pedir a senha que você definiu ao criar a VPS. Depois de autenticado, você já está dentro do terminal do servidor, não mais do seu computador. A partir daqui, todos os comandos do tutorial são rodados dentro do servidor, que roda Ubuntu, então não há mais diferença entre os sistemas operacionais.
Instalando e configurando o PostgreSQL
O servidor vem limpo, sem nada instalado. O primeiro passo é atualizar os pacotes do sistema:
apt update -yDepois instalamos as ferramentas necessárias para adicionar o repositório oficial do PostgreSQL:
apt install postgresql-common -yCom o pacote instalado, rodamos o script que adiciona o repositório oficial do PostgreSQL ao sistema, para termos acesso a versões mais recentes:
/usr/share/postgresql-common/pgdg/apt.postgresql.org.shAtualizamos os repositórios novamente e instalamos o PostgreSQL de fato:
apt update
apt install postgresql -yDepois de instalado, o serviço já costuma iniciar automaticamente. Para conferir se está tudo certo:
systemctl status postgresqlSe por algum motivo ele não estiver ativo, é só rodar systemctl start postgresql. Vale também habilitar o serviço para iniciar sozinho toda vez que o servidor reiniciar:
systemctl enable postgresqlDefinindo senha e criando o banco
Para acessar o PostgreSQL, é preciso entrar com o usuário próprio dele, e não com o root:
sudo -i -u postgres psqlJá dentro do console do PostgreSQL, definimos uma senha para esse usuário:
\password postgresEle vai pedir a senha duas vezes para confirmar. Com isso feito, criamos o banco que a aplicação vai usar:
CREATE DATABASE teste_deploy;Para conferir que o banco foi criado, dá para listar todos os bancos existentes:
\lE para sair do console do PostgreSQL:
\qCom isso o banco de dados já está instalado, configurado e pronto para receber a aplicação.
Clonando o projeto
Prefiro clonar o projeto direto na raiz do servidor. Para ir até lá:
cd /
git clone https://github.com/seu-usuario/seu-projeto.git
cd seu-projetoO Ubuntu já vem com o Git instalado, então esse passo não costuma dar trabalho. Falta apenas o Node e o npm, que instalamos assim:
apt install npm -yCom o npm disponível, instalamos as dependências do projeto:
npm installConfigurando as variáveis de ambiente
Com o projeto clonado, o próximo passo é editar o arquivo de variáveis de ambiente para apontar para o banco que acabamos de criar. Usando o vim, por exemplo:
vim .envO importante aqui é trocar o ambiente para produção e ajustar a string de conexão com o usuário, senha e nome do banco que você definiu:
NODE_ENV=production
DATABASE_URL="postgresql://postgres:SUA_SENHA@localhost:5432/teste_deploy"
Rodando as migrations e o seed
Com a conexão configurada, aplicamos a estrutura do banco de dados. Em ambiente de produção, usamos migrate deploy em vez de migrate dev:
npx prisma migrate deploySe o projeto tiver um seed configurado para popular dados iniciais, também é possível rodá-lo:
npx prisma db seedBuild da aplicação
Com o banco pronto, geramos o build de produção do Next.js:
npm run buildDependendo do tamanho do projeto e da capacidade do servidor, esse passo pode demorar um pouco mais.
Só o npm start já coloca a aplicação no ar, só que presa àquele terminal: se você fechar a sessão, o processo cai junto. Por isso não vale a pena rodar assim em produção, é melhor deixar isso para o PM2.
Mantendo o processo rodando com o PM2
O PM2 é uma ferramenta para rodar processos Node.js em segundo plano, muito usada em produção justamente para isso. Instalamos ele de forma global no servidor:
npm install -g pm2E iniciamos a aplicação com um nome de referência:
pm2 start npm --name "teste-deploy" -- startPara ver o que está rodando no PM2 a qualquer momento:
pm2 listA partir daqui, a aplicação continua rodando internamente, mesmo sem terminal aberto, na porta 3000.
Criando um script de Deploy
Antes de partir para o Nginx, vale configurar um jeito rápido de atualizar a aplicação sempre que algo mudar no código. No package.json, criamos um script novo:
{
"scripts": {
"deploy": "git pull origin main && npm install && npx prisma migrate deploy && next build && pm2 restart teste-deploy"
}
}Esse comando puxa a versão mais nova do repositório, instala eventuais dependências novas, aplica migrations pendentes, gera o build e reinicia o processo no PM2. É a forma mais simples de ter uma espécie de CI/CD manual: depois de subir uma alteração para o repositório, basta entrar no servidor e rodar:
npm run deployInstalando e configurando o Nginx
Até aqui a aplicação só responde na porta 3000, internamente. Para deixar ela acessível pela porta 80 (HTTP) e depois pela 443 (HTTPS), usamos o Nginx como proxy reverso. Instalamos ele com:
apt install nginx -yCriamos um arquivo de configuração para o site, usando o mesmo nome do domínio:
vim /etc/nginx/sites-available/seu-dominio.com.brE dentro dele, configuramos o bloco de servidor apontando para a porta onde a aplicação está rodando:
server {
listen 80;
server_name seu-dominio.com.br www.seu-dominio.com.br;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Depois de salvar, criamos um link simbólico para ativar esse site:
ln -s /etc/nginx/sites-available/seu-dominio.com.br /etc/nginx/sites-enabled/E reiniciamos o Nginx para aplicar a configuração:
systemctl restart nginxNesse ponto, o site já deveria responder na porta 80, via HTTP.
Emitindo o certificado SSL com o Certbot
Para ter HTTPS, que hoje em dia é o padrão esperado por qualquer site, usamos o Certbot. Além de emitir o certificado gratuitamente, ele também cuida da renovação automática a cada poucos meses.
apt update
apt install certbot python3-certbot-nginx -yCom o Certbot instalado, rodamos ele apontando para o domínio configurado:
certbot --nginx -d seu-dominio.com.brEle vai pedir um e-mail de contato para notificações e a confirmação dos termos de serviço. Depois disso, ele mesmo edita o arquivo de configuração do Nginx para adicionar o bloco da porta 443 com o certificado.
Para aplicar tudo, reiniciamos o Nginx mais uma vez:
systemctl restart nginxA partir daqui, o site já responde com HTTPS, certificado válido, banco de dados configurado e processo mantido pelo PM2.
Publicando novas alterações
Com toda a estrutura pronta, publicar uma alteração nova é simples. No seu ambiente local, você faz o commit e o push normalmente:
git add .
git commit -m "Alguma alteração"
git push origin mainE no servidor, dentro da pasta do projeto, basta rodar o script que criamos:
npm run deployEle puxa o código novo, reinstala dependências se precisar, aplica migrations pendentes, gera o build e reinicia a aplicação no PM2, tudo em um único comando.
Um detalhe sobre segurança
O banco de dados criado nesse tutorial fica acessível apenas internamente, dentro do próprio servidor, mesmo com uma senha simples. Não dá para acessar ele remotamente por fora, a não ser via SSH. Se em algum momento você precisar expor esse banco para acesso remoto, isso abre uma superfície a mais de ataque, então vale configurar usuário e senha fortes e restringir o acesso por IP, entre outros cuidados. Mas isso já é assunto para outro conteúdo.
Resumindo
Conectar na VPS via SSH, instalar e configurar o PostgreSQL, clonar o projeto, configurar as variáveis de ambiente, rodar migrations e build, manter o processo vivo com o PM2, configurar o Nginx como proxy reverso e emitir o certificado SSL com o Certbot. Depois disso, qualquer atualização se resume a um git push e um npm run deploy.
São várias etapas, mas nenhuma delas é complicada isoladamente. O importante é entender o papel de cada peça: o PostgreSQL guarda os dados, o PM2 mantém a aplicação rodando em segundo plano, o Nginx direciona o tráfego externo para a porta certa, e o Certbot cuida da parte de segurança da conexão. Juntando tudo, você tem uma aplicação Next.js completa, no ar, com HTTPS e pronta para receber atualizações.
Leia também