Skip to content

2026/04

VS Code como plataforma de IA: agentes, skills y tools propias

Resumen

VS Code no es solo un editor de código. Con las extensiones de GitHub Copilot y el soporte para agentes, instructions y skills, se convierte en una plataforma de IA personalizable donde puedes crear agentes especializados que actúan según tu dominio técnico, con tools propias (scripts locales o MCP servers) que ejecutan acciones específicas. Útil para automatizar flujos de trabajo, crear asistentes técnicos especializados, o integrar herramientas propias sin escribir extensiones tradicionales.

En la práctica, este enfoque funciona junto a GitHub Copilot Chat: Copilot aporta el motor conversacional y de generación, y VS Code aporta el entorno, los agentes personalizados, las tools y el control de contexto.

¿Qué es el modelo de agentes en VS Code?

VS Code permite definir agentes —programas de IA especializados— mediante archivos de configuración que actúan como puntos de entrada (entry points) o subagentes delegados por otros agentes. Cada agente tiene:

  • Instructions (.instructions.md): Directivas de comportamiento y contexto
  • Skills (.skill.md): Módulos reutilizables de conocimiento dominio-específico
  • Tools: Funciones que el agente puede ejecutar (built-ins de VS Code, scripts locales o MCP servers)
  • Frontmatter YAML: Metadatos de configuración (nombre, descripción, herramientas permitidas)

Diferencia clave:

  • Extensions: requieren código TypeScript, compilación y empaquetado
  • Agents + Tools (scripts locales): agente con execute en tools → llama directamente a cualquier script del repo
  • Agents + Tools (MCP): configuración declarativa + servidor backend independiente en Python/Node/Go

Arquitectura: cómo trabajan juntos

flowchart LR
    USER["Usuario en VS Code"]
    CHAT["Chat de Copilot"]
    ORCHESTRATOR["Agente Orquestador
    (entry point)"]
    WORKER1["Worker Agent 1
    Especialista A"]
    WORKER2["Worker Agent 2
    Especialista B"]
    TOOLS1["MCP Server 1
    Tools: search, read"]
    TOOLS2["MCP Server 2
    Tools: deploy, query"]
    SKILL1["Skill: Azure patterns"]
    SKILL2["Skill: Testing best practices"]

    USER -->|prompt| CHAT
    CHAT -->|delega| ORCHESTRATOR
    ORCHESTRATOR -->|decide| WORKER1
    ORCHESTRATOR -->|decide| WORKER2
    WORKER1 -->|usa| TOOLS1
    WORKER1 -->|consulta| SKILL1
    WORKER2 -->|usa| TOOLS2
    WORKER2 -->|consulta| SKILL2
    TOOLS1 -->|ejecuta| RESULT1["Resultado 1"]
    TOOLS2 -->|ejecuta| RESULT2["Resultado 2"]
    RESULT1 -->|síntesis| CHAT
    RESULT2 -->|síntesis| CHAT

Método práctico para montar tu stack de agentes

Para evitar caos (y prompts gigantes), aplica un método incremental en capas:

  1. Define reglas globales en copilot-instructions.md (estilo, seguridad, límites)
  2. Separa conocimiento reusable en skills (SKILL.md), por dominio
  3. Crea agentes por rol (planner, implementer, reviewer), no por tecnología
  4. Añade tools solo cuando haya fricción real (scripts locales primero; MCP server si necesitas protocolo estándar o server persistente)
  5. Itera con ciclos cortos: prompt → resultado → ajuste de instrucciones/skill

Esto mantiene el sistema simple, testeable y fácil de evolucionar en equipo.

Instructions: directivas de comportamiento

Las instructions definen cómo el agente debe pensar y actuar. Archivo: .instructions.md o .copilot-instructions.md en la raíz del workspace.

# Rol y Contexto
Eres un especialista en seguridad de Azure.
Tu objetivo es auditar configuraciones y proponer hardening.

## Convenciones
- Usa rol "Cloud Security Architect" para análisis técnico
- Siempre valida contra Microsoft Docs (MCP tools)
- Proporciona comandos Bicep/Terraform ejecutables

## Restricciones
- No inventes capacidades de Azure
- Cita documentación oficial en referencias
- Declara limitaciones explícitamente

El agente lee esto y ajusta su comportamiento sin código adicional.

Skills: módulos de conocimiento reutilizable

Los skills son ficheros .skill.md que empaquetan guías, patrones o procedimientos específicos de un dominio.

Estructura típica:

# Skill: Azure Kubernetes Service Production Setup

## Cuándo aplicar
- Crear cluster AKS para workloads críticos
- Keywords: "setup AKS", "production cluster", "deploy on Kubernetes"

## Pasos (checklist)
1. Validar quotas en región
2. Activar Azure Policy
3. Configurar ingress controller
4. Habilitar Azure Monitor con Container Insights
...

## Archivos de referencia
- [aks-best-practices skill](./aks-best-practices/SKILL.md)

Cuando el usuario dice "setup AKS production", el agente detecta automáticamente el skill aplicable y lo carga en contexto.

Agentes: dos modelos de trabajo

1. Agente orquestador (entry point)

Agente que el usuario invoca manualmente. Lee el prompt, decide si delegar a subagentes especializados.

Configuración (.agent.md):

---
name: Cloud Architecture Coordinator
description: Diseña infraestructura multi-cloud con auditoría de seguridad
user-invocable: true
disable-model-invocation: false
tools: ['agent', 'read', 'search']
agents:
  - Azure Security Auditor
  - Terraform Generator
---

Comportamiento: el usuario lanza el agente desde el dropdown de VS Code → el agente analiza el prompt → decide si usar sus propios skills o delegar a workers.

2. Agente worker (subagente)

No aparece en el dropdown. Solo se invoca como subagente desde un coordinador.

---
name: Azure Security Auditor
description: Audita configuración de Azure y sugiere hardening
user-invocable: false
disable-model-invocation: true
tools: ['read', 'search', 'azure_compliance/*']
agents: []
---

El coordinador lo invoca con: runSubagent(agentName: "Azure Security Auditor", prompt: "...")

Tools propias: scripts locales y MCP servers

Las tools de un agente no tienen por qué ser MCP servers. La opción más simple es habilitar execute en el frontmatter del agente y dejar que invoque scripts que ya tienes en el repo.

Opción 1: script local (sin MCP)

Si el agente tiene execute entre sus tools, puede ejecutar cualquier script del workspace directamente:

---
name: Azure Auditor
tools: ['read', 'search', 'execute']
---

Ejemplo de script que el agente invoca:

# scripts/check_azure_costs.sh
#!/usr/bin/env bash
SUBSCRIPTION_ID="$1"
DAYS="${2:-30}"
az costmanagement query \
  --type ActualCost \
  --dataset-aggregation '{"totalCost": {"name": "Cost", "function": "Sum"}}' \
  --timeframe Custom \
  --time-period from="$(date -d "-${DAYS} days" +%Y-%m-%d)" to="$(date +%Y-%m-%d)"

El agente lo llama así en su razonamiento interno:

Ejecuta: bash scripts/check_azure_costs.sh $SUBSCRIPTION_ID 30

Nada de servidores, nada de protocolo: solo un script en bash/Python/PowerShell que ya existe.

Cuándo usar scripts locales:

  • Automatización simple (validar, consultar, transformar datos)
  • El script ya existe en el repo y no necesita ser un servicio
  • Entorno controlado (el agente corre en tu máquina)
  • Prototipado rápido antes de decidir si merece un MCP server

Opción 2: MCP server

Un MCP (Model Context Protocol) server es un programa que expone funciones (tools) disponibles para agentes. Tiene más overhead que un script, pero también más capacidades.

Ejemplo: MCP server Python simple

# mcp_server_example.py
import json
from mcp.server import Server

server = Server("my-tools")

@server.tool()
def get_azure_costs(subscription_id: str, days: int = 30) -> dict:
    """Obtiene costos de Azure de los últimos N días"""
    # Lógica real: llamar a Azure Cost Management API
    return {
        "subscription": subscription_id,
        "period_days": days,
        "estimated_cost": 1234.56,
        "top_services": ["Storage", "Compute", "Networking"]
    }

@server.tool()
def validate_bicep_template(bicep_file: str) -> dict:
    """Valida sintaxis y mejores prácticas de Bicep"""
    # Lógica real: llamar a bicep validate + custom linting
    return {"valid": True, "warnings": []}

if __name__ == "__main__":
    server.run()

Registrar en mcp.json

Archivo en la raíz del workspace: mcp.json

{
  "mcpServers": {
    "my-azure-tools": {
      "command": "python",
      "args": ["mcp_server_example.py"],
      "disabled": false
    }
  }
}

Luego, en el frontmatter del agente:

tools:
  - 'my-azure-tools/*'  # Acceso a todas las tools del servidor

El agente ahora puede llamar get_azure_costs() y validate_bicep_template() directamente en su lógica.

Creación práctica: workflow completo

1. Crear estructura de agentes

.
├── .instructions.md              # Contexto global del workspace
├── mcp.json                      # Registro de MCP servers
├── .agents/
│   ├── coordinator.agent.md      # Agente orquestador
│   ├── worker-1.agent.md         # Worker especialista
│   └── worker-2.agent.md         # Worker especialista
└── .skills/
    ├── azure-best-practices/SKILL.md
    └── terraform-patterns/SKILL.md

2. Definir coordinator

---
name: DevOps Pipeline Architect
description: Diseña pipelines CI/CD, IaC y auditoría completa
user-invocable: true
disable-model-invocation: false
tools: ['agent', 'read', 'search']
agents:
  - Infrastructure Validator
  - Pipeline Generator
---

Tu rol es coordinador. Cuando el usuario pide una arquitectura DevOps:

1. Solicita al worker Infrastructure Validator que audite la configuración actual
2. Solicita al worker Pipeline Generator que cree YAML de GitHub Actions
3. Sintetiza ambos resultados en un plan coherente

3. Crear MCP server con utilidades

mkdir mcp-servers/devops-tools && cd mcp-servers/devops-tools
npm init -y
npm install @modelcontextprotocol/sdk
// index.js
const { Server } = require("@modelcontextprotocol/sdk");

const server = new Server({
  name: "devops-tools",
  version: "1.0.0",
});

server.tool("lint-terraform", {
  description: "Valida código Terraform con tflint",
  inputSchema: { type: "object", properties: { file_path: { type: "string" } } },
  handler: async (args) => {
    // Ejecutar: tflint args.file_path
    return { valid: true, issues: [] };
  },
});

server.tool("estimate-cost-terraform", {
  description: "Estima costo de infraestructura Terraform",
  inputSchema: { type: "object", properties: { tf_directory: { type: "string" } } },
  handler: async (args) => {
    // Ejecutar: terraform plan + infracost
    return { estimated_monthly_cost: 1234.56, breakdown: {} };
  },
});

server.connect(process.stdin, process.stdout);

Registrar en mcp.json:

{
  "mcpServers": {
    "devops-tools": {
      "command": "node",
      "args": ["mcp-servers/devops-tools/index.js"],
      "disabled": false
    }
  }
}

4. Usar en el agente

En el prompt del agente worker:

Usa la tool 'lint-terraform' para validar el archivo ${file_path}
Luego usa 'estimate-cost-terraform' para mostrar costos

El agente ejecuta automáticamente las tools cuando es necesario.

Voice + text-to-speech en VS Code (con Copilot)

VS Code incluye soporte de voz mediante la extensión VS Code Speech y se integra con el chat de Copilot:

  • Dictado en editor: Voice: Start Dictation in Editor
  • Voice chat con Copilot: Chat: Start Voice Chat
  • Text-to-Speech (TTS) de respuestas en chat, activando accessibility.voice.autoSynthesize
  • Ajuste de envío automático por pausa con accessibility.voice.speechTimeout

En resumen: puedes hablarle a Copilot, recibir respuesta en texto y, si quieres, escuchar la respuesta en voz sin salir de VS Code.

Buenas prácticas

  • Granularidad: un agente por especialidad (no un agente que hace todo)
  • Tools pequeñas y puras: cada tool resuelve un problema específico
  • Instructions claras: especifica rol, restricciones y formato de salida esperado
  • Versionado de skills: documenta qué cambios entre versiones
  • Scripts primero, MCP después: implementa la lógica como script ejecutable antes de envolverla en un MCP server. Es más fácil de testear y depurar
  • Testing de MCP servers: prueba las tools localmente antes de registrar en mcp.json
  • Logging: los MCP servers deben escribir logs en stderr para debugging; los scripts a un archivo de log en logs/

Note

Los agentes se ejecutan en tu máquina local (VS Code). No hay datos que suban a servidores Microsoft/OpenAI sin tu consentimiento. Todo es privado.

Warning

El prompt que pasas a un subagente NO incluye el historial de chat completo. Debes incluir todo el contexto necesario en el prompt de delegación. Es autocontenido.

Casos de uso

  • Auditoría de seguridad: agente especializado valida Azure/AWS contra marcos CIS
  • Generación IaC: workers especializados en Terraform, Bicep, CloudFormation
  • Análisis de logs: MCP server que consulta Azure Log Analytics/DataDog
  • Refactoring asistido: skill con patrones de refactoring + tool que aplica cambios automáticas

Referencias

Pi-hole: bloqueador de anuncios y filtro DNS a nivel de red

Resumen

Pi-hole es una solución de DNS-level ad-blocking que funciona como un servidor DNS en tu red local. Intercepta todas las solicitudes DNS de los dispositivos conectados y bloquea dominios clasificados como anuncios, malware o rastreadores, sin necesidad de instalar software en cada dispositivo. Se despliega típicamente en una Raspberry Pi (de ahí el nombre), aunque corre en cualquier Linux, contenedor Docker o VM. Útil para redes caseras, laboratorios, pequeñas oficinas o como infraestructura de seguridad en entornos de desarrollo.

¿Qué es Pi-hole?

Pi-hole es un servidor DNS que actúa como un proxy entre tus dispositivos y el DNS upstream (Google, Cloudflare, etc.). Cuando un dispositivo intenta resolver un dominio, Pi-hole consulta su lista de bloqueo (blocklist) y si el dominio está en ella, devuelve una respuesta NXDOMAIN o una IP local en lugar de permitir la conexión.

Diferencia clave con adblockers de navegador:

  • Los adblockers en el navegador solo filtran en ese navegador
  • Pi-hole funciona a nivel de DNS, bloqueando en toda la red y en todos los dispositivos, incluyendo apps móviles, IoT, etc.

Arquitectura

flowchart LR
    D1["Dispositivo 1
    PC"] --> DNS1["Pi-hole
    DNS Server"]
    D2["Dispositivo 2
    Móvil"] --> DNS1
    D3["Dispositivo 3
    IoT"] --> DNS1
    D4["Dispositivo 4
    TV"] --> DNS1
    DNS1 --> LIST{"Blocklist
    Verificación"}
    LIST -->|Bloqueado| BLOCK["NXDOMAIN
    o 0.0.0.0"]
    LIST -->|Permitido| UP["Upstream DNS
    Google/Cloudflare"]
    UP --> DNS1
    DNS1 --> D1
    DNS1 --> D2
    DNS1 --> D3
    DNS1 --> D4

Configuración en Docker

Para entornos de laboratorio o integración en stack de contenedores:

docker run -d \
  --name pihole \
  --net=host \
  -e TZ="Europe/Madrid" \
  -e WEBPASSWORD="your-password" \
  -e DNS1="1.1.1.1" \
  -e DNS2="1.0.0.1" \
  -p 53:53/tcp -p 53:53/udp \
  -p 80:80 \
  -v pihole_config:/etc/pihole \
  -v pihole_dnsmasq:/etc/dnsmasq.d \
  --restart unless-stopped \
  pihole/pihole:latest

O con docker-compose:

version: '3'
services:
  pihole:
    image: pihole/pihole:latest
    hostname: pihole
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80"
    environment:
      TZ: "Europe/Madrid"
      WEBPASSWORD: "your-secure-password"
      DNS1: "1.1.1.1"
      DNS2: "1.0.0.1"
    volumes:
      - pihole_config:/etc/pihole
      - pihole_dnsmasq:/etc/dnsmasq.d
    restart: unless-stopped

volumes:
  pihole_config:
  pihole_dnsmasq:

Instalación en TrueNAS Scale (Apps)

TrueNAS Scale incluye un catálogo de aplicaciones containerizadas. Pi-hole está disponible en TrueCharts, el repositorio comunitario de apps para TrueNAS.

Pasos para instalar Pi-hole en TrueNAS Scale

1. Agregar el repositorio de TrueCharts

Desde el dashboard de TrueNAS Scale:

Apps → Manage Catalogs → Add Catalog

Name: truecharts
Repository: https://github.com/truecharts/catalog
Branch: main
Preferred Trains: community

Apps → Discover → Buscar "Pi-hole"

Selecciona Pi-hole y haz click en Install.

3. Configuración de Pi-hole

En la pantalla de configuración, ajusta los siguientes parámetros:

Application Configuration:

Campo Valor Descripción
Application Name pihole Nombre del contenedor
Timezone Europe/Madrid Tu zona horaria local
Web Password •••••• Contraseña para el dashboard web (mínimo 8 caracteres)
Shared Memory Size 64 Tamaño de memoria compartida en MiB
4. Configuración de red

Network Configuration:

Parámetro Valor Propósito
WebUI Port 20720 Puerto alternativo para acceso web (evita conflictos con puerto 80)
Port Bind Mode Publish port on the host Permite acceso desde otros dispositivos
HTTPS Port 30132 Puerto HTTPS del dashboard
DNS Port 53 Puerto DNS (estándar)
DNS Bind Mode Publish port on the host Hace disponible DNS en toda la red
Host IP (DNS) 192.168.xx.xx IP del TrueNAS donde responde DNS

Note

El puerto DNS (53) debe estar disponible en la red. Si otro servicio lo usa, cámbialo a uno > 1024 (ej: 5353), pero entonces los clientes necesitan configurar ese puerto específicamente.

5. Configuración de almacenamiento

Storage Configuration:

Volumen Tipo Descripción
Pi-Hole Config ixVolume Dataset automático para /etc/pihole
Pi-Hole DNSMASQ Config ixVolume Dataset automático para /etc/dnsmasq.d

Activa Enable ACL en ambos para permisos adecuados.

6. Configuración de recursos

Resources Configuration:

Recurso Valor Nota
CPUs 2 Suficiente para resolver ~5k consultas/min
Memory 4096 MB (4 GB) Mínimo para cache DNS decente

Warning

No asignes todos los cores del servidor. Deja al menos 2 cores libres para TrueNAS. Monitorea uso real con Apps → Installed Applications → Pi-hole → Resources.

7. Desplegar

Haz click en Install. TrueNAS crea el contenedor, lo inicia y gestiona automáticamente su ciclo de vida.

8. Acceder al dashboard

Una vez desplegado (estado "Running"), accede a:

http://<IP-truenas>:20720/admin

O si usaste puerto 80:

http://<IP-truenas>/admin

Contraseña: la que configuraste en Web Password.

Ventajas de instalación en TrueNAS Scale

  • Almacenamiento integrado: Los datos de Pi-hole se guardan en datasets ZFS con snapshots automáticos
  • Aislamiento: Corre en contenedor sin afectar al OS de TrueNAS
  • Gestión centralizada: Actualización, reinicio y logs desde el dashboard de TrueNAS
  • Persistencia: La configuración se mantiene incluso si TrueNAS se reinicia
  • Fácil respaldo: Snapshot automático del dataset con tank/ix-applications/pihole

Monitoreo en TrueNAS

Desde Apps → Installed Applications → Pi-hole:

Status: Running / Stopped
Resources: CPU, RAM, Network I/O
Logs: Ver stdout/stderr en tiempo real
Actions: Restart, Stop, Shell

Para ver logs en tiempo real:

# Desde Advanced → Shell en TrueNAS
kubectl logs -f -n ix-pihole deployment/pihole

Note

Si usas TrueNAS Core (no Scale), necesitas ejecutar Pi-hole como contenedor Docker independiente o instalarlo directamente en FreeBSD. TrueNAS Core no tiene el catálogo de Apps integrado.

Configurar dispositivos para usar Pi-hole

En el router (opción recomendada)

Configura el DNS primario en tu router WiFi/LAN para que apunte a la IP de Pi-hole. Así todos los dispositivos usan automáticamente Pi-hole como DNS sin configuración individual.

Router → Settings → DHCP → Primary DNS: <IP-de-pihole>

En dispositivos individuales

Si no puedes modificar el router:

Windows:

Settings → Network & Internet → Change adapter options → 
IPv4 Properties → Use these DNS servers: <IP-pihole>

macOS / Linux:

# En /etc/resolv.conf
nameserver <IP-pihole>

iPhone / iPad:

Settings → WiFi → [Tu red] → Configure DNS → Manual
Add DNS Server: <IP-pihole>

Gestionar listas de bloqueo

Dashboard web

Accede a http://<IP-pihole>/admin

En Settings → Adlists:

https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://adaway.org/hosts.txt
https://www.claudedrake.de/amalgamated_hosts.txt

Estas son listas comunitarias verificadas de dominios de anuncios y malware.

Agregar dominios personalizados

En Whitelist / Blacklist:

  • Whitelist: dominios que quieres permitir (útil para desbloquear un sitio bloqueado por error)
  • Blacklist: dominios adicionales que quieres bloquear
# Ejemplo: bloquear un rastreador específico
tracker.example.com
analytics.badcompany.net

Buenas prácticas

  • Backup del dashboard: exporte la configuración regularmente desde Settings → Teleport
  • Monitorización: revisa el panel Query Log periódicamente para detectar patrones anómalos
  • Actualizar listas: agrega listas comunitarias confiables pero no todas a la vez; prueba el impacto en experiencia de usuario
  • HA en pequeña escala: despliega una segunda instancia de Pi-hole como fallback en caso de que la primera no esté disponible

Warning

Algunos servicios legítimos pueden estar bloqueados por listas demasiado agresivas. Si una app o web no funciona correctamente tras instalar Pi-hole, verifica el Query Log para confirmar que el dominio está siendo bloqueado y añádelo a la whitelist.

Note

Pi-hole es software de código abierto. Revisa periódicamente el repositorio GitHub para actualizaciones de seguridad y nuevas blocklists comunitarias.

Casos de uso comunes

  • Red doméstica: reduce publicidad y rastreadores sin adblocks de navegador
  • Laboratorio de seguridad: simula comportamiento de malware analizando qué dominios intenta contactar
  • Red corporativa pequeña: filtrado de contenido inapropiado a nivel de DNS
  • IoT: bloquea conexiones no deseadas de dispositivos smart home

Referencias

TrueNAS: almacenamiento de datos escalable con ZFS

Resumen

TrueNAS es un sistema de almacenamiento en red (NAS) de código abierto basado en ZFS, construido sobre FreeBSD o Linux. Proporciona almacenamiento centralizado, snapshots, replicación, y acceso a datos vía SMB/NFS/iSCSI para pequeñas oficinas, laboratorios y entornos empresariales. Se despliega en hardware propio o virtualizado, y su modelo de gestión es muy intuitivo: desde el dashboard web configuran desde la capacidad de almacenamiento hasta políticas de respaldo y acceso de usuarios.

¿Qué es TrueNAS?

TrueNAS es un appliance de almacenamiento basado en ZFS (filesystem con capacidades avanzadas como snapshots, compresión y deduplicación). Corre sobre un OS Linux (TrueNAS Core/Scale) o FreeBSD (TrueNAS Enterprise) y proporciona:

  • Almacenamiento centralizado: acceso desde múltiples clientes (Windows, macOS, Linux)
  • Snapshots y replicación: backup y DR integrado
  • Gestión de datos: cuotas, compresión, deduplicación
  • Escalabilidad: desde 2 bahías hasta sistemas multi-exabyte
flowchart LR
    C1["Cliente Windows
    SMB"] --> NAS["TrueNAS
    ZFS Storage"]
    C2["Cliente Linux
    NFS"] --> NAS
    C3["Cliente iSCSI
    SAN"] --> NAS
    NAS --> POOL["Storage Pool
    RAID-Z"]
    POOL --> DISK1["Disk 1"]
    POOL --> DISK2["Disk 2"]
    POOL --> DISK3["Disk 3"]
    POOL --> DISK4["Disk 4"]

Variantes de TrueNAS

Variante Base OS Licencia Uso
TrueNAS Core FreeBSD Open Source Laboratorio, hogar, PYME
TrueNAS Scale Linux (Debian) Open Source Entornos modernos, Kubernetes
TrueNAS Enterprise FreeBSD Comercial Empresas con soporte SLA

Instalación en hardware propio

Requisitos mínimos

  • CPU: x86-64 moderno (Intel/AMD)
  • RAM: 8GB mínimo (16GB recomendado)
  • Almacenamiento: 2+ discos SATA/SAS de 2TB+
  • Red: Gigabit Ethernet

Pasos de instalación

  1. Descargar imagen ISO: desde truenas.com/downloads
  2. Crear USB instalable: con Etcher o dd
  3. Bootear desde USB y seguir el instalador
  4. Configurar red: IP estática, gateway, DNS
  5. Acceder al dashboard: https://<IP-truenas>:6000

Configuración inicial: crear un Pool de almacenamiento

Desde el dashboard web:

Storage → Create Pool:

Pool name: tank (nombre convencional)
Disks: Seleccionar mínimo 2 discos
Layout: RAID-Z1 (redundancia 1 disco)
      o RAID-Z2 (redundancia 2 discos para pools grandes)

Esquema de RAID-Z recomendado

Discos Layout Capacidad útil Redundancia
4 RAID-Z1 3 discos 1 fallo
6 RAID-Z2 4 discos 2 fallos
8 RAID-Z3 5 discos 3 fallos

Crear datasets y comparticiones

Dataset (contenedor lógico)

Storage → Datasets → Add Dataset
Name: tank/homes
Encryption: On (recomendado)

Compartición SMB (para Windows/macOS)

Sharing → Windows Shares (SMB) → Add
Dataset: tank/homes
Name: homes
Purpose: Default share
Permissions: Administrador (propietario)

Los usuarios acceden vía \\<IP-truenas>\homes en Windows.

Compartición NFS (para Linux)

Sharing → Unix (NFS) Shares → Add
Dataset: tank/homes
Mapall User: nobody
Path: /mnt/tank/homes

Los clientes Linux montan: mount -t nfs <IP-truenas>:/mnt/tank/homes /mnt/homes

Point-in-time recovery y replicación

Crear recuperación puntual automática (Point-in-time Snapshots)

TrueNAS crea versiones puntuales de los datasets en momentos específicos. Estos NO son backups completos, sino "fotografías" del estado del filesystem que permiten restaurar archivos a un momento anterior si se modifican o se borran accidentalmente.

Tasks → Periodic Snapshot Tasks
Dataset: tank/homes
Schedule: Daily at 2:00 AM
Retention: Keep last 7 days

Replicar a otro TrueNAS (backup remoto)

Para backup verdadero, la replicación copia los datos hacia otra instancia de TrueNAS (o almacenamiento remoto):

Tasks → Replication Tasks
Source Dataset: tank/homes
Target: <IP-otro-truenas>:/mnt/backup/homes
Schedule: Daily after snapshot

Note

Las versiones puntuales (snapshots) NO ocupan espacio inicial en ZFS; crece bajo demanda según cambios. Son ideales para recuperación rápida de archivos eliminados, no para DR. Para disaster recovery, necesitas replicación o backup remoto.

Actualización de software de TrueNAS

TrueNAS SCALE usa "trains" (ramas de actualización) que siguen caminos de versiones lineales. Desde System → Update:

Perfiles disponibles

  • Stable: Versiones probadas y recomendadas (default para producción)
  • Nightly: Versiones en desarrollo diario (solo testing)
  • Release Candidate: Candidatos a versión estable

Proceso de actualización

  1. Antes de actualizar: crear un backup de configuración

    System → General → Save Configuration
    ✅ Marcar: Export Password Secret Seed
    

  2. Realizar actualización:

    System → Update → Check for Updates
    → Install Update
    

  3. Durante la actualización: TrueNAS descarga archivos y reinicia automáticamente

  4. Después: limpiar caché del navegador (CTRL+F5) antes de loguear

Warning

Actualiza durante ventanas de mantenimiento programado. Los clientes desconectados durante la actualización experimentarán un corte de servicio. Todos los parámetros auxiliares pueden cambiar entre versiones mayores; revisa la documentación de cambios (release notes) antes de actualizar.

Instalación de apps en TrueNAS Scale

TrueNAS Scale incluye TrueCharts o iX Apps —catálogos de aplicaciones containerizadas que corren en Kubernetes integrado.

Apps → Discover Apps → [Buscar aplicación]
    → Install → Configurar
    → Deploy

Las apps comparten el almacenamiento de TrueNAS directamente, útil para servicios como Pi-hole, Plex, Home Assistant, etc.

Monitoreo y alertas

Dashboard → Reporting:

  • Uso de almacenamiento en tiempo real
  • Temperatura y estado de discos
  • Performance (IOPS, throughput)

Sistema → Settings → Email:

Configura notificaciones automáticas si:

  • Un disco falla
  • Capacidad del pool > 85%
  • Temperatura de discos alta

Buenas prácticas

  • Planifica capacidad: deja 10-20% de espacio libre en el pool para que ZFS funcione óptimamente
  • Monitorea salud: revisa el estado de discos regularmente desde Storage → Disks
  • Respalda la configuración: System → General → Save Configuration
  • Actualiza regularmente: System → Update → Check for Updates
# Desde shell (Advanced → Shell), ver estado del pool
zpool status tank

# Ver dataset usage
zfs list -o space

Warning

NO añadas discos a un pool existente esperando aumentar capacidad. Los RAID-Z no se pueden expandir; necesitas migrar a un nuevo pool o usar RAID concatenado (no recomendado). Planifica el tamaño inicial correctamente.

Referencias

Defender for Containers en GA en Azure Government y AKS Automatic K8s gated deployment

Resumen

La semana del 22 de abril cierra el ciclo de novedades del primer cuatrimestre de 2026 con dos GAs relevantes en Defender for Cloud: Defender for Containers alcanza GA en Azure Government —igualando la paridad con la nube comercial— y Kubernetes gated deployment en AKS Automatic pasa a GA (disponible desde el 12 de marzo). Este último permite bloquear automáticamente el despliegue de cargas de trabajo en AKS que no cumplan las políticas de seguridad definidas en Defender for Cloud, sin intervención manual.

Defender for Containers GA en Azure Government

Hasta ahora, los clientes en Azure Government tenían acceso limitado a Defender for Containers. Con la GA de abril 2026, las capacidades disponibles en la nube comercial son ahora paridad completa:

Capacidad Nube Comercial Azure Government (GA abr 2026)
Vulnerability assessment de imágenes
Runtime threat protection
Binary drift detection
Anti-malware en runtime
Kubernetes security posture
Code to Runtime enrichment ✅ (preview) Preview

Habilitar en Azure Government

# Conectarse al entorno de Government
az cloud set --name AzureUSGovernment
az login

# Habilitar Defender for Containers
az security pricing create \
  --name Containers \
  --tier Standard

AKS Automatic K8s Gated Deployment (GA desde 12 marzo)

¿Qué es Kubernetes Gated Deployment?

Gated Deployment integra Defender for Cloud con el flujo de despliegue de AKS Automatic. Cuando un deployment llega al cluster, la gate evalúa el estado de seguridad antes de permitir que los pods se inicien:

flowchart LR
    DEV[Developer\nkubectl apply] --> API[AKS API Server]
    API --> GATE[Security Gate\nDefender for Cloud]
    GATE --> EVAL{Evaluación}
    EVAL -->|Cumple políticas| OK[Pods iniciados]
    EVAL -->|No cumple| BLOCK[Deployment bloqueado\nEvento de auditoría]
    BLOCK --> ALT[Alerta en\nDefender for Cloud]

Qué políticas puede evaluar la gate

  • Imagen con vulnerabilidades críticas no parcheadas
  • Imagen desde registry no confiable
  • Contenedor con privileged: true sin excepción
  • Ausencia de readiness/liveness probes
  • Uso de latest como tag de imagen

Habilitar Gated Deployment

Requiere AKS Automatic (no AKS Standard):

# Crear cluster AKS Automatic con Gated Deployment
az aks create \
  --resource-group myRG \
  --name myAKSAutomatic \
  --tier standard \
  --aks-custom-headers AKSHTTPCustomFeatures=Microsoft.ContainerService/AKSAutomatic \
  --enable-defender \
  --defender-config '{
    "gatedDeployment": {
      "enabled": true,
      "blockOnVulnerabilities": true,
      "blockOnUntrustedRegistry": true
    }
  }'

Configurar excepciones

Para workloads legítimas que requieren privilegios especiales:

apiVersion: v1
kind: Pod
metadata:
  name: my-privileged-pod
  annotations:
    security.microsoft.com/gated-deployment-exception: "approved"
    security.microsoft.com/gated-deployment-approver: "security-team"
    security.microsoft.com/gated-deployment-reason: "Required for node monitoring"
spec:
  containers:
  - name: monitor
    image: myacr.azurecr.io/node-monitor:1.2.3  # imagen con tag explícito
    securityContext:
      privileged: true

Warning

Las excepciones deben ser revisadas periódicamente. Un proceso de aprobación sin revisión se convierte en una brecha: con el tiempo, todos los deployments problemáticos tienen excepción y la gate pierde efectividad.

Integrar Gated Deployment con el pipeline CI/CD

La práctica recomendada es que los problemas se detecten antes de llegar al cluster:

flowchart LR
    PR[Pull Request] --> SAST[Análisis estático\nDefender for DevOps]
    SAST --> BUILD[Build imagen]
    BUILD --> SCAN[Scan de imagen\nMicrosoft Defender]
    SCAN --> PUSH[Push a ACR]
    PUSH --> DEPLOY[kubectl apply]
    DEPLOY --> GATE[Gated Deployment\nDefender for Cloud]
    GATE --> PROD[Producción]

La gate actúa como última línea de defensa, no como sustituto del análisis en pipeline.

Buenas prácticas

  • Empieza con la gate en modo audit (solo registra, no bloquea) para identificar qué deployments existentes no cumplirían las políticas antes de activar el bloqueo.
  • Define un proceso de gestión de excepciones claro: quién aprueba, cuánto tiempo dura la excepción y cómo se revisa.
  • Para Azure Government: verifica que las políticas de seguridad de tu agencia permiten el uso de capacidades en preview (como Code to Runtime) antes de habilitarlas.
# Ver eventos de gated deployment en el cluster
kubectl get events --namespace kube-system |
    grep -i "gated\|blocked\|security"

Referencias

Azure Backup para AKS: experiencia CLI simplificada para habilitar protección

Resumen

En abril de 2026, Azure Backup lanza una experiencia de CLI simplificada para habilitar backup en clusters de AKS. El proceso anterior requería múltiples pasos manuales: crear el Backup vault, registrar extensiones, configurar permisos RBAC en el cluster y en las cuentas de storage, y asociar la política. Ahora es posible hacerlo en un único comando az aks backup enable. Útil para equipos que gestionan muchos clusters o necesitan estandarizar el backup de AKS en pipelines de CI/CD.

Arquitectura de backup de AKS

Azure Backup para AKS hace snapshots de:

  • Recursos de Kubernetes (deployments, configmaps, secrets, PVCs y sus definiciones)
  • Volúmenes persistentes (datos en disco, via CSI snapshot)

El proceso usa una extensión de backup instalada en el cluster que interactúa con el Backup vault:

flowchart TD
    AKS[Cluster AKS] --> EXT[Backup Extension\nInstalada en el cluster]
    EXT --> VAULT[Backup Vault]
    EXT --> SNAP[Snapshot de volúmenes\nAzure Disk / ANF]
    VAULT --> POL[Backup Policy\nRetención y frecuencia]
    POL --> RP[Recovery Points]

    subgraph Backup flow
        EXT
        SNAP
    end

Habilitación con el nuevo comando simplificado

Antes (proceso manual)

# 1. Crear Backup vault
# 2. Instalar extensión de backup en el cluster
# 3. Crear backup instance manualmente
# 4. Asignar permisos RBAC al vault en el cluster
# 5. Asignar permisos en el Resource Group de snapshots
# (5+ comandos, gestión manual de IDs)

Ahora (comando unificado)

az aks backup enable \
  --resource-group myRG \
  --cluster-name myAKSCluster \
  --vault-name myBackupVault \
  --vault-resource-group myBackupRG \
  --backup-policy-name dailyAKSPolicy \
  --backup-storage-location-name eastus

Este comando:

  1. Instala la extensión de backup en el cluster si no está presente
  2. Crea el Backup vault si no existe (o usa uno existente)
  3. Configura automáticamente los role assignments necesarios
  4. Crea la Backup instance asociando cluster, vault y policy

Gestionar políticas de backup

Crear una política personalizada

# Ver políticas disponibles en el vault
az dataprotection backup-policy list \
  --resource-group myBackupRG \
  --vault-name myBackupVault \
  --output table

# Crear política con retención de 30 días y backup diario
az dataprotection backup-policy create \
  --resource-group myBackupRG \
  --vault-name myBackupVault \
  --name dailyAKSPolicy \
  --datasource-types AzureKubernetesService \
  --policy '{
    "policyRules": [
      {
        "backupParameters": {
          "objectType": "AzureBackupParams",
          "backupType": "Incremental"
        },
        "trigger": {
          "objectType": "ScheduleBasedTriggerContext",
          "schedule": {
            "repeatingTimeIntervals": ["R/2026-01-01T02:00:00+00:00/P1D"]
          },
          "taggingCriteria": [{"tagInfo": {"tagName": "Default"}, "isDefault": true}]
        },
        "dataStore": {
          "dataStoreType": "OperationalStore",
          "objectType": "DataStoreInfoBase"
        },
        "name": "BackupHourly",
        "objectType": "AzureBackupRule"
      }
    ]
  }'

Verificar el estado del backup

# Ver instancias de backup del cluster
az dataprotection backup-instance list \
  --resource-group myBackupRG \
  --vault-name myBackupVault \
  --query "[?contains(name,'myAKSCluster')].{Name:name, Status:properties.currentProtectionState}" \
  --output table

# Ver recovery points disponibles
az dataprotection recovery-point list \
  --resource-group myBackupRG \
  --vault-name myBackupVault \
  --backup-instance-name <backup-instance-name> \
  --output table

Restaurar desde un recovery point

az aks backup restore \
  --resource-group myRG \
  --cluster-name myAKSCluster \
  --vault-name myBackupVault \
  --vault-resource-group myBackupRG \
  --recovery-point-id <recovery-point-id> \
  --restore-location eastus \
  --restore-to-cluster-id <target-cluster-resource-id>

Warning

La restauración de AKS es destructiva para los recursos restaurados. Si restauras en el mismo cluster, los recursos existentes con los mismos nombres serán sobreescritos. Considera siempre restaurar primero en un cluster de prueba.

Integrar en pipelines de CI/CD

# Ejemplo: GitHub Actions step para habilitar backup en nuevo cluster
- name: Enable AKS Backup
  run: |
    az aks backup enable \
      --resource-group ${{ env.RESOURCE_GROUP }} \
      --cluster-name ${{ env.CLUSTER_NAME }} \
      --vault-name ${{ env.BACKUP_VAULT }} \
      --vault-resource-group ${{ env.BACKUP_RG }} \
      --backup-policy-name dailyAKSPolicy \
      --backup-storage-location-name ${{ env.LOCATION }}

Buenas prácticas

  • Almacena el Backup vault en un Resource Group separado del cluster. Si el RG del cluster se elimina accidentalmente, los backups permanecen.
  • Habilita soft delete en el Backup vault para prevenir la eliminación accidental de recovery points.
  • Prueba la restauración al menos una vez al mes en un cluster de staging para validar que los backups son funcionales.
# Habilitar soft delete en el vault
az dataprotection backup-vault update \
  --resource-group myBackupRG \
  --vault-name myBackupVault \
  --soft-delete-state On \
  --soft-delete-retention-duration-in-days 14

Referencias

AVD RDP Multipath: resiliencia de red con múltiples rutas TCP en preview

Resumen

En abril de 2026, Azure Virtual Desktop lanza en preview RDP Multipath, una extensión del protocolo RDP que mantiene múltiples rutas TCP simultáneas entre el cliente y el session host. Si una ruta falla —por ejemplo, una interfaz de red, un ISP o una VPN— la sesión continúa automáticamente a través de las rutas restantes sin reconexión visible para el usuario. Es especialmente útil para usuarios móviles o con conectividad variable que requieren sesiones RDP estables.

¿Cómo funciona RDP Multipath?

RDP Multipath usa el protocolo MPTCP (Multipath TCP) para establecer subrutas (subflows) sobre diferentes interfaces de red o rutas. Si el cliente tiene conectividad Wi-Fi y 4G/5G simultáneamente, Multipath puede usar ambas:

flowchart LR
    C[Cliente AVD] --> SF1[Subflow 1\nWi-Fi / Ethernet]
    C --> SF2[Subflow 2\n4G / 5G]
    SF1 --> SH[Session Host\nAzure]
    SF2 --> SH

    note1[Si SF1 falla → SF2 mantiene la sesión]
    note2[Carga distribuida entre rutas activas]

Diferencia con RDP Shortpath

Característica RDP Shortpath RDP Multipath
Protocolo base UDP TCP
Objetivo principal Reducir latencia Aumentar resiliencia
Rutas simultáneas 1 Múltiples
Escenario ideal Redes corporativas estables Usuarios móviles o con WAN redundante
Estado (abril 2026) GA Preview

Ambas características son complementarias y pueden estar activas al mismo tiempo.

Requisitos de la preview

  • Session hosts: Windows Server 2025 o Windows 11 24H2
  • Cliente: Windows App versión 2.0.80 o superior
  • Red: El cliente debe tener múltiples interfaces activas para aprovechar las rutas paralelas
  • OS del cliente: Windows 11 con MPTCP habilitado

Verificar MPTCP en el cliente Windows

# Verificar estado de MPTCP en Windows 11
Get-NetTCPSetting | Select-Object SettingName, AutoTuningLevelLocal, MultiPath

# Habilitar MPTCP si está desactivado
Set-NetTCPSetting -SettingName InternetCustom -MultiPath Enabled

Habilitar RDP Multipath en el host pool

En el portal de AVD → Host pool → RDP Properties → Network settings

O vía CLI:

az desktopvirtualization hostpool update \
  --resource-group myRG \
  --name myHostPool \
  --custom-rdp-property "multipath:i:1"

Verificar que Multipath está activo

Durante una sesión activa, en Windows App:

Connection Information → Transport: TCP (RDP Multipath)
                       → Active paths: 2

Desde el session host, verificar conexiones MPTCP activas:

# Ver conexiones TCP con información de subflows (Windows Server 2025)
Get-NetTCPConnection -State Established |
    Where-Object { $_.LocalPort -eq 3389 -or $_.RemotePort -eq 3389 } |
    Select-Object LocalAddress, RemoteAddress, State

Casos de uso recomendados

  • Usuarios móviles con laptops que alternan entre Wi-Fi corporativo y datos móviles
  • Sesiones críticas que no pueden interrumpirse por cambios de red (salas de control, trading, soporte remoto crítico)
  • Oficinas con doble ISP donde los usuarios necesitan failover transparente

Warning

En la preview, RDP Multipath puede no estar disponible en todas las regiones de Azure. Verifica la disponibilidad regional en la documentación oficial antes de planificar el rollout.

Note

RDP Multipath y RDP Shortpath pueden coexistir en la misma configuración de host pool: Shortpath mejora la latencia en redes con buena calidad, mientras que Multipath añade resiliencia. Si Shortpath (UDP) no está disponible por restricciones de red, la sesión cae a TCP, donde Multipath puede proporcionar resiliencia.

Buenas prácticas

  • Despliega la preview en un subconjunto de usuarios itinerantes y recoge feedback antes del rollout general.
  • Monitoriza el consumo de ancho de banda: con múltiples rutas activas, el tráfico total puede aumentar si el cliente usa ambas interfaces simultáneamente.
  • Documenta las interfaces de red disponibles en los dispositivos de los usuarios; si todos están en redes Ethernet de un solo path, Multipath no aportará beneficio.

Referencias

Defender for Cloud: protección de modelos de IA en Azure ML registries y workspaces

Resumen

El 30 de marzo de 2026, Defender for Cloud lanzó en preview la protección de seguridad para modelos de IA en Azure Machine Learning. Cubre dos activos críticos de MLOps: los model registries (donde se almacenan y versionan los modelos) y los workspaces (donde se entrenan y despliegan). La feature detecta anomalías en acceso a modelos, cambios no autorizados en artefactos y comportamientos de inferencia sospechosos en endpoints desplegados.

¿Por qué proteger los modelos de ML?

Los modelos de ML son activos de alto valor y vectores de ataque emergentes:

Riesgo Descripción
Model theft Descarga no autorizada de modelos entrenados con datos propietarios
Model poisoning Modificación de artefactos del modelo para alterar su comportamiento
Inference abuse Uso masivo del endpoint para extraer información del modelo (model extraction)
Data leakage via output El modelo memoriza y devuelve datos de entrenamiento sensibles
flowchart TD
    REG[Model Registry\nAzure ML] --> D[Defender for Cloud\nAI Model Security]
    WS[ML Workspace] --> D
    EP[Inference Endpoint] --> D
    D --> A1[Acceso anómalo\nal registro]
    D --> A2[Cambio no autorizado\nen artefacto]
    D --> A3[Comportamiento\nde inferencia inusual]
    A1 & A2 & A3 --> ALT[Security Alert\nDefender for Cloud]

Qué detecta la preview

En Model Registries

  • Descarga masiva de artefactos de modelos fuera del patrón habitual
  • Acceso desde IPs o identidades no habituales al registro
  • Cambios en versiones de modelos sin actividad de entrenamiento previa (posible sustitución)

En Workspaces

  • Notebooks que acceden a datasets fuera del scope del proyecto
  • Jobs de entrenamiento con destinos de almacenamiento inusuales
  • Acceso a secretos del workspace desde identidades no esperadas

En Inference Endpoints

  • Volumen de requests anómalo (posible model extraction)
  • Prompts con patrones de adversarial attack detectados
  • Respuestas que contienen patrones de PII no esperados

Habilitar la protección

Requiere Defender for Azure Machine Learning habilitado:

az security pricing create \
  --name MachineLearning \
  --tier Standard

Verificar que los workspaces están cubiertos

az security pricing show --name MachineLearning \
  --query "{Tier:pricingTier, Extensions:extensions}" \
  --output json

Revisar alertas de AI model security

En Defender for Cloud → Security alerts, filtra por categoría Machine Learning:

# Listar alertas activas de ML vía CLI
az security alert list \
  --query "[?contains(alertType,'MachineLearning')].{Alert:alertDisplayName, Severity:severity, Time:timeGeneratedUtc}" \
  --output table

KQL para Microsoft Sentinel

SecurityAlert
| where ProductName == "Azure Defender for Machine Learning"
| extend ResourceId = tostring(Entities[0].ResourceId)
| summarize Alerts = count() by AlertDisplayName, Severity, bin(TimeGenerated, 1d)
| sort by Alerts desc

Recomendaciones de endurecimiento para workspaces de ML

Defender for Cloud genera recomendaciones específicas para reducir la superficie de ataque:

  • Desactivar acceso público al workspace: usar Private Link
  • Restringir el rol Contributor del workspace a pipelines de CI/CD solamente
  • Habilitar customer-managed keys para el storage de artefactos
  • Activar audit logging en el workspace
# Deshabilitar acceso público al workspace de Azure ML
az ml workspace update \
  --name myWorkspace \
  --resource-group myRG \
  --public-network-access Disabled

Warning

Esta feature está en preview y no tiene SLA de cobertura completa. Algunos tipos de ataques sofisticados (model extraction lento y distribuido, por ejemplo) pueden no detectarse en esta versión. Combina con rate limiting en los inference endpoints y monitorización de costes de inferencia.

Buenas prácticas

  • Aplica el principio de mínimo privilegio en el acceso a model registries: separa roles de lectura (para inferencia) y escritura (para pipelines de entrenamiento).
  • Versiona los modelos con checksums verificables y almacénalos en contenedores de storage con immutability policies habilitadas.
  • Configura alertas de Azure Monitor en los inference endpoints para detectar picos de uso fuera de las horas habituales.

Referencias