Files
claude-plugins/infraestrutura/skills/easypanel-api/SKILL.md
T
ealmeida faef9b47dc fix(project-manager): remover Dify KB das descriptions, marcar nota TODO
Dify foi removido 06-03-2026. Skills brainstorm/discover ainda referenciam-no
no corpo. Bump v1.2 + nota top-of-file. Reescrita workflow para próxima sessão.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 04:52:03 +01:00

13 KiB

name, description
name description
easypanel-api Referência completa da API tRPC oficial do EasyPanel — todos os endpoints para projectos, serviços, deploy e configurações.

/easypanel-api - API Oficial EasyPanel

Referência da API tRPC do EasyPanel. Baseado em engenharia reversa do SDK oficial.


Autenticação

TOKEN=$(cat /etc/easypanel/.api-token)
# Header obrigatório em todos os pedidos:
-H "Authorization: Bearer $TOKEN"

Base URL: http://localhost:3000/api/trpc/

Usar sempre via SSH localhost. Nunca expor externamente.


Formato de Pedidos

Método Quando usar Formato
GET Leitura (list, inspect, get) ?input=URL_ENCODED_JSON
POST Escrita (create, update, deploy, destroy) -d '{"json":{...}}' com Content-Type: application/json
# GET
curl -s "http://localhost:3000/api/trpc/ENDPOINT?input=URL_ENCODED_JSON" \
  -H "Authorization: Bearer $TOKEN"

# POST
curl -s -X POST "http://localhost:3000/api/trpc/ENDPOINT" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"json":{...}}'

Projects API

Endpoint Tipo Descrição
projects.listProjects GET Listar todos os projectos
projects.listProjectsAndServices GET Projectos + todos os serviços
projects.createProject POST Criar projecto (name)
projects.destroyProject POST Destruir projecto (projectName)
projects.inspectProject GET Inspecionar projecto (projectName)
# Listar projectos (teste rápido de autenticação)
curl -s "http://localhost:3000/api/trpc/projects.listProjects" \
  -H "Authorization: Bearer $TOKEN"

# Criar projecto
curl -s -X POST "http://localhost:3000/api/trpc/projects.createProject" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"json":{"name":"novo-projecto"}}'

Services API

Endpoints completos com exemplos curl: ver references/services-api.md

Verificados 12-03-2026 (engenharia reversa do backend.js minificado):

Endpoint Tipo Descrição
services.app.createService POST Criar serviço app
services.postgres.createService POST Criar PostgreSQL
services.mysql.createService POST Criar MySQL
services.redis.createService POST Criar Redis
services.app.inspectService GET Inspecionar serviço
services.app.deployService POST Fazer deploy
services.app.stopService POST Parar serviço
services.app.startService POST Iniciar serviço
services.app.restartService POST Reiniciar serviço
services.app.destroyService POST Destruir serviço

Endpoints que NAO existem (removidos da versao anterior): enableService, disableService — usar startService/stopService em vez disso.

Parâmetros obrigatórios: projectName + serviceName em todos os endpoints de serviços.

Regra Descomplicar: projectName:"descomplicar" para serviços próprios.


Service Configuration API

Endpoints completos com exemplos curl: ver references/service-config-api.md

Verificados 12-03-2026:

Endpoint Descrição Verificado
services.app.updateSourceGithub Source GitHub (owner, repo, ref, path) Sim
services.app.updateSourceGit Source Git custom (repo, ref, path) — params no nivel raiz, NAO dentro de source Sim
services.app.updateSourceImage Source Docker image (image) Sim
services.app.updateEnv Variáveis de ambiente (env como string multi-linha) Sim
services.app.updateBuild Build config (type, buildCommand, startCommand) Sim
services.app.updateResources CPU/RAM (memoryLimit, cpuLimit, etc.) Sim
services.app.updateAdvanced Deploy avançado (replicas, command, zeroDowntime) Sim
services.app.updateRedirects Redireccionamentos HTTP Sim
services.app.updateBasicAuth Autenticacao basica Sim
services.app.updateMaintenance Modo manutencao Sim

Endpoints que NAO existem na versao instalada:

  • services.app.updateDomains — dominios so via UI do EasyPanel
  • services.app.updateMounts — nao encontrado
  • services.app.updatePorts — nao encontrado

Domains API (Verificado 12-03-2026)

Os dominios NAO sao geridos por services.app.* mas sim pelo namespace domains.*.

Endpoint Tipo Descricao
domains.listDomains GET Listar dominios do projecto (projectName)
domains.createDomain POST Criar dominio
domains.updateDomain POST Actualizar dominio
domains.deleteDomain POST Remover dominio
# Listar dominios
INPUT='{"json":{"projectName":"descomplicar"}}'
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$INPUT'))")
curl -s "http://localhost:3000/api/trpc/domains.listDomains?input=$ENCODED" \
  -H "Authorization: Bearer $TOKEN"

# Criar dominio para servico
curl -s -X POST "http://localhost:3000/api/trpc/domains.createDomain" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"json":{
    "id":"meu-dominio-id",
    "https":true,
    "host":"app.descomplicar.pt",
    "path":"/",
    "middlewares":[],
    "certificateResolver":"letsencrypt",
    "wildcard":false,
    "destinationType":"service",
    "serviceDestination":{
      "protocol":"http",
      "port":3000,
      "path":"/",
      "projectName":"descomplicar",
      "serviceName":"meu-servico"
    }
  }}'

Nota: O id pode ser qualquer string unica (cuid ou slug). O certificateResolver deve ser "letsencrypt" para HTTPS com certificado automatico, ou "" para dominios internos.


Monitor API

# Stats do sistema
curl -s "http://localhost:3000/api/trpc/monitor.getSystemStats" \
  -H "Authorization: Bearer $TOKEN"

# Stats de serviço (URL encode necessário)
# input: {"json":{"projectName":"descomplicar","serviceName":"api"}}
curl -s "http://localhost:3000/api/trpc/monitor.getServiceStats?input=..." \
  -H "Authorization: Bearer $TOKEN"

# Stats Docker tasks
curl -s "http://localhost:3000/api/trpc/monitor.getDockerTaskStats" \
  -H "Authorization: Bearer $TOKEN"

Logs API

# Logs de serviço (tail=100)
# input: {"json":{"projectName":"descomplicar","serviceName":"api","tail":100}}
curl -s "http://localhost:3000/api/trpc/logs.getServiceLogs?input=..." \
  -H "Authorization: Bearer $TOKEN"

Settings API

Endpoint Tipo Descrição
settings.getServerIp GET IP do servidor
settings.getPanelDomain GET Domínio do painel
settings.setPanelDomain POST Definir domínio (domain)
settings.getLetsEncryptEmail GET Email Let's Encrypt
settings.setLetsEncryptEmail POST Definir email (email)
settings.restartTraefik POST Reiniciar Traefik
settings.restartEasypanel POST Reiniciar EasyPanel
settings.pruneDockerImages POST Limpar imagens Docker

URL Encoding para GET

INPUT='{"json":{"projectName":"descomplicar","serviceName":"api"}}'
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$INPUT'))")
curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=$ENCODED" \
  -H "Authorization: Bearer $TOKEN"

Wrapper Script

Criar /usr/local/bin/easypanel-api:

#!/bin/bash
TOKEN=$(cat /etc/easypanel/.api-token)
BASE="http://localhost:3000/api/trpc"

if [ -z "$2" ]; then
  curl -s "$BASE/$1" -H "Authorization: Bearer $TOKEN"
else
  curl -s -X POST "$BASE/$1" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d "$2"
fi

Uso: easypanel-api projects.listProjects


Checklist de Uso

  • SSH para servidor easy
  • TOKEN=$(cat /etc/easypanel/.api-token)
  • Testar: curl -s ".../projects.listProjects" -H "Authorization: Bearer $TOKEN"
  • Usar endpoints conforme documentado
  • Validar resposta em result.data.json

Limitações de Mounts

O EasyPanel usa Docker Swarm internamente. Isto impõe limitações nos mounts que diferem do Docker standalone.

Tipos de mount suportados

Tipo API type Comportamento Limitações
Volume mount volume Volume gerido pelo Docker Swarm Funciona bem. Dados persistem no nó. Sem acesso directo ao filesystem do host
Bind mount bind Monta directório do host no container Limitado no Swarm — só funciona se o serviço estiver fixo a um nó específico
File mount file Monta ficheiro individual (config) Funciona. Ideal para ficheiros de configuração

Limitações críticas

  1. Bind mounts no Swarm — O Docker Swarm não garante que o container corra sempre no mesmo nó. Um bind mount (type: "bind") aponta para um path no host, mas se o container migrar para outro nó, esse path pode não existir. O EasyPanel mitiga isto parcialmente por correr num único nó, mas a limitação arquitectural mantém-se.

  2. Sem suporte nativo a NFS/CIFS — O EasyPanel nao suporta drivers de volume remotos (NFS, CIFS, etc.) directamente via API. Para volumes partilhados, e necessario criar o volume Docker manualmente com o driver adequado e depois referencia-lo.

  3. Permissões — Volumes criados via API pertencem a root:root por defeito. Containers que correm com utilizador não-root podem ter problemas de permissões. Workaround: usar command no updateAdvanced para corrigir permissões no arranque.

  4. Substituicao total — Mounts sao geridos via UI do EasyPanel. O endpoint updateMounts NAO foi encontrado na versao instalada. Configurar mounts directamente na interface web.

Workarounds conhecidos

# 1. Obter mounts actuais antes de adicionar novo
INSPECT=$(curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=..." \
  -H "Authorization: Bearer $TOKEN")
# Extrair mounts existentes do JSON e adicionar o novo

# 2. Volume com permissões corrigidas — usar initCommand
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateAdvanced" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"json":{
    "projectName":"descomplicar",
    "serviceName":"minha-api",
    "deploy":{
      "command":"chown -R 1000:1000 /app/data && node dist/index.js"
    }
  }}'

# 3. Volume Docker manual com driver NFS (fora da API)
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.10,rw \
  --opt device=:/export/data \
  vol-nfs-data
# Depois referenciar na API:
# {"type":"volume","name":"vol-nfs-data","mountPath":"/app/data"}

Recomendações

  • Preferir volume sobre bind — mais portável e compatível com Swarm
  • Usar file para configs individuais (nginx.conf, .env, etc.)
  • Inspeccionar antes de actualizar — a API substitui a lista inteira de mounts
  • Documentar volumes manuais — volumes criados fora da API não aparecem no painel EasyPanel até serem referenciados por um serviço

Seguranca

ATENCAO: services.app.inspectService retorna TODAS as variaveis de ambiente em texto limpo, incluindo passwords, tokens API e credenciais de base de dados. Nunca incluir output bruto de inspectService em reports, logs ou comentarios. Sanitizar sempre antes de mostrar ao utilizador.

Campos sensiveis tipicos no env: DB_PASS, API_TOKEN, SERVER_PASS, GATEWAY_PASS, EASYPANEL_API_TOKEN.

Anti-Patterns

Anti-Pattern Risco Alternativa
Expor API externamente Seguranca critica Usar apenas via SSH localhost
Hardcode token Leak de credenciais Usar /etc/easypanel/.api-token
Nao validar response Erros silenciosos Verificar result.data.json
POST sem Content-Type Request falha Sempre incluir header
Mostrar output de inspectService Expoe passwords em texto limpo Sanitizar env vars

Ficheiros de Referência

Ficheiro Conteúdo
references/services-api.md Endpoints de servicos com curl completo (create, inspect, deploy, stop/start/restart, destroy)
references/service-config-api.md Endpoints de configuracao (source, env, resources, build, deploy, domains, backup BD)

Healing Log

Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.

{"date":"","issue":"","fix":"","source":"user|auto"}

Adicionar nova linha após cada erro corrigido.