Files
claude-plugins/infraestrutura/skills/easypanel-init/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

11 KiB

name, description, disable-model-invocation
name description disable-model-invocation
easypanel-init Inicialização de projectos EasyPanel com configuração adequada via API oficial — scaffold automático para Node.js, PHP ou sites estáticos. true

EasyPanel Init

Scaffold automático de projectos optimizados para deploy no EasyPanel.

Quando Usar

  • Iniciar novo projecto do zero
  • Converter projecto existente para EasyPanel
  • Setup rápido com best practices
  • Criar estrutura standardizada
  • Prototype rapidamente

Sintaxe

/easypanel-init <project-name> <domain> [--type nodejs|python|go] [--db postgres|mysql|none]

Exemplos

# Node.js API sem database
/easypanel-init dashboard-api dashboard.descomplicar.pt --type nodejs

# Node.js API com PostgreSQL
/easypanel-init crm-api crm.descomplicar.pt --type nodejs --db postgres

# Python API (futuro)
/easypanel-init ml-api ml.descomplicar.pt --type python

# Go API (futuro)
/easypanel-init fast-api api.descomplicar.pt --type go

Workflow Completo

1. Criar Estrutura de Pastas

project-root/
├── src/
│   ├── index.ts (ou main.py, main.go)
│   └── routes/
│       └── health.ts
├── Dockerfile (template multi-stage)
├── docker-compose.yml (Traefik labels)
├── .dockerignore
├── .gitignore
├── .env.example
├── package.json (scripts padronizados)
├── tsconfig.json (se TypeScript)
├── .gitea/
│   └── workflows/
│       └── deploy.yml (CI/CD)
└── README.md (deploy guide)

2. Generate Templates

Dockerfile (Multi-stage Node.js)

# Stage 1: Dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Stage 2: Builder
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 3: Runner
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package*.json ./

RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

USER nodejs

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

CMD ["npm", "start"]

docker-compose.yml (Traefik)

version: '3.8'

services:
  app:
    build: .
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - PORT=3000
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.PROJECTNAME.rule=Host(`DOMAIN`)"
      - "traefik.http.routers.PROJECTNAME.entrypoints=websecure"
      - "traefik.http.routers.PROJECTNAME.tls.certresolver=letsencrypt"
      - "traefik.http.services.PROJECTNAME.loadbalancer.server.port=3000"
      - "traefik.http.services.PROJECTNAME.loadbalancer.healthcheck.path=/health"
      - "traefik.http.services.PROJECTNAME.loadbalancer.healthcheck.interval=10s"

networks:
  traefik:
    external: true

Health Endpoint (Express)

import { Router } from 'express'
import type { Request, Response } from 'express'

const router = Router()

router.get('/health', (req: Request, res: Response) => {
  res.status(200).json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    environment: process.env.NODE_ENV || 'development'
  })
})

export default router

Gitea Workflow (.gitea/workflows/deploy.yml)

name: Deploy to EasyPanel

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '22'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build

      - name: Trigger EasyPanel Deploy
        run: |
          curl -X POST ${{ secrets.EASYPANEL_WEBHOOK_URL }}

package.json (scripts)

{
  "name": "PROJECT_NAME",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "lint": "eslint .",
    "test": "vitest"
  }
}

README.md

# PROJECT_NAME

## Setup Local

1. npm install
2. cp .env.example .env.local
3. npm run dev

## Deploy EasyPanel

1. Push to main: `git push origin main`
2. CI/CD auto-deploy via Gitea Actions
3. Health check: https://DOMAIN/health

## Environment Variables

See `.env.example` for required variables.

## Architecture

- Multi-stage Docker build (80% smaller image)
- Traefik routing with SSL
- Health checks every 10s
- Non-root user for security

3. Initialize Git

git init
git add .
git commit -m "chore: initial project setup via /easypanel-init"

4. Criar Projecto no EasyPanel via API

# Obter token
TOKEN=$(cat /etc/easypanel/.api-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":"PROJECT_NAME"}}'

# Criar serviço app
curl -s -X POST "http://localhost:3000/api/trpc/services.app.createService" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"json":{"projectName":"PROJECT_NAME","serviceName":"app"}}'

# 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":{
    "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 (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",
    "repo":"https://ealmeida:GITEA_TOKEN@git.descomplicar.pt/ealmeida/REPO",
    "ref":"main",
    "path":"/"
  }}'

5. Push to Gitea (opcional)

# Criar repo via MCP Gitea
mcp__gitea__create_repo({
  name: PROJECT_NAME,
  private: false,
  auto_init: false
})

# Add remote and push
git remote add origin git@git.descomplicar.pt:ORG/PROJECT_NAME.git
git push -u origin main

6. Output Summary

✅ Project scaffolded: PROJECT_NAME

📁 Structure created:
   - Dockerfile (multi-stage, 3 layers, ~80MB final image)
   - docker-compose.yml (Traefik configured for DOMAIN)
   - Health endpoint: src/routes/health.ts
   - CI/CD: .gitea/workflows/deploy.yml
   - README.md (deploy guide + troubleshooting)

🔧 Configuration:
   - Domain: DOMAIN
   - Port: 3000
   - Node.js: 22-alpine
   - Health check: GET /health

📦 Next Steps:
   1. cd PROJECT_NAME
   2. npm install
   3. cp .env.example .env.local && edit .env.local
   4. npm run dev (test locally)
   5. git push origin main (trigger deploy)

📚 Documentation:
   - README.md: Quick start
   - Checklist: Use /easypanel-validate before deploy

🚀 EasyPanel Setup:
   1. Create service → Custom (Docker Compose)
   2. Connect repository: git.descomplicar.pt/ORG/PROJECT_NAME
   3. Set environment variables (copy from .env.example)
   4. Create webhook (for CI/CD)
   5. Deploy

⏱️ Estimated setup time: 5min (vs 30min manual)

Database Support (--db)

PostgreSQL

Adiciona ao docker-compose.yml:

services:
  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - traefik

volumes:
  postgres_data:

Adiciona a .env.example:

DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}

MySQL

Similar ao PostgreSQL, usando mysql:8-alpine.

Type Support (--type)

nodejs (default)

  • Node.js 22-alpine
  • TypeScript + ESM
  • tsx para dev
  • Express boilerplate

python (futuro)

  • Python 3.12-alpine
  • FastAPI boilerplate
  • poetry para dependencies
  • uvicorn para server

go (futuro)

  • Go 1.21-alpine
  • Gin ou Echo boilerplate
  • Multi-stage build (builder + runtime)
  • Binário estático

API Endpoints Usados

Ver skill /easypanel-api para documentação completa.

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

Após scaffold, executar automaticamente:

/easypanel-validate

Se score < 9/10, reportar issues.

Templates Base

Usar templates de: /media/ealmeida/Dados/Dev/Docs/EasyPanel-Deploy-Research/

  • TEMPLATE_Dockerfile_NodeJS_MultiStage
  • TEMPLATE_docker-compose.yml
  • TEMPLATE_gitea-workflow-deploy.yml
  • TEMPLATE_health-endpoint.ts

Customização

User pode customizar após scaffold:

  • Port (default 3000)
  • Node version (default 22)
  • Package manager (npm, pnpm, yarn)
  • Framework (Express, Fastify, Koa)

Checklist Execução

  • Verificar nome projecto válido (lowercase, no spaces)
  • Verificar domain válido (DNS format)
  • Criar estrutura pastas
  • Gerar Dockerfile multi-stage
  • Gerar docker-compose.yml com Traefik labels
  • Criar health endpoint
  • Gerar .dockerignore
  • Gerar .gitignore
  • Gerar .env.example
  • Criar package.json com scripts
  • Gerar tsconfig.json (se TS)
  • Criar CI/CD workflow
  • Gerar README.md
  • Git init
  • Git commit inicial
  • Executar /easypanel-validate
  • Output summary com next steps

Versão: 1.0.0 | Autor: Descomplicar® | Data: 2026-02-04

Metadata (Desk CRM Task #65)

Tarefa: SKL: /easypanel-init - Scaffold EasyPanel Project
Milestone: 294 (Skills Claude Code)
Tags: skill(79), stackworkflow(75), claude-code(81), activo(116)
Responsáveis: Emanuel(1), AikTop(25)
Status: 4 (Em progresso) → 5 (Concluído)

/ @author Descomplicar® | @link descomplicar.pt | @copyright 2026 **/


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.