DevOps

Aprende Portainer CE paso a paso: Stacks, App Templates y GitOps para tu homelab

Por qué una GUI si ya te defiendes con el CLI de Docker

Llevo años administrando contenedores con docker ps, docker compose y docker logs -f. Funciona, pero tiene un problema concreto: cada vez que tocas un servidor nuevo (o le pasas el proyecto a un colega), tienes que volver a recordar dónde vive cada volumen, qué stack está corriendo en qué puerto y por qué traefik se está comiendo toda la RAM otra vez. Una buena GUI web no compite con el CLI: lo complementa. Te da visión agregada de todos tus hosts, te deja ver logs en pantalla sin abrir cuatro terminales, y te permite enseñar el estado del homelab en una sola pestaña.

Portainer CE cumple ese rol desde hace años sin pedirte que migres a Kubernetes ni que compres licencia. La versión vigente en octubre de 2026 es Portainer 2.45.2 LTS (8 de octubre) y el anuncio oficial del blog de Portainer habla del salto a 3.0 como STS inicial todavía en preparación. Si hoy quieres una GUI que funcione en tu homelab sin sorpresas, sigues en 2.x LTS — y este post es sobre cómo sacarle el máximo provecho en su flujo de trabajo diario.

Lo que vas a tener al final

TL;DR — Lo que vas a tener al final

  • Tiempo de setup: 45–60 minutos asumiendo que Docker ya está instalado; 90 minutos si partes desde cero.
  • Requisitos: Linux con kernel 5.10+, Docker Engine 24+ y Docker Compose v2, 1 GB de RAM libre para el contenedor de Portainer, puertos 9443 y 9000 disponibles.
  • Resultado: panel web HTTPS en https://tu-host:9443 con cinco flujos claros: App Templates para desplegar con un clic, Stacks declarativos desde un repo Git, GitOps automático al hacer push, operaciones del día a día (logs, consolas, reinicios, redes) y un script de backup reproducible.
  • Troubleshooting: cuando Portainer queda en bucle tras un update, restaura desde el volumen portainer_data en menos de 3 minutos con el procedimiento descrito en la sección final.

Cheat sheet: Docker CLI puro vs Portainer, de un vistazo

Para los que vienen del CLI y quieren entender rápido qué cubre cada flujo desde el panel, esta tabla resume el mapeo mental. No es exhaustiva — solo los comandos que vas a tocar en el día a día.

Tarea Docker CLI tradicional Lo que hace Portainer
Ver contenedores activos docker ps Container list (auto-refresco configurable)
Logs de un contenedor docker logs -f nombre Click en contenedor → Logs, con búsqueda y follow
Abrir shell interactivo docker exec -it nombre bash Click en contenedor → Console, shell embebido sin abrir SSH
Desplegar stack desde YAML docker compose up -d Stacks → Add stack, con URL a repo Git
Re-desplegar tras cambio git pull && docker compose up -d GitOps auto (webhook) o Pull and redeploy
Crear red personalizada docker network create proxy Networks → Add network (bridge, host, MACVLAN)
Inspeccionar volumen docker run --rm -it -v vol:/data alpine Volumes → Browse files (mount temporal automático)
Backup del estado Scripts a mano con cron y tar Volumen portainer_data con script reproducible

Pre-requisitos: Docker engine y un volumen persistente

Antes de levantar Portainer asegúrate de tres cosas. La primera es que tu Linux tiene Docker Engine y el plugin de Docker Compose v2. La segunda es que existe un volumen persistente para los datos del propio Portainer (si lo pierdes, pierdes toda la configuración). La tercera es que tu firewall o tu proxy reverso no está ocupando los puertos 9443 (HTTPS del panel) y 9000 (API, opcional).

Verifica versión de engine y compose con un solo comando. Si alguno de los dos binarios devuelve “command not found”, la instalación de Docker no está completa.

docker --version
docker compose version

En Debian y Ubuntu instala Docker con el script oficial si todavía no lo tienes. El script configura el repositorio docker-ce, añade tu usuario al grupo docker para no invocar sudo en cada comando, y deja listo el socket en /var/run/docker.sock.

curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER"
exec sudo -u "$USER" "$SHELL"

Si necesitas profundizar en Docker Compose para homelab (volúmenes nombrados, redes overlay, secretos), te sirve como base el material que ya cubrimos en posts anteriores del blog; aquí asumo que esas piezas las dominas.

Levanta Portainer con Docker Compose en tres minutos

Este es el camino más limpio porque declaras la configuración en un YAML versionado y reproducible. Crea una carpeta de trabajo y dentro el archivo compose.yaml con el siguiente contenido. Lo importante: el volumen portainer_data es donde viven la base interna y todos tus stacks, y el bind del socket /var/run/docker.sock le da a Portainer visibilidad total del host Docker local.

mkdir -p ~/portainer && cd ~/portainer
services:
  portainer:
    image: portainer/portainer-ce:2.45.2
    container_name: portainer
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - portainer_data:/data
    ports:
      - "9443:9443"
      - "9000:9000"
volumes:
  portainer_data:
    name: portainer_data

Arranca el stack con docker compose up -d y mira los logs en tiempo real para confirmar que no hay errores. La primera línea esperada es un mensaje de Portainer indicando el puerto del panel y la URL del endpoint REST; si en su lugar ves “permission denied” sobre docker.sock, el problema es de permisos del socket (más sobre esto en la sección de troubleshooting).

docker compose up -d
docker compose logs -f --tail=200 portainer

Si ya tienes Portainer corriendo desde un tutorial anterior, este es un buen momento para forzar la actualización a la última imagen LTS. Solo tienes que pedirle a Compose que baje y recree el contenedor, sin tocar el volumen de datos.

docker compose pull portainer
docker compose up -d

Si tu instalación previa venía de la imagen portainer/portainer-ce:lts (sin número de versión) o del antiguo tag portainer/portainer (sin sufijo -ce), reemplaza el nombre de la imagen en el YAML antes de recrear el contenedor; el viejo tag ya no se mantiene al día.

Conecta tu primer environment con el socket de Docker

El primer entorno (environment) que añadas será el host local donde corre el propio Portainer. En la pantalla inicial Portainer te pregunta el tipo de environment a agregar: para el host local elige Docker (no Kubernetes ni Edge Agent todavía). Elige la opción “Socket” en lugar de “Agent” si solo quieres leer el host local sin comunicación bidireccional cifrada.

Portainer detectará automáticamente el endpoint como local y te mostrará tres números clave: cantidad de contenedores corriendo, imágenes y volúmenes. Lo importante aquí es validar que el agente puede enumerar tanto contenedores como imágenes: si la página se queda cargando eternamente en “loading environment”, el socket no es legible por el usuario dentro del contenedor (el error se soluciona añadiendo al usuario del contenedor al grupo del host que tenga acceso al socket).

Qué hacer cuando el socket es ilegible

El error típico es que /var/run/docker.sock pertenece a root:docker en el host y Portainer corre como UID 1000 por defecto dentro del contenedor. Tienes dos arreglos, y debes aplicar uno.

La opción correcta en producción es montar el socket en modo solo lectura (como en el YAML anterior) y ajustar los permisos del socket al arrancar. Si necesitas debugar un momento, abre el socket en lectura/escritura; el riesgo es que un contenedor comprometido pueda manipular otros contenedores, así que restringe el grupo docker a usuarios de confianza.

sudo chmod 660 /var/run/docker.sock
ls -l /var/run/docker.sock

Si el host usa SELinux en modo enforcing (Fedora, RHEL, Rocky), el permiso 660 no alcanza: el contenedor necesita el contexto adecuado. Añade :z al final del bind mount, o desactiva el módulo container_runtime_t solo si sabes lo que estás haciendo.

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro,z
      - portainer_data:/data

App Templates: desplegar apps self-hosted con un clic

App Templates es la “tienda” de Portainer: una lista curada de stacks preconfigurados (Nextcloud, Pi-hole, Jellyfin, Grafana, Uptime Kuma, etc.) listos para desplegar con un clic, ajustando parámetros sensibles a través del formulario web. Portainer trae una colección propia (unos 30 stacks populares) y admite cargar URLs de templates externos: la comunidad mantiene repositorios como portainer-templates.as93.net (700+ plantillas) y lissy93/portainer-templates (800+ plantillas).

Cargar una colección externa de templates

Para activar la lista de la comunidad, ve a Settings → App Templates y pega la URL del manifiesto JSON. La URL pública de la colección de Lissy93 es la más estable; se actualiza periódicamente y está pensada para Portainer 2.x. Tras pegar la URL, refresca la página y la nueva colección aparece en el menú App Templates del entorno.

# Verificar que la URL responde y devuelve JSON válido
curl -s https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json 
  | head -c 200

Cada plantilla expone los campos editables (volúmenes, contraseñas, puertos publicados) en una pantalla con checkboxes y campos de texto. Lo mejor de este enfoque es que el JSON de templates es versionable en un repo Git propio: si quieres una lista a medida para tu homelab, mantén tu propio templates.json en tu Git y apúntalo desde Settings. Este es exactamente el mismo patrón GitOps que vas a usar para Stacks (la siguiente sección).

Cuándo NO usar App Templates

App Templates resuelve el 80% del homelab rápido (la típica suite con Vaultwarden, Nextcloud, Immich, Paperless, Jellyfin) pero no escala bien cuando necesitas configuraciones no triviales: variables de entorno sensibles complejas, dependencias entre stacks, redes overlay, montajes NFS. Para esos casos, ve directo a Stacks desde Git — el resto del post.

Stacks desde Git: docker-compose declarativo versionado

Un Stack en Portainer es exactamente un docker-compose.yml gestionado a través del panel. La diferencia frente a ejecutar docker compose up a mano es que Portainer mantiene el estado (qué servicios están corriendo, sus IDs, las últimas actualizaciones) y te permite revisar/editar el YAML desde la web, con syntax highlighting y validación básica. Cuando tu stack vive en un repo Git, además, queda versionado: cada cambio deja un commit y un autor, y puedes volver a cualquier versión anterior.

Crea un repo Git con tus stacks

Estructura recomendada para homelab: un repo por familia de stacks (casa, ofimatica, monitoring, red) o un solo repo con directorios por stack. Cada docker-compose.yml debe ser autocontenido y leer variables desde .env local (que NO va al repo). Esta es la convención más limpia.

mkdir -p ~/portainer-stacks && cd ~/portainer-stacks
git init -b main
cat > .gitignore <<'EOF'
.env
.env.*
EOF
mkdir -p observabilidad
cat > observabilidad/docker-compose.yml <<'EOF'
services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - uptime_data:/app/data
    ports:
      - "3001:3001"
  grafana:
    image: grafana/grafana:11.2.0
    container_name: grafana
    restart: unless-stopped
    volumes:
      - grafana_data:/var/lib/grafana
    ports:
      - "3000:3000"
volumes:
  uptime_data:
  grafana_data:
EOF
git add . && git commit -m "stack inicial observabilidad"

Sube el repo a tu forja favorita (la mía es Forgejo self-hosted pero GitHub o Codeberg sirven). Luego entra al panel de Portainer, ve a Stacks → Add stack, pega la URL del repo y la ruta al YAML. Portainer descarga el archivo, te lo muestra pre-rellenado y te deja sobrescribir variables de entorno antes de desplegar.

Sincronización inicial y variables de entorno

Los campos críticos del formulario son cuatro. Repository URL es la URL HTTPS o SSH (HTTPS pide token personal o user/password en URL; SSH necesita una clave privada cargada en Portainer). Compose path es la ruta interna del archivo, por defecto docker-compose.yml. Reference es la rama o tag. Repository authentication carga las credenciales si tu repo es privado.

# Validar que el YAML de tu repo es sintácticamente correcto ANTES
# de pegarlo a Portainer (Portainer no valida mucho en su UI)
docker compose -f observabilidad/docker-compose.yml config --quiet 
  && echo OK

Las variables de entorno tienen un truco: si declaras ${MI_VARIABLE} en el YAML y no tienes nada en la sección Environment del stack, Docker Compose reemplaza con string vacío. Portainer te permite inyectarlas desde la UI antes del deploy (botón "Use a Secrets manager" en versiones nuevas, o el editor plano en versiones LTS) — úsalo para claves API y tokens; nunca dejes secretos en el repo.

GitOps automático: cómo Portainer re-despliega cuando haces push

La pieza más útil de Portainer para homelab es el modo GitOps: cuando lo activas en un Stack, Portainer hace git pull en cada cambio de tu rama y, si el YAML cambia, reconstruye y re-despliega los servicios. Te olvidas del ssh servidor && cd /srv && git pull && docker compose up -d que todo sysadmin repite 30 veces al día.

Para activarlo abre el stack ya creado, ve a la sección GitOps updates (a veces etiquetada Auto update) y marca la casilla. Portainer te da tres opciones de mecanismo: webhook (portainer espera un POST HTTP, tú lo disparas desde tu CI o manualmente), polling (portainer pregunta al repo cada X minutos) y manual (el botón "Pull and redeploy"). Para homelab recomiendo polling cada 5 minutos — sin necesidad de exponer el panel a Internet y sin montar un CI completo.

Webhook con GitHub Actions para producción pequeña

Si prefieres GitOps con latencia sub-segundo (re-deploy en cuanto el PR se mergea), registra el webhook de Portainer en GitHub con el flujo siguiente. Primero copia el webhook_url que Portainer muestra al activar GitOps; luego guárdalo como secreto en tu repo (PORTAINER_WEBHOOK) y dispara al hacer push a main.

name: portainer-redeploy
on:
  push:
    branches: [main]
    paths:
      - observabilidad/**
jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Portainer webhook
        run: |
          curl -sS -X POST "${{ secrets.PORTAINER_WEBHOOK }}" 
            -H "X-Provider: github" 
            -o /dev/null -w "%{http_code}n"

El secreto vive cifrado en GitHub y no queda expuesto en logs. Una limitación práctica: Portainer re-despliega solo si el YAML cambió. Si haces commit de un README.md dentro del mismo directorio, el webhook se dispara pero el YAML no cambia, así que Portainer ignora el push y no gasta recursos.

Cuándo falla el GitOps (y cómo lo notas)

Tres escenarios reales que verás en homelab. El primero: el token del repo vence y Portainer empieza a devolver 401 en cada poll — el síntoma es que la columna "Last update" queda congelada y el status del stack pasa a "Git fetch failed". La solución: regenera el token en la forja y actualiza el campo de autenticación del stack. El segundo: el YAML tiene un error de sintaxis y Portainer revierte a la versión anterior automáticamente, mostrando un banner rojo en el panel — lee el error en la pestaña "Logs" del stack y corrige. El tercero: el repo usa LFS y Portainer no soporta LFS en la versión 2.45 (sí está en roadmap). La salida es mover binarios grandes fuera de LFS o usar un repo paralelo para assets.

Operaciones del día a día: logs, consola, redes y volúmenes

La GUI brilla en el día a día. Desde el panel accedes a todas las dimensiones del entorno sin memorizar flags de docker. Las funciones que más uso, ordenadas por frecuencia:

  • Container logs: panel lateral con búsqueda y siguiente/anterior sobre el stream de stdout/stderr. Mucho más cómodo que abrir tres pestañas SSH. Tiene un toggle "follow" para ver los logs en tiempo real.
  • Container console: shell interactivo dentro del contenedor (executa comandos como si estuvieras dentro). Útil para debugar init scripts, examinar permisos y hacer ls sin tener que instalar docker exec en tu shell.
  • Container stats: CPU, RAM, red y disco por contenedor, con histórico de 5 minutos. Si tu host tiene cAdvisor activado, ves también el uso por cgroup y los bloqueos de I/O.
  • Networks: crear, eliminar y conectar contenedores a redes bridge, host o personalizadas. Para Caddy/Traefik la red suele llamarse proxy y todos los stacks que quieres exponer se unen a esa red.
  • Volumes: navegar el contenido de un volumen con un navegador de archivos embebido (mount temporal del volumen en un contenedor Alpine). Para inspección rápida sin tener que docker run -v vol:/data --rm -it alpine.

Para administración masiva, la sección Container → Bulk actions deja arrancar/parar/reiniciar varios contenedores a la vez filtrando por stack o label. Combinado con labels en tu docker-compose.yml, te permite operar por categoría: env=prod, grupo=monitoring, etc.

Backups reproducibles del propio Portainer

Todo lo que has configurado vive dentro del volumen portainer_data. Hacer backup es tan simple como detener el servicio, copiar el volumen a un tar.gz, y volver a arrancar. La clave para que el backup sea válido es parar el contenedor mientras copias: Portainer escribe continuamente en SQLite y un snapshot en caliente puede quedar inconsistente.

docker compose stop portainer
docker run --rm 
  -v portainer_data:/from:ro 
  -v "$PWD:/to" 
  alpine:3.20 
  tar -czf /to/portainer-backup-$(date +%Y%m%d-%H%M).tgz -C /from .
docker compose start portainer
ls -lh portainer-backup-*.tgz

El tar incluye la base SQLite interna, los certificados TLS autogenerados, las plantillas custom que hayas cargado y los secretos que hayas declarado en Portainer (si usas su Secrets manager). Para restaurar basta con montar el tar en un volumen nuevo y arrancar el contenedor.

docker compose stop portainer
docker volume rm portainer_data
docker volume create portainer_data
docker run --rm 
  -v portainer_data:/to 
  -v "$PWD:/from" 
  alpine:3.20 
  tar -xzf /from/portainer-backup-YYYYMMDD-HHMM.tgz -C /to
docker compose start portainer

Para automatizar, mete los dos scripts anteriores en un cron del host que borra backups con más de 14 días, o usa el script backup-portainer.sh del proyecto portainer-compose-tools que gestiona la rotación por días.

Troubleshooting: los cinco errores reales que vas a ver

Después de instalar Portainer en decenas de servidores y leer foros varios, hay un grupo recurrente de errores. Los enumero en orden de probabilidad.

1. "Unable to connect to the Docker socket" en la pantalla inicial tras agregar un environment local. Causa típica: el contenedor no tiene permiso de lectura sobre /var/run/docker.sock por mismatch de UIDs. Solución: añade tu usuario al grupo docker y reinicia el contenedor, o monta el socket con :z en SELinux.

sudo usermod -aG docker "$USER"
newgrp docker
docker compose restart portainer

2. "Failed to fetch git repository" en un Stack con GitOps. Causa típica: token expirado o SSH key sin permisos. Verifica la conexión manual desde el host para descartar problema de red.

git ls-remote https://github.com/usuario/repo.git HEAD

3. Stack queda en estado "in progress" indefinidamente. Causa típica: una imagen voluminosa que está bajándose con la red del host congestionada. Solución: abre la pestaña "Logs" del stack y verás "Pulling fs layer" durante minutos; paciencia o usa imágenes más ligeras (Alpine, distroless). Si la imagen no existe en el registro (typo en el tag), Portainer la marca como error tras el timeout del pull.

4. "Out of memory" en el contenedor de Portainer. Causa típica: 50+ stacks con logs verbosos vuelcan en SQLite de Portainer. Reduce el log driver max-size en cada servicio a 5MB y deja Portainer con 1 GB de RAM por defecto; si necesitara más, declara el limite de memoria en el compose del propio Portainer.

    pids_limit: 512
    mem_limit: 1g

5. Portainer se reinicia tras cada update de imagen pero el stack no se actualiza. Causa típica: el stack usa la etiqueta :latest y Portainer detecta el cambio solo si el hash del manifiesto cambia. Solución práctica: fija versiones semánticas (por ejemplo grafana/grafana:11.2.0) en producción y automatiza el bump con Renovate o Dependabot.

Cuándo NO usar Portainer CE: tres escenarios honestos

Portainer brilla para homelab y pequeños clusters pero tiene fricciones reales en tres contextos, todos legítimos.

El primer escenario es Kubernetes a escala de producción. Para clusters serios con más de cinco nodos, GitOps declarativo puro (ArgoCD, Flux) y operadores custom, Portainer queda corto en automatización y observabilidad. ArgoCD o Flux, combinados con Helm, hacen lo mismo en k8s sin la capa GUI.

El segundo escenario es multi-tenancy estricto (varios clientes en la misma infra). El RBAC de Portainer Community es limitado: existen tres roles (admin, user, edge-admin) y el control granular de recursos por equipo se queda en la versión Business. Si tu organización necesita SSO SAML, audit logs y roles personalizados, evalúa la licencia Business o sal directo a Backstage + Argo.

El tercer escenario es homelab de recursos muy limitados (Raspberry Pi con 1 GB de RAM y SD como almacenamiento). El propio Portainer consume ~150 MB de RAM en reposo y cada contenedor extra que ves en el listado come adicionales ~5 MB. Funciona, pero si tu Pi está al 90% de RAM, agrega más swap y considera una de las alternativas ultraligeras como Yacht o Dockge.

Resumen

Portainer 2.45.2 LTS sigue siendo, en octubre de 2026, la forma más rápida de tener visibilidad web completa de tus contenedores sin atarte a un orquestador complejo. El salto a Portainer 3.0 viene anunciado como STS inicial en el blog oficial; cuando sea estable, los pasos de migración están documentados y consisten en recrear el contenedor preservando el volumen portainer_data. Mientras tanto, lo que vale la pena dominar son los flujos que cubrimos: conexión del primer environment, App Templates para desplegar con un clic, Stacks desde un repo Git versionado, GitOps automático por webhook o polling, operaciones del día a día desde el panel, y backups reproducibles con un script corto. Con eso te basta para administrar un homelab de uno o dos hosts con la misma soltura con la que tocarías un servidor grande.

Preguntas frecuentes

¿Portainer 3.0 ya está disponible o debo quedarme en 2.45 LTS?

Portainer 3.0 viene anunciado por el fabricante como una nueva major version con un ciclo de releases STS antes de LTS. En octubre de 2026 la versión recomendada para producción sigue siendo Portainer 2.45.2 LTS, porque es la rama estable con soporte de seguridad a largo plazo. Cuando 3.0 LTS esté disponible, la migración documentada es recrear el contenedor preservando el volumen portainer_data.

¿Necesito un Portainer Agent separado para gestionar hosts remotos?

Sí, Portainer Agent es un contenedor ligero que se instala en cada Docker host remoto y se comunica con el Portainer Server mediante un túnel cifrado (por defecto puerto 9001). El agent permite al panel central enviar comandos al host remoto sin abrir Docker socket a la red. Para Edge Agents detrás de NAT o firewall corporativo es la única vía soportada. El socket local en el mismo host del Server no requiere agent.

¿Cómo recupero Portainer si el volumen portainer_data se corrompe?

La recuperación rápida es recrear el volumen desde un tar.gz tomado con el script de backup que cubrimos: docker run --rm con alpine y tar -czf del volumen detenido. Si no tienes backup pero el contenedor arranca, exporta los stacks desde la GUI a archivos individuales y vuelve a importarlos tras recrear el volumen. La pérdida sin backup es total: Portainer no replica su estado fuera del volumen.

¿Portainer CE aguanta clústeres Kubernetes medianos?

El soporte Kubernetes de Portainer CE es válido para aprendizaje y clusters pequeños (uno o dos nodos). Para producción con más de cinco nodos, operators custom, GitOps declarativo puro y observabilidad avanzada, herramientas especializadas como ArgoCD o Flux son más adecuadas. Portainer complementa en lugar de sustituir a esos stacks cuando la escala sube.

¿Qué pasa con los secretos si los declaro en Portainer en lugar de en el YAML?

Portainer tiene un Secrets manager integrado que cifra los secretos con AES y los monta en los contenedores como variables de entorno o archivos dentro de /run/secrets. Para homelab con tres stacks es suficiente, pero tiene limitaciones: no hay rotación automática, ni integración nativa con HashiCorp Vault, ni separación entre operadores y auditores. Para producción con compliance serio conviene Vault o SOPS con KMS antes que el manager interno.

Lee también

Alfonso Moreno | Sysadmin Senior

Soy Alfonso, sysadmin senior con RHCE y más de 10 años administrando sistemas Linux para empresas y proyectos personales. Me especializo en infraestructura, redes, virtualización, monitoring, automation y self-hosting. Sobre SoyLinux.com SoyLinux.com es un blog técnico en español sobre Linux, software libre y self-hosting. Lo mantengo en mi tiempo libre. Áreas de expertise - Linux server administration: RHEL, CentOS, Rocky, Alma, Fedora, Debian, Ubuntu - Network services: Postfix, BIND, Samba, NFS, Squid - Virtualización y containers: KVM, Proxmox, Docker, Podman - Monitoring: Prometheus, Grafana, Zabbix - Automation: Ansible, Bash scripting - Self-hosting: Vaultwarden, Nextcloud, Jellyfin, Immich, Homelab Contacto - Email: [email protected]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *