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>
This commit is contained in:
@@ -23,6 +23,8 @@ skills:
|
||||
- easypanel-deploy
|
||||
- easypanel-troubleshoot
|
||||
- easypanel-rollback
|
||||
- easypanel-monitor
|
||||
- easypanel-cicd
|
||||
- easypanel-api
|
||||
desk_task: 1502
|
||||
desk_project: 65
|
||||
|
||||
@@ -216,3 +216,15 @@ curl -sk "https://auth.descomplicar.pt/api/v3/admin/system/" \
|
||||
3. Pesquisar duplicados antes de criar users (como CRM)
|
||||
4. Passwords devem ter minimo 12 caracteres
|
||||
5. Verificar groups existentes antes de associar
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -182,3 +182,15 @@ Ver runbook completo passo-a-passo em `references/scripts.md` (seccao Runbook Di
|
||||
| Ficheiro | Conteudo |
|
||||
|----------|----------|
|
||||
| [references/scripts.md](references/scripts.md) | Scripts MySQL/PostgreSQL/WordPress/CWP, rotacao GFS, cron, rclone, teste restore, runbook DR |
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -257,3 +257,15 @@ curl -sI http://DOMINIO | head -5
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com/cwp-admin-api, wiki.centos-webpanel.com/cwp-scripts
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -227,3 +227,15 @@ rm -rf /tmp/restore_test
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com/cwp-scripts, wiki.centos-webpanel.com/category/backups
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -240,3 +240,15 @@ tail -100 /var/log/maillog
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -239,3 +239,15 @@ Integrar insights do NotebookLM nas recomendações e decisões.
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com/php-selector, wiki.centos-webpanel.com/php-version-switcher
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -274,3 +274,15 @@ Integrar insights do NotebookLM nas recomendações e decisões.
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com/cwp-scripts
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -315,3 +315,15 @@ Integrar insights do NotebookLM nas recomendações e decisões.
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com/csf-firewall-command-line
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -250,3 +250,15 @@ curl -sI https://DOMINIO | head -5
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** Documentação oficial CWP (docs.control-webpanel.com, wiki.centos-webpanel.com)
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -266,3 +266,15 @@ tail -20 /var/log/nginx/error.log
|
||||
|
||||
**Versão:** 1.0.0 | **Autor:** Descomplicar®
|
||||
**Fonte:** wiki.centos-webpanel.com/cwp-admin-api, wiki.centos-webpanel.com/cwp-scripts
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -71,6 +71,8 @@ curl -s -X POST "http://localhost:3000/api/trpc/projects.createProject" \
|
||||
|
||||
Endpoints completos com exemplos curl: ver [references/services-api.md](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 |
|
||||
@@ -79,10 +81,14 @@ Endpoints completos com exemplos curl: ver [references/services-api.md](referenc
|
||||
| `services.redis.createService` | POST | Criar Redis |
|
||||
| `services.app.inspectService` | GET | Inspecionar serviço |
|
||||
| `services.app.deployService` | POST | Fazer deploy |
|
||||
| `services.app.enableService` | POST | Activar serviço |
|
||||
| `services.app.disableService` | POST | Desactivar serviço |
|
||||
| `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.
|
||||
@@ -93,19 +99,70 @@ Endpoints completos com exemplos curl: ver [references/services-api.md](referenc
|
||||
|
||||
Endpoints completos com exemplos curl: ver [references/service-config-api.md](references/service-config-api.md)
|
||||
|
||||
| Endpoint | Descrição |
|
||||
|----------|-----------|
|
||||
| `services.app.updateSourceGithub` | Source GitHub (`owner`, `repo`, `ref`, `path`) |
|
||||
| `services.app.updateSourceGit` | Source Git custom (`repo`, `ref`, `path`) |
|
||||
| `services.app.updateSourceImage` | Source Docker image (`image`) |
|
||||
| `services.app.updateEnv` | Variáveis de ambiente (`env` como string multi-linha) |
|
||||
| `services.app.updateDomains` | Domínios (`domains[]` com `host`, `https`, `port`) |
|
||||
| `services.app.updateMounts` | Volumes (`mounts[]` com `type`, `name`, `mountPath`) |
|
||||
| `services.app.updatePorts` | Portas TCP/UDP (`ports[]` com `published`, `target`, `protocol`) |
|
||||
| `services.app.updateResources` | CPU/RAM (`memoryLimit`, `cpuLimit`, etc.) |
|
||||
| `services.app.updateBuild` | Build config (`type`, `buildCommand`, `startCommand`) |
|
||||
| `services.app.updateAdvanced` | Deploy avançado (`replicas`, `command`, `zeroDowntime`) |
|
||||
| `services.postgres.updateBackup` | Backup BD para S3 |
|
||||
**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 |
|
||||
|
||||
```bash
|
||||
# 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.
|
||||
|
||||
---
|
||||
|
||||
@@ -214,11 +271,11 @@ O EasyPanel usa Docker Swarm internamente. Isto impõe limitações nos mounts q
|
||||
|
||||
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** — A API `updateMounts` não suporta drivers de volume remotos (NFS, CIFS, etc.) directamente. Para volumes partilhados, é necessário criar o volume Docker manualmente com o driver adequado e depois referenciá-lo.
|
||||
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. **Substituição total** — `updateMounts` substitui **todos** os mounts existentes. Para adicionar um mount, é preciso primeiro obter os mounts actuais via `inspectService` e enviar a lista completa com o novo mount incluído.
|
||||
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
|
||||
|
||||
@@ -259,14 +316,21 @@ docker volume create --driver local \
|
||||
|
||||
---
|
||||
|
||||
## 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 | Segurança crítica | Usar apenas via SSH localhost |
|
||||
| Expor API externamente | Seguranca critica | Usar apenas via SSH localhost |
|
||||
| Hardcode token | Leak de credenciais | Usar `/etc/easypanel/.api-token` |
|
||||
| Não validar response | Erros silenciosos | Verificar `result.data.json` |
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
@@ -274,5 +338,17 @@ docker volume create --driver local \
|
||||
|
||||
| Ficheiro | Conteúdo |
|
||||
|----------|----------|
|
||||
| [references/services-api.md](references/services-api.md) | Endpoints de serviços com curl completo (create, inspect, deploy, enable/disable, destroy) |
|
||||
| [references/service-config-api.md](references/service-config-api.md) | Endpoints de configuração (source, env, domains, mounts, ports, resources, build, deploy, backup BD) |
|
||||
| [references/services-api.md](references/services-api.md) | Endpoints de servicos com curl completo (create, inspect, deploy, stop/start/restart, destroy) |
|
||||
| [references/service-config-api.md](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.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# EasyPanel API - Service Configuration
|
||||
|
||||
**Verificado:** 12-03-2026 (engenharia reversa do backend.js)
|
||||
|
||||
---
|
||||
|
||||
## Actualizar Source (GitHub)
|
||||
|
||||
```bash
|
||||
@@ -18,6 +22,8 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateSourceGithub"
|
||||
|
||||
## Actualizar Source (Git Custom)
|
||||
|
||||
**IMPORTANTE:** Os parametros `repo`, `ref`, `path` devem estar no nivel RAIZ do JSON, NAO dentro de um objecto `source`.
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateSourceGit" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
@@ -25,12 +31,22 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateSourceGit" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"repo":"https://git.descomplicar.pt/org/repo",
|
||||
"repo":"https://ealmeida:TOKEN@git.descomplicar.pt/ealmeida/repo",
|
||||
"ref":"main",
|
||||
"path":"/"
|
||||
}}'
|
||||
```
|
||||
|
||||
**Errado (causa zodErrors):**
|
||||
```json
|
||||
{"json":{"projectName":"x","serviceName":"y","source":{"type":"git","repo":"...","ref":"main","path":"/"}}}
|
||||
```
|
||||
|
||||
**Correcto:**
|
||||
```json
|
||||
{"json":{"projectName":"x","serviceName":"y","repo":"...","ref":"main","path":"/"}}
|
||||
```
|
||||
|
||||
## Actualizar Source (Docker Image)
|
||||
|
||||
```bash
|
||||
@@ -57,48 +73,20 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateEnv" \
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Domains
|
||||
## Actualizar Build Config
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateDomains" \
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateBuild" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"domains":[
|
||||
{"host":"api.descomplicar.pt","https":true,"port":3000}
|
||||
]
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Mounts
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateMounts" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"mounts":[
|
||||
{"type":"volume","name":"data","mountPath":"/app/data"}
|
||||
]
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Ports (non-HTTP)
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updatePorts" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"ports":[
|
||||
{"published":8080,"target":3000,"protocol":"tcp"}
|
||||
]
|
||||
"build":{
|
||||
"type":"nixpacks",
|
||||
"buildCommand":"npm run build",
|
||||
"startCommand":"npm start"
|
||||
}
|
||||
}}'
|
||||
```
|
||||
|
||||
@@ -120,23 +108,6 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateResources" \
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Build Config
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateBuild" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"build":{
|
||||
"type":"nixpacks",
|
||||
"buildCommand":"npm run build",
|
||||
"startCommand":"npm start"
|
||||
}
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Deploy (Replicas, Command)
|
||||
|
||||
```bash
|
||||
@@ -154,6 +125,45 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateAdvanced" \
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Redirects
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateRedirects" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"redirects":[]
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Basic Auth
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateBasicAuth" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"basicAuth":{"enabled":false}
|
||||
}}'
|
||||
```
|
||||
|
||||
## Actualizar Maintenance Mode
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateMaintenance" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{
|
||||
"projectName":"descomplicar",
|
||||
"serviceName":"minha-api",
|
||||
"maintenance":{"enabled":false}
|
||||
}}'
|
||||
```
|
||||
|
||||
## Database Backup Config
|
||||
|
||||
```bash
|
||||
@@ -176,3 +186,98 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.postgres.updateBackup"
|
||||
}
|
||||
}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domains API (Namespace separado)
|
||||
|
||||
**IMPORTANTE:** Os dominios NAO sao geridos por `services.app.*` mas sim pelo namespace `domains.*`.
|
||||
|
||||
### Listar Dominios (GET)
|
||||
|
||||
```bash
|
||||
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 (POST)
|
||||
|
||||
```bash
|
||||
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"
|
||||
}
|
||||
}}'
|
||||
```
|
||||
|
||||
**Notas:**
|
||||
- O `id` pode ser qualquer string unica (cuid ou slug)
|
||||
- `certificateResolver`: `"letsencrypt"` para HTTPS, `""` para dominios internos
|
||||
- `destinationType`: `"service"` para servicos EasyPanel, `"custom"` para destinos externos
|
||||
|
||||
### Actualizar Dominio (POST)
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/domains.updateDomain" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{...mesmo schema de createDomain...}}'
|
||||
```
|
||||
|
||||
### Remover Dominio (POST)
|
||||
|
||||
```bash
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/domains.deleteDomain" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"id":"meu-dominio-id"}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resumo de Endpoints de Configuracao
|
||||
|
||||
| Endpoint | Tipo | Descricao | Verificado |
|
||||
|----------|------|-----------|:----------:|
|
||||
| `services.app.updateSourceGithub` | POST | Source GitHub (`owner`,`repo`,`ref`,`path`) | Sim |
|
||||
| `services.app.updateSourceGit` | POST | Source Git custom (`repo`,`ref`,`path` RAIZ) | Sim |
|
||||
| `services.app.updateSourceImage` | POST | Source Docker image (`image`) | Sim |
|
||||
| `services.app.updateEnv` | POST | Variaveis de ambiente (`env` string) | Sim |
|
||||
| `services.app.updateBuild` | POST | Build config (`type`,`buildCommand`,`startCommand`) | Sim |
|
||||
| `services.app.updateResources` | POST | CPU/RAM limits | Sim |
|
||||
| `services.app.updateAdvanced` | POST | Deploy avancado (replicas, command, zeroDowntime) | Sim |
|
||||
| `services.app.updateRedirects` | POST | Redireccionamentos HTTP | Sim |
|
||||
| `services.app.updateBasicAuth` | POST | Autenticacao basica | Sim |
|
||||
| `services.app.updateMaintenance` | POST | Modo manutencao | Sim |
|
||||
| `domains.listDomains` | GET | Listar dominios (`projectName`) | Sim |
|
||||
| `domains.createDomain` | POST | Criar dominio | Sim |
|
||||
| `domains.updateDomain` | POST | Actualizar dominio | Sim |
|
||||
| `domains.deleteDomain` | POST | Remover dominio | Sim |
|
||||
|
||||
**Endpoints que NAO existem na versao instalada:**
|
||||
- ~~`services.app.updateDomains`~~ — usar `domains.createDomain`
|
||||
- ~~`services.app.updateMounts`~~ — nao encontrado
|
||||
- ~~`services.app.updatePorts`~~ — nao encontrado
|
||||
- ~~`services.app.saveDomains`~~ — nao existe
|
||||
- ~~`services.app.saveGithubSource`~~ — usar `updateSourceGithub` ou `updateSourceGit`
|
||||
|
||||
---
|
||||
|
||||
*Actualizado: 12-03-2026*
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# EasyPanel API - Services
|
||||
|
||||
**Verificado:** 12-03-2026 (engenharia reversa do backend.js)
|
||||
|
||||
## Service Types
|
||||
|
||||
| Type | Descricao |
|
||||
|------|-----------|
|
||||
| `app` | Aplicacao (Node.js, Python, Go, etc.) |
|
||||
| `app` | Aplicacao (Node.js, Python, Go, Rust, etc.) |
|
||||
| `mysql` | MySQL database |
|
||||
| `mariadb` | MariaDB database |
|
||||
| `postgres` | PostgreSQL database |
|
||||
@@ -42,14 +44,16 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.redis.createService" \
|
||||
-d '{"json":{"projectName":"descomplicar","serviceName":"cache"}}'
|
||||
```
|
||||
|
||||
## Inspeccionar Servico
|
||||
## Inspeccionar Servico (GET)
|
||||
|
||||
```bash
|
||||
curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=%7B%22json%22%3A%7B%22projectName%22%3A%22descomplicar%22%2C%22serviceName%22%3A%22dashboard_descomplicar%22%7D%7D" \
|
||||
INPUT='{"json":{"projectName":"descomplicar","serviceName":"dashboard_descomplicar"}}'
|
||||
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"
|
||||
```
|
||||
|
||||
Response:
|
||||
Response parcial:
|
||||
```json
|
||||
{
|
||||
"projectName": "descomplicar",
|
||||
@@ -74,22 +78,30 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.deployService" \
|
||||
-d '{"json":{"projectName":"descomplicar","serviceName":"minha-api"}}'
|
||||
```
|
||||
|
||||
## Enable/Disable Servico
|
||||
## Stop / Start / Restart Servico
|
||||
|
||||
```bash
|
||||
# Disable
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.disableService" \
|
||||
# Parar servico
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.stopService" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"descomplicar","serviceName":"minha-api"}}'
|
||||
|
||||
# Enable
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.enableService" \
|
||||
# Iniciar servico
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.startService" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"descomplicar","serviceName":"minha-api"}}'
|
||||
|
||||
# Reiniciar servico
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.restartService" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"descomplicar","serviceName":"minha-api"}}'
|
||||
```
|
||||
|
||||
**IMPORTANTE:** `enableService` e `disableService` NAO existem na versao instalada. Usar `startService`/`stopService`.
|
||||
|
||||
## Destruir Servico
|
||||
|
||||
```bash
|
||||
@@ -98,3 +110,26 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.destroyService" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"descomplicar","serviceName":"minha-api"}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resumo de Endpoints
|
||||
|
||||
| Endpoint | Tipo | Descricao | Verificado |
|
||||
|----------|------|-----------|:----------:|
|
||||
| `services.app.createService` | POST | Criar servico app | Sim |
|
||||
| `services.postgres.createService` | POST | Criar PostgreSQL | Sim |
|
||||
| `services.mysql.createService` | POST | Criar MySQL | Sim |
|
||||
| `services.redis.createService` | POST | Criar Redis | Sim |
|
||||
| `services.app.inspectService` | GET | Inspeccionar servico | Sim |
|
||||
| `services.app.deployService` | POST | Fazer deploy | Sim |
|
||||
| `services.app.stopService` | POST | Parar servico | Sim |
|
||||
| `services.app.startService` | POST | Iniciar servico | Sim |
|
||||
| `services.app.restartService` | POST | Reiniciar servico | Sim |
|
||||
| `services.app.destroyService` | POST | Destruir servico | Sim |
|
||||
|
||||
**Endpoints que NAO existem:** `enableService`, `disableService`, `redeployService`
|
||||
|
||||
---
|
||||
|
||||
*Actualizado: 12-03-2026*
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
---
|
||||
name: easypanel-cicd
|
||||
description: Configuracao de CI/CD com Gitea Actions para auto-deploy no EasyPanel via webhook — setup de workflows, secrets e validacao.
|
||||
---
|
||||
|
||||
# /easypanel-cicd - CI/CD Gitea Actions para EasyPanel
|
||||
|
||||
Configuracao completa de pipelines CI/CD que ligam repositorios Gitea ao EasyPanel para auto-deploy.
|
||||
|
||||
---
|
||||
|
||||
## Quando usar
|
||||
|
||||
- Configurar auto-deploy de um repositorio Gitea para EasyPanel
|
||||
- Criar workflow Gitea Actions com testes + deploy
|
||||
- Obter e configurar webhook URL de um servico
|
||||
- Diagnosticar pipelines CI/CD falhados
|
||||
- Adicionar CI/CD a projectos existentes no EasyPanel
|
||||
|
||||
## Quando nao usar
|
||||
|
||||
- Para deploy manual (usar `/easypanel-deploy`)
|
||||
- Para scaffold de projecto novo (usar `/easypanel-init`)
|
||||
- Para troubleshooting de containers (usar `/easypanel-troubleshoot`)
|
||||
|
||||
---
|
||||
|
||||
## Sintaxe
|
||||
|
||||
```bash
|
||||
/easypanel-cicd <repo-name> # Setup completo (workflow + secrets + webhook)
|
||||
/easypanel-cicd <repo-name> --webhook-only # Apenas obter/configurar webhook
|
||||
/easypanel-cicd <repo-name> --diagnose # Diagnosticar pipeline falhado
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
Gitea (push main) --> Gitea Actions Runner --> Testes + Build --> Webhook POST --> EasyPanel Redeploy
|
||||
(3 runners activos) (deploy URL) (build + container)
|
||||
```
|
||||
|
||||
**Componentes:**
|
||||
- **Gitea Actions Runners:** 3 replicas activas (`descomplicar_gitea-runner`)
|
||||
- **Webhook URL:** Cada servico EasyPanel tem `deploymentUrl` unico
|
||||
- **Formato:** `http://<IP>:3000/api/deploy/<service-token>`
|
||||
|
||||
---
|
||||
|
||||
## Workflow completo
|
||||
|
||||
### 1. Obter webhook URL do servico
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
|
||||
# Via inspectService — campo deploymentUrl
|
||||
INPUT='{"json":{"projectName":"descomplicar","serviceName":"SERVICE_NAME"}}'
|
||||
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" \
|
||||
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['result']['data']['json']['deploymentUrl'])"
|
||||
```
|
||||
|
||||
**Formato da URL:** `http://178.63.18.51:3000/api/deploy/<service-token>`
|
||||
|
||||
**Nota:** O token e unico por servico e nao expira. Nao confundir com o API token geral.
|
||||
|
||||
### 2. Configurar secret no repositorio Gitea
|
||||
|
||||
Via MCP Gitea:
|
||||
```
|
||||
mcp__gitea__upsert_repo_action_secret({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
secretname: "EASYPANEL_DEPLOY_URL",
|
||||
body: { data: "http://178.63.18.51:3000/api/deploy/<service-token>" }
|
||||
})
|
||||
```
|
||||
|
||||
Secrets adicionais recomendados:
|
||||
- `EASYPANEL_DEPLOY_URL` — webhook URL (obrigatorio)
|
||||
- `DEPLOY_DOMAIN` — dominio do servico (opcional, para health check)
|
||||
|
||||
### 3. Criar workflow Gitea Actions
|
||||
|
||||
Criar `.gitea/workflows/deploy.yml` no repositorio:
|
||||
|
||||
#### Template basico (apenas deploy)
|
||||
|
||||
```yaml
|
||||
name: Deploy to EasyPanel
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}")
|
||||
if [ "$RESPONSE" != "200" ]; then
|
||||
echo "Deploy trigger failed with HTTP $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo "Deploy triggered successfully"
|
||||
```
|
||||
|
||||
#### Template completo (testes + build + deploy + health check)
|
||||
|
||||
```yaml
|
||||
name: CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint --if-present
|
||||
|
||||
- name: Test
|
||||
run: npm test --if-present
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
deploy:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
||||
steps:
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
echo "Triggering deploy..."
|
||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}")
|
||||
if [ "$RESPONSE" != "200" ]; then
|
||||
echo "Deploy trigger failed with HTTP $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
echo "Deploy triggered (HTTP $RESPONSE)"
|
||||
|
||||
- name: Wait for deployment
|
||||
run: sleep 120
|
||||
|
||||
- name: Health check
|
||||
if: ${{ secrets.DEPLOY_DOMAIN != '' }}
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do
|
||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://${{ secrets.DEPLOY_DOMAIN }}/health" || echo "000")
|
||||
echo "Health check $i/5: HTTP $STATUS"
|
||||
if [ "$STATUS" = "200" ]; then
|
||||
echo "Service healthy"
|
||||
exit 0
|
||||
fi
|
||||
sleep 15
|
||||
done
|
||||
echo "Health check failed after 5 attempts"
|
||||
exit 1
|
||||
```
|
||||
|
||||
#### Template Python
|
||||
|
||||
```yaml
|
||||
name: CI/CD Pipeline (Python)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- run: pip install -r requirements.txt
|
||||
- run: python -m pytest --if-present
|
||||
|
||||
deploy:
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
curl -sf -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}" || exit 1
|
||||
```
|
||||
|
||||
### 4. Commit e push
|
||||
|
||||
```bash
|
||||
git add .gitea/workflows/deploy.yml
|
||||
git commit -m "ci: add Gitea Actions deploy pipeline"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### 5. Validar pipeline
|
||||
|
||||
```bash
|
||||
# Via MCP Gitea — verificar runs
|
||||
mcp__gitea__list_repo_action_runs({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
limit: 5
|
||||
})
|
||||
```
|
||||
|
||||
Ou verificar logs:
|
||||
```bash
|
||||
mcp__gitea__list_repo_action_run_jobs({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
run_id: RUN_ID
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Diagnostico (--diagnose)
|
||||
|
||||
### Pipeline nao dispara
|
||||
|
||||
1. Verificar se o ficheiro esta em `.gitea/workflows/` (nao `.github/workflows/`)
|
||||
2. Verificar se o branch e `main` (ou o configurado no `on.push.branches`)
|
||||
3. Verificar se os runners estao activos:
|
||||
```bash
|
||||
docker service ls | grep gitea-runner
|
||||
# Esperado: 3/3 replicas
|
||||
```
|
||||
|
||||
### Webhook falha (HTTP != 200)
|
||||
|
||||
1. Verificar se o `deploymentUrl` esta correcto (servico pode ter sido recriado)
|
||||
2. Verificar se o EasyPanel esta acessivel internamente:
|
||||
```bash
|
||||
curl -s http://localhost:3000/api/trpc/projects.listProjects -H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
3. Verificar se o token do servico nao mudou (re-obter via inspectService)
|
||||
|
||||
### Build falha no EasyPanel
|
||||
|
||||
1. Verificar Dockerfile:
|
||||
```bash
|
||||
/easypanel-validate
|
||||
```
|
||||
2. Verificar logs do build:
|
||||
```bash
|
||||
/easypanel-troubleshoot SERVICE_NAME
|
||||
```
|
||||
|
||||
### Testes falham no runner
|
||||
|
||||
1. Verificar logs do job:
|
||||
```bash
|
||||
mcp__gitea__get_repo_action_job_log_preview({
|
||||
owner: "ealmeida",
|
||||
repo: "REPO_NAME",
|
||||
job_id: JOB_ID
|
||||
})
|
||||
```
|
||||
2. Verificar se dependencias estao no `package.json`/`requirements.txt`
|
||||
3. Verificar se env vars de teste estao configuradas
|
||||
|
||||
---
|
||||
|
||||
## Servicos com CI/CD activo (inventario)
|
||||
|
||||
Para listar todos os servicos com source git (candidatos a CI/CD):
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
curl -s "http://localhost:3000/api/trpc/projects.listProjectsAndServices" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
| python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)['result']['data']['json']
|
||||
for s in d.get('services',[]):
|
||||
src=s.get('source',{}) or {}
|
||||
if src.get('type')=='git' and s.get('type')=='app':
|
||||
repo=src.get('repo','').split('@')[-1] if '@' in src.get('repo','') else src.get('repo','')
|
||||
print(f\"{s['projectName']}/{s['name']} | repo={repo} | ref={src.get('ref','?')}\")
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checklist de execucao
|
||||
|
||||
- [ ] Identificar servico EasyPanel alvo (projectName + serviceName)
|
||||
- [ ] Obter deploymentUrl via inspectService (SSH ao servidor easy)
|
||||
- [ ] Criar secret EASYPANEL_DEPLOY_URL no repo Gitea (via MCP)
|
||||
- [ ] Criar secret DEPLOY_DOMAIN no repo Gitea (opcional, para health check)
|
||||
- [ ] Criar `.gitea/workflows/deploy.yml` com template adequado
|
||||
- [ ] Commit e push do workflow
|
||||
- [ ] Verificar que o primeiro run dispara (list_repo_action_runs)
|
||||
- [ ] Verificar que o deploy completa no EasyPanel
|
||||
- [ ] Health check do servico apos deploy
|
||||
|
||||
---
|
||||
|
||||
## MCPs necessarios
|
||||
|
||||
- `ssh-unified` — Acesso ao servidor easy para obter deploymentUrl
|
||||
- `gitea` — Criar secrets e verificar action runs
|
||||
|
||||
---
|
||||
|
||||
## Skills relacionadas
|
||||
|
||||
| Skill | Quando usar |
|
||||
|-------|-------------|
|
||||
| `/easypanel-deploy` | Deploy manual com validacao completa |
|
||||
| `/easypanel-validate` | Validar projecto antes de configurar CI/CD |
|
||||
| `/easypanel-init` | Scaffold novo projecto (ja inclui workflow template) |
|
||||
| `/easypanel-troubleshoot` | Diagnosticar deploy falhado |
|
||||
| `/easypanel-api` | Referencia API tRPC |
|
||||
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 24-03-2026 | Descomplicar(r)*
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
@@ -314,26 +314,34 @@ Root cause detected: App listening on port 8080, Traefik expects 3000
|
||||
|
||||
## Integration com CI/CD
|
||||
|
||||
O deploy automatico via Gitea Actions usa o webhook do EasyPanel (nao esta skill directamente).
|
||||
Cada servico tem um `deploymentUrl` unico (visivel em `inspectService`).
|
||||
|
||||
```yaml
|
||||
# .gitea/workflows/deploy.yml
|
||||
steps:
|
||||
- name: Deploy
|
||||
- name: Trigger EasyPanel Deploy
|
||||
run: |
|
||||
/easypanel-deploy --skip-tests
|
||||
env:
|
||||
EASYPANEL_TOKEN: ${{ secrets.EASYPANEL_TOKEN }}
|
||||
curl -s -X POST "${{ secrets.EASYPANEL_DEPLOY_URL }}"
|
||||
# EASYPANEL_DEPLOY_URL = http://IP:3000/api/deploy/<service-token>
|
||||
```
|
||||
|
||||
Ver skill `/easypanel-cicd` para configuracao completa de CI/CD com Gitea Actions.
|
||||
|
||||
## API Endpoints Usados
|
||||
|
||||
Ver skill `/easypanel-api` para documentação completa.
|
||||
|
||||
| Acção | Endpoint |
|
||||
|-------|----------|
|
||||
| Deploy serviço | `POST services.app.deployService` |
|
||||
| Redeploy | `POST services.app.redeployService` |
|
||||
| Estado serviço | `GET services.app.inspectService` |
|
||||
| Logs | `GET services.app.getServiceLogs` |
|
||||
| Acção | Endpoint | Verificado |
|
||||
|-------|----------|:----------:|
|
||||
| Deploy serviço | `POST services.app.deployService` | Sim |
|
||||
| Estado serviço | `GET services.app.inspectService` | Sim |
|
||||
| Parar serviço | `POST services.app.stopService` | Sim |
|
||||
| Iniciar serviço | `POST services.app.startService` | Sim |
|
||||
| Reiniciar serviço | `POST services.app.restartService` | Sim |
|
||||
| Logs serviço | `GET logs.getServiceLogs` | Sim |
|
||||
|
||||
**Endpoints que NAO existem:** `redeployService` — usar `deployService` para re-deploy.
|
||||
|
||||
## MCPs Necessários
|
||||
|
||||
@@ -403,4 +411,15 @@ Status: 4 (Em progresso) → 5 (Concluído)
|
||||
|
||||
---
|
||||
|
||||
**/** @author Descomplicar® | @link descomplicar.pt | @copyright 2026 **/
|
||||
**/** @author Descomplicar® | @link descomplicar.pt | @copyright 2026 **/
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -259,20 +259,43 @@ curl -s -X POST "http://localhost:3000/api/trpc/services.app.createService" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"PROJECT_NAME","serviceName":"app"}}'
|
||||
|
||||
# Configurar domínio
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.saveDomains" \
|
||||
# Configurar dominio (namespace domains.*, NAO services.app.*)
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/domains.createDomain" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"PROJECT_NAME","serviceName":"app","domains":[{"host":"DOMAIN"}]}}'
|
||||
-d '{"json":{
|
||||
"id":"PROJECT_NAME-app",
|
||||
"https":true,
|
||||
"host":"DOMAIN",
|
||||
"path":"/",
|
||||
"middlewares":[],
|
||||
"certificateResolver":"letsencrypt",
|
||||
"wildcard":false,
|
||||
"destinationType":"service",
|
||||
"serviceDestination":{
|
||||
"protocol":"http",
|
||||
"port":3000,
|
||||
"path":"/",
|
||||
"projectName":"PROJECT_NAME",
|
||||
"serviceName":"app"
|
||||
}
|
||||
}}'
|
||||
|
||||
# Configurar Git source
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.saveGithubSource" \
|
||||
# Configurar Git source (params RAIZ, NAO dentro de source)
|
||||
# Para repos Gitea privados, incluir token no URL
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.updateSourceGit" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"PROJECT_NAME","serviceName":"app","owner":"ORG","repo":"REPO","ref":"refs/heads/main","autoDeploy":true}}'
|
||||
-d '{"json":{
|
||||
"projectName":"PROJECT_NAME",
|
||||
"serviceName":"app",
|
||||
"repo":"https://ealmeida:GITEA_TOKEN@git.descomplicar.pt/ealmeida/REPO",
|
||||
"ref":"main",
|
||||
"path":"/"
|
||||
}}'
|
||||
```
|
||||
|
||||
### 5. Optional: Push to Gitea
|
||||
### 5. Push to Gitea (opcional)
|
||||
|
||||
```bash
|
||||
# Criar repo via MCP Gitea
|
||||
@@ -287,7 +310,7 @@ git remote add origin git@git.descomplicar.pt:ORG/PROJECT_NAME.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### 5. Output Summary
|
||||
### 6. Output Summary
|
||||
|
||||
```
|
||||
✅ Project scaffolded: PROJECT_NAME
|
||||
@@ -383,13 +406,16 @@ Similar ao PostgreSQL, usando `mysql:8-alpine`.
|
||||
|
||||
Ver skill `/easypanel-api` para documentação completa.
|
||||
|
||||
| Acção | Endpoint |
|
||||
|-------|----------|
|
||||
| Criar projecto | `POST projects.createProject` |
|
||||
| Criar serviço | `POST services.app.createService` |
|
||||
| Configurar domínio | `POST services.app.saveDomains` |
|
||||
| Configurar Git source | `POST services.app.saveGithubSource` |
|
||||
| Deploy inicial | `POST services.app.deployService` |
|
||||
| Acção | Endpoint | Verificado |
|
||||
|-------|----------|:----------:|
|
||||
| Criar projecto | `POST projects.createProject` | Sim |
|
||||
| Criar serviço | `POST services.app.createService` | Sim |
|
||||
| Configurar dominio | `POST domains.createDomain` | Sim |
|
||||
| Configurar Git source | `POST services.app.updateSourceGit` | Sim |
|
||||
| Configurar GitHub source | `POST services.app.updateSourceGithub` | Sim |
|
||||
| Deploy inicial | `POST services.app.deployService` | Sim |
|
||||
|
||||
**Endpoints que NAO existem:** `saveDomains`, `saveGithubSource` — usar `domains.createDomain` e `updateSourceGit`/`updateSourceGithub`.
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -458,9 +484,12 @@ Status: 4 (Em progresso) → 5 (Concluído)
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
## Quando NÃO Usar
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
- Para tarefas fora do domínio de especialização desta skill
|
||||
- Quando outra skill mais específica está disponível
|
||||
- Para operações que requerem confirmação manual do utilizador
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -74,8 +74,58 @@ Para cada servico DOWN, obter logs:
|
||||
docker service logs <nome-servico> --tail 10 --no-trunc 2>&1
|
||||
```
|
||||
|
||||
### Passo 3: Uso de recursos (docker stats)
|
||||
### Passo 3: Uso de recursos via API (preferido)
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
|
||||
# Stats do sistema — retorna estrutura aninhada
|
||||
curl -s "http://localhost:3000/api/trpc/monitor.getSystemStats" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Estrutura real da resposta (verificado 24-03-2026):**
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"data": {
|
||||
"json": {
|
||||
"uptime": 3118351.41,
|
||||
"memInfo": {
|
||||
"totalMemMb": 32096.51,
|
||||
"usedMemMb": 16885.52,
|
||||
"freeMemMb": 15210.99,
|
||||
"usedMemPercentage": 52.61,
|
||||
"freeMemPercentage": 47.39
|
||||
},
|
||||
"diskInfo": {
|
||||
"totalGb": "192.7",
|
||||
"usedGb": "89.7",
|
||||
"freeGb": "103.0",
|
||||
"usedPercentage": "46.5",
|
||||
"freePercentage": "53.5"
|
||||
},
|
||||
"cpuInfo": {
|
||||
"usedPercentage": 13.65,
|
||||
"count": 6,
|
||||
"loadavg": [5.58, 6.34, 6.51]
|
||||
},
|
||||
"network": {
|
||||
"inputMb": 0,
|
||||
"outputMb": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Campos a usar:**
|
||||
- CPU: `cpuInfo.usedPercentage`
|
||||
- RAM: `memInfo.usedMemPercentage` e `memInfo.usedMemMb`
|
||||
- Disco: `diskInfo.usedPercentage` e `diskInfo.usedGb`
|
||||
|
||||
**Fallback via SSH (se API indisponivel):**
|
||||
```bash
|
||||
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}"
|
||||
```
|
||||
@@ -88,7 +138,9 @@ docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\
|
||||
| RAM | <70% | 70-85% | >85% |
|
||||
| RAM absoluto | <512MB | 512MB-1GB | >1GB |
|
||||
|
||||
### Passo 4: Espaco em disco
|
||||
### Passo 4: Espaco em disco (via API ou fallback)
|
||||
|
||||
Usar `diskInfo` da resposta do passo 3. Fallback:
|
||||
|
||||
```bash
|
||||
df -h / /var/lib/docker
|
||||
@@ -208,16 +260,17 @@ docker stats --no-stream --filter "name=<servico>"
|
||||
|
||||
## Integracao com API EasyPanel
|
||||
|
||||
Alternativa via API tRPC (ver `/easypanel-api`):
|
||||
A API e o metodo **preferido** (ver `/easypanel-api`). Os comandos Docker sao fallback.
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
|
||||
# Stats do sistema
|
||||
# Stats do sistema (CPU, RAM, Disco — ver estrutura no Passo 3)
|
||||
curl -s "http://localhost:3000/api/trpc/monitor.getSystemStats" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Stats Docker tasks
|
||||
# Stats Docker tasks (actual/desired replicas por servico)
|
||||
# Resposta: {"serviceName": {"actual": 1, "desired": 1}, ...}
|
||||
curl -s "http://localhost:3000/api/trpc/monitor.getDockerTaskStats" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
@@ -226,6 +279,8 @@ curl -s "http://localhost:3000/api/trpc/projects.listProjectsAndServices" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Nota de seguranca:** `inspectService` expoe variaveis de ambiente em texto limpo (incluindo passwords e tokens). Nunca incluir output bruto de `inspectService` em reports — sanitizar sempre.
|
||||
|
||||
---
|
||||
|
||||
## MCPs necessarios
|
||||
@@ -278,4 +333,16 @@ curl -s "http://localhost:3000/api/trpc/projects.listProjectsAndServices" \
|
||||
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 12-03-2026 | Descomplicar(r)*
|
||||
*Skill v1.1.0 | 24-03-2026 | Descomplicar(r) | Fix: estrutura real monitor.getSystemStats (nested memInfo/cpuInfo/diskInfo)*
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -134,8 +134,8 @@ git push origin main
|
||||
# Obter token
|
||||
TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
|
||||
# Trigger redeploy via API
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.redeployService" \
|
||||
# Trigger deploy via API (redeployService NAO existe, usar deployService)
|
||||
curl -s -X POST "http://localhost:3000/api/trpc/services.app.deployService" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"json":{"projectName":"PROJECT","serviceName":"SERVICE"}}'
|
||||
@@ -378,12 +378,13 @@ Quando `/easypanel-deploy` detecta falha, chama automaticamente:
|
||||
|
||||
Ver skill `/easypanel-api` para documentação completa.
|
||||
|
||||
| Acção | Endpoint |
|
||||
|-------|----------|
|
||||
| Inspeccionar serviço | `GET services.app.inspectService` |
|
||||
| Redeploy | `POST services.app.redeployService` |
|
||||
| Obter logs | `GET services.app.getServiceLogs` |
|
||||
| Estado serviço | `GET services.app.inspectService` |
|
||||
| Acção | Endpoint | Verificado |
|
||||
|-------|----------|:----------:|
|
||||
| Inspeccionar serviço | `GET services.app.inspectService` | Sim |
|
||||
| Deploy (redeploy) | `POST services.app.deployService` | Sim |
|
||||
| Obter logs | `GET logs.getServiceLogs` | Sim |
|
||||
|
||||
**Endpoints que NAO existem:** `redeployService`, `getServiceLogs` (logs estao em `logs.*`, nao `services.app.*`).
|
||||
|
||||
## MCPs Necessários
|
||||
|
||||
@@ -455,9 +456,14 @@ Status: 4 (Em progresso) → 5 (Concluído)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Quando NÃO Usar
|
||||
## Healing Log
|
||||
|
||||
- Para tarefas fora do domínio de especialização desta skill
|
||||
- Quando outra skill mais específica está disponível
|
||||
- Para operações que requerem confirmação manual do utilizador
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -51,8 +51,8 @@ TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=$(echo -n '{"json":{"projectName":"PROJECT","serviceName":"SERVICE"}}' | jq -sRr @uri)" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.result.data.json'
|
||||
|
||||
# Obter logs via API
|
||||
curl -s "http://localhost:3000/api/trpc/services.app.getServiceLogs?input=$(echo -n '{"json":{"projectName":"PROJECT","serviceName":"SERVICE","lines":100}}' | jq -sRr @uri)" \
|
||||
# Obter logs via API (namespace logs.*, NAO services.app.*)
|
||||
curl -s "http://localhost:3000/api/trpc/logs.getServiceLogs?input=$(echo -n '{"json":{"projectName":"PROJECT","serviceName":"SERVICE","tail":100}}' | jq -sRr @uri)" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
@@ -203,12 +203,15 @@ CPU: X%
|
||||
|
||||
Ver skill `/easypanel-api` para documentação completa.
|
||||
|
||||
| Acção | Endpoint |
|
||||
|-------|----------|
|
||||
| Estado serviço | `GET services.app.inspectService` |
|
||||
| Logs serviço | `GET services.app.getServiceLogs` |
|
||||
| Listar projectos | `GET projects.listProjects` |
|
||||
| Estatísticas monitor | `GET monitor.getStats` |
|
||||
| Acção | Endpoint | Verificado |
|
||||
|-------|----------|:----------:|
|
||||
| Estado serviço | `GET services.app.inspectService` | Sim |
|
||||
| Logs serviço | `GET logs.getServiceLogs` | Sim |
|
||||
| Listar projectos | `GET projects.listProjects` | Sim |
|
||||
| Stats sistema | `GET monitor.getSystemStats` | Sim |
|
||||
| Stats Docker | `GET monitor.getDockerTaskStats` | Sim |
|
||||
|
||||
**Endpoints que NAO existem:** `services.app.getServiceLogs` (usar `logs.getServiceLogs`), `monitor.getStats` (usar `monitor.getSystemStats`).
|
||||
|
||||
## MCPs Necessários
|
||||
|
||||
@@ -278,4 +281,15 @@ Status: 4 (Em progresso) → 5 (Concluído)
|
||||
|
||||
---
|
||||
|
||||
**/** @author Descomplicar® | @link descomplicar.pt | @copyright 2026 **/
|
||||
**/** @author Descomplicar® | @link descomplicar.pt | @copyright 2026 **/
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -165,8 +165,8 @@ TOKEN=$(cat /etc/easypanel/.api-token)
|
||||
curl -s "http://localhost:3000/api/trpc/services.app.inspectService?input=$(echo -n '{"json":{"projectName":"PROJECT","serviceName":"SERVICE"}}' | jq -sRr @uri)" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.result.data.json'
|
||||
|
||||
# Verificar estatísticas de recursos
|
||||
curl -s "http://localhost:3000/api/trpc/monitor.getStats" \
|
||||
# Verificar estatisticas de recursos
|
||||
curl -s "http://localhost:3000/api/trpc/monitor.getSystemStats" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
@@ -262,12 +262,14 @@ Uso em CI/CD:
|
||||
|
||||
Ver skill `/easypanel-api` para documentação completa.
|
||||
|
||||
| Acção | Endpoint |
|
||||
|-------|----------|
|
||||
| Inspeccionar serviço | `GET services.app.inspectService` |
|
||||
| Estatísticas monitor | `GET monitor.getStats` |
|
||||
| Listar projectos | `GET projects.listProjects` |
|
||||
| Estado do sistema | `GET settings.getSystemInfo` |
|
||||
| Acção | Endpoint | Verificado |
|
||||
|-------|----------|:----------:|
|
||||
| Inspeccionar serviço | `GET services.app.inspectService` | Sim |
|
||||
| Stats sistema | `GET monitor.getSystemStats` | Sim |
|
||||
| Listar projectos | `GET projects.listProjects` | Sim |
|
||||
| IP servidor | `GET settings.getServerIp` | Sim |
|
||||
|
||||
**Endpoints que NAO existem:** `monitor.getStats` (usar `monitor.getSystemStats`), `settings.getSystemInfo` (usar `settings.getServerIp`).
|
||||
|
||||
## Tools Necessários
|
||||
|
||||
@@ -338,18 +340,14 @@ Status: 4 (Em progresso) → 5 (Concluído)
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Quando NÃO Usar
|
||||
## Healing Log
|
||||
|
||||
- Para tarefas fora do domínio de especialização desta skill
|
||||
- Quando outra skill mais específica está disponível
|
||||
- Para operações que requerem confirmação manual do utilizador
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
## Protocolo
|
||||
|
||||
1. Analisar requisitos da tarefa
|
||||
2. Verificar disponibilidade de ferramentas necessárias
|
||||
3. Executar operações de forma incremental
|
||||
4. Validar resultados antes de concluir
|
||||
5. Reportar status e próximos passos
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -1,220 +1,221 @@
|
||||
---
|
||||
name: gateway-check
|
||||
description: Health check rapido dos MCPs no gateway.descomplicar.pt — estado services (systemd+pm2), portas, memoria/CPU, erros recentes. Output tabela resumo.
|
||||
description: Gestao completa dos MCPs no gateway.descomplicar.pt — health check, restart, troubleshoot, mapa de portas, adicionar MCPs. Usar quando MCP falha, health check, ou gestao gateway.
|
||||
context: fork
|
||||
---
|
||||
|
||||
# /gateway-check v1.0
|
||||
# /gateway-check v2.0
|
||||
|
||||
Health check rapido dos MCPs no servidor gateway (mcp-hub.descomplicar.pt).
|
||||
Gestao e health check dos MCPs no servidor gateway (VM 103, gateway.descomplicar.pt).
|
||||
|
||||
**Referencia:** PROC-MCP-Desenvolvimento.md | Memory: `mcp-gateway.md`, `infra.md`
|
||||
**Referencia:** Memory `mcp-gateway.md` | PROC-MCP-Desenvolvimento.md
|
||||
|
||||
---
|
||||
|
||||
## Inventario MCPs Gateway
|
||||
## Acesso
|
||||
|
||||
- **VM:** 103 no Proxmox (QEMU)
|
||||
- **IP:** 5.9.90.69
|
||||
- **SSH:** `mcp__ssh-unified__ssh_execute(server="gateway")`
|
||||
- **HTTPS:** `https://gateway.descomplicar.pt/v1/<nome>/mcp`
|
||||
- **Nginx whitelist:** 188.251.199.30 (IP fixo NOS). Se 403 -> verificar IP com `curl -4 ifconfig.me`
|
||||
- **Nginx config:** `/etc/nginx/sites-enabled/` no gateway
|
||||
- **NAO confundir com:** server (VM 100, 5.9.90.105), easy (VM 101, 5.9.90.70), dev (LXC 102)
|
||||
|
||||
---
|
||||
|
||||
## Mapa de MCPs (30 services — actualizado 28-03-2026)
|
||||
|
||||
### pm2 (Node.js — /opt/mcp-gateway/)
|
||||
|
||||
| pm2 ID | Nome | Porta | Prioridade |
|
||||
|--------|------|-------|------------|
|
||||
| 0 | mcp-desk-crm | 3150 | P1 |
|
||||
| 1 | mcp-memory | 3151 | P2 |
|
||||
| 2 | mcp-wikijs | 3152 | P3 |
|
||||
| 4 | mcp-moloni | 3158 | P2 |
|
||||
| pm2 ID | Nome | Porta | nginx path | Prioridade |
|
||||
|--------|------|-------|------------|------------|
|
||||
| 0 | mcp-desk-crm | 3150 | /v1/desk-crm/mcp | P1 |
|
||||
| 1 | mcp-memory | 3151 | /v1/memory/mcp | P1 |
|
||||
| 2 | mcp-wikijs | 3152 | /v1/wikijs/mcp | P3 |
|
||||
| 5 | mcp-moloni | 3158 | /v1/moloni/mcp | P2 |
|
||||
| 6 | mcp-youtube-research | 3157 | /v1/youtube-research/mcp | P3 |
|
||||
| 7 | mcp-youtube | 3187 | /v1/youtube/mcp | P3 |
|
||||
|
||||
### systemd (24 services)
|
||||
|
||||
| Service | Porta | Tipo | Prioridade |
|
||||
|---------|-------|------|------------|
|
||||
| mcp-time | 3163 | Node | P1 |
|
||||
| google-workspace-mcp | 3164 | Python/FastMCP | P1 |
|
||||
| n8n-mcp | 3157 | Node | P2 |
|
||||
| gitea-mcp | 3162 | Go | P2 |
|
||||
| gsc-mcp | 3153 | Python/FastMCP | P2 |
|
||||
| google-analytics-mcp | 3156 | Python/FastMCP | P2 |
|
||||
| imap-enterprise | 3155 | Node | P2 |
|
||||
| context7-mcp | 3159 | Node | P3 |
|
||||
| cwp-mcp | 3183 | Node/supergateway | P3 |
|
||||
| cloudflare-dns-mcp | 3171 | Node/supergateway | P3 |
|
||||
| mcp-youtube | 3187 | Python/FastMCP | P3 |
|
||||
| youtube-research | 3184 | Node | P3 |
|
||||
| magic-mcp | 3172 | Node/supergateway | P3 |
|
||||
| mcp-echarts-mcp | 3173 | Node/supergateway | P3 |
|
||||
| mcp-mermaid-mcp | 3174 | Node/supergateway | P3 |
|
||||
| metabase-mcp | 3175 | Node/supergateway | P3 |
|
||||
| pixabay-mcp | 3176 | Node/supergateway | P3 |
|
||||
| replicate-mcp | 3177 | Node/supergateway | P3 |
|
||||
| outline-api-mcp | 3178 | Node/supergateway | P3 |
|
||||
| pexels-mcp | 3179 | Node/supergateway | P3 |
|
||||
| penpot-mcp | 3180 | Node/supergateway | P3 |
|
||||
| vimeo-mcp | 3181 | Node/supergateway | P3 |
|
||||
| presenton-mcp | 3182 | Node/supergateway | P3 |
|
||||
| mcp-reonic | 3160 | Node | P3 |
|
||||
| Service | Porta | nginx path | Tipo | Prioridade |
|
||||
|---------|-------|------------|------|------------|
|
||||
| google-workspace-mcp | 3164 | /v1/google-workspace/mcp | Python/FastMCP | P1 |
|
||||
| mcp-time | 3163 | /v1/mcp-time/mcp | Node | P1 |
|
||||
| imap-enterprise | 3160 | /v1/imap/mcp | Node | P2 |
|
||||
| gitea-mcp | 3162 | /v1/gitea/mcp | Go | P2 |
|
||||
| n8n-mcp | 3161 | /v1/n8n/mcp | Node | P2 |
|
||||
| gsc-mcp | 3153 | /v1/gsc/mcp | Python/FastMCP | P2 |
|
||||
| google-analytics-mcp | 3156 | /v1/google-analytics/mcp | Python/FastMCP | P2 |
|
||||
| context7-mcp | 3159 | /v1/context7/mcp | Node | P2 |
|
||||
| mcp-reonic | 3170 | /v1/reonic/mcp | Node | P3 |
|
||||
| cloudflare-dns-mcp | 3171 | /v1/cloudflare-dns/mcp | supergateway | P3 |
|
||||
| magic-mcp | 3172 | /v1/magic/mcp | supergateway | P3 |
|
||||
| mcp-echarts-mcp | 3173 | /v1/mcp-echarts/mcp | supergateway | P3 |
|
||||
| mcp-mermaid-mcp | 3174 | /v1/mcp-mermaid/mcp | supergateway | P3 |
|
||||
| metabase-mcp | 3175 | /v1/metabase/mcp | supergateway | P3 |
|
||||
| pixabay-mcp | 3176 | /v1/pixabay/mcp | supergateway | P3 |
|
||||
| replicate-mcp | 3177 | /v1/replicate/mcp | supergateway | P3 |
|
||||
| outline-api-mcp | 3178 | /v1/outline-api/mcp | supergateway | P3 |
|
||||
| pexels-mcp | 3179 | /v1/pexels/mcp | supergateway | P3 |
|
||||
| penpot-mcp | 3180 | /v1/penpot/mcp | supergateway | P3 |
|
||||
| vimeo-mcp | 3181 | /v1/vimeo/mcp | supergateway | P3 |
|
||||
| presenton-mcp | 3182 | /v1/presenton/mcp | supergateway | P3 |
|
||||
| cwp-mcp | 3183 | /v1/cwp/mcp | supergateway | P3 |
|
||||
| design-engine-mcp | 3184 | /v1/design-engine/mcp | supergateway | P3 |
|
||||
|
||||
**Prioridades:** P1=critico (bloqueia trabalho) | P2=importante (degrada workflow) | P3=util
|
||||
**Proxima porta livre:** 3188
|
||||
|
||||
---
|
||||
|
||||
## Protocolo de Execucao
|
||||
## Protocolo de Health Check
|
||||
|
||||
### 1. Estado dos services
|
||||
Executar via `mcp__ssh-unified__ssh_execute(server="gateway")` em 2 chamadas:
|
||||
|
||||
```bash
|
||||
# Executar via mcp__ssh-unified__ssh_execute(server="gateway")
|
||||
### Chamada 1 — estado geral
|
||||
|
||||
# pm2
|
||||
pm2 jlist 2>/dev/null | python3 -c "
|
||||
import sys,json
|
||||
for p in json.load(sys.stdin):
|
||||
print(f\"{p['name']:20s} {p['pm2_env']['status']:10s} cpu={p['monit']['cpu']}% mem={p['monit']['memory']//1024//1024}MB restarts={p['pm2_env']['restart_time']} uptime={round(($(date +%s)*1000-p['pm2_env']['pm_uptime'])/3600000,1)}h\")
|
||||
"
|
||||
|
||||
# systemd — estado + memoria
|
||||
systemctl list-units --type=service --state=running,failed --no-pager | grep -i mcp
|
||||
systemctl list-units --type=service --state=failed --no-pager | grep -i mcp
|
||||
```
|
||||
|
||||
### 2. Verificar portas activas
|
||||
|
||||
```bash
|
||||
# Confirmar que todas as portas esperadas estao a escutar
|
||||
for port in 3150 3151 3152 3153 3155 3156 3157 3158 3159 3160 3162 3163 3164 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3187; do
|
||||
if ss -tln | grep -q ":${port} "; then
|
||||
echo "OK :${port}"
|
||||
else
|
||||
echo "DOWN :${port}"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
### 3. Memoria e CPU por MCP
|
||||
|
||||
```bash
|
||||
# Top consumers de memoria
|
||||
ps aux --sort=-%mem | head -20 | grep -E 'node|python|supergateway|mcp'
|
||||
|
||||
# Memoria total MCPs
|
||||
ps aux | grep -E 'mcp|supergateway' | awk '{sum+=$6} END {printf "Total MCP RAM: %.0f MB\n", sum/1024}'
|
||||
|
||||
# Load do servidor
|
||||
uptime
|
||||
free -h
|
||||
```
|
||||
|
||||
### 4. Erros recentes (ultimos 30min)
|
||||
|
||||
```bash
|
||||
# pm2 logs com erros
|
||||
pm2 logs --err --lines 5 --nostream 2>/dev/null
|
||||
|
||||
# systemd services com erros recentes
|
||||
for svc in $(systemctl list-units --type=service --state=running | grep -i mcp | awk '{print $1}'); do
|
||||
errs=$(journalctl -u $svc --since "30 min ago" -p err --no-pager -q 2>/dev/null | wc -l)
|
||||
if [ "$errs" -gt 0 ]; then
|
||||
echo "=== $svc ($errs erros) ==="
|
||||
journalctl -u $svc --since "30 min ago" -p err --no-pager -q 2>/dev/null | tail -3
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
### 5. Gateway nginx health
|
||||
|
||||
```bash
|
||||
# Verificar nginx activo
|
||||
systemctl is-active nginx
|
||||
|
||||
# Testar endpoint health (se existir)
|
||||
curl -s -o /dev/null -w "%{http_code}" http://localhost/health 2>/dev/null || echo "no-health-endpoint"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Execucao Pratica
|
||||
|
||||
Executar os 5 passos via `mcp__ssh-unified__ssh_execute(server="gateway")`. Agrupar comandos para minimizar chamadas SSH (maximo 2-3 chamadas).
|
||||
|
||||
**Chamada 1 — estado geral:**
|
||||
```bash
|
||||
echo "=== PM2 ===" && pm2 list 2>/dev/null && echo "=== SYSTEMD ===" && systemctl list-units --type=service --state=running --no-pager | grep -i mcp && echo "=== FAILED ===" && systemctl list-units --type=service --state=failed --no-pager | grep -i mcp && echo "=== LOAD ===" && uptime && free -h
|
||||
```
|
||||
|
||||
**Chamada 2 — portas + memoria + erros:**
|
||||
### Chamada 2 — portas + erros
|
||||
|
||||
```bash
|
||||
echo "=== PORTAS ===" && for port in 3150 3151 3152 3153 3155 3156 3157 3158 3159 3160 3162 3163 3164 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3187; do if ss -tln | grep -q ":${port} "; then echo "OK :${port}"; else echo "DOWN :${port}"; fi; done && echo "=== RAM MCPs ===" && ps aux | grep -E 'mcp|supergateway' | grep -v grep | awk '{sum+=$6} END {printf "Total: %.0f MB\n", sum/1024}' && echo "=== PM2 ERROS ===" && pm2 logs --err --lines 3 --nostream 2>/dev/null && echo "=== SYSTEMD ERROS (30min) ===" && for svc in $(systemctl list-units --type=service --state=running | grep -i mcp | awk '{print $1}'); do errs=$(journalctl -u $svc --since "30 min ago" -p err --no-pager -q 2>/dev/null | wc -l); if [ "$errs" -gt 0 ]; then echo "--- $svc ($errs erros) ---"; journalctl -u $svc --since "30 min ago" -p err --no-pager -q 2>/dev/null | tail -2; fi; done
|
||||
echo "=== PORTAS ===" && for port in 3150 3151 3152 3153 3156 3157 3158 3159 3160 3161 3162 3163 3164 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3187; do if ss -tln | grep -q ":${port} "; then echo "OK :${port}"; else echo "DOWN :${port}"; fi; done && echo "=== RAM MCPs ===" && ps aux | grep -E 'mcp|supergateway' | grep -v grep | awk '{sum+=$6} END {printf "Total: %.0f MB\n", sum/1024}' && echo "=== ERROS (30min) ===" && for svc in $(systemctl list-units --type=service --state=running | grep -i mcp | awk '{print $1}'); do errs=$(journalctl -u $svc --since "30 min ago" -p err --no-pager -q 2>/dev/null | wc -l); if [ "$errs" -gt 0 ]; then echo "--- $svc ($errs) ---"; journalctl -u $svc --since "30 min ago" -p err --no-pager -q 2>/dev/null | tail -2; fi; done && echo "=== PM2 ERROS ===" && pm2 logs --err --lines 3 --nostream 2>/dev/null
|
||||
```
|
||||
|
||||
### Output esperado
|
||||
|
||||
Apresentar como tabela resumo com data via mcp-time:
|
||||
|
||||
```
|
||||
## Gateway Health — [data]
|
||||
Servidor: gateway.descomplicar.pt | Load: X.XX | RAM: X.XG/XG | MCPs RAM: XXXMB
|
||||
X/30 operacionais | Alertas: N
|
||||
```
|
||||
|
||||
**Criterios:** OK=running+porta escuta | WARN=running com erros ou >5 restarts | DOWN=parado ou porta fechada
|
||||
|
||||
---
|
||||
|
||||
## Operacoes
|
||||
|
||||
### Restart de um MCP
|
||||
|
||||
```bash
|
||||
# pm2
|
||||
pm2 restart <nome>
|
||||
|
||||
# systemd
|
||||
systemctl restart <nome>.service
|
||||
```
|
||||
|
||||
### Ver logs de um MCP
|
||||
|
||||
```bash
|
||||
# pm2
|
||||
pm2 logs <nome> --lines 30 --nostream
|
||||
|
||||
# systemd
|
||||
journalctl -u <nome>.service --since "1h ago" --no-pager | tail -30
|
||||
```
|
||||
|
||||
### Testar endpoint especifico
|
||||
|
||||
```bash
|
||||
# Internamente no gateway
|
||||
curl -s http://127.0.0.1:<porta>/mcp -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json, text/event-stream" \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}'
|
||||
|
||||
# Externamente
|
||||
curl -s https://gateway.descomplicar.pt/v1/<nome>/mcp -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json, text/event-stream" \
|
||||
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
## Troubleshooting
|
||||
|
||||
Apresentar resultado como tabela resumo:
|
||||
### MCP DOWN
|
||||
|
||||
```markdown
|
||||
## Gateway Health Check — [data via mcp-time]
|
||||
1. Verificar service: `systemctl status <nome>` ou `pm2 show <nome>`
|
||||
2. Ver logs: `journalctl -u <nome> --since "1h ago" --no-pager | tail -30`
|
||||
3. Se supergateway: verificar preload `catch-errors.mjs` (ver abaixo)
|
||||
4. Tentar restart: `systemctl restart <nome>`
|
||||
5. Re-verificar porta: `ss -tln | grep :<porta>`
|
||||
|
||||
**Servidor:** mcp-hub.descomplicar.pt | **Load:** X.XX | **RAM:** X.XG/XG | **MCPs RAM:** XXXMB
|
||||
### Supergateway crash (bug conhecido)
|
||||
|
||||
### Estado MCPs (X/28 operacionais)
|
||||
- **Erro:** `No connection established for request ID: 0`
|
||||
- **Fix:** preload script em `/opt/mcp-gateway/supergateway-catch-errors.mjs`
|
||||
- **Activacao:** `Environment="NODE_OPTIONS=--import /opt/mcp-gateway/supergateway-catch-errors.mjs"` no unit file
|
||||
- **15 services patchados:** todos os supergateway na tabela acima
|
||||
- **Ao adicionar novo supergateway:** OBRIGATORIO adicionar esta linha ao unit file
|
||||
|
||||
| # | MCP | Porta | Gestor | Estado | RAM | Notas |
|
||||
|---|-----|-------|--------|--------|-----|-------|
|
||||
| 1 | mcp-desk-crm | 3150 | pm2 | OK/DOWN/WARN | XXmb | restarts, erros |
|
||||
| ... | ... | ... | ... | ... | ... | ... |
|
||||
### FastMCP Python + nginx (DNS rebinding)
|
||||
|
||||
### Alertas
|
||||
- [P1] MCP X esta DOWN — accao sugerida
|
||||
- [WARN] MCP Y tem N restarts nas ultimas Xh
|
||||
- [WARN] RAM total MCPs > 2GB (limite recomendado)
|
||||
|
||||
### Erros Recentes
|
||||
[lista de erros se existirem, agrupados por MCP]
|
||||
FastMCP 1.26+ bloqueia Host headers externos. No nginx:
|
||||
```nginx
|
||||
proxy_set_header Host "127.0.0.1:<PORTA>"; # CORRECTO
|
||||
# proxy_set_header Host $host; # ERRADO — FastMCP bloqueia
|
||||
```
|
||||
**Detectar:** Se MCP retorna `Invalid Host header` via HTTPS mas funciona em `curl localhost` -> e este problema.
|
||||
|
||||
**Criterios de estado:**
|
||||
- **OK** — service running + porta a escutar + sem erros recentes
|
||||
- **WARN** — running mas com erros recentes OU >5 restarts OU memoria >250MB
|
||||
- **DOWN** — service parado OU porta nao escuta
|
||||
### 403 Forbidden
|
||||
|
||||
IP nao esta na whitelist nginx. Verificar: `curl -4 ifconfig.me`
|
||||
IP autorizado: `188.251.199.30`. Actualizar em `/etc/nginx/sites-enabled/` se mudou.
|
||||
|
||||
### RAM total > 2GB
|
||||
|
||||
1. Identificar top consumers: `ps aux --sort=-%mem | head -20 | grep -E 'node|python|supergateway'`
|
||||
2. Processos orphan: `ps aux | grep -c supergateway`
|
||||
3. Se orphans > 24: `pkill -f supergateway` e restart escalonado
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Automatico
|
||||
## Adicionar novo MCP ao gateway
|
||||
|
||||
```
|
||||
Se MCP DOWN:
|
||||
1. Verificar service: systemctl status <nome>
|
||||
2. Ver logs: journalctl -u <nome> --since "1h ago" --no-pager | tail -20
|
||||
3. Se supergateway: verificar preload catch-errors.mjs (mcp-gateway.md)
|
||||
4. Tentar restart: systemctl restart <nome>
|
||||
5. Re-verificar porta
|
||||
|
||||
Se RAM total > 2GB:
|
||||
1. Identificar top consumers
|
||||
2. Verificar processos orphan: ps aux | grep -c supergateway
|
||||
3. Se orphans > 28: limpar com pkill e restart escalonado (infra.md)
|
||||
|
||||
Se muitos restarts pm2:
|
||||
1. pm2 logs <nome> --err --lines 20
|
||||
2. Verificar se e o bug conhecido do supergateway (mcp-gateway.md)
|
||||
```
|
||||
1. Instalar em `/opt/mcp-gateway/<nome>/` (Node) ou `/opt/mcp-<nome>/` (Python)
|
||||
2. Porta: proxima livre (actualmente **3188**)
|
||||
3. Criar unit file systemd (se supergateway: incluir preload catch-errors)
|
||||
4. Criar bloco nginx (se FastMCP Python: Host header fix obrigatorio)
|
||||
5. `systemctl daemon-reload && systemctl enable --now <nome>.service`
|
||||
6. `nginx -t && systemctl reload nginx`
|
||||
7. Testar internamente e externamente (ver comandos curl acima)
|
||||
8. Adicionar a `~/.claude.json`: `{"type":"http","url":"https://gateway.descomplicar.pt/v1/<nome>/mcp"}`
|
||||
9. Actualizar esta skill (mapa de portas + proxima porta livre)
|
||||
10. Actualizar memory `mcp-gateway.md`
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- **Nunca** fazer restart massivo sem verificar primeiro (pode causar downtime)
|
||||
- **Nunca** restart massivo sem verificar primeiro
|
||||
- **Nunca** ignorar MCP P1 em estado DOWN
|
||||
- **Sempre** reportar estado mesmo que tudo esteja OK (confirma que o check correu)
|
||||
- **Sempre** incluir timestamp via mcp-time no output
|
||||
- **Nunca** confundir gateway (VM 103) com dev/server/easy
|
||||
- **Sempre** reportar estado mesmo que tudo OK
|
||||
- **Sempre** testar endpoint apos restart
|
||||
- **Sempre** actualizar mapa de portas ao adicionar/remover MCPs
|
||||
|
||||
---
|
||||
|
||||
## Integracao
|
||||
|
||||
- **/today** pode invocar `/gateway-check` como parte do checkup diario
|
||||
- **/infra-check** faz verificacao mais ampla (inclui despesas); `/gateway-check` e focado apenas nos MCPs gateway
|
||||
- Resultado pode ser publicado na discussao #31 (Logs) do projecto #65
|
||||
*Skill v2.0.0 | 28-03-2026 | Descomplicar*
|
||||
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 12-03-2026 | Descomplicar*
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -162,3 +162,15 @@ Se MCP falha:
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 04-03-2026 | Descomplicar®*
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -274,3 +274,15 @@ npm run eval:ci # build + evaluations (para CI/CD)
|
||||
---
|
||||
|
||||
*Skill v2.0.0 | Descomplicar® | 2026-03-10*
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -137,3 +137,15 @@ Projecto: Cluster Proxmox Descomplicar (#65)
|
||||
Tarefa: Migracao Infraestrutura (#1712)
|
||||
Tags: pbs, backup, retention, deduplication, sync
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -486,3 +486,15 @@ Integrar insights do NotebookLM nas recomendações e decisões.
|
||||
---
|
||||
|
||||
**/** @author Descomplicar® | @copyright 2026 **/
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -172,3 +172,15 @@ ha-manager set vm:ID --state started
|
||||
- **NotebookLM:** 276ccdde-6b95-42a3-ad96-4e64d64c8d52
|
||||
- **HA Manager Docs:** https://pve.proxmox.com/pve-docs/ha-manager.1.html
|
||||
- **Fencing:** https://pve.proxmox.com/wiki/Fencing
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -149,3 +149,15 @@ systemctl restart sshd
|
||||
---
|
||||
|
||||
Projecto: Cluster Proxmox Descomplicar (#65) | Tarefa: #1712
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -162,3 +162,15 @@ mcp__notebooklm__notebook_query({
|
||||
|----------|----------|
|
||||
| [references/owasp-checklist.md](references/owasp-checklist.md) | OWASP Top 10 detalhado com codigo vulneravel vs seguro e testes |
|
||||
| [references/report-template.md](references/report-template.md) | Template relatorio, GDPR checklist, ferramentas SAST/DAST, hardening checklists |
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -20,7 +20,7 @@ Auditoria de seguranca dos servidores Descomplicar. Verifica SSL, portas, actual
|
||||
|-------|------|----|----|----------|------------|
|
||||
| server | server.descomplicar.pt | 176.9.3.158 | CentOS (CWP) | CSF v15 | acme.sh |
|
||||
| easy | qibspu.easypanel.host | 178.63.18.51 | Ubuntu 24.04 | — | EasyPanel/Traefik |
|
||||
| gateway | mcp-hub.descomplicar.pt | — | — | — | nginx/acme |
|
||||
| gateway | gateway.descomplicar.pt | — | — | — | nginx/acme |
|
||||
|
||||
---
|
||||
|
||||
@@ -318,3 +318,15 @@ Muitos bloqueios CSF (>100/dia):
|
||||
---
|
||||
|
||||
*Skill v1.0.0 | 12-03-2026 | Descomplicar*
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -161,3 +161,15 @@ Inclui:
|
||||
| Ficheiro | Conteudo |
|
||||
|----------|----------|
|
||||
| [references/commands.md](references/commands.md) | Comandos SSH por passo, queries MySQL, quick mode, deep dive, limpeza cache, template output, troubleshooting |
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
@@ -155,3 +155,15 @@ curl -s http://localhost:3000/api/trpc/projects.list | jq > /tmp/easypanel-servi
|
||||
- **NotebookLM:** 276ccdde-6b95-42a3-ad96-4e64d64c8d52
|
||||
- **Guia Hub:** Guia-Definitivo-Proxmox-Hetzner.md (Modulo 4: Workloads)
|
||||
- **Desk CRM:** Projecto #65, Tarefa #1712
|
||||
|
||||
---
|
||||
|
||||
## Healing Log
|
||||
|
||||
Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar.
|
||||
|
||||
```jsonl
|
||||
{"date":"","issue":"","fix":"","source":"user|auto"}
|
||||
```
|
||||
|
||||
*Adicionar nova linha após cada erro corrigido.*
|
||||
|
||||
Reference in New Issue
Block a user