commit 411c22a2f8837e0d4746b61b60ba66d849e762f9 Author: josedario87 Date: Fri Oct 31 18:41:29 2025 -0600 Initial commit: MeshCentral deployment setup Configuración completa de MeshCentral con: - Integración OIDC con Authentik - Docker Compose para deployment - Gitea Actions workflow para CI/CD - Traefik labels para routing y SSL - Separación de rutas de usuario y agentes diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..786a80a --- /dev/null +++ b/.env.example @@ -0,0 +1,10 @@ +# Configuración de la aplicación +APP_NAME=meshcentral +APP_DOMAIN=mesh.nucleoriofrio.com +MESH_PORT=4430 + +# Configuración de Authentik OIDC +# Obtener estos valores desde Authentik después de crear el Provider +AUTHENTIK_ISSUER=https://authentik.nucleoriofrio.com/application/o/meshcentral/ +AUTHENTIK_CLIENT_ID=your-client-id-here +AUTHENTIK_CLIENT_SECRET=your-client-secret-here diff --git a/.gitea/workflows/build-and-deploy.yml b/.gitea/workflows/build-and-deploy.yml new file mode 100644 index 0000000..0dccd1d --- /dev/null +++ b/.gitea/workflows/build-and-deploy.yml @@ -0,0 +1,111 @@ +name: deploy-meshcentral + +on: + push: + branches: [ main, master ] + +jobs: + deploy: + runs-on: docker + env: + APP_NAME: ${{ vars.APP_NAME }} + APP_DOMAIN: ${{ vars.APP_DOMAIN }} + MESH_PORT: ${{ vars.MESH_PORT }} + # Authentik OIDC configuration + AUTHENTIK_ISSUER: ${{ vars.AUTHENTIK_ISSUER }} + AUTHENTIK_CLIENT_ID: ${{ secrets.AUTHENTIK_CLIENT_ID }} + AUTHENTIK_CLIENT_SECRET: ${{ secrets.AUTHENTIK_CLIENT_SECRET }} + steps: + - uses: actions/checkout@v3 + + - name: Info about deployment + run: | + echo "ℹ️ Deploying MeshCentral" + echo " Domain: ${{ vars.APP_DOMAIN }}" + echo " Container: ${{ vars.APP_NAME }}" + echo " Network: principal" + + - name: Create required directories + run: | + mkdir -p meshcentral-data + mkdir -p meshcentral-files + mkdir -p meshcentral-backup + mkdir -p meshcentral-config + + - name: Generate MeshCentral config.json + run: | + cat > meshcentral-data/config.json <<'EOF' + { + "settings": { + "cert": "${{ vars.APP_DOMAIN }}", + "port": 4430, + "aliasPort": 443, + "redirPort": 0, + "AgentPong": 300, + "TlsOffload": "127.0.0.1", + "SelfUpdate": false, + "AllowFraming": false, + "WebRTC": true, + "ClickOnce": false, + "AllowHighQualityDesktop": true, + "DesktopAspectRatios": "1.33,1.5,1.6,1.7,1.778,2.0" + }, + "domains": { + "": { + "title": "MeshCentral - Nucleo Rio Frio", + "title2": "Remote Management Platform", + "newAccounts": false, + "certUrl": "https://${{ vars.APP_DOMAIN }}:443/", + "geoLocation": true, + "cookieIpCheck": false, + "allowLoginToken": true, + "allowFraming": false, + "authStrategies": { + "authentik": { + "issuer": "${{ vars.AUTHENTIK_ISSUER }}", + "clientid": "${{ secrets.AUTHENTIK_CLIENT_ID }}", + "clientsecret": "${{ secrets.AUTHENTIK_CLIENT_SECRET }}", + "callbackurl": "https://${{ vars.APP_DOMAIN }}/auth-oidc-callback" + } + }, + "passwordRequirements": { + "min": 8, + "max": 128, + "upper": 1, + "lower": 1, + "numeric": 1, + "nonalpha": 1 + }, + "agentInviteCodes": false, + "userNameIsEmail": false + } + } + } + EOF + + - name: Set correct permissions + run: | + chmod -R 755 meshcentral-data + chmod -R 755 meshcentral-files + chmod -R 755 meshcentral-backup + chmod -R 755 meshcentral-config + + - name: Pull latest MeshCentral image + run: docker pull ghcr.io/ylianst/meshcentral:latest + + - name: Clean up existing stack + run: docker compose --project-name $APP_NAME down || true + + - name: Start MeshCentral stack + run: docker compose --project-name $APP_NAME up -d --remove-orphans --wait + + - name: Wait for MeshCentral to be ready + run: | + echo "⏳ Waiting for MeshCentral to start..." + sleep 10 + docker logs ${APP_NAME} + + - name: Deployment complete + run: | + echo "✅ MeshCentral deployed successfully" + echo " Access at: https://${{ vars.APP_DOMAIN }}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fea92f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Environment files +.env + +# MeshCentral data directories (contienen datos sensibles) +meshcentral-data/ +meshcentral-files/ +meshcentral-backup/ +meshcentral-config/ + +# Node modules +node_modules/ + +# Logs +*.log +npm-debug.log* + +# OS files +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Temporary files +*.tmp +*.temp diff --git a/README.md b/README.md new file mode 100644 index 0000000..f79c113 --- /dev/null +++ b/README.md @@ -0,0 +1,191 @@ +# MeshCentral - Nucleo Rio Frio + +Sistema de gestión remota de dispositivos basado en MeshCentral, integrado con Authentik para autenticación SSO. + +## Características + +- ✅ **Acceso remoto completo**: Terminal, RDP, transferencia de archivos +- ✅ **Autenticación SSO**: Integrado con Authentik via OIDC +- ✅ **Multi-tenancy**: Gestión de múltiples clientes/grupos +- ✅ **Deployment automatizado**: CI/CD con Gitea Actions +- ✅ **Seguridad**: Forward Auth de Authentik en rutas de usuario + +## Arquitectura + +``` +Cliente (PC remota) + ↓ +MeshAgent (servicio Windows/Linux) + ↓ +Conexión WSS saliente → mesh.nucleoriofrio.com + ↓ +Traefik (reverse proxy + SSL) + ↓ +MeshCentral (contenedor Docker) +``` + +## Deployment + +### Requisitos previos + +1. **Servidor con Docker** y `docker-compose` +2. **Traefik** configurado con: + - Red `principal` + - Red `traefik-network` + - Middleware `authentik-forward-auth@file` +3. **Authentik** con Provider OIDC configurado + +### Variables de entorno en Gitea + +Configurar en **Settings > Actions > Secrets and Variables**: + +#### Variables (`vars`): +``` +APP_NAME=meshcentral +APP_DOMAIN=mesh.nucleoriofrio.com +MESH_PORT=4430 +AUTHENTIK_ISSUER=https://authentik.nucleoriofrio.com/application/o/meshcentral/ +``` + +#### Secrets (`secrets`): +``` +AUTHENTIK_CLIENT_ID= +AUTHENTIK_CLIENT_SECRET= +``` + +### Configuración de Authentik + +1. **Crear OAuth2/OIDC Provider**: + - Name: `meshcentral-oidc` + - Client Type: `Confidential` + - Redirect URIs: `https://mesh.nucleoriofrio.com/auth-oidc-callback` + - Signing Key: `authentik Self-signed Certificate` + +2. **Crear Application**: + - Name: `MeshCentral` + - Slug: `meshcentral` + - Provider: `meshcentral-oidc` + - Launch URL: `https://mesh.nucleoriofrio.com` + +3. **Obtener credenciales**: + - Client ID: Copiar desde el Provider + - Client Secret: Copiar desde el Provider + +### Deployment automático + +```bash +git push origin main +``` + +Gitea Actions se encargará de: +1. Generar `config.json` con configuración OIDC +2. Crear directorios necesarios +3. Bajar el stack anterior (si existe) +4. Levantar MeshCentral con docker-compose +5. Exponer via Traefik + +### Acceso + +1. **Web UI**: `https://mesh.nucleoriofrio.com` +2. **Primer login**: Usar "Login with Authentik" +3. **Crear grupos de dispositivos**: Organizar por cliente/ubicación + +## Instalación de agentes + +### Windows + +1. Ir a `https://mesh.nucleoriofrio.com` +2. Login con Authentik +3. Click en el grupo de dispositivos +4. Click en "Add Agent" +5. Descargar el instalador Windows +6. Ejecutar en la PC del cliente (requiere admin) + +### Linux + +```bash +wget -O meshagent https://mesh.nucleoriofrio.com/meshagents?id=XXXX +chmod +x meshagent +sudo ./meshagent -install +``` + +## Seguridad + +### Protección con Authentik + +- **Rutas de usuario**: Protegidas con Forward Auth de Authentik +- **Rutas de agentes**: Sin autenticación (los agentes usan certificados propios) + +### Rutas protegidas vs. públicas + +**Protegidas** (requieren login en Authentik): +- `/` - Panel principal +- `/login` - Login (si no se usa OIDC) +- `/admin` - Administración +- Todo lo demás no especificado abajo + +**Públicas** (para agentes): +- `/agent.ashx` - Comunicación de agentes +- `/meshrelay.ashx` - Relay P2P +- `/devicefile.ashx` - Transferencia de archivos +- `/amtactivate` - Activación Intel AMT +- `/meshsettings` - Configuración de agentes +- `/devicepower.ashx` - Control de energía + +## Mantenimiento + +### Ver logs + +```bash +docker logs meshcentral +``` + +### Backup manual + +Los datos importantes están en: +- `./meshcentral-data` - Base de datos y configuración +- `./meshcentral-files` - Archivos compartidos +- `./meshcentral-backup` - Backups automáticos + +### Reiniciar servicio + +```bash +docker compose --project-name meshcentral restart +``` + +### Actualizar + +```bash +git pull origin main +git push origin main # Trigger deployment +``` + +## Troubleshooting + +### Los agentes no se conectan + +1. Verificar que las rutas de agentes no estén bloqueadas por Authentik +2. Revisar prioridad de routers en Traefik (agentes debe ser > 200) +3. Verificar certificados SSL + +### Login OIDC no funciona + +1. Verificar `AUTHENTIK_ISSUER` termina con `/` +2. Verificar Redirect URI en Authentik coincide exactamente +3. Revisar logs: `docker logs meshcentral` + +### No puedo acceder al panel + +1. Verificar Forward Auth de Authentik está configurado +2. Verificar DNS apunta correctamente +3. Verificar certificados SSL de Traefik + +## Documentación oficial + +- [MeshCentral Docs](https://ylianst.github.io/MeshCentral/) +- [MeshCentral GitHub](https://github.com/Ylianst/MeshCentral) +- [Authentik Docs](https://docs.goauthentik.io/) + +## Soporte + +Para problemas o consultas: claudeCode0@nucleoriofrio.com diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dd6f076 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,68 @@ +version: '3.8' + +services: + meshcentral: + image: ghcr.io/ylianst/meshcentral:latest + container_name: ${APP_NAME:-meshcentral} + restart: unless-stopped + ports: + - "${MESH_PORT:-4430}:4430" + volumes: + - ./meshcentral-data:/opt/meshcentral/meshcentral-data + - ./meshcentral-files:/opt/meshcentral/meshcentral-files + - ./meshcentral-backup:/opt/meshcentral/meshcentral-backup + - ./meshcentral-config:/opt/meshcentral/meshcentral-config + environment: + - HOSTNAME=${APP_DOMAIN} + - REVERSE_PROXY=traefik + - REVERSE_PROXY_TLS_PORT=443 + - IFRAME=false + - ALLOWLOGINTOKEN=true + - LOCALSESSIONRECORDING=false + - MINIFY=true + - WEBRTC=true + - CLICKONCE=false + - ALLOWHIGHQUALITYDESKTOP=true + - DESKTOPASPECTRATIOS=1.33,1.5,1.6,1.7,1.778,2.0 + - ALLOWFRAMING=false + - COOKIEENCODING=hex + - SESSIONRECORDINGCHUNKSIZE=1000000 + networks: + - principal + - traefik-network + labels: + - "traefik.enable=true" + - "traefik.docker.network=principal" + + # Service + - "traefik.http.services.${APP_NAME}.loadbalancer.server.port=4430" + - "traefik.http.services.${APP_NAME}.loadbalancer.server.scheme=https" + + # Router principal con Authentik Forward Auth para rutas de usuario + - "traefik.http.routers.${APP_NAME}.rule=Host(`${APP_DOMAIN}`) && !PathPrefix(`/agent.ashx`) && !PathPrefix(`/meshrelay.ashx`) && !PathPrefix(`/devicefile.ashx`) && !PathPrefix(`/amtactivate`) && !PathPrefix(`/meshsettings`) && !PathPrefix(`/devicepower.ashx`)" + - "traefik.http.routers.${APP_NAME}.entrypoints=websecure" + - "traefik.http.routers.${APP_NAME}.tls=true" + - "traefik.http.routers.${APP_NAME}.tls.certresolver=letsencrypt" + - "traefik.http.routers.${APP_NAME}.service=${APP_NAME}" + - "traefik.http.routers.${APP_NAME}.priority=100" + - "traefik.http.routers.${APP_NAME}.middlewares=authentik-forward-auth@file,${APP_NAME}-headers" + + # Router para agentes (sin autenticación) - mayor prioridad + - "traefik.http.routers.${APP_NAME}-agents.rule=Host(`${APP_DOMAIN}`) && (PathPrefix(`/agent.ashx`) || PathPrefix(`/meshrelay.ashx`) || PathPrefix(`/devicefile.ashx`) || PathPrefix(`/amtactivate`) || PathPrefix(`/meshsettings`) || PathPrefix(`/devicepower.ashx`))" + - "traefik.http.routers.${APP_NAME}-agents.entrypoints=websecure" + - "traefik.http.routers.${APP_NAME}-agents.tls=true" + - "traefik.http.routers.${APP_NAME}-agents.tls.certresolver=letsencrypt" + - "traefik.http.routers.${APP_NAME}-agents.service=${APP_NAME}" + - "traefik.http.routers.${APP_NAME}-agents.priority=200" + - "traefik.http.routers.${APP_NAME}-agents.middlewares=${APP_NAME}-headers" + + # Custom headers middleware + - "traefik.http.middlewares.${APP_NAME}-headers.headers.customrequestheaders.X-Forwarded-Proto=https" + - "traefik.http.middlewares.${APP_NAME}-headers.headers.customrequestheaders.X-Forwarded-Host=${APP_DOMAIN}" + - "traefik.http.middlewares.${APP_NAME}-headers.headers.sslredirect=true" + +networks: + principal: + external: true + traefik-network: + external: true