--- name: easypanel-init description: Initialize EasyPanel projects with proper configuration via API oficial. Sets up Node.js, PHP, or static sites on EasyPanel. Use when user mentions "easypanel init", "new easypanel", "setup easypanel", "deploy easypanel", "easypanel setup". author: Descomplicar® Crescimento Digital version: 2.0.0 quality_score: 70 user_invocable: true desk_task: TBD allowed-tools: Task dependencies: - easypanel-api --- # 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 ```bash /easypanel-init [--type nodejs|python|go] [--db postgres|mysql|none] ``` ## Exemplos ```bash # 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) ```dockerfile # 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) ```yaml 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) ```typescript 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) ```yaml 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) ```json { "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 ```markdown # 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 ```bash git init git add . git commit -m "chore: initial project setup via /easypanel-init" ``` ### 4. Criar Projecto no EasyPanel via API ```bash # 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 domínio curl -s -X POST "http://localhost:3000/api/trpc/services.app.saveDomains" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"json":{"projectName":"PROJECT_NAME","serviceName":"app","domains":[{"host":"DOMAIN"}]}}' # Configurar Git source curl -s -X POST "http://localhost:3000/api/trpc/services.app.saveGithubSource" \ -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}}' ``` ### 5. Optional: Push to Gitea ```bash # 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 ``` ### 5. 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: ```yaml 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 | |-------|----------| | 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` | ## Validation Após scaffold, executar automaticamente: ```bash /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 **/ --- ## Quando NÃO Usar - 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