#!/bin/bash # -- byad12.pages.dev/scripts/proxmox.sh # -- https://www.chemahosting.eu ############################################################## # VARIABLES ############################################################## dominio="chemahosting.eu" ############################################################## # CODIFICACIÓN DEL SCRIPT ############################################################## export LANG=C.UTF-8 export LC_ALL=C.UTF-8 ############################################################## # INSTALAR DEPENDENCIAS ############################################################## PAQUETES=() #command -v /usr/games/cowsay >/dev/null 2>&1 || PAQUETES+=("cowsay") command -v cmatrix >/dev/null 2>&1 || PAQUETES+=("cmatrix") command -v curl >/dev/null 2>&1 || PAQUETES+=("curl") if [ ${#PAQUETES[@]} -gt 0 ]; then apt-get update apt-get install -y "${PAQUETES[@]}" fi ############################################################## # ANIMACIÓN DE CMATRIX ############################################################## clear if command -v cmatrix &> /dev/null; then cmatrix -b & PID=$! sleep 2 kill $PID 2>/dev/null wait $PID 2>/dev/null fi clear ############################################################## # DEFINIR BUCLE ############################################################## while true; do clear Ne=$'\033[1m' # Texto en negrita Bl=$'\033[0m' # Resetear formato Ro=$'\033[31;1m' # Texto en negrita y en rojo Ro_=$'\033[22;31m' # Quita negrita (22) y pone rojo (31) Ve=$'\033[32;1m' # Texto en negrita y en verde Ve_=$'\033[22;32m' # Quita negrita (22) y pone verde (32) Am=$'\033[33;1m' # Texto en negrita y en amarillo Am_=$'\033[22;33m' # Quita negrita (22) y pone amarillo (33) Az=$'\033[34;1m' # Texto en negrita y en azul Az_=$'\033[22;34m' # Quita negrita (22) y pone azul (34) echo -e "\nScript hecho por ${Az}byAd12.pages.dev${Bl} para ${Az}www.${dominio}${Bl} en 2025\n${Bl}" printf "%b\n" \ " | ${Az}CONFIGURACIÓN BÁSICA ${Bl}" \ " | ============================" \ "${Ne}1${Bl} | Configuración inicial" \ "${Ne}2${Bl} | Apagado automático" \ "${Ne}3${Bl} | Instalar temas de Proxmox UI" \ " | " \ " | ${Az}PROXMOX ${Bl}" \ " | ================" \ "${Ne}4${Bl} | Clúster" \ "${Ne}5${Bl} | Corosync" \ "${Ne}6${Bl} | Contenedores LXC" \ " | " \ " | ${Az}SERVICIOS ${Bl}" \ " | ===========" \ "${Ne}7${Bl} | Cloudflared" \ "${Ne}8${Bl} | Docker" \ "${Ne}9${Bl} | NFS" \ "${Ne}10${Bl} | Python" \ " | " \ " | ${Az}VPN ${Bl}" \ " | =======" \ "${Ne}11${Bl} | Netbird" \ "${Ne}12${Bl} | OpenVPN" \ " | " \ " | ${Az}MENÚ ${Bl}" \ " | ======" \ "${Ne}0${Bl} | Cerrar" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var echo -e "${Bl}" case $var in ############################################################## # CERRAR PROGRAMA ############################################################## 0) break ;; q) break ;; quit) break ;; exit) break ;; ############################################################## # CONFIGURACIÓN INICIAL ############################################################## 1) clear echo -e "\n${Az}Configuración actual de '${Bl}timedatectl${Az}'...${Bl}" timedatectl echo -e "\n${Az}Sincronizando reloj (NTP) y fijando BIOS en UTC...${Bl}" timedatectl set-timezone Europe/Madrid timedatectl set-local-rtc 0 chronyc makestep hwclock -w echo -e "\n${Az}Verificando los cambios de '${Bl}timedatectl${Az}'...${Bl}" timedatectl echo -e "\n${Az}Instalando el paquete '${Bl}fastfetch${Az}' mediante APT...${Bl}" apt-get install -y fastfetch echo -e "\n${Az}Aplicando modificaciones en '${Bl}~/.bashrc${Az}'...${Bl}" if ! grep -q "clear" ~/.bashrc; then echo "clear" >> ~/.bashrc fi if ! grep -q "fastfetch" ~/.bashrc; then echo "fastfetch" >> ~/.bashrc echo "echo ''" >> ~/.bashrc fi ;; ############################################################## # APAGADO AUTOMÁTICO ############################################################## 2) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Ejecutar la opción número '${Bl}1${Am_}' del script → '${Bl}Configuración inicial${Am_}'.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" read -p 'Hora a apagar (00-23): ' hora; [[ -z "${hora// /}" || "${hora}" == "exit" ]] && continue read -p 'Minutos a apagar (00-59): ' minuto; [[ -z "${minuto// /}" || "${minuto}" == "exit" ]] && continue read -p 'Segundos a apagar (00-59): ' segundos; [[ -z "${segundos// /}" || "${segundos}" == "exit" ]] && continue echo -e "\n${Az}Verificando los valores recibidos...${Bl}" if ! [[ "${hora}" =~ ^[0-9]+$ ]] || ! [[ "${minuto}" =~ ^[0-9]+$ ]] || ! [[ "${segundos}" =~ ^[0-9]+$ ]]; then echo -e "${Ro}Error: ${Ro_}Solo se permiten números.${Bl}\n" read -p "Pulse ENTER para reiniciar el programa:" continue fi if [ "${hora}" -gt 23 ] || [ "${minuto}" -gt 59 ] || [ "${segundos}" -gt 59 ]; then echo -e "${Ro}Error: ${Ro_}Hora, minuto o segundos fuera de rango.${Bl}\n" read -p "Pulse ENTER para reiniciar el programa:" continue fi echo -e "\n${Az}Añadiendo la regla de apagado con Crontab...${Bl}" tarea="${minuto} ${hora} * * * /sbin/shutdown -h now" (crontab -l 2>/dev/null; echo "${tarea}") | crontab - ;; ############################################################## # INSTALAR TEMAS DE PROXMOX UI ############################################################## 3) clear echo -e "${Az}Descargando '${Bl}PVEThemes${Az}' desde GitHub...${Bl}" git clone https://github.com/Happyrobot33/PVEThemes echo -e "\n${Az}Asignando permisos de ejecución al script '${Bl}install.sh${Az}'...${Bl}" cd PVEThemes chmod +x install.sh echo -e "\n${Am}A continuación se ejecutará el script. Porfavor, ejecute la opción '${Bl}instalar${Am}'.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" echo -e "${Az}Ejecutando el script '${Bl}install.sh${Az}'...${Bl}" ./install.sh echo -e "\n${Am}Importante:${Bl}" echo -e "${Am_} - Elimina la caché de la página web y luego vaya al apartado de '${Bl}temas${Am_}'.${Bl}" ;; ############################################################## # PROXMOX - CLÚSTER ############################################################## 4) clear printf "%b\n" \ " | ${Az}CLÚSTER - OPCIONES | CONTRASEÑA | MÁSTER ${Bl}" \ " | ============================= | ========== | ======" \ "${Ne}1${Bl} | Crear un clúster | | Sí" \ "${Ne}2${Bl} | Unirse a un clúster existente | | " \ "${Ne}3${Bl} | Quitar un nodo del clúster | Sí | Sí" \ "${Ne}4${Bl} | Eliminar un clúster | Sí | " \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # PROXMOX - CLÚSTER - CREAR UN CLÚSTER ############################################################## 1) clear read -p 'Nombre del clúster a crear: ' nombre_cluster; [[ -z "${nombre_cluster// /}" || "$nombre_cluster" == "exit" ]] && continue echo -e "\n${Az}Creando un clúster con el nombre '${Bl}${nombre_cluster}${Az}'...${Bl}" pvecm create "${nombre_cluster}" echo -e "\n${Az}Forzando la actualización de los certificados...${Bl}" pvecm updatecerts --force ;; ############################################################## # PROXMOX - CLÚSTER - UNIRSE A CLÚSTER EXISTENTE ############################################################## 2) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. No tener ningún CT ni VM creada en el sistema.${Bl}" echo -e "${Am_} 2. Ejecutar la opción '${Bl}Instalar y entrar en Netbird${Am_}' del apartado de '${Bl}Netbird${Am_}'.${Bl}" echo -e "${Am_} 3. Seleccionar el nodo máster que creó el clúster.${Bl}" echo -e "${Am_} 4. Saber la contraseña del nodo máster.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" read -p 'Nodo máster (coruna1): ' nodo_nombre; [[ -z "${nodo_nombre// /}" || "$nodo_nombre" == "exit" ]] && continue echo -e "\n${Az}Comprobando la conexión con el nodo máster con un PING...${Bl}" ping -c 2 "${nodo_nombre}" if [ $? -ne 0 ]; then echo -e "${Ro}Error: ${Ro_}No se puede contactar con '${Bl}${nodo_nombre}${Ro}'.${Bl}\n" read -p "Pulse ENTER para reiniciar el programa:" continue fi echo -e "\n${Az}Forzando la actualización de los certificados...${Bl}" pvecm updatecerts --force echo -e "\n${Az}Intentando unirse al clúster de '${Bl}${nodo_nombre}${Az}'...${Bl}" pvecm add "${nodo_nombre}" ;; ############################################################## # PROXMOX - CLÚSTER - QUITAR UN NODO DEL CLÚSTER ############################################################## 3) clear read -p "[ 1/2 ] ${Am_}¿Estás seguro de querer quitar este nodo del clúster?${Bl} (s/n): " verificacion1; [[ "$verificacion1" != "s" && "$verificacion1" != "S" ]] && continue read -p "[ 2/2 ] ${Am_}¿Estás seguro de querer quitar este nodo del clúster?${Bl} (s/n): " verificacion2; [[ "$verificacion2" != "s" && "$verificacion2" != "S" ]] && continue echo -e "" read -p "${Am_}Ingrese la contraseña para ejecutar esta función: ${Bl}" verificacion3; [[ -z "${verificacion3// /}" || "${verificacion3}" == "exit" ]] && continue hash_ingresado=$(echo -n "$verificacion3" | sha256sum | awk '{print $1}') if [ "$hash_ingresado" == "f2e53c927c66fe711e8e88ef9b37a8e3187f1652216b313fc8eb2513883dd360" ]; then read -p 'Nodo que se desea quitar del clúster: ' nodo_nombre; [[ -z "${nodo_nombre// /}" || "${nodo_nombre}" == "exit" ]] && continue echo -e "\n${Az}Intentando quitar del clúster al nodo '${Bl}${nodo_nombre}${Az}'...${Bl}" pvecm del "${nodo_nombre}" else echo -e "${Ro}Error: ${Ro_}La contraseña es incorrecta.${Bl}" fi ;; ############################################################## # PROXMOX - CLÚSTER - ELIMINAR UN CLUSTER ############################################################## 4) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Solo puedes ejecutar esta opción en el nodo maestro.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" read -p "${Ro_}1/2 ¿Estás seguro de querer eliminar el clúster? (s/${Ro}n${Ro_}): ${Bl}" verificacion1; [[ "${verificacion1}" != "s" && "${verificacion1}" != "S" ]] && continue read -p "${Ro_}2/2 ¿Estás seguro de querer eliminar el clúster? (s/${Ro}n${Ro_}): ${Bl}" verificacion2; [[ "${verificacion2}" != "s" && "${verificacion2}" != "S" ]] && continue echo -e "" read -p "${Am_}Ingrese la contraseña para ejecutar esta función: ${Bl}" verificacion3; [[ -z "${verificacion3// /}" || "${verificacion3}" == "exit" ]] && continue hash_ingresado=$(echo -n "${verificacion3}" | sha256sum | awk '{print $1}') if [ "${hash_ingresado}" == "f2e53c927c66fe711e8e88ef9b37a8e3187f1652216b313fc8eb2513883dd360" ]; then echo -e "${Ve_}Contraseña correcta${Bl}" echo -e "\n${Az}Deteniendo los servicios '${Bl}pve-cluster${Az}' y '${Bl}corosync${Az}'...${Bl}" systemctl stop pve-cluster corosync killall -9 pmxcfs 2>/dev/null echo -e "\n${Az}Haciendo una copia de seguridad de Corosync...${Bl}" mkdir -p /root/pve_backup cp -r /etc/pve/corosync.conf /root/pve_backup/ 2>/dev/null echo -e "${Ve}La copia de seguridad de '${Bl}/etc/pve${Ve}' se encuentra en '${Bl}/root/pve_backup${Ve}'.${Bl}" echo -e "\n${Az}Limpiando los ficheros de configuración de Corosync...${Bl}" rm -f /etc/pve/corosync.conf rm -rf /etc/corosync/* echo -e "\n${Az}Forzando la actualización de los certificados...${Bl}" pmxcfs -l pvecm updatecerts --force echo -e "\n${Az}Reiniciando el servicio '${Bl}pve-cluster${Az}'...${Bl}" systemctl restart pve-cluster echo -e "\n${Az}Deteniendo el servicio '${Bl}corosync${Az}'...${Bl}" systemctl stop corosync echo -e "\n${Az}Deshabilitando el servicio '${Bl}corosync${Az}'...${Bl}" systemctl disable corosync else echo -e "${Ro}Error: ${Ro_}La contraseña es incorrecta.${Bl}" fi ;; ############################################################## # PROXMOX - CLÚSTER - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # PROXMOX - COROSYNC ############################################################## 5) clear printf "%b\n" \ " | ${Az}COROSYNC - OPCIONES | CONTRASEÑA | MÁSTER ${Bl}" \ " | ======================= | ========== | ======" \ "${Ne}1${Bl} | Editar la configuración | | Sí" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # PROXMOX - COROSYNC - EDITAR LA CONFIGURACIÓN ############################################################## 1) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Solo puedes ejecutar esta opción en el nodo maestro.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" echo -e "${Az}Deteniendo el servicio '${Bl}pve-cluster${Az}'...${Bl}" systemctl stop pve-cluster echo -e "\n${Az}Iniciando '${Bl}pmxcfs${Az}' en modo local...${Bl}" pmxcfs -l echo -e "\n${Az}Iniciando el editor de texto con el fichero '${Bl}/etc/pve/corosync.conf${Az}'...${Bl}" /usr/bin/nano /etc/pve/corosync.conf clear echo -e "${Az}Cerrando todos los procesos de '${Bl}pmxcfs${Az}'...${Bl}" killall pmxcfs echo -e "\n${Az}Iniciando los servicios '${Bl}pve-cluster${Az}', '${Bl}pvedaemon${Az}' y '${Bl}pvestatd${Az}'...${Bl}" systemctl start pve-cluster pvedaemon pvestatd ;; ############################################################## # PROXMOX - COROSYNC - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # PROXMOX - CONTENEDORES LXC ############################################################## 6) clear printf "%b\n" \ " | ${Az}CT LXC - OPCIONES ${Bl}" \ " | ===================" \ "${Ne}1${Bl} | Crear un backup" \ "${Ne}2${Bl} | Restaurar un backup" \ "${Ne}3${Bl} | Quitar bloqueo" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # PROXMOX - CONTENEDORES LXC - CREAR UN BACKUP ############################################################## 1) clear read -p 'ID del contenedor a hacer una backup: ' id_ct; [[ -z "${id_ct// /}" || "${id_ct}" == "exit" ]] && continue read -p 'Almacenamiento (local): ' almacenamiento; [[ -z "${almacenamiento// /}" || "${almacenamiento}" == "exit" ]] && continue echo -e "\n${Az}Creando el backup del contenedor con ID '${Bl}${id_ct}${Az}'...${Bl}" vzdump "${id_ct}" --mode stop --compress lzo --storage "${almacenamiento}" ;; ############################################################## # PROXMOX - CONTENEDORES LXC - RESTAURAR UN BACKUP ############################################################## 2) clear read -p 'ID del contenedor a restaurar una backup: ' id_ct; [[ -z "${id_ct// /}" || "${id_ct}" == "exit" ]] && continue read -p 'Ruta al backup (.tar.lzo): ' ruta; [[ -z "${ruta// /}" || "${ruta}" == "exit" ]] && continue read -p 'Almacenamiento (local-lvm): ' almacenamiento; [[ -z "${almacenamiento// /}" || "${almacenamiento}" == "exit" ]] && continue echo -e "\n${Az}Restaurando el backup del contenedor con ID '${Bl}${id_ct}${Az}'...${Bl}" pct restore "${id_ct}" "${ruta}" --storage "${almacenamiento}" ;; ############################################################## # PROXMOX - CONTENEDORES LXC - QUITAR BLOQUEO ############################################################## 3) clear read -p 'ID del contenedor bloqueado: ' id_ct; [[ -z "${id_ct// /}" || "${id_ct}" == "exit" ]] && continue echo -e "\n${Az}Verificando el estado el contenedor con ID '${Bl}${id_ct}${Az}'...${Bl}" pct status "${id_ct}" echo -e "\n${Az}Desbloqueando el contenedor con ID '${Bl}${id_ct}${Az}'...${Bl}" pct unlock "${id_ct}" echo -e "\n${Az}Verificando el estado el contenedor con ID '${Bl}${id_ct}${Az}'...${Bl}" pct status "${id_ct}" echo -e "\n${Am}Si el contenedor sigue bloqueado, puede eliminar el bloqueo manualmente con el siguiente comando:${Bl}" echo -e " rm /var/lock/lxc/${id_ct}.lock" ;; ############################################################## # PROXMOX - CONTENEDORES LXC - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # SERVICIOS - CLOUDFLARED ############################################################## 7) clear printf "%b\n" \ " | ${Az}CLOUDFLARED - OPCIONES ${Bl}" \ " | ===================================" \ "${Ne}1${Bl} | Instalar e iniciar sesión" \ "${Ne}2${Bl} | Crear un túnel - HTTP(S)" \ "${Ne}3${Bl} | Actualizar la versión del servicio" \ "${Ne}4${Bl} | Desinstalar y purgar configuración" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # SERVICIOS - CLOUDFLARED - INSTALAR E INICIAR SESIÓN ############################################################## 1) clear echo -e "${Am_}Requisitos:${Bl}" echo -e "${Am_} 1. El administrador debe estar activo para permitir el inicio de sesión.${Bl}" echo -e "${Am_} 2. Tener un sistema Debian/Ubuntu con AMD64.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" echo -e "${Az}Instalando Cloudflared AMD64 desde GitHub...${Bl}" curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb apt-get install -y ./cloudflared.deb echo -e "${Az}Eliminando el fichero temporal...${Bl}" rm -f ./cloudflared.deb echo -e "\n${Az}Configurando el repositorio de paquetes...${Bl}" mkdir -p /etc/apt/keyrings curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /etc/apt/keyrings/cloudflare-main.gpg >/dev/null echo "deb [signed-by=/etc/apt/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bookworm main" | tee /etc/apt/sources.list.d/cloudflare-main.list echo -e "\n${Az}Porfavor, inicie sesión con la siguiente URL:${Bl}" cloudflared login echo -e "\n${Az}Verificando la versión del servicio '${Bl}cloudflared${Az}'...${Bl}" cloudflared --version ;; ############################################################## # SERVICIOS - CLOUDFLARED - CREAR UN TÚNEL HTTP(S) ############################################################## 2) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Ejecutar la opción '${Bl}Instalar e iniciar sesión${Am_}' del apartado de '${Bl}Cloudflared${Am_}'.${Bl}" echo -e "${Am_} 2. El administrador debe eliminar el registro DNS si existe.${Bl}" echo -e "${Am_} 3. No tener ningún túnel previamente creado.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" read -p 'Nombre del túnel a crear (sin espacios): ' nombre_tunel; [[ -z "${nombre_tunel// /}" || "${nombre_tunel}" == "exit" ]] && continue read -p 'Nombre del subdominio (solo subdominio): ' nombre_dominio; [[ -z "${nombre_dominio// /}" || "${nombre_dominio}" == "exit" ]] && continue read -p 'Puerto del servicio web: ' puerto_web; [[ -z "${puerto_web// /}" || "${puerto_web}" == "exit" ]] && continue read -p 'http/https: ' tipo_conexion; [[ -z "${tipo_conexion// /}" || "${tipo_conexion}" == "exit" ]] && continue echo -e "\n${Az}Creando un nuevo túnel...${Bl}" info=$(cloudflared tunnel create "${nombre_tunel}") echo -e "\n${Az}Extrayendo el UUID del túnel...${Bl}" uuid=$(echo "${info}" | grep -oE '[0-9a-fA-F-]{36}' | head -n 1) echo -e "UUID del túnel: ${Am}${uuid}${Bl}" echo -e "\n${Az}Creando la carpeta '${Bl}/etc/cloudflared/${Az}'...${Bl}" mkdir -p /etc/cloudflared echo -e "\n${Az}Creando y configurando el fichero '${Bl}/etc/cloudflared/config.yml${Az}'...${Bl}" cat < /etc/cloudflared/config.yml tunnel: $uuid credentials-file: /etc/cloudflared/${uuid}.json loglevel: debug originRequest: noTLSVerify: true ingress: - hostname: ${nombre_dominio}.${dominio} service: ${tipo_conexion}://127.0.0.1:${puerto_web} - service: http_status:404 EOF echo -e "\n${Az}Copiando las credenciales del túnel en '${Bl}/etc/cloudflared/${Az}'...${Bl}" cp ~/.cloudflared/"${uuid}".json /etc/cloudflared/ echo -e "\n${Az}Asignando permisos a las credenciales...${Bl}" chmod 600 /etc/cloudflared/"${uuid}".json chown root:root /etc/cloudflared/"${uuid}".json echo -e "\n${Az}Creando un nuevo registro DNS de tipo CNAME...${Bl}" cloudflared tunnel route dns "${nombre_tunel}" "${nombre_dominio}" echo -e "\n${Az}Instalando el servicio '${Bl}cloudflared${Az}'...${Bl}" cloudflared service install echo -e "\n${Az}Habilitando el servicio '${Bl}cloudflared${Az}'...${Bl}" systemctl enable --now cloudflared echo -e "\n${Az}Verificando la sintaxis de '${Bl}/etc/cloudflared/config.yml${Az}'...${Bl}" cloudflared tunnel ingress validate ;; ############################################################## # SERVICIOS - CLOUDFLARED - ACTUALIZAR LA VERSIÓN DEL SERVICIO ############################################################## 3) clear echo -e "${Az}Versión del servicio '${Bl}cloudflared${Az}' antes de la actualización:${Bl}" cloudflared --version echo -e "\n${Az}Configurando el repositorio de paquetes...${Bl}" mkdir -p /etc/apt/keyrings curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /etc/apt/keyrings/cloudflare-main.gpg >/dev/null echo "deb [signed-by=/etc/apt/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bookworm main" | tee /etc/apt/sources.list.d/cloudflare-main.list echo -e "\n${Az}Actualizando los paquetes con APT...${Bl}" apt-get update echo -e "\n${Az}Actualizando el paquete '${Bl}cloudflared${Az}'...${Bl}" apt-get install --only-upgrade -y cloudflared echo -e "\n${Az}Reiniciando el servicio '${Bl}cloudflared${Az}'...${Bl}" systemctl restart cloudflared echo -e "\n${Az}Verificando la versión del servicio '${Bl}cloudflared${Az}'...${Bl}" cloudflared --version ;; ############################################################## # SERVICIOS - CLOUDFLARED - DESINSTALAR Y PURGAR CONFIGURACIÓN ############################################################## 4) clear echo -e "${Am}Aviso:${Bl}" echo -e "${Am_} - Los túneles creados se eliminarán localmente, pero no en Cloudflare.${Bl}" echo -e "${Am_} - Los registros DNS deben eliminarse manualmente.${Bl}" echo -e "" echo -e "\n${Az}Deteniendo el servicio '${Bl}cloudflared${Az}'...${Bl}" systemctl stop cloudflared echo -e "\n${Az}Deshabilitando el servicio '${Bl}cloudflared${Az}'...${Bl}" systemctl disable cloudflared echo -e "\n${Az}Desinstalando el servicio '${Bl}cloudflared${Az}'...${Bl}" cloudflared service uninstall echo -e "\n${Az}Purgando con APT el paquete '${Bl}cloudflared${Az}'...${Bl}" apt-get purge cloudflared -y echo -e "\n${Az}Eliminando las configuraciones de '${Bl}/etc/cloudflared/${Az}' y '${Bl}/root/.cloudflared/${Az}'...${Bl}" rm -rf /etc/cloudflared/* rm -rf /root/.cloudflared/* ;; ############################################################## # SERVICIOS - CLOUDFLARED - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # SERVICIOS - DOCKER ############################################################## 8) clear printf "%b\n" \ " | ${Az}DOCKER - OPCIONES ${Bl}" \ " | ====================================" \ "${Ne}1${Bl} | Instalar Docker en Debian" \ "${Ne}2${Bl} | Configurar 'favonia/cloudflare-ddns'" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # SERVICIOS - DOCKER - INSTALAR DOCKER EN DEBIAN ############################################################## 1) clear echo -e "${Am}Aviso:${Bl}" echo -e "${Am_} - Esta instalación se basa en un sistema Debian.${Bl}" echo -e "" echo -e "${Az}Desinstalando paquetes conflictivos...${Bl}" apt-get remove $(dpkg --get-selections docker.io docker-compose docker-doc podman-docker containerd runc | cut -f1) echo -e "\n${Az}Instalando las dependencias '${Bl}ca-certificates${Az}' y '${Bl}curl${Az}'...${Bl}" apt-get update apt-get install -y ca-certificates curl echo -e "\n${Az}Añadiendo el repositorio oficial de Docker...${Bl}" install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc tee /etc/apt/sources.list.d/docker.sources <> /etc/exports echo -e "\n${Az}Aplicando los cambios...${Bl}" exportfs -ra echo -e "\n${Az}Reiniciando el servicio '${Am_}nfs-kernel-server${Az}'...${Bl}" systemctl restart nfs-kernel-server ;; ############################################################## # SERVICIOS - NFS - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # SERVICIOS - PYTHON ############################################################## 10) clear printf "%b\n" \ " | ${Az}PYTHON - OPCIONES ${Bl}" \ " | =====================================" \ "${Ne}1${Bl} | Ejecutar un fichero .py como servicio" \ "${Ne}2${Bl} | Configurar alertas de Discord" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # SERVICIOS - PYTHON - EJECUTAR UN FICHERO .PY COMO SERVICIO ############################################################## 1) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Hay que tener python previamente instalado.${Bl}" echo -e "${Am_} 2. Al principio del fichero .py debe haber esta línea: '${Bl}#!/usr/bin/env python3${Am_}'.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" read -p 'Ruta absoluta al fichero: ' ruta_fichero; [[ -z "${ruta_fichero// /}" || "${ruta_fichero}" == "exit" ]] && continue echo -e "\n${Az}Realizando las verificaciones necesarias...${Bl}" if [[ ! -f "${ruta_fichero}" ]]; then echo -e "${Ro}Error: ${Ro_}El fichero no existe.${Bl}\n" read -p "Pulse ENTER para reiniciar el programa:" continue fi echo -e "\n${Az}Definiendo las variables necesarias...${Bl}" nombre_script=$(basename "${ruta_fichero}") directorio_trabajo=$(dirname "${ruta_fichero}") echo -e "\n${Az}Detectando el entorno de Python...${Bl}" python_path=$(which python3) echo -e "\n${Az}Creando un nuevo servicio systemd llamado '${Bl}script-python${Az}'...${Bl}" cat < /etc/systemd/system/script-python.service [Unit] Description=Servicio Python: ${nombre_script} After=network.target [Service] Type=simple User=root WorkingDirectory=${directorio_trabajo} ExecStart=${python_path} -u ${ruta_fichero} Restart=on-failure RestartSec=5 StandardOutput=append:/var/log/script-python.log StandardError=append:/var/log/script-python.log [Install] WantedBy=multi-user.target EOF echo -e "\n${Az}Configurando los permisos y registros...${Bl}" chmod +x "${ruta_fichero}" touch /var/log/script-python.log echo -e "\n${Az}Recargando systemd...${Bl}" systemctl daemon-reload echo -e "\n${Az}Habilitando el servicio '${Bl}script-python${Az}'...${Bl}" systemctl enable --now script-python.service echo -e "\n${Az}Verificando el estado del servicio '${Bl}script-python${Az}'...${Bl}" systemctl status --no-pager script-python.service echo -e "${Am}Nota:${Bl}" echo -e "${Am_} En caso de error utilice el siguiente comando: '${Bl}tail -f /var/log/script-python.log${Am_}'.${Bl}" echo -e "" ;; ############################################################## # SERVICIOS - PYTHON - CONFIGURAR ALERTAS DE DISCORD ############################################################## 2) clear read -p 'Webhook de Discord: ' webhook; [[ -z "${webhook// /}" || "${webhook}" == "exit" ]] && continue echo -e "\n${Az}Instalando la dependencia '${Bl}curl${Az}'...${Bl}" apt-get install -y curl echo -e "\n${Az}Creando el script '${Bl}/usr/local/bin/discord-alerta.sh${Az}'...${Bl}" cat < /usr/local/bin/discord-alerta.sh #!/bin/bash WEBHOOK="${webhook}" EOF cat <<'EOF' >> /usr/local/bin/discord-alerta.sh [[ "$1" == *"discord-alerta.sh"* ]] && exit 0 HOSTNAME=$(hostname) USER_NAME=$(whoami) USER_ID=$(id -u) CLEAN_CMD=$(echo "$1" | sed 's/"/\\"/g') MESSAGE="### host $HOSTNAME • $USER_NAME • uid \`$USER_ID\`\n\n\`\`\`bash\n$CLEAN_CMD\n\`\`\`" PAYLOAD="{\"content\": \"$MESSAGE\"}" curl -s -H "Content-Type: application/json" -X POST -d "$PAYLOAD" "$WEBHOOK" > /dev/null 2>&1 & EOF echo -e "\n${Az}Asignando permisos al script '${Bl}/usr/local/bin/discord-alerta.sh${Az}'...${Bl}" chmod +x /usr/local/bin/discord-alerta.sh echo -e "\n${Az}Inyectando el hook en '${Bl}/etc/bash.bashrc${Az}'...${Bl}" if ! grep -q "Monitor Discord" /etc/bash.bashrc; then cat <<'EOF' >> /etc/bash.bashrc # --- Monitor Discord --- # ----------------------- logger_discord() { local ULTIMO_CMD=$(history 1 | sed 's/^[ ]*[0-9]*[ ]*//') if [[ "${ULTIMO_CMD}" != "${LAST_CMD_DISCORD}" ]] && [[ -n "${ULTIMO_CMD}" ]] && [[ "${ULTIMO_CMD}" != "exit" ]]; then /usr/local/bin/discord-alerta.sh "${ULTIMO_CMD}" export LAST_CMD_DISCORD="${ULTIMO_CMD}" fi } if [[ $- == *i* ]]; then PROMPT_COMMAND="history -a; logger_discord; $PROMPT_COMMAND" fi # ----------------------- EOF echo -e "${Ve}El hook ha sido inyectado correctamente en '${Bl}/etc/bash.bashrc${Ve}'.${Bl}" else echo -e "${Ro}El hook ya existe en '${Bl}/etc/bash.bashrc${Ro}', omitiendo...${Bl}" fi echo -e "\n${Am}Importante:${Bl}" echo -e "${Am_} - REINICIA LA SESIÓN para activar las alertas.${Bl}" ;; ############################################################## # SERVICIOS - PYTHON - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # VPN - NETBIRD ############################################################## 11) clear printf "%b\n" \ " | ${Az}NETBIRD - OPCIONES ${Bl}" \ " | =====================================" \ "${Ne}1${Bl} | Instalar y entrar en la red" \ "${Ne}2${Bl} | Cambiar la IP de este peer en la red" \ "${Ne}3${Bl} | Actualizar la versión del servicio" \ "${Ne}4${Bl} | Desinstalar y purgar la configuración" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # VPN - NETBIRD - INSTALAR Y ENTRAR EN LA RED ############################################################## 1) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Debes tener el Set-up key de Netbird.${Bl}" echo -e "${Am_} 2. Un administrador debe cambiar la IPv4 desde el panel de administración.${Bl}" echo -e "${Am_} 3. La IPv4 que se vaya a configurar debe estar libre.${Bl}" echo -e "${Am_} 4. Se debe eliminar del fichero '${Bl}/etc/hosts${Am_}' cualquier registro antiguo.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" read -p 'Set-up key de Netbird: ' llave_netbird; [[ -z "${llave_netbird// /}" || "${llave_netbird}" == "exit" ]] && continue read -p 'Nombre que se le asignará en NetBird: ' nombre_equipo; [[ -z "${nombre_equipo// /}" || "${nombre_equipo}" == "exit" ]] && continue echo -e "\n${Az}Instalando la dependencia '${Bl}curl${Az}'...${Bl}" apt-get install -y curl echo -e "\n${Az}Instalando Netbird mediante un script oficial...${Bl}" curl -fsSL https://pkgs.netbird.io/install.sh | bash echo -e "\n${Az}Iniciando la conexión con Netbird...${Bl}" netbird up --setup-key "${llave_netbird}" --allow-server-ssh --enable-ssh-root --hostname "${nombre_equipo}" echo -e "\n${Az}Habilitando el servicio '${Bl}netbird${Az}'...${Bl}" systemctl enable --now netbird echo -e "\n${Az}Añadiendo los nodos de Proxmox en '${Bl}/etc/hosts${Az}'...${Bl}" grep -q "coruna1" /etc/hosts || cat <> /etc/hosts 172.16.0.100 coruna1 172.16.0.101 coruna2 172.16.0.102 malaga1 172.16.0.103 almeria1 EOF echo -e "\n${Az}Tu IPv4 actual en NetBird es:${Bl}" netbird status --ipv4 echo -e "\n${Am}Cambie ahora la IPv4 de este peer en '${Bl}https://app.netbird.io/peers${Am}', luego puse ENTER:${Bl}" read -p '' respuesta_enter echo -e "${Az}Reiniciando la conexión con Netbird...${Bl}" netbird down systemctl restart netbird # Aquí se debería hacer el netbird up automáticamente sleep 2 echo -e "\n${Az}Verificando la conexión con Netbird...${Bl}" netbird up --setup-key "${llave_netbird}" --allow-server-ssh --enable-ssh-root --hostname "${nombre_equipo}" echo -e "\n${Az}Tu IPv4 actual en NetBird es:${Bl}" netbird status --ipv4 ;; ############################################################## # VPN - NETBIRD - CAMBIAR LA IP DE ESTE PEER EN LA RED ############################################################## 2) clear echo -e "${Am}Requisitos:${Bl}" echo -e "${Am_} 1. Debes tener el Set-up key de Netbird.${Bl}" echo -e "${Am_} 2. Un administrador debe cambiar la IPv4 desde el panel de administración.${Bl}" echo -e "${Am_} 3. La IPv4 que se vaya a configurar debe estar libre.${Bl}" echo -e "${Am_} 4. Se debe eliminar del fichero '${Bl}/etc/hosts${Am_}' cualquier registro antiguo.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" echo -e "\n${Az}Tu IPv4 actual en NetBird es:${Bl}" netbird status --ipv4 echo -e "\n${Am}Cambie ahora la IPv4 de este peer en '${Bl}https://app.netbird.io/peers${Am}', luego puse ENTER:${Bl}" read -p '' respuesta_enter echo -e "${Az}Reiniciando la conexión con Netbird...${Bl}" netbird down systemctl restart netbird # Aquí se debería hacer el netbird up automáticamente sleep 2 echo -e "\n${Az}Tu IPv4 actual en NetBird es:${Bl}" netbird status --ipv4 ;; ############################################################## # VPN - NETBIRD - ACTUALIZAR LA VERSIÓN DEL SERVICIO ############################################################## 3) clear echo -e "${Am}Aviso:${Bl}" echo -e "${Am_} - La conexión a la red de NetBird será interrumpida si hay una nueva versión disponible.${Bl}" echo -e "${Am_} - Si se requiere, se deberá autentificar manualmente a la red.${Bl}" echo -e "" echo -e "${Az}Versión del servicio '${Bl}netbird${Az}' antes de la actualización:${Bl}" netbird version echo -e "\n${Az}Actualizando el paquete '${Bl}netbird${Az}'...${Bl}" apt-get install --only-upgrade -y netbird echo -e "\n${Az}Verificando la versión del servicio '${Bl}netbird${Az}'...${Bl}" netbird version ;; ############################################################## # VPN - NETBIRD - DESINSTALAR Y PURGAR LA CONFIGURACIÓN ############################################################## 4) clear read -p "${Ro_}¿Estás seguro de querer desinstalar Netbird? (s/${Ro}n${Ro_}): ${Bl}" verificacion1; [[ "$verificacion1" != "s" && "$verificacion1" != "S" ]] && continue echo -e "\n${Az}Desconectando el peer de la red...${Bl}" netbird down echo -e "\n${Az}Quitando el peer de la red...${Bl}" netbird deregister echo -e "\n${Az}Deteniendo el servicio '${Bl}netbird${Az}'...${Bl}" systemctl stop netbird systemctl disable netbird echo -e "\n${Az}Desinstalando mediante APT el paquete '${Bl}netbird${Az}'...${Bl}" apt-get remove --purge netbird -y echo -e "\n${Az}Eliminando el repositorio y la clave GPG...${Bl}" rm -f /etc/apt/sources.list.d/netbird.list rm -f /usr/share/keyrings/netbird-archive-keyring.gpg echo -e "\n${Az}Borrando los ficheros y carpetas de configuración...${Bl}" rm -rf /etc/netbird rm -rf /var/lib/netbird rm -rf /var/log/netbird rm -rf ~/.config/netbird rm -rf ~/.netbird ;; ############################################################## # VPN - NETBIRD - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## # VPN - OPENVPN ############################################################## 12) clear printf "%b\n" \ " | ${Az}OPENVPN - OPCIONES ${Bl}" \ " | ======================================" \ "${Ne}1${Bl} | Crear un CT y ejecutar openvpn-install" \ "${Ne}2${Bl} | Solo ejecutar openvpn-install" \ | column --table --separator '|' --keep-empty-lines echo "" read -p "Opción: ${Am}" var_sec echo -e "${Bl}" case $var_sec in ############################################################## # VPN - OPENVPN - CREAR Y CONFIGURAR UN CONTENEDOR ############################################################## 1) clear read -p 'ID para asignar al CT: ' id_ct; [[ -z "${id_ct// /}" || "${id_ct}" == "exit" ]] && continue read -p 'Nombre para asignar al CT (a-z; 0-9; -): ' name_ct; [[ -z "${name_ct// /}" || "${name_ct}" == "exit" ]] && continue read -p 'Storage donde se guardará la plantilla: ' storage_name_template; [[ -z "${storage_name_template// /}" || "${storage_name_template}" == "exit" ]] && continue read -p 'Storage donde se guardará el disco del CT: ' storage_name_ct; [[ -z "${storage_name_ct// /}" || "${storage_name_ct}" == "exit" ]] && continue read -p 'Cantidad de GigaBytes de disco para asignar al CT: ' ct_gigabytes; [[ -z "${ct_gigabytes// /}" || "${ct_gigabytes}" == "exit" ]] && continue echo -e "" read -p 'Dirección IPv4/Máscara CIDR: ' ip_address; [[ -z "${ip_address// /}" || "${ip_address}" == "exit" ]] && continue read -p 'Dirección IPv4 del Gateway: ' gateway_address; [[ -z "${gateway_address// /}" || "${gateway_address}" == "exit" ]] && continue template="debian-13-standard_13.6-1_amd64.tar.zst" echo -e "\n${Az}Descargando la plantilla '${Bl}${template}${Az}'...${Bl}" if ! pveam list "${storage_name_template}" | grep -q "${template}"; then pveam update pveam download "${storage_name_template}" "${template}" fi echo -e "\n${Az}Creando el CT usando la plantilla descargada...${Bl}" pct create "${id_ct}" "${storage_name_template}":vztmpl/"${template}" \ --unprivileged 1 -features nesting=1 \ --net0 name=eth0,bridge=vmbr0,firewall=0,ip="${ip_address}",gw="${gateway_address}",type=veth \ --nameserver 1.1.1.1 \ --onboot 1 \ --hostname "${name_ct}" \ --rootfs "${storage_name_ct}":"${ct_gigabytes}" echo -e "\n${Az}Editando el fichero '${Bl}/dev/net/tun${Az}'...${Bl}" conf="/etc/pve/lxc/${id_ct}.conf" grep -qxF "lxc.cgroup2.devices.allow: c 10:200 rwm" "${conf}" || echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >> "${conf}" grep -qxF "lxc.mount.entry: /dev/net dev/net none bind,create=dir" "${conf}" || echo "lxc.mount.entry: /dev/net dev/net none bind,create=dir" >> "${conf}" if [[ -e /dev/net/tun ]]; then chown 100000:100000 /dev/net/tun ls -l /dev/net/tun fi echo -e "\n${Az}Iniciando el CT...${Bl}" pct start "${id_ct}" echo -e "\n${Az}Instalando las dependencias en el CT...${Bl}" pct exec "${id_ct}" -- apt-get update pct exec "${id_ct}" -- apt-get dist-upgrade -y pct exec "${id_ct}" -- apt-get install -y openvpn git pct exec "${id_ct}" -- git clone https://github.com/Nyr/openvpn-install /root/openvpn-install clear echo -e "\n${Az}Asigne una contraseña para el usuario '${Bl}root${Az}'...${Bl}" pct exec "${id_ct}" -- passwd root echo -e "\n${Az}Iniciando el instalador de OpenVPN...${Bl}" pct exec "${id_ct}" -- bash -c "cd /root/openvpn-install && bash openvpn-install.sh" clear echo -e "\n${Az}Verificando el servicio de '${Bl}openvpn${Az}'...${Bl}" pct exec "${id_ct}" -- systemctl | grep openvpn echo -e "\n${Az}Verificando el puerto de '${Bl}openvpn${Az}'...${Bl}" pct exec "${id_ct}" -- ps aux | grep vpn ;; ############################################################## # VPN - OPENVPN - EJECUTAR OPENVPN-INSTALL ############################################################## 2) clear echo -e "${Az}Creando la carpeta '${Bl}/root/openvpn-install/${Az}'...${Bl}" mkdir -p /root/openvpn-install/ echo -e "\n${Az}Descargando el script en '${Bl}/root/openvpn-install/openvpn-install.sh${Az}'...${Bl}" wget --no-cache -O /root/openvpn-install/openvpn-install.sh https://raw.githubusercontent.com/Nyr/openvpn-install/refs/heads/master/openvpn-install.sh echo -e "${Az}Asignando permisos de ejecución al script '${Bl}/root/openvpn-install/openvpn-install.sh${Az}'...${Bl}" chmod +x /root/openvpn-install/openvpn-install.sh echo -e "\n${Am}Importante:${Bl}" echo -e "${Am_} - Al acabar de configurar el script, copie el perfil '${Bl}.ovpn${Am_}' creado.${Bl}" echo -e "" read -p "Pulse ENTER para continuar con el programa: " respuesta_enter; [[ "${respuesta_enter}" == "exit" ]] && continue echo -e "" echo -e "\n${Az}Ejecutando el script '${Bl}/root/openvpn-install/openvpn-install.sh${Az}' mediante '${Bl}bash${Az}'...${Bl}" bash /root/openvpn-install/openvpn-install.sh ;; ############################################################## # VPN - OPENVPN - MENÚ ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac ;; ############################################################## *) echo -e "${Ro}Valor inválido${Bl}" ;; esac echo read -p "Pulse ENTER para reiniciar el programa: " _ done