API remota do runner
v2.161.0+. O runner pode expor uma API HTTP para disparar deploy, enviar
sinais e consultar apps de fora do servidor. Ela roda como serviço do
systemd, fica atrás do Traefik com TLS e exige X-API-Key em toda rota
menos /health.
1. Criar e ligar o serviço
O modo server nasce desativado. Ligar é sempre um passo deliberado:
runner service init --enable-api # grava service.yml e gera a API key; a unit fica DESATIVADA
runner service start # liga: inicia agora e passa a subir no bootO init grava /opt/runner/service.yml (permissão 0600) e instala a unit
runner.service sem habilitá-la. Sem --enable-api, a API fica desligada e
sem chave; para ligá-la depois, use runner service config --enable-api. A
API escuta só em 127.0.0.1:9090.
Guarde num gerenciador de senhas a chave que o comando imprime.
2. Publicar num domínio
O DNS do domínio tem que apontar para este servidor.
runner service expose --domain runner.exemplo.com --vpn-onlyO comando:
detecta como o Traefik alcança o host e escolhe o endereço de escuta:
- Traefik na rede do host:
127.0.0.1; - Traefik numa rede bridge: o gateway dessa rede.
A API nunca escuta em
0.0.0.0.- Traefik na rede do host:
grava a rota
runner-api.ymlno diretório dinâmico do Traefik, com ocertResolverdas apps. Só/healthe/api/v1/*são publicados;reinicia o serviço e espera
https://runner.exemplo.com/healthresponder.
--vpn-only acrescenta o middleware vpn-only@file, e a API só responde
para quem está na VPN. --middleware <nome> acrescenta outros middlewares.
Quando a API escuta no gateway de uma bridge, o expose grava o IP do
container do Traefik em api.trusted_proxies. Só ele e o próprio host falam
com a API. Outro container recebe 403 origem_nao_permitida, então ninguém
contorna os middlewares falando direto com o gateway. Se o container do
Traefik for recriado com outro IP, rode o expose de novo.
3. Chamar a API
curl -H "X-API-Key: {API_KEY}" https://runner.exemplo.com/api/v1/appsSem a chave, ou com a chave errada, a resposta é 401.
4. Disparar um deploy
curl -X POST -H "X-API-Key: {API_KEY}" -H "Content-Type: application/json" \
-d '{"force": true}' https://runner.exemplo.com/api/v1/deploy/minha-app
# 202 {"deploy_id":"3f9a1c2b","status":"rodando","app":"minha-app","instance":"production"}
curl -H "X-API-Key: {API_KEY}" https://runner.exemplo.com/api/v1/deploy/3f9a1c2b
# 200 {"deploy_id":"3f9a1c2b","status":{"app":"minha-app","estado":"sucesso","versao":"1.4.0"}}| Resposta | Quando |
|---|---|
202 |
Deploy aceito; acompanhe pelo deploy_id |
409 lock_contended |
Já há uma operação na app (cron, outro deploy). holder diz qual |
404 |
App inexistente, ou deploy_id desconhecido |
413 |
Corpo maior que 64 KiB. Atrás do Traefik pode chegar como 502 |
503 desligando |
O serviço está parando. Tente de novo em instantes |
O status por deploy_id fica na memória do serviço e some num restart. O
histórico durável é o runner logs history <app>.
Parar ou reiniciar o serviço
systemctl stop runner (e o restart que o expose e o config fazem) espera
os deploys disparados pela API terminarem, por até 10 minutos. Nesse
intervalo, deploy novo recebe 503.
5. Trocar a chave ou despublicar
runner service config --api-key # gera chave nova; com o serviço ativo, reinicia para aplicar
runner service unexpose # remove a rota; a API volta a escutar só em 127.0.0.1Erros ao subir
| Mensagem | Causa |
|---|---|
api_key_ausente |
API habilitada sem chave. Rode runner service init ou service config --api-key |
api_key_formato |
Chave fora do formato rk_<8 hex>_<24 hex> |
bind_invalido |
api.bind não é um endereço IP |
mtls_incompleto |
mTLS ligado com arquivo de certificado faltando |
mtls_atras_do_traefik |
expose com mTLS ligado: o Traefik termina o TLS |
expose_sem_resposta |
O domínio não respondeu em 60 s. Confira DNS e certificado |