Skip to content

Instantly share code, notes, and snippets.

@manelrodero
Last active August 30, 2025 18:13
Show Gist options
  • Select an option

  • Save manelrodero/ab36b56690a8f7b565cdd5c22fd33476 to your computer and use it in GitHub Desktop.

Select an option

Save manelrodero/ab36b56690a8f7b565cdd5c22fd33476 to your computer and use it in GitHub Desktop.
Crear un LXC desde la CLI de Proxmox
#!/bin/bash
# Crear LXC desde CLI Proxmox v3.0 (2025-08-29) by Manel Rodero
# Valores predeterminados
default_template="local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
default_privileged="no"
default_docker="no"
default_disk_size=8
default_memory=512
default_cores=1
default_nameserver="192.168.1.81 192.168.1.82"
default_mount_samba="no"
default_mount_rsync="no"
default_swap=512
default_gateway="192.168.1.1"
# Función para comprobar si el CT ID ya existe
function ct_id_exists {
pct list | awk '{print $1}' | grep -qw "$1"
}
# Pedir datos al usuario con valores por defecto
# Obtener lista de plantillas disponibles en el almacenamiento local
echo "Plantillas disponibles en 'local':"
templates=()
display_names=()
while IFS= read -r line; do
if [[ "$line" == local:vztmpl/* ]]; then
templates+=("$line")
# Eliminar el prefijo para mostrarlo más limpio
display_names+=("${line#local:vztmpl/}")
fi
done < <(pveam list local | awk '{print $1}' | grep '^local:vztmpl/')
# Mostrar las plantillas numeradas
for i in "${!display_names[@]}"; do
echo "$((i+1)). ${display_names[$i]}"
done
# Preguntar al usuario cuál desea usar
while true; do
read -p "Introduce el número de la plantilla que quieres usar: " template_choice
if [[ "$template_choice" =~ ^[0-9]+$ ]] && (( template_choice >= 1 && template_choice <= ${#templates[@]} )); then
template="${templates[$((template_choice-1))]}"
break
else
echo "Opción inválida. Introduce un número entre 1 y ${#templates[@]}."
fi
done
while true; do
read -p "Introduce el CT ID: " ct_id
if ct_id_exists "$ct_id"; then
echo "Error: El CT ID $ct_id ya existe. Por favor, introduce un CT ID diferente."
else
break
fi
done
read -p "Introduce el nombre del contenedor: " hostname
read -p "Privilegiado (yes/no) [${default_privileged}]: " privileged
privileged=${privileged:-$default_privileged}
# Preguntar si utilizará Docker
read -p "¿Utilizarás Docker? (yes/no) [${default_docker}]: " docker
docker=${docker:-$default_docker}
# Pedir el password dos veces para confirmación
while true; do
read -s -p "Introduce el password del usuario 'root': " password1
echo
read -s -p "Confirma el password del usuario 'root': " password2
echo
if [ "$password1" == "$password2" ]; then
password=$password1
break
else
echo "Error: Los passwords no coinciden. Por favor, inténtalo de nuevo."
fi
done
read -p "Introduce el tamaño del disco (GB) [${default_disk_size}]: " disk_size
disk_size=${disk_size:-$default_disk_size}
read -p "Introduce la memoria RAM (MB) [${default_memory}]: " memory
memory=${memory:-$default_memory}
read -p "Introduce el número de cores [${default_cores}]: " cores
cores=${cores:-$default_cores}
read -p "Introduce la dirección IP (192.168.1.x): " ip
read -p "Introduce los servidores DNS (separados por espacios) [${default_nameserver}]: " nameserver
nameserver=${nameserver:-$default_nameserver}
# Preguntar si se desea montar /datos/samba/media
read -p "¿Quieres montar /datos/samba/media en el CT? (yes/no) [${default_mount_samba}]: " mount_samba
mount_samba=${mount_samba:-$default_mount_samba}
# Preguntar si se desea montar /backup/rsync
read -p "¿Quieres montar /backups/rsync en el CT? (yes/no) [${default_mount_rsync}]: " mount_rsync
mount_rsync=${mount_rsync:-$default_mount_rsync}
# Convertir "yes" o "no" a valores para el flag de privilegio
if [ "$privileged" == "yes" ]; then
unprivileged=0
else
unprivileged=1
fi
# Mostrar un resumen de los datos
echo "Resumen de datos:"
echo "Plantilla: $template"
echo "CT ID: $ct_id"
echo "Nombre del contenedor: $hostname"
echo "Privilegiado: $privileged"
echo "Utilizará Docker: $docker"
echo "Password: [oculto]"
echo "Tamaño del disco: ${disk_size}GB"
echo "Memoria RAM: ${memory}MB"
echo "Cores: $cores"
echo "IP: $ip"
echo "Servidores DNS: $nameserver"
echo "Montar /datos/samba/media: $mount_samba"
echo "Montar /backups/rsync: $mount_rsync"
echo "Memoria SWAP: ${default_swap}MB"
echo "Gateway: $default_gateway"
# Confirmación del usuario
read -p "¿Son correctos estos datos? (yes/no) [no]: " confirm
confirm=${confirm:-no}
if [ "$confirm" == "yes" ]; then
# Ejecutar el comando para crear el LXC
pct create $ct_id $template \
--ostype debian --arch amd64 \
--hostname $hostname --unprivileged $unprivileged --password $password --ssh-public-keys /root/id_edcsa.pub \
--storage local-lvm --rootfs volume=local-lvm:${disk_size} \
--cores $cores \
--memory $memory --swap $default_swap \
--net0 name=eth0,bridge=vmbr0,firewall=1,ip=${ip}/24,gw=$default_gateway \
--nameserver "$nameserver" \
--start false
# Verificar si el contenedor se creó correctamente
if ct_id_exists "$ct_id"; then
# Configurar opciones adicionales si se utilizará Docker
if [ "$docker" == "yes" ]; then
pct set $ct_id -features nesting=1,keyctl=1
fi
# Configurar punto de montaje si se desea montar /datos/samba/media
if [ "$mount_samba" == "yes" ]; then
pct set $ct_id -mp0 /datos/samba/media,mp=/mnt/samba
fi
# Configurar punto de montaje si se desea montar /backups/rsync
if [ "$mount_rsync" == "yes" ]; then
pct set $ct_id -mp1 /backups/rsync,mp=/mnt/rsync
fi
else
echo "Error: No se pudo crear el contenedor con CT ID $ct_id."
fi
else
echo "Operación cancelada por el usuario."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment