Tutoriais de VPS
Configurar um runner auto-hospedado do GitHub Actions em uma VPS (2026): instalação, build com Docker, cache, atualizações automáticas e isolamento de segurança
Tutorial completo para implantar um runner auto-hospedado do GitHub Actions em uma VPS, cobrindo escolha de configuração, execução como serviço Linux, labels, build com Docker, cache e disco, isolamento de segurança, atualizações automáticas e solução de problemas comuns.

Configurar um runner auto-hospedado do GitHub Actions em uma VPS (2026): instalação, build com Docker, cache, atualizações automáticas e isolamento de segurança
Quando os jobs do GitHub Actions ficam na fila, os minutos de runner hospedado não são suficientes, ou o build precisa acessar um banco de dados interno, a primeira reação de muitas pessoas é comprar uma VPS e rodar um runner auto-hospedado.
Esse caminho realmente pode economizar dinheiro e tornar o ambiente de build totalmente controlável. Mas não é "poder de computação gratuito que você instala e esquece": o código dos workflows é executado diretamente na sua VPS. O que o runner pode ler, a que pode se conectar e se pode operar o Docker determinam o tamanho do impacto quando algo dá errado.
Este artigo trata de apenas uma coisa: usar uma VPS Ubuntu/Debian para instalar, transformar em serviço e gerenciar de forma estável um runner auto-hospedado do GitHub Actions.
Se o projeto é público, os jobs são poucos e não há necessidade de acesso à rede interna, eu usaria primeiro um runner hospedado do GitHub. Ele fornece um ambiente relativamente limpo a cada vez, e você não precisa se preocupar com a manutenção da máquina.
O runner auto-hospedado é mais adequado para as seguintes situações:
- Builds de repositórios privados demoram muito e você quer reduzir o consumo de minutos hospedados;
- As imagens Docker são grandes e você quer reutilizar o cache de camadas local;
- Os builds precisam acessar uma VPN, serviços internos ou um IP de saída fixo;
- Você precisa de uma arquitetura de CPU especial, dependências de sistema ou hardware;
- Você já tem uma VPS ociosa e está disposto a assumir os custos de segurança e operação.
Se a sua necessidade real é "fazer o build em runners hospedados do GitHub e depois implantar a imagem em uma VPS", é mais adequado consultar Migrar da compilação manual na VPS para GitHub Actions + Docker. Este artigo trata do contrário: fazer a própria VPS ser o runner que executa os jobs de build.
O programa do runner em si é leve; o que realmente consome recursos são suas compilações, testes e builds Docker.
| Uso | Configuração inicial sugerida | Recomendação de disco |
|---|---|---|
| Shell, Go, testes pequenos de Node | 2 núcleos, 2GB | 30GB SSD |
| Builds Node/Java, imagens Docker comuns | 2–4 núcleos, 4GB | 60GB SSD |
| Imagens multi-stage, frontends grandes ou testes em paralelo | 4 núcleos, 8GB+ | 100GB+ SSD |
O disco geralmente enche antes da memória. _work, camadas do Docker, caches de ferramentas e logs se acumulam cada vez mais. Antes de escolher a máquina, consulte a lista de configuração de VPS para desenvolvimento e testes; não olhe apenas o preço mensal.
A seguir, usa-se Ubuntu/Debian como exemplo:
sudo adduser --disabled-password --gecos "" github-runner
sudo apt update
sudo apt install -y curl ca-certificates git jq tar
sudo install -d -o github-runner -g github-runner /home/github-runner/actions-runner
O runner geralmente só precisa se conectar ativamente ao GitHub via HTTPS na porta 443; não é necessário abrir portas de entrada públicas especificamente para ele. Se a VPS tiver um firewall de saída rígido ou proxy, libere o tráfego conforme a lista de domínios de comunicação do GitHub.
Não copie números de versão e valores de verificação do runner de blogs antigos. Acesse o repositório:
Settings → Actions → Runners → New self-hosted runner
Após selecionar Linux e a arquitetura real, o GitHub gera os comandos de download, verificação e configuração. Troque para o usuário dedicado e execute os comandos atuais da página no diretório de instalação:
sudo -iu github-runner
cd ~/actions-runner
#在这里执行 GitHub 页面当前显示的 curl、sha256sum 和 tar 命令
./config.sh \
--url https://github.com/OWNER/REPOSITORY \
--token REGISTRATION_TOKEN \
--name vps-runner-01 \
--labels docker \
--work _work
REGISTRATION_TOKEN é um token de registro gerado temporariamente pelo GitHub; a documentação oficial atualmente informa que ele é válido por 1 hora. Não é um Secret de longo prazo, então não o coloque em scripts, capturas de tela ou artigos. Se expirar, volte à página de configurações e gere novamente.
Após uma configuração bem-sucedida, o runner inclui por padrão as labels self-hosted, sistema operacional e arquitetura; aqui foi adicionada também docker. As labels são apenas condições de roteamento; não instalam o Docker automaticamente nem verificam se a máquina realmente tem a capacidade correspondente.
Primeiro saia do usuário dedicado e depois instale o serviço no diretório do runner:
exit
cd /home/github-runner/actions-runner
sudo ./svc.sh install github-runner
sudo ./svc.sh start
sudo ./svc.sh status
svc.sh cria actions.runner.*.service. Para ver os logs em tempo real:
sudo journalctl -u 'actions.runner.*' -f
Ver Idle na página Runners do GitHub significa que ele está conectado e aguardando jobs; Active indica que está executando um job; Offline normalmente significa que o serviço não foi iniciado, a máquina está sem rede ou não consegue se conectar ao GitHub.
Crie um novo .github/workflows/self-hosted-test.yml:
name: self-hosted-runner-test
on:
workflow_dispatch:
jobs:
test:
runs-on: [self-hosted, linux, x64, docker]
steps:
- uses: actions/checkout@v4
- run: |
uname -a
docker version
Cada label do array deve corresponder simultaneamente a um mesmo runner online. Quando um job fica em Queued, primeiro verifique maiúsculas e minúsculas, arquitetura e labels personalizadas, e depois confira se esse runner permite que o repositório atual o utilize.
Se a VPS for ARM64, altere x64 para o ARM64 exibido na página do runner; não falsifique labels só para fazer os jobs rodarem.
Se os workflows precisarem criar imagens, primeiro instale o Docker Engine pelo método oficial do Docker e depois adicione o usuário do runner ao grupo docker:
sudo usermod -aG docker github-runner
sudo ./svc.sh stop
sudo ./svc.sh start
Atenção: poder acessar /var/run/docker.sock geralmente equivale a poder obter controle de nível root do host. Os workflows podem montar diretórios do host, ler variáveis de ambiente de outros contêineres e até iniciar contêineres privilegiados.
Por isso eu não misturaria banco de dados de produção, contêineres de negócio e runner na mesma VPS. No mínimo:
- Atender apenas repositórios privados confiáveis;
- Usar uma VPS separada ou uma máquina virtual separada para o runner;
- Definir as permissões de
GITHUB_TOKENcomo somente leitura por padrão, abrindo-as de forma mínima por Job; - Fixar Actions de terceiros em versões confiáveis e, em cenários críticos, em um commit SHA;
- Não permitir que PRs de forks não revisados cheguem a um runner persistente;
- Não permitir que a rede onde está o runner acesse diretamente a rede interna de produção.
O GitHub também alerta explicitamente: forks de repositórios públicos podem enviar workflows maliciosos por meio de pull requests, e runners auto-hospedados quase nunca devem ser usados diretamente para repositórios públicos.
Esses três conceitos são fáceis de confundir:
actions/cacheé usado para reutilizar dependências ou caches de build; mesmo com um runner auto-hospedado, o cache continua sendo armazenado no armazenamento em nuvem gerenciado pelo GitHub;- Os Artifacts são usados para guardar o resultado de uma execução de workflow, como relatórios de teste, arquivos compactados e binários;
- O
_worklocal do runner, as camadas do Docker e os caches de npm ou Maven ficam no disco da VPS; são rápidos, mas persistem e podem ser contaminados por jobs posteriores.
Para builds reproduzíveis, trate o cache local como um acelerador, não como a única cópia. Para healthchecks, logs e estratégias de rollback em produção com Docker, consulte o guia de configuração de produção do Docker Compose.
Verifique pelo menos uma vez por semana:
df -h
du -sh /home/github-runner/actions-runner/_work
docker system df
journalctl -u actions.runner.* --disk-usage
Não execute docker system prune -af diretamente só porque viu o disco cheio. Ele exclui contêineres, redes, imagens e caches de build não utilizados; se você adicionar --volumes, também pode excluir volumes não utilizados.
Uma ordem mais segura é: confirmar que não há nenhum Job em execução → excluir diretórios de trabalho antigos que você tem certeza de que não precisa → usar docker builder prune para limpar caches de build reconstruíveis → depois tratar as imagens antigas conforme a lista. Para dados importantes, primeiro verifique se é possível recuperá-los com o guia de simulação de backup e restauração.
O runner é atualizado automaticamente por padrão: se houver um job em execução e ele detectar uma nova versão, será atualizado; se ficar muito tempo sem jobs, também tentará se atualizar dentro de uma semana após o lançamento.
Para uma VPS persistente, recomenda-se manter a atualização automática padrão. Se você usou --disableupdate no registro, o GitHub exige concluir a atualização dentro de 30 dias após o lançamento de uma nova versão; em atualizações de segurança críticas, versões antigas podem deixar de receber jobs ainda mais cedo.
O que você realmente deve fazer backup não é o binário do runner, mas as seguintes informações reconstruíveis:
- O repositório ou organização ao qual o runner pertence;
- As convenções de usuário, diretório, labels e diretório de trabalho;
- As etapas de instalação do Docker e das dependências de build;
- As políticas de firewall e rede;
- Os scripts de monitoramento, limpeza de disco e reconstrução.
Conseguir reinstalar em meia hora depois de quebrar a VPS é mais prático do que fazer um backup completo do disco de _work.
cd /home/github-runner/actions-runner
sudo ./svc.sh status
sudo journalctl -u 'actions.runner.*' -n 200 --no-pager
sudo -u github-runner ./config.sh --check \
--url https://github.com/OWNER/REPOSITORY \
--pat YOUR_FINE_GRAINED_PAT
Os resultados detalhados de --check são gravados em _diag no diretório de instalação. Não desative a verificação TLS por muito tempo só para economizar esforço.
Verifique se o runner está Idle, se todas as labels runs-on correspondem e se o repositório tem permissão para usar o runner. Se houver apenas um processo de runner na mesma máquina, ele geralmente só consegue processar um Job por vez; enquanto o anterior não termina, os seguintes só podem ficar na fila.
Primeiro vá à página de Actions para confirmar se o Job realmente ainda está em execução, depois verifique _diag/Runner_*.log e _diag/Worker_*.log. Se for um build Docker descontrolado, primeiro preserve os logs e as informações de processo, confirme o impacto antes de parar o serviço e não reinicie diretamente toda a máquina de produção.
sudo -u github-runner docker version
id github-runner
ls -l /var/run/docker.sock
Após confirmar o grupo de usuários, reinicie o serviço do runner para que as permissões do novo grupo entrem em vigor. Se ainda falhar, verifique o Docker rootless ou o caminho do socket, em vez de alterar o serviço para rodar como root.
Na página de detalhes do runner no GitHub, clique em Remove; a página gerará um token de remoção com tempo limitado. Depois execute os comandos da página no diretório de instalação:
sudo ./svc.sh stop
sudo ./svc.sh uninstall
sudo -u github-runner ./config.sh remove --token REMOVE_TOKEN
Se a máquina já estiver danificada, você pode forçar a remoção na página do GitHub. Um runner persistente normal que fica 14 dias consecutivos sem se conectar também é removido automaticamente, mas não use esse mecanismo como processo de limpeza.
Os jobs de computação são executados na sua própria máquina, mas cache, Artifacts, rede e outros serviços do GitHub ainda podem ser afetados pelas regras do plano e de cobrança. O que você economiza são recursos de computação hospedados; isso não significa que todos os custos do Actions sejam zerados.
Sim, cada runner usa um diretório, nome e serviço independentes. Mas eles vão disputar CPU, memória, disco e o daemon do Docker. Em uma máquina pequena, é melhor instalar um primeiro e decidir se vai expandir com base na concorrência de Jobs e nos dados de fila.
Tecnicamente sim, mas é preciso ter cautela com a segurança. Uma abordagem mais estável é o runner de build produzir apenas imagens assinadas ou Artifacts, e a etapa de implantação passar por aprovações de ambiente e uma identidade de publicação com menos permissões.
Antes de executá-lo a longo prazo, revise mais uma vez a lista de reforço de segurança de VPS e a configuração de monitoramento e alertas de VPS. O que há de mais valioso em um runner auto-hospedado não é o "poder de computação gratuito", mas o controle; se permissões, disco e o processo de reconstrução também estiverem sob controle, aí sim ele realmente economiza tempo.