Files
ProxMenux/scripts/share/guia.md
2025-09-08 15:01:00 +02:00

19 KiB

📘 Guía Completa: Compartir Recursos entre Proxmox Host y Contenedores LXC

🎯 Introducción

Esta guía explica paso a paso cómo compartir carpetas y recursos entre el host de Proxmox y contenedores LXC (privilegiados y no privilegiados). Aprenderás los conceptos fundamentales de permisos en Linux y cómo configurar correctamente NFS, Samba y directorios locales.

¿Por qué es importante?

En Proxmox es común necesitar que varios contenedores accedan a los mismos datos:

  • Compartir archivos entre múltiples servicios
  • Servir contenido por red (NFS/Samba)
  • Centralizar almacenamiento de datos
  • Hacer backups centralizados

El mayor desafío son los permisos, especialmente en contenedores no privilegiados que usan mapeo de IDs.


📚 Conceptos Fundamentales

¿Qué son los Usuarios y Grupos en Linux?

Usuario: Identidad que ejecuta procesos y posee archivos

  • Cada usuario tiene un UID (User ID) numérico único
  • Ejemplo: root tiene UID 0, www-data tiene UID 33

Grupo: Colección de usuarios que comparten permisos

  • Cada grupo tiene un GID (Group ID) numérico único
  • Un usuario puede pertenecer a múltiples grupos
  • Ejemplo: grupo sharedfiles con GID 1000
# Ver información de un usuario
id www-data
# Salida: uid=33(www-data) gid=33(www-data) groups=33(www-data),1000(sharedfiles)

# Ver todos los grupos del sistema
cat /etc/group | grep shared
# Salida: sharedfiles:x:1000:www-data,root

¿Qué son los Permisos en Linux?

Cada archivo y directorio tiene tres tipos de permisos para tres categorías:

Categorías:

  • Propietario (u): El usuario dueño del archivo
  • Grupo (g): El grupo propietario del archivo
  • Otros (o): Todos los demás usuarios

Permisos:

  • Lectura (r): Ver contenido (valor 4)
  • Escritura (w): Modificar contenido (valor 2)
  • Ejecución (x): Ejecutar archivo o acceder a directorio (valor 1)
# Ejemplo de permisos
ls -l /mnt/shared_data
# -rwxrw-r-- 1 root sharedfiles 1024 sep 8 archivo.txt
#  |||||||
#  ||||||└─ Otros: lectura
#  |||||└── Grupo: lectura + escritura  
#  ||||└─── Propietario: lectura + escritura + ejecución
#  |||└──── Tipo: - (archivo regular)
#  ||└───── Propietario: root
#  |└────── Grupo: sharedfiles
#  └─────── Tamaño: 1024 bytes

¿Qué son las ACLs (Access Control Lists)?

Las ACLs permiten permisos más granulares que el sistema tradicional Unix:

# Ver ACLs de un directorio
getfacl /mnt/shared_data
# Salida:
# file: /mnt/shared_data
# owner: root
# group: sharedfiles
# user::rwx
# group::rwx
# group:sharedfiles:rwx
# mask::rwx
# other::r-x
# default:user::rwx
# default:group::rwx
# default:group:sharedfiles:rwx
# default:mask::rwx
# default:other::r-x

¿Por qué usar ACLs?

  • Garantizan permisos consistentes independientemente de la umask
  • Permiten permisos por defecto para archivos nuevos
  • Esenciales para NFS (que solo entiende UIDs/GIDs numéricos)

Contenedores Privilegiados vs No Privilegiados

Privilegiados:

  • Usan los mismos UIDs/GIDs que el host
  • root en contenedor = root en host (UID 0)
  • Más simples de configurar pero menos seguros

No Privilegiados:

  • UIDs/GIDs desplazados +100000
  • root en contenedor (UID 0) = UID 100000 en host
  • www-data en contenedor (UID 33) = UID 100033 en host
  • Más seguros pero requieren configuración especial

🛠️ Configuración Paso a Paso

Paso 1: Preparar el Host

1.1 Crear Directorio Base y Grupo Universal

# Crear directorio compartido
mkdir -p /mnt/shared_data

# Crear grupo universal con GID específico
groupadd -g 101000 sharedfiles

# Verificar creación
getent group sharedfiles
# Salida: sharedfiles:x:101000:

¿Por qué GID 101000?

  • Es el mapeo que corresponde a GID 1000 dentro de contenedores no privilegiados
  • Permite compatibilidad universal entre contenedores privilegiados y no privilegiados

1.2 Configurar Permisos Base

# Asignar propietario y grupo
chown root:sharedfiles /mnt/shared_data

# Establecer permisos con setgid
chmod 2775 /mnt/shared_data

Explicación del chmod 2775:

  • 2: setgid bit - Los archivos nuevos heredan el grupo del directorio padre
  • 7: Propietario (root) - lectura, escritura, ejecución
  • 7: Grupo (sharedfiles) - lectura, escritura, ejecución
  • 5: Otros - lectura, ejecución (sin escritura)

1.3 Aplicar ACLs

# ACLs para contenido existente
setfacl -R -m g:sharedfiles:rwx /mnt/shared_data

# ACLs por defecto para contenido nuevo
setfacl -d -m g:sharedfiles:rwx /mnt/shared_data

# Verificar ACLs aplicadas
getfacl /mnt/shared_data

¿Por qué ACLs?

  • -R: Aplica a todo el contenido existente recursivamente
  • -d: Define permisos por defecto para archivos/directorios nuevos
  • Garantiza que el grupo sharedfiles siempre tenga acceso completo

Paso 2: Configurar Contenedor Privilegiado

# 2.1 Entrar al contenedor
pct exec 100 -- bash

# 2.2 Crear grupo idéntico al host
groupadd -g 101000 sharedfiles

# 2.3 Añadir usuarios relevantes al grupo
usermod -aG sharedfiles root
usermod -aG sharedfiles www-data

# Si tienes otros usuarios (nextcloud, etc.)
usermod -aG sharedfiles ncp 2>/dev/null || true

# 2.4 Verificar membresía
groups root
groups www-data

# 2.5 Salir del contenedor
exit

¿Es necesario configurar grupos en contenedores privilegiados?

SÍ, es necesario por las siguientes razones:

  1. Consistencia de permisos: Aunque el contenedor privilegiado usa los mismos UIDs que el host, los grupos pueden no existir dentro del contenedor
  2. Servicios específicos: Aplicaciones como Apache (www-data) o Nextcloud (ncp) necesitan pertenecer al grupo para escribir archivos
  3. ACLs: Las ACLs verifican tanto UIDs como GIDs, por lo que el grupo debe existir en ambos lados
  4. Futuras migraciones: Si conviertes el contenedor a no privilegiado, ya tendrás la configuración correcta

Ejemplo práctico:

# Sin configurar grupo en contenedor privilegiado
echo "test" > /mnt/shared/archivo.txt
ls -l /mnt/shared/archivo.txt
# -rw-r--r-- 1 root root 5 sep 8 archivo.txt  ← Grupo incorrecto

# Con grupo configurado
echo "test2" > /mnt/shared/archivo2.txt  
ls -l /mnt/shared/archivo2.txt
# -rw-rw-r-- 1 root sharedfiles 6 sep 8 archivo2.txt  ← Grupo correcto

Paso 3: Configurar Contenedor No Privilegiado

# 3.1 Entrar al contenedor
pct exec 101 -- bash

# 3.2 Crear grupo con GID mapeado
groupadd -g 1000 sharedfiles
# Importante: GID 1000 en contenedor = GID 101000 en host

# 3.3 Añadir usuarios al grupo
usermod -aG sharedfiles root
usermod -aG sharedfiles www-data
usermod -aG sharedfiles ncp 2>/dev/null || true

# 3.4 Verificar configuración
id www-data
# Salida esperada: uid=33(www-data) gid=33(www-data) groups=33(www-data),1000(sharedfiles)

# 3.5 Salir del contenedor
exit

Añadir Usuarios Adicionales

Método 1: Añadir usuarios específicos

# Dentro del contenedor
usermod -aG sharedfiles usuario1
usermod -aG sharedfiles usuario2

Método 2: Añadir todos los usuarios del sistema (automático)

# Script para añadir todos los usuarios con UID >= 1000
for user in $(awk -F: '$3>=1000 && $1!="nobody" {print $1}' /etc/passwd); do
    usermod -aG sharedfiles "$user" 2>/dev/null || true
    echo "Usuario $user añadido al grupo sharedfiles"
done

Método 3: Añadir usuarios interactivamente

# Mostrar usuarios disponibles
echo "Usuarios disponibles en el sistema:"
awk -F: '$3>=1000 && $1!="nobody" {print "- " $1 " (UID: " $3 ")"}' /etc/passwd

# Preguntar qué usuarios añadir
read -p "¿Qué usuarios quieres añadir al grupo sharedfiles? (separados por espacios): " usuarios
for user in $usuarios; do
    if id "$user" >/dev/null 2>&1; then
        usermod -aG sharedfiles "$user"
        echo "✓ Usuario $user añadido"
    else
        echo "✗ Usuario $user no existe"
    fi
done

Paso 4: Montar el Directorio en los Contenedores

# 4.1 Para contenedor privilegiado (ID 100)
pct set 100 -mp0 /mnt/shared_data,mp=/mnt/shared,backup=0,acl=1,shared=1

# 4.2 Para contenedor no privilegiado (ID 101)  
pct set 101 -mp0 /mnt/shared_data,mp=/mnt/shared,backup=0,acl=1,shared=1

# 4.3 Reiniciar contenedores para activar montajes
pct reboot 100
pct reboot 101

# Esperar a que arranquen
sleep 10

Explicación de parámetros:

  • mp0: Mount point 0 (primer punto de montaje)
  • /mnt/shared_data: Ruta en el host
  • mp=/mnt/shared: Ruta dentro del contenedor
  • backup=0: Excluir del backup de vzdump
  • acl=1: Habilitar soporte para ACLs
  • shared=1: Importante para clusters - permite migración sin copiar datos

¿Por qué shared=1?

  • En clusters Proxmox, permite migrar contenedores entre nodos
  • El almacenamiento debe estar disponible en todos los nodos
  • Sin shared=1, Proxmox intentará copiar los datos durante la migración

🌐 Configurar Recursos de Red

Opción A: Montar Recurso NFS Existente

A.1 Instalar Cliente NFS en el Host

# Debian/Ubuntu
apt update && apt install nfs-common

# Verificar servicios NFS
systemctl status rpc-statd
systemctl status rpc-gssd

A.2 Crear Punto de Montaje y Montar

# Crear directorio de montaje
mkdir -p /mnt/nfs_share

# Montar temporalmente para probar
mount -t nfs 192.168.1.50:/export/shared /mnt/nfs_share

# Verificar montaje
df -h | grep nfs
mount | grep nfs

A.3 Hacer Montaje Persistente

# Añadir a /etc/fstab
echo "192.168.1.50:/export/shared /mnt/nfs_share nfs rw,hard,nofail,rsize=131072,wsize=131072,timeo=600,retrans=2,_netdev 0 0" >> /etc/fstab

# Verificar sintaxis
mount -a

# Comprobar que funciona tras reinicio
umount /mnt/nfs_share
mount /mnt/nfs_share

Explicación de opciones NFS:

  • rw: Lectura y escritura
  • hard: Reintentar indefinidamente si el servidor no responde
  • nofail: No fallar el arranque si no se puede montar
  • rsize/wsize=131072: Tamaño de buffer de lectura/escritura (128KB)
  • timeo=600: Timeout de 60 segundos (600 décimas)
  • retrans=2: Reintentar 2 veces antes de reportar error
  • _netdev: Esperar a que la red esté disponible
  • 0 0: No hacer dump ni fsck (siempre para recursos de red)

A.4 Configurar Permisos en el Recurso NFS

# Aplicar configuración de permisos al recurso montado
chown root:sharedfiles /mnt/nfs_share
chmod 2775 /mnt/nfs_share
setfacl -R -m g:sharedfiles:rwx /mnt/nfs_share
setfacl -d -m g:sharedfiles:rwx /mnt/nfs_share

Opción B: Montar Recurso Samba/CIFS

B.1 Instalar Cliente Samba

# Instalar herramientas CIFS
apt update && apt install cifs-utils

# Verificar instalación
which mount.cifs

B.2 Crear Credenciales Seguras

# Crear archivo de credenciales
cat > /etc/cifs-credentials << EOF
username=tu_usuario
password=tu_password
domain=tu_dominio
EOF

# Proteger archivo
chmod 600 /etc/cifs-credentials
chown root:root /etc/cifs-credentials

B.3 Montar Recurso Samba

# Crear punto de montaje
mkdir -p /mnt/samba_share

# Montar temporalmente
mount -t cifs //192.168.1.60/shared /mnt/samba_share -o credentials=/etc/cifs-credentials,iocharset=utf8,vers=3.0

# Verificar montaje
df -h | grep cifs

B.4 Hacer Montaje Persistente

# Añadir a /etc/fstab
echo "//192.168.1.60/shared /mnt/samba_share cifs credentials=/etc/cifs-credentials,iocharset=utf8,vers=3.0,_netdev,nofail 0 0" >> /etc/fstab

# Probar configuración
umount /mnt/samba_share
mount /mnt/samba_share

Explicación de opciones CIFS:

  • credentials=: Archivo con usuario/contraseña
  • iocharset=utf8: Codificación de caracteres
  • vers=3.0: Versión del protocolo SMB
  • _netdev: Esperar red disponible
  • nofail: No fallar arranque si no se puede montar

B.5 Configurar Permisos en Samba

# Aplicar permisos al recurso Samba montado
chown root:sharedfiles /mnt/samba_share
chmod 2775 /mnt/samba_share
setfacl -R -m g:sharedfiles:rwx /mnt/samba_share
setfacl -d -m g:sharedfiles:rwx /mnt/samba_share

Opción C: Crear Directorio Local

# Crear directorio local para compartir
mkdir -p /mnt/local_share

# Aplicar configuración estándar
chown root:sharedfiles /mnt/local_share
chmod 2775 /mnt/local_share
setfacl -R -m g:sharedfiles:rwx /mnt/local_share
setfacl -d -m g:sharedfiles:rwx /mnt/local_share

# Crear estructura de ejemplo
mkdir -p /mnt/local_share/{documentos,imagenes,backups}
chown -R root:sharedfiles /mnt/local_share/*

Verificación y Pruebas

Prueba 1: Verificar Montajes

# En el host
df -h | grep -E "(nfs|cifs|/mnt)"
mount | grep -E "(nfs|cifs|/mnt)"

# Verificar permisos
ls -la /mnt/shared_data
getfacl /mnt/shared_data

Prueba 2: Probar Escritura desde Contenedores

# Contenedor privilegiado (100)
pct exec 100 -- bash -c "echo 'Prueba desde privilegiado' > /mnt/shared/test_privilegiado.txt"

# Contenedor no privilegiado (101)  
pct exec 101 -- bash -c "echo 'Prueba desde no privilegiado' > /mnt/shared/test_no_privilegiado.txt"

# Verificar en el host
ls -la /mnt/shared_data/
# Ambos archivos deben tener grupo 'sharedfiles'

Prueba 3: Verificar Permisos Cruzados

# Desde contenedor 100, modificar archivo creado por contenedor 101
pct exec 100 -- bash -c "echo 'Modificado por privilegiado' >> /mnt/shared/test_no_privilegiado.txt"

# Desde contenedor 101, modificar archivo creado por contenedor 100
pct exec 101 -- bash -c "echo 'Modificado por no privilegiado' >> /mnt/shared/test_privilegiado.txt"

# Verificar contenido
cat /mnt/shared_data/test_privilegiado.txt
cat /mnt/shared_data/test_no_privilegiado.txt

Prueba 4: Verificar Persistencia tras Reinicio

# Reiniciar host
reboot

# Tras reinicio, verificar montajes automáticos
df -h | grep -E "(nfs|cifs)"
ls -la /mnt/shared_data/

# Verificar que contenedores pueden seguir escribiendo
pct start 100 && pct start 101
sleep 10
pct exec 100 -- bash -c "echo 'Post-reinicio privilegiado' > /mnt/shared/test_post_reboot.txt"
pct exec 101 -- bash -c "echo 'Post-reinicio no privilegiado' >> /mnt/shared/test_post_reboot.txt"

🔧 Solución de Problemas

Error: "Permission denied" al escribir

Síntomas:

pct exec 101 -- bash -c "echo test > /mnt/shared/test.txt"
# bash: /mnt/shared/test.txt: Permission denied

Diagnóstico:

# Verificar permisos del directorio
ls -la /mnt/shared_data/
getfacl /mnt/shared_data/

# Verificar grupo en contenedor
pct exec 101 -- groups www-data
pct exec 101 -- id www-data

Soluciones:

  1. Falta grupo en contenedor:

    pct exec 101 -- groupadd -g 1000 sharedfiles
    pct exec 101 -- usermod -aG sharedfiles www-data
    
  2. Faltan ACLs en host:

    setfacl -R -m g:sharedfiles:rwx /mnt/shared_data
    setfacl -d -m g:sharedfiles:rwx /mnt/shared_data
    
  3. Permisos base incorrectos:

    chmod 2775 /mnt/shared_data
    chown root:sharedfiles /mnt/shared_data
    

Error: "No such file or directory" al montar

Síntomas:

mount: /mnt/nfs_share: mount point does not exist

Solución:

# Crear punto de montaje
mkdir -p /mnt/nfs_share

# Verificar conectividad al servidor
ping 192.168.1.50
showmount -e 192.168.1.50

Error: Archivos aparecen con propietario incorrecto

Síntomas:

ls -la /mnt/shared_data/
# -rw-r--r-- 1 100033 100033 5 sep 8 archivo.txt

Diagnóstico:

  • UIDs/GIDs numéricos indican problema de mapeo
  • 100033 = UID 33 (www-data) en contenedor no privilegiado

Solución:

# Verificar mapeo en configuración LXC
cat /etc/pve/lxc/101.conf | grep -E "(lxc.idmap|mp0)"

# Debe mostrar:
# lxc.idmap: u 0 100000 65536
# lxc.idmap: g 0 100000 65536
# mp0: /mnt/shared_data,mp=/mnt/shared,backup=0,acl=1,shared=1

# Corregir permisos con ACLs
setfacl -R -m g:sharedfiles:rwx /mnt/shared_data

Error: Montaje no persiste tras reinicio

Síntomas:

  • Tras reinicio, df -h no muestra el recurso montado
  • Contenedores no pueden acceder a /mnt/shared

Diagnóstico:

# Verificar /etc/fstab
cat /etc/fstab | grep -E "(nfs|cifs)"

# Probar montaje manual
mount -a

Solución:

# Corregir entrada en /etc/fstab
# Para NFS:
192.168.1.50:/export/shared /mnt/nfs_share nfs rw,hard,nofail,_netdev 0 0

# Para Samba:
//192.168.1.60/shared /mnt/samba_share cifs credentials=/etc/cifs-credentials,_netdev,nofail 0 0

# Probar configuración
umount /mnt/nfs_share
mount /mnt/nfs_share

Error: "Transport endpoint is not connected"

Síntomas:

ls /mnt/nfs_share
# ls: cannot access '/mnt/nfs_share': Transport endpoint is not connected

Solución:

# Desmontar forzosamente
umount -f /mnt/nfs_share

# O si no funciona:
umount -l /mnt/nfs_share  # lazy unmount

# Verificar conectividad
ping 192.168.1.50
showmount -e 192.168.1.50

# Remontar
mount /mnt/nfs_share

📋 Comandos de Referencia Rápida

Gestión de Grupos

# Crear grupo con GID específico
groupadd -g 101000 sharedfiles

# Añadir usuario a grupo
usermod -aG sharedfiles usuario

# Ver grupos de un usuario
groups usuario
id usuario

# Ver miembros de un grupo
getent group sharedfiles

Gestión de Permisos

# Permisos básicos con setgid
chmod 2775 /directorio
chown root:sharedfiles /directorio

# ACLs
setfacl -R -m g:sharedfiles:rwx /directorio    # Existente
setfacl -d -m g:sharedfiles:rwx /directorio    # Por defecto
getfacl /directorio                            # Ver ACLs

Montajes de Red

# NFS
mount -t nfs servidor:/ruta /punto/montaje
showmount -e servidor

# Samba/CIFS  
mount -t cifs //servidor/recurso /punto/montaje -o credentials=/archivo
smbclient -L servidor

Contenedores LXC

# Configurar punto de montaje
pct set ID -mp0 /host/path,mp=/container/path,backup=0,acl=1,shared=1

# Ejecutar comando en contenedor
pct exec ID -- comando

# Ver configuración
cat /etc/pve/lxc/ID.conf

🎯 Resumen Final

Flujo Completo de Configuración

  1. Host: Crear directorio + grupo + permisos + ACLs
  2. Recurso: Montar NFS/Samba o usar directorio local
  3. Contenedores: Crear grupo + añadir usuarios
  4. Montaje: Configurar puntos de montaje con shared=1,acl=1
  5. Verificar: Probar escritura cruzada entre contenedores

Puntos Clave

  • Grupo universal: sharedfiles con GID 101000 en host, GID 1000 en contenedores no privilegiados
  • Setgid bit: chmod 2775 asegura herencia de grupo
  • ACLs: Garantizan permisos consistentes independientemente de umask
  • shared=1: Esencial para clusters y migraciones
  • _netdev: Necesario en /etc/fstab para recursos de red

Compatibilidad

Esta configuración funciona con:

  • Contenedores privilegiados y no privilegiados
  • NFS (todas las versiones)
  • Samba/CIFS
  • Directorios locales
  • Clusters Proxmox
  • Migraciones en vivo
  • Backups con vzdump (excluye puntos de montaje)

Con esta guía tendrás un sistema robusto y escalable para compartir recursos entre tu host Proxmox y contenedores LXC, manteniendo permisos correctos y compatibilidad total.