#!/bin/bash ################################################################# # auto-elearning # # Instala automáticamente una Wiki (MediaWiki) y un Campus # # Virtual (Moodle). # # Para ello instala un entorno LEMP (GNU/Linux+Nginx+MySQL/ # # MariaDB+PHP) o LAMP (GNU/Linux+Apache+MySQL/MariaDB+PHP). # # Además instala certificados SSL/TLS válidos de Let's Encrypt # # (o auto-firmados) y genera copias de seguridad diariamente. # # # # Guzman Castanedo Villalba (guzman@castanedo.es) Junio 2018 # # GPLv3 (https://www.gnu.org/licenses/gpl.html) # ################################################################# ayuda() { # Muestra ayuda al usuario y termina echo -en "AYUDA AUTO-ELEARNING:\n" echo -en " Instala automáticamente una Wiki (MediaWiki) y un Campus Virtual (Moodle).\n" echo -en " Para ello instala un entorno LEMP (GNU/Linux+Nginx+MySQL/MariaDB+PHP) o LAMP (GNU/Linux+Apache+MySQL/MariaD+PHP).\n" echo -en " Además instala certificados SSL/TLS válidos de Let's Encrypt (o auto-firmados) y genera copias de seguridad diariamente.\n" echo -en " Licencia: GPLv3 (Autor: Guzmán Castanedo Villalba [guzman@castanedo.es]).\n" echo -en "\nSINOPSIS:\n" echo -en " sudo ./"$(basename $0)" (Forma 1)\n" echo -en " sudo ./"$(basename $0)" [OPCIONES] (Forma 2)\n" echo -en "\nDESCRIPCIÓN:\n" echo -en " La primera forma permite instalarlo todo de forma INTERACTIVA (contestando a unas preguntas que saldrán por pantalla).\n" echo -en " La segunda forma permite hacer lo mismo de forma NO INTERACTIVA (indicando todas las opciones desde el terminal).\n" echo -en " Esta aplicación requiere de permisos de administrador (root).\n" echo -en "\nCOMPATIBILIDAD:\n" echo -en " Esta aplicación es compatible con Ubuntu 18.04, 16.04, Debian 9, CentOS 7 y Fedora 28.\n" echo -en " Requiere de un sistema moderno que tenga instalado SystemD.\n" echo -en " Se irán añadiendo nuevas distribuciones en futuras versiones.\n" echo -en "\nOPCIONES:\n" echo -en " -d, --dominio, --fqdn : dominio principal del servidor (OBLIGATORIO)\n" echo -en " --lemp: activa servidor web Nginx (Por Defecto)\n" echo -en " --lamp: activa servidor web Apache2\n" echo -en " --mariadb: activa base de datos mariadb (Por Defecto)\n" echo -en " --mysql: activa base de datos mysql\n" echo -en " Sólo es posible para Ubuntu 18.04\n" echo -en " --password-sql : contraseña root de base de datos (OBLIGATORIO)\n" echo -en " --max-upload-size : tamaño de subida permitido (Por Defecto: \"100M\")\n" echo -en " --lets-encrypt: activa certificados SSL/TLS de Let's Encrypt\n" echo -en " --auto-firmados: activa certificadaos SSL/TLS auto-firmados (sólo para pruebas)\n" echo -en "\nOPCIONES MEDIA WIKI:\n" echo -en " --media-wiki: activa instalación de Media Wiki (Por Defecto)\n" echo -en " Si se activa esta opción --nombre-mw, --dominios-mw y --password-mw son OBLIGARIOS\n" echo -en " --no-media-wiki: desactiva instalación de Media Wiki\n" echo -en " --nombre-mw : nombre de la wiki\n" echo -en " --dominios-mw : dominios para Media Wiki\n" echo -en " Deben estar configuradas las DNS para que estos apunten a este servidor\n" echo -en " Se pueden indicar más de uno separándolos con espacios\n" echo -en " --password-mw : contraseña para usuario 'admin'\n" echo -en "\nOPCIONES MOODLE:\n" echo -en " --moodle: activa instalación de Moodle (Por Defecto)\n" echo -en " Si se activa esta opción --nombre-mo, --nombre-corto-mo, --dominios-mo y --password-mo son OBLIGARIOS\n" echo -en " --no-moodle: desactiva instalación de Moodle\n" echo -en " --nombre-mo : nombre del campus\n" echo -en " --nombre-corto-mo : nombre corto del campus (una sola palabra)\n" echo -en " --dominio-mo : dominio para Moodle\n" echo -en " Deben estar configuradas las DNS para que estos apunten a este servidor\n" echo -en " Sólo se puede indicar UN DOMINIO\n" echo -en " --password-mo : contraseña para usuario 'admin'\n" echo -en "\nOTRAS OPCIONES:\n" echo -en " --php-info: activa info.php (sólo para pruebas)\n" echo -en " --no-php-info: desactiva info.php (Por Defecto)\n" echo -en " --backup: activa los backups automáticos (Por Defecto)\n" echo -en " --no-backup: desactiva los backups automáticos\n" echo -en "\nEJEMPLOS:\n" echo -en " sudo "$0"\n" echo -en " Activa el programa en modo interactivo\n" echo -en " sudo "$0" -d ejemplo.com --lemp --mariadb --password-sql 123456 --media-wiki --nombre-mw \"Wiki de Ejemplo\" --dominios-mw \"ejemplo.com www.ejemplo.com wiki.ejemplo.com\" --password-mw qwerty --no-moodle\n" echo -en " Instala LEMP con mariadb y Media Wiki\n" echo -en " sudo "$0" -d ejemplo.com --lamp --mysql --password-sql 123456 --no-media-wiki --moodle --nombre-mo \"Campus Virtual\" --nombre-corto-mo EJEMPLO --dominio-mo moodle.ejemplo.com --password-mo qwerty\n" echo -en " Instala LAMP con MySQL y Moodle\n\n" } comprobarError() { # Permite comprobar si se ha producido un error y de serlo devuelve un código de error # comprobarError exitNum codeNum extraInfo # 1xx: Servidor Web # 2xx: Base de Datos # 3xx: PHP # 4xx: SSL/TLS # 5xx: MediaWiki # 6xx: Moodle # 7xx: Backup automático # 8xx: Dependencias # 9xx: Servicios & Firewall type="ERROR" exitNum=$1 shift codeNum=$1 shift extraInfo=$@ case $codeNum in 1) error="$type $codeNum:\tInstalación interrumpida por el usuario.\n" ;; 2) error="$type $codeNum:\tError interno (selección express).\n" ;; 3) error="$type $codeNum:\tError interno (selección avanzada).\n" ;; 4) error="\n$type $codeNum:\tEl archivo '"$(realpath $extraInfo)"' no existe.\n" ;; 5) error="\n$type $codeNum:\tEl directorio '"$(realpath $extraInfo)"' no existe.\n" ;; 6) error="$type $codeNum:\tError interno (selección SSL/TLS).\n" ;; 10) error="$type $codeNum:\tOpción inesperada '$extraInfo'.\n" ;; 11) error="$type $codeNum:\tDominio Principal no definido ('--hostname \"ejemplo.com\"').\n" ;; 12) error="$type $codeNum:\tContraseña SQL no definida ('--password-sql \"pass\"').\n" ;; 13) error="$type $codeNum:\tTamaño de subida no definido ('--max-upload-size \"100M\"').\n" ;; 14) error="$type $codeNum:\tNombre Media Wiki no definida (--nombre-mw \"Wiki de Ejemplo\").\n" ;; 15) error="$type $codeNum:\tDominios Media Wiki no definidos (--dominios-mw \"ejemplo.com wiki.ejemplo.com\").\n" ;; 16) error="$type $codeNum:\tContraseña Media Wiki no definida (--password-mw \"pass\").\n" ;; 17) error="$type $codeNum:\tNombre Moodle no definido (--nombre-mo \"Campus Virtual de Ejemplo\").\n" ;; 18) error="$type $codeNum:\tNombre Corto Moodle no definido (--nombre-corto-mo \"Ejemplo\").\n" ;; 19) error="$type $codeNum:\tDominio Moodle no definido (--dominio-mo \"moodle.ejemplo.com\").\n" ;; 20) error="$type $codeNum:\tContraseña Moodle no definida (--password-mo \"pass\").\n" ;; 100) error="$type $codeNum:\tError interno (selección del servidor web).\n" ;; 101) error="\n$type $codeNum:\tError al instalar Apache2.\nDetalles:\n$extraInfo\n" ;; 102) error="\n$type $codeNum:\tError al instalar Nginx.\nDetalles:\n$extraInfo\n" ;; 103) error="\n$type $codeNum:\tError al nstalar repositorio 'epel-release'.\nDetalles:\n$extraInfo\n" ;; 104) error="\n$type $codeNum:\tError interno (instalación Apache2).\n" ;; 105) error="\n$type $codeNum:\tError interno (instalación Nginx).\n" ;; 106) type="WARNING" error="\n$type $codeNum:\tImposible instalar 'info.php'.\n" ;; 107) error="\n$type $codeNum:\tError al configurar Nginx.\n" ;; 108) error="\n$type $codeNum:\tError al configurar Apache2.\n" ;; 200) error="$type $codeNum:\tError interno (selección de base de datos).\n" ;; 201) error="\n$type $codeNum:\tError al instalar MySQL.\nDetalles:\n$extraInfo\n" ;; 202) error="\n$type $codeNum:\tError al instalar MariaDB.\nDetalles:\n$extraInfo\n" ;; 203) error="\n$type $codeNum:\tError interno (instalación MySQL).\n" ;; 204) error="\n$type $codeNum:\tError interno (instalación MariaDB).\n" ;; 205) error="\n$type $codeNum:\t$DIST no incluye MySQL en sus repositorios.\n" ;; 206) type="WARNING" error="\n$type $codeNum:\tUsuario 'root' ya dispone de contraseña." ;; 207) error="\n$type $codeNum:\tImposible cambiar la contraseña de 'root'." ;; 208) error="\n$type $codeNum:\tImposible desactivar acceso 'root' desde el exterior." ;; 209) error="\n$type $codeNum:\tImposible eliminar usuarios anónimos." ;; 210) type="WARNING" error="\n$type $codeNum:\tImposible eliminar bases de datos de pruebas." ;; 211) type="WARNING" error="\n$type $codeNum:\tImposible eliminar los permisos de las bases de datos de pruebas." ;; 212) error="\n$type $codeNum:\tImposible recargar base de datos." ;; 213) error="\n$type $codeNum:\tImposible configurar SQL.\n" ;; 214) type="WARNING" error="\n$type $codeNum:\tSQL ya está configurado." ;; 300) error="\n$type $codeNum:\tError interno (instalación PHP-7).\n" ;; 301) error="\n$type $codeNum:\tError interno (Web Server no seleccionado).\n" ;; 302) error="\n$type $codeNum:\tError al instalar PHP-7.\nDetalles:\n$extraInfo\n" ;; 303) error="\n$type $codeNum:\tError al instalar Repositorio Remi.\nDetalles:\n$extraInfo\n" ;; 304) error="\n$type $codeNum:\tSistema Operativo no compatible con PHP-7 ($OS $DIST $REV).\n" ;; 305) error="\n$type $codeNum:\tImposible configurar PHP-7.\n" ;; 401) error="\n$type $codeNum:\tError al instalar 'certbot' (Let's Encrypt).\n" ;; 402) error="\n$type $codeNum:\tImposible generar Certificados Autofirmados.\n" ;; 403) error="\n$type $codeNum:\tImposible generar claves de intercambio Diffie-Hellman.\n" ;; 404) error="\n$type $codeNum:\tImposible generar Certificados Let's Encrypt.\n" ;; 501) error="\n$type $codeNum:\tImposible descargar MediaWiki-1.31.0.\n" ;; 502) error="\n$type $codeNum:\tImposible configurar MediaWiki-1.31.0.\n" ;; 503) type="WARNING" error="\n$type $codeNum:\tYa existe una copia configurada de MediaWiki en el dominio: '$extraInfo'." ;; 601) error="\n$type $codeNum:\tImposible descargar Moodle-3.5.1.\n" ;; 602) error="\n$type $codeNum:\tImposible configurar Moodle-3.5.1.\n" ;; 603) type="WARNING" error="\n$type $codeNum:\tYa existe una copia configurada de Moodle en el dominio: '$extraInfo'." ;; 604) error="\n$type $codeNum:\tImposible configurar SELinux.\n" ;; 605) error="\n$type $codeNum:\tImposible instalar 'policycoreutils-python'.Detalles:\n$extraInfo\n" ;; 701) type="WARNING" error="\n$tupe $codeNum:\tImposible configurar actualizaciones automáticas.\n" ;; 800) error="$type $codeNum:\tEs necesario ser root ('sudo $0').\n" ;; 801) error="$type $codeNum:\t'whiptail' no instalado.\n" ;; 802) error="$type $codeNum:\t'hostnamectl' no instalado.\n" ;; 803) error="$type $codeNum:\t'apt-get' no instalado.\n" ;; 804) error="$type $codeNum:\t'yum' no instalado.\n" ;; 805) error="\n$type $codeNum:\tImposible actualizar repositorio\nDetalles:\n$extraInfo.\n" ;; 806) error="$type $codeNum:\t'ufw' no instalado.\nDetalles:\n$extraInfo\n" ;; 807) error="$type $codeNum:\t'firewall-cmd' no instalado.\n" ;; 808) error="$type $codeNum:\t'tput' no instalado.\nDetalles:\n$extraInfo\n" ;; 809) error="$type $codeNum:\t'sed' no instalado.\nDetalles:\n$extraInfo\n" ;; 810) error="$type $codeNum:\t'curl' no instalado.\nDetalles:\n$extraInfo\n" ;; 811) error="$type $codeNum:\t'tar' no instalado.\nDetalles:\n$extraInfo\n" ;; 812) error="$type $codeNum:\t'gzip' no instalado.\nDetalles:\n$extraInfo\n" ;; 813) error="$type $codeNum:\t'bzip2' no instalado.\nDetalles:\n$extraInfo\n" ;; 814) error="$type $codeNum:\t'xz' no instalado.\nDetalles:\n$extraInfo\n" ;; 815) error="$type $codeNum:\t'openssl' no instalado.\nDetalles:\n$extraInfo\n" ;; 816) error="$type $codeNum:\t'find' no instalado.\n" ;; 817) error="$type $codeNum:\tLa Distribución '$OS $DIST $REV' no está soportada.\nSoportadas: Ubuntu 16.04, 18.04, Debian 9, CentOS 7 y Fedora 28.\n" ;; 900) error="$type $codeNum:\tError interno (habilitar servicio).\n" ;; 901) error="$type $codeNum:\tImposible encender servicio '$extraInfo'.\n" ;; 902) error="$type $codeNum:\tImposible habilitar servicio '$extraInfo' durante el arranque.\n" ;; 903) error="$type $codeNum:\tError interno (deshabilitar servicio).\n" ;; 904) error="$type $codeNum:\tImposible parar servicio '$extraInfo'.\n" ;; 905) error="$type $codeNum:\tImposible deshabilitar servicio '$extraInfo' durante el arranque.\n" ;; 906) type="WARNING" error="\n$type $codeNum:\tImposible añadir regla al cortafuegos ('$extraInfo').\n" ;; 907) type="WARNING" error="\n$type $codeNum:\tImposible encender cortafuegos.\n" ;; 908) error="\n$type $codeNum:\tError interno (instalar Virtual Host).\n" ;; 909) error="\n$type $codeNum:\tVirtual Host '$extraInfo' no existe.\n" ;; 910) error="\n$type $codeNum:\tImposible copiar Virtual Host '$extraInfo'.\n" ;; 911) error="\n$type $codeNum:\tImposible activar Virtual Host '$extraInfo'.\n" ;; 912) error="\n$type $codeNum:\tError interno (recargar servicio).\n" ;; 913) error="\n$type $codeNum:\tImposible recargar servicio '$extraInfo'.\n" ;; *) error="ERROR 13:\tError interno (comprobación de errores)\n" exitNum=1 codeNum=13 ;; esac if [ $exitNum -ne 0 ];then echo -en "$error" | tee -a $logFile if [ $type = "ERROR" ];then exit $codeNum fi fi unset error exitNum codeNum type } OSInfo() { # Detecta el OS en el que se está ejecutando el programa, así como su versión # Sólo continuará si se trata de una distribución compatible echo -en "Detectando SO..." >> $logFile OS=$(uname -s) if [ $OS = "Linux" ]; then OS="GNU/Linux" if [ -f /etc/os-release ]; then DIST=$(grep ^NAME= /etc/os-release | cut -d = -f 2 | cut -d '"' -f 2) REV=$(grep ^VERSION= /etc/os-release | cut -d = -f 2 | cut -d '"' -f 2) ID=$(grep ^ID= /etc/os-release | cut -d = -f 2 | cut -d '"' -f 2) VERSION=$(grep ^VERSION_ID= /etc/os-release | cut -d = -f 2 | cut -d '"' -f 2) for i in $ID; do case $i in debian) case $VERSION in 9) # Debian 9 Soportado ;; *) comprobarError 1 817 ;; esac break ;; ubuntu) case $VERSION in 18.04) # Ubuntu 18.04 Soportado ;; 16.04) # Ubuntu 16.04 Soportado ;; *) comprobarError 1 817 ;; esac break ;; rhel|centos) case $VERSION in 7) # CentOS 7 Soportado ;; *) comprobarError 1 817 ;; esac break ;; fedora) case $VERSION in 28) # Fedora 28 Soportado ;; *) comprobarError 1 817 ;; esac break ;; *) comprobarError 1 817 ;; esac done else # Other Linux (No Soportado) comprobarError 1 817 fi else # UNIX, OS X, ... (No Soportado) comprobarError 1 817 fi echo -en " $OS $DIST $REV\n" >> $logFile HDInfo=$(df -h | head -1)"\n"$(df -h | grep ^/dev/sd)"\n"$(df -h | grep ^/dev/mapper) echo -en "$HDInfo\n" >> $logFile } comprobarRoot() { # Comprueba si se está ejecutando con privilegios de root comprobarError $(id -u) 800 } comprobarDependencias() { # Comprueba si están instalados todos los programas necesarios. # En la mayoría de los casos, trata de instalarlos. # Comprobamos whiptail which whiptail > /dev/null 2>&1 comprobarError $? 801 # Comprobamos hostnamectl which hostnamectl > /dev/null 2>&1 comprobarError $? 802 which find > /dev/null 2>&1 comprobarError $? 816 case $ID in debian|ubuntu) # Comprobamos apt-get which apt-get > /dev/null 2>&1 comprobarError $? 803 # Actualizamos base de datos del repositorio echo -en "Actualizando repositorio APT..." | tee -a $logFile result=$(apt-get -q -y update 2>&1) comprobarError $? 805 $result echo -en " OK.\n" | tee -a $logFile # Comprobamos Firewall (ufw) which ufw > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install ufw 2>&1) comprobarError $? 806 $result fi # Comprobamos tput which tput > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install ncurses-bin 2>&1) comprobarError $? 808 $result fi # Comprobar sed which sed > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install sed 2>&1) comprobarError $? 809 $result fi # Comprobar curl which curl > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install curl 2>&1) comprobarError $? 810 $result fi # Comprobamos tar, gzip, bzip2 y xz which tar > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install tar 2>&1) comprobarError $? 811 $result fi which gzip > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install gzip 2>&1) comprobarError $? 812 $result fi which bzip2 > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install bzip2 2>&1) comprobarError $? 813 $result fi which xz > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install xz-utils 2>&1) comprobarError $? 814 $result fi which openssl > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(apt-get -q -y install openssl 2>&1) comprobarError $? 815 $result fi ;; centos|fedora) # Comprobamos yum which yum > /dev/null 2>&1 comprobarError $? 804 # Actualizamos base de datos del repositorio echo -en "Actualizando repositorio YUM..." | tee -a $logFile result=$(yum -y makecache 2>&1) comprobarError $? 805 $result echo -en " OK.\n" | tee -a $logFile # Comprobamos Firewall (firewall-cmd) which firewall-cmd > /dev/null 2>&1 comprobarError $? 807 # Comprobamos tput which tput > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install ncurses 2>&1) comprobarError $? 808 $result fi # Comprobar sed which sed > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install sed 2>&1) comprobarError $? 809 $result fi # Comprobar curl which curl > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install curl 2>&1) comprobarError $? 810 $result fi # Comprobamos tar, gzip, bzip2 y xz which tar > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install tar 2>&1) comprobarError $? 811 $result fi which gzip > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install gzip 2>&1) comprobarError $? 812 $result fi which bzip2 > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install bzip2 2>&1) comprobarError $? 813 $result fi which xz > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install xz 2>&1) comprobarError $? 814 $result fi which openssl > /dev/null 2>&1 if [ $? -ne 0 ];then result=$(yum -y install openssl 2>&1) comprobarError $? 815 $result fi ;; esac } inicializarVariables() { # Inicializa las variables que necesitan de un estado previo apacheOn=false nginxOn=false mySQLOn=false mariaDBOn=false phpOn=false sslOn=false letsEncryptOn=false mediaWikiOn=false moodleOn=false infoPHPOn=false backupOn=false hostname="" logFile="./."$(basename $0)".log" maxUpload="100M" webServerName="" webServerUser="" webServerGroup="" sqlServerName="" dbType="" phpFPMName="" nombreMediaWiki="" dominioMediaWiki="" passwdMediaWiki="" nombreMoodle="" nombreCortoMoodle="" dominioMoodle="" passwdMoodle="" } instalacionExpress() { # Permite una instalación rápida, haciendo el menor número de preguntas # Defecto: Nginx + MariaDB + PHP + Let's Encrypt + MediaWiki + Moodle + Backup nginxOn=true case $ID in debian) mySQLOn=true dbType="mariadb" ;; ubuntu|centos|fedora) mariaDBOn=true dbType="mariadb" ;; esac phpOn=true sslOn=true letsEncryptOn=true mediaWikiOn=true moodleOn=true backupOn=true } mostrarBienvenida() { # Pantalla de bienvenida y muestra SO y estado de los discos ANCHO=$(tput cols) ALTO=$(tput lines) whiptail --title "INSTALACION MEDIAWIKI" --yesno "Este script automatiza completamente la instalación de una WIKI y un CAMPUS VIRTUAL.\nPara ello instala un servidor LAMP, el software MediaWiki y configura todo lo necesario.\n\nInformación del sistema:\nOS: $OS $DIST $REV\n$HDInfo" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --yes-button "Continuar" --no-button "Salir" comprobarError $? 1 } mostrarExpress() { # Pantalla de elección entre instalación express o avanzada express=$(whiptail --title "INSTALACION EXPRESS" --radiolist ": seleccionar : cambiar : moverse\n\nLa instalación express instala Nginx, MariaDB, PHP-7, Let's Encrypt, MediaWiki, Moodle y backups automático.\nSeleccione el tipo de instalación que desee:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) 2 \ "Express" "Instalación rápida" ON \ "Avanzada" "Permite escoger todas las opciones disponibles" OFF \ --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 case $express in Express) instalacionExpress # Preguntas mínimas establecerFQDN leerSQLPasswd mostrarMediaWiki mostrarMoodle mostrarConfirmacion ;; Avanzada) mostrarAvanzada ;; *) comprobarError 1 2 ;; esac unset express } mostrarAvanzada() { # Pantalla que permite instalar un servidor LAMP o LEMP webServer=$(whiptail --title "INSTALACION AVANZADA" --radiolist ": seleccionar : cambiar : moverse\n\nEscoge el tipo de Servidor Web que quieres instalar:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) 2 \ "LEMP" "GNU/Linux + (E)Nginx + MySQL/MariaDB + PHP-7" ON \ "LAMP" "GNU/Linux + Apache + MySQL/MariaDB + PHP-7" OFF \ --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 for i in $webServer; do case $i in LEMP) nginxOn=true ;; LAMP) apacheOn=true ;; *) comprobarError 1 100 ;; esac done # Opciones comunes establecerFQDN mostrarDatabase phpOn=true establecerMaxUpload mostrarComponentes mostrarConfirmacion unset webServer } mostrarComponentes() { # Pantalla de elección de componentes (SSL/TLS, MediaWiki, Moodle, InfoPHP y Backup) componentes=$(whiptail --title "INSTALACION AVANZADA" --checklist ": seleccionar : cambiar : moverse\n\nEscoge los componentes que quieres instalar:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) 5 \ "SSL/TLS" "Instalar certificados para activar HTTPS" ON \ "MediaWiki" "Instalar wiki con MediaWiki" ON \ "Moodle" "Instalar campus virtual con Moodle" ON \ "InfoPHP" "Instalar info.php (sólo para pruebas)" OFF \ "Backup" "Programar backups automáticos" ON \ --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 # Mejora: autodetección de componentes ya instalados for i in $componentes; do case $i in \"SSL/TLS\") # 2 Opciones: Let's Encrypt o Autofirmado mostrarSSL ;; \"MediaWiki\") mediaWikiOn=true mostrarMediaWiki ;; \"Moodle\") moodleOn=true mostrarMoodle ;; \"InfoPHP\") infoPHPOn=true ;; \"Backup\") backupOn=true ;; *) comprobarError 1 3 ;; esac done unset componentes } mostrarSSL() { # Pantalla que permite seleccionar el tipo de certificados ssl=$(whiptail --title "INSTALACION SSL/TLS" --radiolist ": seleccionar : cambiar : moverse\n\nEscoge el tipo de Certificado SSL/TLS que quieres instalar:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) 2 \ "LetsEncrypt" "Compatible con todos los navegadores" ON \ "Auto-Firmado" "Certificados auto-firmados (sólo para pruebas)" OFF \ --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 for i in $ssl; do case $i in LetsEncrypt) sslOn=true letsEncryptOn=true ;; Auto-Firmado) sslOn=true ;; *) comprobarError 1 6 ;; esac done unset ssl } mostrarMediaWiki(){ # Pantalla que pregunta sobre las opciones necesarias para configurar MediaWiki # Introducir nombre wiki while [ -z "$nombreMediaWiki" ]; do nombreMediaWiki=$(whiptail --title "CONFIGURACION MEDIAWIKI" --inputbox "Introduzca el nombre de la Wiki:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 done # Introducir dominio while [ -z "$dominioMediaWiki" ]; do dominioMediaWiki=$(whiptail --title "CONFIGURACION MEDIAWIKI" --inputbox "Introduzca el dominio/subdominio de la Wiki.\nTenga en cuenta que debes apuntar este dominio a la dirección IP de esta máquina mediante un registro DNS de tipo CNAME.\nSi quiere introducir varios dominios sepárelos con espacios. El primero será el principal.\nPor ejemplo: 'www.$hostname $hostname wiki.$hostname'" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) wiki.$hostname --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 done cont=1 serverName="" aliasMediaWiki="" for dominio in $dominioMediaWiki;do if [ $cont -eq 1 ];then # Dominio Principal (ServerName) serverName=$dominio else # Dominios Secundarios (ServerAlias) aliasMediaWiki=$aliasMediaWiki" "$dominio fi cont=$((cont + 1)) done dominioMediaWiki=$serverName # Introducir contraseña control=false error="" while [ $control = false ]; do passwdMediaWiki=$(whiptail --title "CONFIGURACION MEDIAWIKI" --passwordbox "$error""Introduzca la contraseña para el usuario administrador 'admin':" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --nocancel 3>&1 1>&2 2>&3) comprobarError $? 1 passwdMediaWiki2=$(whiptail --title "CONFIGURACION MEDIAWIKI" --passwordbox "Confirme la contraseña:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --nocancel 3>&1 1>&2 2>&3) comprobarError $? 1 if [ -z "$passwdMediaWiki" ] || [ -z "$passwdMediaWiki2" ]; then error="ERROR: LA CONTRASEÑA NO PUEDE ESTAR VACIA.\n" elif [ $passwdMediaWiki != $passwdMediaWiki2 ];then error="ERROR: LAS CONTRASEÑAS NO COINCIDEN.\n" else control=true fi done unset control error passwdMediaWiki2 dominio cont serverName } mostrarMoodle() { # Pantalla que pregunta sobre las opciones necesarias para configurar Moodle # Introducir Nombre Moodle while [ -z "$nombreMoodle" ]; do nombreMoodle=$(whiptail --title "CONFIGURACION MOODLE" --inputbox "Introduzca el NOMBRE COMPLETO del campus virtual.\nPor ejemplo: 'Campus Virtual Ejemplo'." $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 done # Introducir Nombre Corto Moodle while [ -z "$nombreCortoMoodle" ]; do nombreCortoMoodle=$(whiptail --title "CONFIGURACION MOODLE" --inputbox "Introduzca el NOMBRE CORTO del campus virtual.\nPor ejemplo: 'Ejemplo'." $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 done nombreCortoMoodle=$(echo $nombreCortoMoodle | cut -d ' ' -f 1) # Introducir dominio while [ -z "$dominioMoodle" ]; do dominioMoodle=$(whiptail --title "CONFIGURACION MOODLE" --inputbox "Introduzca el dominio/subdominio del campus virtual.\nMoodle SÓLO permite un ÚNICO DOMINIO." $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) moodle.$hostname --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 done cont=1 serverName="" aliasMoodle="" for dominio in $dominioMoodle;do if [ $cont -eq 1 ];then # Dominio Principal (ServerName) serverName=$dominio else # Dominios Secundarios (ServerAlias) aliasMoodle=$aliasMoodle" "$dominio fi cont=$((cont + 1)) done dominioMoodle=$serverName # Introducir contraseña control=false error="" while [ $control = false ]; do passwdMoodle=$(whiptail --title "CONFIGURACION MOODLE" --passwordbox "$error""Introduzca la contraseña para el usuario administrador 'admin':" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --nocancel 3>&1 1>&2 2>&3) comprobarError $? 1 passwdMoodle2=$(whiptail --title "CONFIGURACION MOODLE" --passwordbox "Confirme la contraseña:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --nocancel 3>&1 1>&2 2>&3) comprobarError $? 1 if [ -z "$passwdMoodle" ] || [ -z "$passwdMoodle2" ]; then error="ERROR: LA CONTRASEÑA NO PUEDE ESTAR VACIA.\n" elif [ $passwdMoodle != $passwdMoodle2 ];then error="ERROR: LAS CONTRASEÑAS NO COINCIDEN.\n" else control=true fi done unset control error passwdMoodle2 dominio cont serverName aliasMoodle } mostrarConfirmacion() { # Pantalla que presenta una confirmación antes de realizar la instalación whiptail --title "INSTALACION" --yesno "ESTA TODO LISTO PARA LA INSTALACION.\nNO SE OLVIDE DE GUARDAR LAS CONFIGURACIONES EN UN LUGAR SEGURO, YA QUE SERÁN IMPORTANTES POR SI DESEA HACER ALGÚN CAMBIO EN EL FUTURO.\n¿DESEA CONTINUAR?" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --yes-button "Instalar" --no-button "Salir" comprobarError $? 1 } establecerFQDN() { # Configura el FQDN (dominio principal del servidor) while [ -z "$hostname" ]; do hostname=$(whiptail --title "FQDN" --inputbox "El nombre de dominio principal (FQDN) de este servidor es:\n"$(hostname)"\n\n¿Quieres cambiarlo por otro?" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Cambiar" --cancel-button "No Cambiar" 3>&1 1>&2 2>&3) if [ $? -eq 0 ] && [ ! -z "$hostname" ]; then hostnamectl set-hostname $hostname else hostname=$(hostname) fi done echo -en "Hostname: $hostname\n" >> $logFile } instalarApache() { # Instala Apache2 case $ID in debian|ubuntu) webServerName="apache2" result=$(apt-get -q -y install apache2 2>&1) comprobarError $? 101 $result ;; centos|fedora) webServerName="httpd" result=$(yum -y install httpd 2>&1) comprobarError $? 101 $result if [ $sslOn = true ];then # Instalamos módulo mod_ssl (no se instala por defecto) result=$(yum -y install mod_ssl 2>&1) comprobarError $? 101 $result fi ;; *) comprobarError 1 104 ;; esac deshabilitarServicio $webServerName } configurarApache() { # Configura Apache2 case $ID in debian|ubuntu) apacheConfFile="./etc/apache2/apache2.conf" if [ ! -f $apacheConfFile ];then comprobarError 1 4 $apacheConfFile fi cp -f $apacheConfFile /etc/$webServerName/apache2.conf 2>/dev/null comprobarError $? 108 webServerUser=$(grep ^User /etc/$webServerName/apache2.conf | cut -d ' ' -f 2) webServerGroup=$(grep ^Group /etc/$webServerName/apache2.conf | cut -d ' ' -f 2) if [ ! -L /etc/$webServerName/logs ];then ln -s /var/log/apache2 /etc/$webServerName/logs 2>/dev/null comprobarError $? 108 fi # Activamos mod_rewrite (no viene activado por defecto) a2enmod rewrite >/dev/null 2>&1 comprobarError $? 108 # Activamos mod_ssl y mod_headers (no viene activado por defecto) if [ $sslOn = true ];then a2enmod ssl >/dev/null 2>&1 comprobarError $? 108 a2enmod headers >/dev/null 2>&1 comprobarError $? 108 fi unset apacheConfFile ;; centos|fedora) apacheConfFile="./etc/apache2/conf/httpd.conf" sslConfFile="./etc/apache2/conf.d/ssl.conf" welcomeConfFile="/etc/apache2/conf.d/welcome.conf" if [ ! -f $apacheConfFile ];then comprobarError 1 4 $apacheConfFile fi cp -f $apacheConfFile /etc/$webServerName/conf/httpd.conf 2>/dev/null comprobarError $? 108 # Desactivamos Mensaje de Bienvenida if [ -f $welcomeConfFile ];then sed -i -e 's/^/#/' $welcomeConfFile comprobarError $? 108 fi # Configuramos mod_ssl if [ $sslOn = true ];then if [ ! -f $sslConfFile ];then comprobarError 1 4 $sslConfFile fi cp -f $sslConfFile /etc/$webServerName/conf.d/ssl.conf 2>/dev/null comprobarError $? 108 fi webServerUser=$(grep ^User /etc/$webServerName/conf/httpd.conf | cut -d ' ' -f 2) webServerGroup=$(grep ^Group /etc/$webServerName/conf/httpd.conf | cut -d ' ' -f 2) unset apacheConfFile sslConfFile welcomeConfFile ;; *) comprobarError 1 108 ;; esac # Creamos directorios sites-available y sites-enabled if [ ! -d "/etc/$webServerName/sites-available" ];then mkdir "/etc/$webServerName/sites-available" 2>/dev/null comprobarError $? 5 "/etc/$webServerName/sites-available" fi if [ ! -d "/etc/$webServerName/sites-enabled" ]; then mkdir "/etc/$webServerName/sites-enabled" 2>/dev/null comprobarError $? 5 "/etc/$webServerName/sites-enabled" else # Eliminar Virtual Host por defecto if [ -f /etc/$webServerName/sites-enabled/000-default.conf ];then rm -f /etc/$webServerName/sites-enabled/000-default.conf 2>/dev/null fi fi } instalarNginx() { # Instala Nginx webServerName="nginx" case $ID in ubuntu|debian) result=$(apt-get -q -y install nginx 2>&1) comprobarError $? 102 $result ;; centos) # Sólo para CentOS result=$(yum -y install epel-release) comprobarError $? 103 $result result=$(yum -y install nginx 2>&1) comprobarError $? 102 $result ;; fedora) result=$(yum -y install nginx 2>&1) comprobarError $? 102 $result ;; *) comprobarError 1 105 ;; esac deshabilitarServicio $webServerName } configurarNginx() { # Configura Nginx rm -Rf "/etc/$webServerName/!(sites-available|sites-enabled)" 2>/dev/null comprobarError $? 107 nginxConfFile="./etc/$webServerName" if [ -d "$nginxConfFile" ];then cp -Rf $nginxConfFile/* /etc/$webServerName/ 2>/dev/null comprobarError $? 107 else comprobarError 1 5 "$nginxConfFile" fi # Creamos directorios sites-available y sites-enabled if [ ! -d "/etc/$webServerName/sites-available" ];then mkdir "/etc/$webServerName/sites-available" 2>/dev/null comprobarError $? 5 "/etc/$webServerName/sites-available" fi if [ ! -d "/etc/$webServerName/sites-enabled" ]; then mkdir "/etc/$webServerName/sites-enabled" 2>/dev/null comprobarError $? 5 "/etc/$webServerName/sites-enabled" else # Eliminar Virtual Host por defecto if [ -f /etc/$webServerName/sites-enabled/default ];then rm -f /etc/$webServerName/sites-enabled/default 2>/dev/null fi fi # Configuramos Usuario y Grupo case $ID in debian|ubuntu) webServerUser="www-data" webServerGroup=$webServerUser ;; centos|fedora) webServerUser="nginx" webServerGroup=$webServerUser ;; esac sed -i '/user /c\user '$webServerUser';' /etc/$webServerName/nginx.conf comprobarError $? 107 unset nginxConfFile } instalarVirtualHost() { # Configuramos un Virtual Host para Apache o Nginx # Uso: instalarVirtualHost $root $virtualHost $dominio $alias if [ $# -ge 3 ];then rootVirtualHost=$(realpath $1) shift virtualHostFile=$(realpath $1) shift dominioVirtualHost=$1 virtualHostName=$dominioVirtualHost".conf" shift aliasVirtualHost=$@ else comprobarError 1 908 fi if [ ! -f $virtualHostFile ];then comprobarError 1 909 $virtualHostName fi if [ $apacheOn = true ];then # Configuramos root, dominio y logs sed -i '/ServerName /c\\tServerName '"$dominioVirtualHost" $virtualHostFile comprobarError $? 908 if [ ! -z "$aliasVirtualHost" ];then sed -i '/ServerName /a\\tServerAlias '"$aliasVirtualHost" $virtualHostFile comprobarError $? 908 fi sed -i '/DocumentRoot /c\\tDocumentRoot '"$rootVirtualHost" $virtualHostFile comprobarError $? 908 sed -i '/ErrorLog /c\\tErrorLog logs/'"$dominioVirtualHost"'-error.log' $virtualHostFile comprobarError $? 908 sed -i '/CustomLog /c\\tCustomLog logs/'"$dominioVirtualHost"'-access.log common' $virtualHostFile comprobarError $? 908 if [ $sslOn = true ];then sed -i '/SSLCertificateFile /c\\tSSLCertificateFile ssl/'"$dominioVirtualHost"'.crt' $virtualHostFile comprobarError $? 908 sed -i '/SSLCertificateKeyFile /c\\tSSLCertificateKeyFile ssl/'"$dominioVirtualHost"'.key' $virtualHostFile comprobarError $? 908 fi elif [ $nginxOn = true ];then # Configuramos root, dominio, logs y php-fpm.sock (NGINX) sed -i '/root /c\\troot '$rootVirtualHost';' "$virtualHostFile" comprobarError $? 908 sed -i '/server_name /c\\tserver_name '"$dominioVirtualHost"' '"$aliasVirtualHost"';' $virtualHostFile comprobarError $? 908 sed -i '/access_log /c\\taccess_log /var/log/nginx/'"$dominioVirtualHost"'-access.log;' $virtualHostFile comprobarError $? 908 sed -i '/error_log /c\\terror_log /var/log/nginx/'"$dominioVirtualHost"'-error.log;' $virtualHostFile comprobarError $? 908 socket=$(find /var/run/ -type s -name 'php*.sock') sed -i '/fastcgi_pass /c\\t\tfastcgi_pass unix:'"$socket"';' $virtualHostFile comprobarError $? 908 if [ $sslOn = true ];then sed -i '/ssl_certificate /c\\tssl_certificate ssl/'"$dominioVirtualHost"'.crt;' $virtualHostFile comprobarError $? 908 sed -i '/ssl_certificate_key /c\\tssl_certificate_key ssl/'"$dominioVirtualHost"'.key;' $virtualHostFile comprobarError $? 908 fi fi # Copiamos ficheros de configuración cp -f $virtualHostFile "/etc/$webServerName/sites-available/$virtualHostName" >> $logFile 2>&1 comprobarError $? 910 if [ -f "/etc/$webServerName/sites-enabled/$virtualHostName" ];then rm -f /etc/$webServerName/sites-enabled/$virtualHostName 2>/dev/null comprobarError 911 $virtualHostName fi ln -s "/etc/$webServerName/sites-available/$virtualHostName" "/etc/$webServerName/sites-enabled/$virtualHostName" >> $logFile 2>&1 comprobarError $? 911 $virtualHostName recargarServicio $webServerName unset rootVirtualHost dominioVirtualHost virtualHostFile virtualHostName aliasVirtualHost socket } mostrarDatabase() { # Pantalla que permite escoger entre instalar MariaDB o MySQL case $ID in debian) whiptail --title "BASE DE DATOS" --yesno "Para su distribucion $OS $DIST $REV, sólo está disponible la base de datos MariaDB." $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --yes-button "Continuar" --no-button "Salir" comprobarError $? 1 # Excepción: aunque es MariaDB (se instala con el nombre de mysql-server) mySQLOn=true dbType="mariadb" ;; ubuntu) case $VERSION in 18.04) database=$(whiptail --title "BASE DE DATOS" --radiolist ": seleccionar : cambiar : moverse\n\nEscoge la base de datos que quieres usar:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) 2 \ "MariaDB" "Instalar la base de datos MariaDB (fork de MySQL)" ON \ "MySQL" "Instalar la base de datos MySQL (uso no comercial)" OFF \ --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 case $database in MariaDB) mariaDBOn=true dbType="mariadb" ;; MySQL) mySQLOn=true dbType="mysqli" ;; *) comprobarError 1 200 ;; esac ;; 16.04) # Ubuntu 16.04 presenta un bug en MySQL (así que lo deshabilitamos) whiptail --title "BASE DE DATOS" --yesno "Para su distribucion $OS $DIST $REV, sólo está disponible la base de datos MariaDB." $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --yes-button "Continuar" --no-button "Salir" comprobarError $? 1 mariaDBOn=true dbType="mariadb" ;; esac ;; centos|fedora) whiptail --title "BASE DE DATOS" --yesno "Para su distribucion $OS $DIST $REV, sólo está disponible la base de datos MariaDB." $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --yes-button "Continuar" --no-button "Salir" comprobarError $? 1 mariaDBOn=true dbType="mariadb" ;; *) comprobarError 1 200 ;; esac # Otras opciones (contraseña) leerSQLPasswd } leerSQLPasswd() { # Pantalla para leer la contraseña para el usuario root de SQL control=false error="" # Leemos la contreseña (stdin) y confirmamos while [ $control = false ]; do sqlPasswd=$(whiptail --title "CONTRASEÑA SQL" --passwordbox "$error""Introduzca la contraseña para el usuario 'root' de la base de datos:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --nocancel 3>&1 1>&2 2>&3) comprobarError $? 1 sqlPasswd2=$(whiptail --title "CONTRASEÑA SQL" --passwordbox "Confirme la contraseña:" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) --ok-button "Continuar" --nocancel 3>&1 1>&2 2>&3) comprobarError $? 1 #echo -en "SQL Password 1: $sqlPasswd\n" #echo -en "SQL Password 2: $sqlPasswd2\n" if [ -z "$sqlPasswd" ] || [ -z "$sqlPasswd2" ]; then error="ERROR: LA CONTRASEÑA NO PUEDE ESTAR VACIA.\n" elif [ $sqlPasswd != $sqlPasswd2 ];then error="ERROR: LAS CONTRASEÑAS NO COINCIDEN.\n" else control=true fi done #echo -en "SQL Password: $sqlPasswd\n" unset control error sqlPasswd2 } establecerSQLPasswd() { # Establecemos SQL root passwd y securizamos BD (mysql_secure_installation) # Comprobamos si ya tiene una contraseña asignada mysql -e "FLUSH PRIVILEGES" >> $logFile 2>&1 if [ $? -eq 0 ];then # Establecemos contraseña del usuario root (y desactivamos posibles plugins para forzar login por contraseña) mysql -e "UPDATE mysql.user SET plugin = '', Password = PASSWORD('$sqlPasswd') WHERE User = 'root'" >> $logFile 2>&1 if [ $? -ne 0 ];then # Lo intentamos de otra forma (para versiones modernas de mysql) mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '$sqlPasswd'" >> $logFile 2>&1 comprobarError $? 207 fi # Aplicamos el cambio de contraseña mysql -e "FLUSH PRIVILEGES" >> $logFile 2>&1 # Desactivamos acceso root desde el exterior (solo localhost) mysql -u root --password=$sqlPasswd -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')" >> $logFile 2>&1 comprobarError $? 208 # Eliminamos todos los usuarios anónimos mysql -u root --password=$sqlPasswd -e "DELETE FROM mysql.user WHERE User=''" >> $logFile 2>&1 comprobarError $? 209 # Eliminamos bases de datos 'test' mysql -u root --password=$sqlPasswd -e "DROP DATABASE IF EXISTS test" >> $logFile 2>&1 comprobarError $? 210 # Eliminamos privilegios de la base de datos 'test' mysql -u root --password=$sqlPasswd -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'" >> $logFile 2>&1 comprobarError $? 211 # Aplicamos los cambios mysql -u root --password=$sqlPasswd -e "FLUSH PRIVILEGES" >> $logFile 2>&1 comprobarError $? 212 else comprobarError 1 206 fi } instalarMySQL() { # Instala MySQL (sólo para Debian) sqlServerName="mysql" case $ID in debian|ubuntu) result=$(apt-get -q -y install mysql-server mysql-client 2>&1) comprobarError $? 201 $result ;; centos|fedora) # MySQL no disponible en RHEL. # No se instalará MySQL en distribuciones RHEL comprobarError 1 205 ;; *) comprobarError 1 203 ;; esac deshabilitarServicio $sqlServerName } instalarMariaDB() { # Instala MariaDB sqlServerName="mariadb" case $ID in debian) result=$(apt-get -q -y install mariadb-server mariadb-client 2>&1) comprobarError $? 202 $result ;; ubuntu) case $VERSION in 16.04) sqlServerName="mysql" ;; esac result=$(apt-get -q -y install mariadb-server mariadb-client 2>&1) comprobarError $? 202 $result ;; centos|fedora) result=$(yum -y install mariadb-server mariadb 2>&1) comprobarError $? 202 $result ;; *) comprobarError 1 204 ;; esac deshabilitarServicio $sqlServerName } configurarSQL() { # Configura BarracudaFS en mysql (necesario para Moodle) # Configura MariaDB o MySQL case $ID in debian|ubuntu) sqlConfFile="/etc/mysql/my.cnf" ;; centos|fedora) sqlConfFile="/etc/my.cnf" ;; *) comprobarError 1 213 ;; esac if [ ! -f $sqlConfFile ];then comprobarError 1 213 fi grep "# Configuration for Moodle" $sqlConfFile >/dev/null 2>&1 if [ $? -ne 0 ];then # Establecemos UTF8 (codificación de caracteres) y Barracuda (sistema de ficheros) echo -en "\n# Configuration for Moodle\n" >> $sqlConfFile echo -en "[client]\n" >> $sqlConfFile echo -en "default-character-set = utf8mb4\n\n" >> $sqlConfFile echo -en "[mysqld]\n" >> $sqlConfFile echo -en "innodb_file_format = Barracuda\n" >> $sqlConfFile echo -en "innodb_file_per_table = 1\n" >> $sqlConfFile echo -en "innodb_large_prefix\n\n" >> $sqlConfFile echo -en "character-set-server = utf8mb4\n" >> $sqlConfFile echo -en "collation-server = utf8mb4_unicode_ci\n" >> $sqlConfFile echo -en "skip-character-set-client-handshake\n\n" >> $sqlConfFile echo -en "[mysql]\n" >> $sqlConfFile echo -en "default-character-set = utf8mb4\n" >> $sqlConfFile else comprobarError 1 214 fi unset sqlConfFile } instalarPHP() { # Instalamos PHP-7 y los módulos PHP que necesitan MediaWiki y Moodle case $ID in debian) phpFPMName="php7.0-fpm" if [ $apacheOn = true ]; then result=$(apt-get -q -y install php libapache2-mod-php php-mysql php-intl php-mbstring php-xml php-apcu php-gd php-curl php-zip php-soap php-xmlrpc 2>&1) comprobarError $? 302 $result elif [ $nginxOn = true ];then result=$(apt-get -q -y install php-fpm php-mysql php-intl php-mbstring php-xml php-apcu php-gd php-curl php-zip php-soap php-xmlrpc 2>&1) comprobarError $? 302 $result deshabilitarServicio $phpFPMName else comprobarError 1 301 fi ;; ubuntu) case $VERSION in 18.04) phpFPMName="php7.2-fpm" ;; 16.04) phpFPMName="php7.0-fpm" ;; esac if [ $apacheOn = true ]; then result=$(apt-get -q -y install php libapache2-mod-php php-mysql php-intl php-mbstring php-xml php-apcu php-gd php-curl php-zip php-soap php-xmlrpc 2>&1) comprobarError $? 302 $result elif [ $nginxOn = true ];then result=$(apt-get -q -y install php-fpm php-mysql php-intl php-mbstring php-xml php-apcu php-gd php-curl php-zip php-soap php-xmlrpc 2>&1) comprobarError $? 302 $result deshabilitarServicio $phpFPMName else comprobarError 1 301 fi ;; centos) phpFPMName="php-fpm" # Necesitamos un repositorio adicional para PHP-7 (EPEL-RELEASE) sólo en CentOS result=$(yum -y install epel-release yum-utils 2>&1) comprobarError $? 103 $result # Necesitamos un repositorio adicional para PHP-7 (REMI-RELEASE) if [ ! -f /etc/yum.repos.d/remi-php72.repo ];then result=$(yum -y install "http://remi.mirrors.cu.be/enterprise/remi-release-7.rpm" 2>&1) comprobarError $? 303 $result fi # Activamos repositorio remi-php72 result=$(yum-config-manager --enable remi-php72 2>&1) comprobarError $? 303 $result # Instalamos PHP-7.2 if [ $apacheOn = true ];then result=$(yum -y install php php-mysql php-intl php-mbstring php-mcrypt php-xml php-pecl-apcu php-gd php-pear-Net-Curl php-pecl-zip php-soap php-xmlrpc 2>&1) comprobarError $? 302 $result elif [ $nginxOn = true ];then result=$(yum -y install php php-fpm php-mysql php-intl php-mbstring php-mcrypt php-xml php-pecl-apcu php-gd php-pear-Net-Curl php-pecl-zip php-soap php-xmlrpc 2>&1) comprobarError $? 302 $result deshabilitarServicio $phpFPMName else comprobarError 1 301 fi ;; fedora) phpFPMName="php-fpm" # Instalamos PHP-7.2 if [ $apacheOn = true ];then result=$(yum -y install php php-mysqlnd php-intl php-mbstring php-pecl-mcrypt php-xml php-pecl-apcu php-gd php-pear-Net-Curl php-pecl-zip php-soap php-xmlrpc php-json 2>&1) comprobarError $? 302 $result elif [ $nginxOn = true ];then result=$(yum -y install php php-fpm php-mysqlnd php-intl php-mbstring php-pecl-mcrypt php-xml php-pecl-apcu php-gd php-pear-Net-Curl php-pecl-zip php-soap php-xmlrpc php-json 2>&1) comprobarError $? 302 $result deshabilitarServicio $phpFPMName else comprobarError 1 301 fi ;; *) comprobarError 1 300 ;; esac } configurarPHP() { # Configura PHP para segurizarlo y establecer máximo de subida. case $ID in debian) phpConfFile="./etc/php/php.ini.debian" phpDest="/etc/php/7.0/cli/php.ini" ;; ubuntu) phpConfFile="./etc/php/php.ini.debian" case $VERSION in 18.04) phpDest="/etc/php/7.2/cli/php.ini" ;; 16.04) phpDest="/etc/php/7.0/cli/php.ini" ;; esac ;; centos|fedora) phpConfFile="./etc/php/php.ini.rhel" phpDest="/etc/php.ini" ;; *) comprobarError 1 305 ;; esac if [ ! -f $phpConfFile ];then comprobarError 1 4 "$phpConfFile" fi # Copiamos configuración cp -f $phpConfFile $phpDest 2>/dev/null comprobarError $? 305 # Configuramos cgi.fix_pathinfo sed -i '/cgi.fix_pathinfo=/c\cgi.fix_pathinfo=0' $phpDest comprobarError $? 305 # Configuramos post_max_size sed -i '/post_max_size =/c\post_max_size = '$maxUpload $phpDest comprobarError $? 305 # Configuramos upload_max_filesize sed -i '/upload_max_filesize =/c\upload_max_filesize = '$maxUpload $phpDest comprobarError $? 305 # Configurar php-fpm (sólo en RHEL con Nginx) case $ID in centos|fedora) if [ $nginxOn = true ];then # Configurar Socket UNIX phpConfFile="./etc/php/php-fpm.d/www.conf" phpDest="/etc/php-fpm.d/www.conf" if [ ! -f $phpConfFile ];then comprobarError $? 4 "$phpConfFile" fi cp -f $phpConfFile $phpDest 2>/dev/null comprobarError $? 305 # Configurar Permisos /var/lib/php chown -R $webServerUser:$webServerGroup /var/lib/php/ comprobarError $? 305 fi ;; esac unset phpConfFile phpDest } establecerMaxUpload() { # Pantalla para establecer el máximo de subida al servidor (vía PHP) control=false error="" while [ $control = false ];do maxUpload2=$(whiptail --title "PHP MAX UPLOAD" --inputbox "$error""Introduzca el tamaño máximo permitido de los ficheros subidos al servidor:\n( )" $((ALTO * 9 / 10)) $((ANCHO * 9 / 10)) $maxUpload --ok-button "Continuar" --cancel-button "Salir" 3>&1 1>&2 2>&3) comprobarError $? 1 if [ -z "$maxUpload2" ];then error="ERROR: NO PUEDES DEJAR ESTE PARÁMETRO VACIO.\n" else control=true fi done maxUpload=$maxUpload2 unset control maxUpload2 } instalarLetsEncrypt() { # Instala certbot (para certificados Let's Encrypt) # Comprobamos si cerbot está instalado which certbot > /dev/null 2>&1 if [ $? -ne 0 ];then # Descargar Let's Encrypt, hacer ejecutable e instalar curl -o ./var/certbot https://dl.eff.org/certbot-auto 2>/dev/null comprobarError $? 401 chmod 755 ./var/certbot 2>/dev/null comprobarError $? 401 cp -f ./var/certbot /usr/bin/certbot 2>/dev/null comprobarError $? 401 # Configurar /etc/cron.d/certbot para renovar automáticamente los certificados echo -en "# /etc/cron.d/certbot: certbot autorenew the certificates twice a day\n" > /etc/cron.d/certbot echo -en "SHELL=/bin/sh\n" >> /etc/cron.d/certbot echo -en "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n\n" >> /etc/cron.d/certbot echo -en "# Job start twice per day (4am & 2pm) in a random minute" >> /etc/cron.d/certbot echo -en "0 4,14 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew\n" >> /etc/cron.d/certbot fi } generarCertLetsEncrypt() { # Generar Certificados SEGUROS Let's Encrypt dominios="" if [ $apacheOn = true ];then # Usamos plugin para apache if [ $mediaWikiOn = true ];then if [ ! -z "$aliasMediaWiki" ];then dominios=$dominioMediaWiki$(echo "$aliasMediaWiki" | sed -e 's/ /,/g') else dominios=$dominioMediaWiki fi certbot -n --agree-tos --email "admin@$hostname" --apache --domains "$dominios" >> $logFile 2>&1 comprobarError $? 404 fi if [ $moodleOn = true ];then certbot -n --agree-tos --email "admin@$hostname" --apache --domains "$dominioMoodle" >> $logFile 2>&1 comprobarError $? 404 fi elif [ $nginxOn = true ];then # Usamos plugin para nginx if [ $mediaWikiOn = true ];then if [ ! -z "$aliasMediaWiki" ];then dominios=$dominioMediaWiki$(echo "$aliasMediaWiki" | sed -e 's/ /,/g') else dominios=$dominioMediaWiki fi certbot -n --agree-tos --email "admin@$hostname" --nginx --domains "$dominios" >> $logFile 2>&1 comprobarError $? 404 fi if [ $moodleOn = true ];then certbot -n --agree-tos --email "admin@$hostname" --nginx --domains "$dominioMoodle" >> $logFile 2>&1 comprobarError $? 404 fi else comprobarError 1 404 fi unset dominios } generarCertAutofirmado() { # Genera certificados autofirmados # Estos certificados no son seguros, pero valen para pruebas o como paso intermedio para obtener los válidos # Uso: generarCertAutofirmado $dominio dominio=$1 sslDir="/etc/$webServerName/ssl" keyFile="$sslDir/$dominio.key" reqFile="$sslDir/$dominio.csr" certFile="$sslDir/$dominio.crt" dhParamFile="$sslDir/dhparam.pem" if [ ! -d "$sslDir" ];then mkdir "$sslDir" 2>/dev/null comprobarError $? 5 "$sslDir" fi # Generamos clave privada RSA de 2048 bits openssl genrsa -out "$keyFile" 2048 >/dev/null 2>&1 comprobarError $? 402 # Generamos petición de firma echo -en "ES\nMadrid\nMadrid\n$dominio\n$dominio\n$dominio\nadmin@$dominio\n\n\n" | openssl req -new -key "$keyFile" -out "$reqFile" >/dev/null 2>&1 comprobarError $? 402 # Autofirmados clave para 2 años (730 días) openssl x509 -req -days 730 -in "$reqFile" -signkey "$keyFile" -out "$certFile" >/dev/null 2>&1 comprobarError $? 402 # Eliminamos petición rm -f $reqFile comprobarError $? 402 # Añadimos clave Diffie-Hellman al certificado if [ -f "$dhParamFile" ];then cat "$dhParamFile" >> $certFile comprobarError $? 402 fi # Cambiamos permisos chmod 644 $certFile comprobarError $? 402 chmod 400 $keyFile comprobarError $? 402 unset dominio sslDir keyFile reqFile certFile dhParamFile } generarDHParam() { # Genera clave de intercambio Diffie-Hellman y lo configuramos # Esto aumenta notablemente la seguridad de SSL/TLS sslDir="/etc/$webServerName/ssl" dhParamFile="$sslDir/dhparam.pem" nginxConfFile="/etc/$webServerName/nginx.conf" if [ ! -d "$sslDir" ];then mkdir "$sslDir" 2>/dev/null comprobarError $? 5 "$sslDir" fi openssl dhparam -out "$dhParamFile" 2048 >/dev/null 2>&1 comprobarError $? 403 # Configuramos Servidor Web if [ $nginxOn = true ];then sed -i '/ssl_param /c\\tssl_dhparam '$dhParamFile';' $nginxConfFile comprobarError $? 403 fi # unset sslDir dhParamFile apacheConfFile nginxConfFile unset sslDir dhParamFile nginxConfFile } habilitarServicio() { # Arrancamos y habilitamos el servicio (con SystemD, Upstart o SystemV) # Intentamos con systemctl (SystemD) #echo -en "Habilitando Servicio '$1'" | tee -a $logFile if [ $# -le 0 ];then comprobarError 1 900 fi which systemctl > /dev/null 2>&1 if [ $? -eq 0 ]; then #echo -en " (SystemD)..." | tee -a $logFile systemctl start $1 > /dev/null 2>&1 comprobarError $? 901 $1 systemctl enable $1 > /dev/null 2>&1 comprobarError $? 902 $1 else # Intentamos con service (Upstart) which service > /dev/null 2>&1 if [ $? -eq 0 ]; then #echo -en " (Upstart)..." | tee -a $logFile service $1 start > /dev/null 2>&1 comprobarError $? 901 $1 else # Intentamos con init.d (SystemV) #echo -en " (SystemV)..." | tee -a $logFile /etc/init.d/$1 start > /dev/null 2>&1 comprobarError $? 901 $1 fi # Intentamos habilitar en el arranque (Upstart) which update-rc.d > /dev/null 2>&1 if [ $? -eq 0 ];then update-rc.d $1 enable comprobarError $? 902 $1 else # Intentamos habilitar en el arranque (SystemV) which chkconfig > /dev/null 2>&1 if [ $? -eq 0 ];then chkconfig $1 on comprobarError $? 902 $1 else # ¿Qué mas opciones nos quedan? comprobarError 1 902 $1 fi fi fi # Mejora: comprobar si el servicio está parado #echo -en " OK.\n" | tee -a $logFile } deshabilitarServicio() { # Paramos y deshabilitamos el servicio (con SystemD, Upstart o SystemV) # Intentamos con systemctl (SystemD) #echo -en "Deshabilitando Servicio '$1'" | tee -a $logFile if [ $# -le 0 ];then comprobarError 1 903 fi which systemctl > /dev/null 2>&1 if [ $? -eq 0 ]; then #echo -en " (SystemD)..." | tee -a $logFile systemctl stop $1 > /dev/null 2>&1 comprobarError $? 904 $1 systemctl disable $1 > /dev/null 2>&1 comprobarError $? 905 $1 else # Intentamos con service (Upstart) which service > /dev/null 2>&1 if [ $? -eq 0 ]; then #echo -en " (Upstart)..." | tee -a $logFile service $1 stop > /dev/null 2>&1 comprobarError $? 904 $1 else # Intentamos con init.d (SystemV) #echo -en " (SystemV)..." | tee -a $logFile /etc/init.d/$1 stop > /dev/null 2>&1 comprobarError $? 904 $1 fi # Intentamos habilitar en el arranque (Upstart) which update-rc.d > /dev/null 2>&1 if [ $? -eq 0 ];then update-rc.d $1 disable comprobarError $? 905 $1 else # Intentamos habilitar en el arranque (SystemV) which chkconfig > /dev/null 2>&1 if [ $? -eq 0 ];then chkconfig $1 off comprobarError $? 905 $1 else # ¿Qué mas opciones nos quedan? comprobarError 1 905 $1 fi fi fi # Mejora: comprobar si el servicio está funcionando #echo -en " OK.\n" | tee -a $logFile } recargarServicio() { # Recargamos el servicio (con SystemD, Upstart o SystemV) # Intentamos con systemctl (SystemD) #echo -en "Recargando Servicio '$1'" | tee -a $logFile if [ $# -le 0 ];then comprobarError 1 912 fi which systemctl > /dev/null 2>&1 if [ $? -eq 0 ]; then #echo -en " (SystemD)..." | tee -a $logFile systemctl reload $1 > /dev/null 2>&1 comprobarError $? 913 $1 else # Intentamos con service (Upstart) which service > /dev/null 2>&1 if [ $? -eq 0 ]; then #echo -en " (Upstart)..." | tee -a $logFile service $1 reload > /dev/null 2>&1 comprobarError $? 913 $1 else # Intentamos con init.d (SystemV) #echo -en " (SystemV)..." | tee -a $logFile /etc/init.d/$1 reload > /dev/null 2>&1 comprobarError $? 913 $1 fi fi # Mejora: comprobar si el servicio está funcionando #echo -en " OK.\n" | tee -a $logFile } configurarCortafuegos() { # Configuramos cortafuegos (añadir reglas y encender) # Comprobamos si estamos usando SSH esSSH $PPID case $ID in debian|ubuntu) ufw allow 80/tcp >> $logFile 2>&1 comprobarError $? 906 "80/tcp" if [ $sshControl = true ];then ufw allow 22/tcp >> $logFile 2>&1 comprobarError $? 906 "22/tcp" fi if [ $sslOn = true ];then ufw allow 443/tcp >> $logFile 2>&1 comprobarError $? 906 "443/tcp" fi ufw --force enable >> $logFile 2>&1 comprobarError $? 907 ;; centos|fedora) firewall-cmd --add-port=80/tcp >> $logFile 2>&1 comprobarError $? 906 "80/tcp" if [ $sshControl = true ];then firewall-cmd --add-port=22/tcp >> $logFile 2>&1 comprobarError $? 906 "22/tcp" fi if [ $sslOn = true ];then firewall-cmd --add-port=443/tcp >> $logFile 2>&1 comprobarError $? 906 "443/tcp" fi firewall-cmd --runtime-to-permanent >> $logFile 2>&1 comprobarError $? 907 habilitarServicio firewalld >> $logFile 2>&1 comprobarError $? 907 ;; esac unset sshControl } esSSH() { # Comprobamos si nuestro terminal usa SSH p=${1:-$PPID} #read pid name x ppid y < <( cat /proc/$p/stat ) read pid name ppid < <( ps -o pid= -o comm= -o ppid= -p $p) [[ "$name" =~ sshd ]] && { sshControl=true; return 0; } [ "$ppid" -le 1 ] && { sshControl=false; return 1; } esSSH $ppid } descargarMediaWiki() { # Descargar la versión 1.31.0 de MediaWiki if [ ! -d ./var ];then comprobarError 1 5 "./var" fi curl "https://releases.wikimedia.org/mediawiki/1.31/mediawiki-1.31.0.tar.gz" 2>/dev/null | tar -xz -C "./var/" comprobarError $? 501 } configurarMediaWiki() { # Configuramos MediaWiki if [ ! -f /var/www/$dominioMediaWiki/LocalSettings.php ];then # Copiamos archivos cp -fR ./var/mediawiki-1.31.0/ /var/www/$dominioMediaWiki comprobarError $? 502 # Configuramos LocalSettings.php (y crea la base de datos por nosotros) nombreDBMW=$(echo $dominioMediaWiki | sed -e 's/\./_/g' | sed -e 's/-/_/g') userDBMW=$(echo "mediawiki_user" | sed -e 's/\./_/g' | sed -e 's/-/_/g') php /var/www/$dominioMediaWiki/maintenance/install.php --dbname=$nombreDBMW --dbserver="localhost" --installdbuser=root --installdbpass=$sqlPasswd --dbuser=$userDBMW --dbpass=$sqlPasswd --scriptpath="" --lang=es --pass=$passwdMediaWiki --with-extensions "$nombreMediaWiki" "admin" >> $logFile 2>&1 comprobarError $? 502 # Configuraciones adicionales sed -i '/$wgLanguageCode =/c\$wgLanguageCode = "es";' /var/www/$dominioMediaWiki/LocalSettings.php comprobarError $? 502 sed -i '/$wgEnableEmail =/c\$wgEnableEmail = false;' /var/www/$dominioMediaWiki/LocalSettings.php comprobarError $? 502 sed -i '/$wgEnableUploads =/c\$wgEnableUploads = true;' /var/www/$dominioMediaWiki/LocalSettings.php comprobarError $? 502 echo -en "\$wgArticlePath = \"/wiki/\$1\";\n" >> /var/www/$dominioMediaWiki/LocalSettings.php echo -en "\$wgUsePathInfo = true;\n" >> /var/www/$dominioMediaWiki/LocalSettings.php echo -en "\$wgGroupPermissions['*']['createaccount'] = true;\n" >> /var/www/$dominioMediaWiki/LocalSettings.php echo -en "\$wgGroupPermissions['*']['edit'] = false;\n" >> /var/www/$dominioMediaWiki/LocalSettings.php echo -en "\$wgGroupPermissions['*']['read'] = true;\n" >> /var/www/$dominioMediaWiki/LocalSettings.php # Actualizamos permisos chown -R $webServerUser:$webServerGroup /var/www/$dominioMediaWiki comprobarError $? 502 # Configuramos VirtualHost if [ $apacheOn = true ] && [ $sslOn = false ];then virtualHost="./etc/apache2/sites-available/mediawiki.conf" elif [ $nginxOn = true ] && [ $sslOn = false ];then virtualHost="./etc/nginx/sites-available/mediawiki.conf" elif [ $apacheOn = true ] && [ $sslOn = true ];then virtualHost="./etc/apache2/sites-available/mediawiki-ssl.conf" elif [ $nginxOn = true ] && [ $sslOn = true ];then virtualHost="./etc/nginx/sites-available/mediawiki-ssl.conf" else comprobarError 1 502 fi if [ ! -f $virtualHost ];then comprobarError $? 502 fi instalarVirtualHost "/var/www/$dominioMediaWiki" $virtualHost $dominioMediaWiki $aliasMediaWiki unset virtualHost else comprobarError 1 503 $dominioMediaWiki fi } descargarMoodle() { # Descargar la versión 1.31.0 de MediaWiki if [ ! -d ./var ];then comprobarError 1 5 "./var" fi #echo -en "Descargando Moodle-3.5-1..." | tee -a $logFile #curl -o "./var/moodle-3.5.1.tgz" "https://download.moodle.org/download.php/direct/stable35/moodle-latest-35.tgz" >> $logFile 2>&1 curl "https://download.moodle.org/download.php/direct/stable35/moodle-latest-35.tgz" 2>/dev/null | tar -xz -C "./var/" comprobarError $? 501 #echo -en " OK.\n" | tee -a $logFile } configurarMoodle() { # Configurar Moodle if [ ! -f /var/www/$dominioMoodle/config.php ];then # Copiamos archivos cp -Rf ./var/moodle/ /var/www/$dominioMoodle comprobarError $? 602 # Crear carperta de datos (no online) if [ ! -d /var/www/moodledata ];then mkdir /var/www/moodledata 2>/dev/null comprobarError $? 602 fi #Actualizamos permisos perm=$(stat -c %a /var/www/moodledata) if [ $perm -ne 777 ];then chmod -R 777 /var/www/moodledata 2>/dev/null comprobarError $? 602 fi perm=$(stat -c %U /var/www/moodledata) if [ $perm != "$webServerUser" ];then chown -R $webServerUser:$webServerGroup /var/www/moodledata 2>/dev/null comprobarError $? 602 fi unset perm # Creamos Base de Datos nombreDBMo=$(echo $dominioMoodle | sed -e 's/\./_/g' | sed -e 's/-/_/g') userDBMo=$(echo "moodle_user" | sed -e 's/\./_/g' | sed -e 's/-/_/g') crearDBMoodle # Configuramos e instalamos Moodle if [ $sslOn = true ];then wwwroot="https://$dominioMoodle" else wwwroot="http://$dominioMoodle" fi php /var/www/$dominioMoodle/admin/cli/install.php --lang=es --wwwroot="$wwwroot" --dataroot="/var/www/moodledata" --dbtype="$dbType" --dbname="$nombreDBMo" --dbuser="$userDBMo" --dbpass="$sqlPasswd" --fullname="$nombreMoodle" --shortname="$nombreCortoMoodle" --adminuser=admin --adminpass="$passwdMoodle" --adminemail="admin@$dominioMoodle" --agree-license --non-interactive >>$logFile 2>&1 comprobarError $? 602 # Actualizamos permisos chown -R $webServerUser:$webServerGroup /var/www/$dominioMoodle /var/www/moodledata # Configurar SE-Linux (RHEL) case $ID in centos|fedora) configurarSELinux ;; esac # Configuramos VirtualHost if [ $apacheOn = true ] && [ $sslOn = false ];then virtualHost="./etc/apache2/sites-available/moodle.conf" elif [ $nginxOn = true ] && [ $sslOn = false ];then virtualHost="./etc/nginx/sites-available/moodle.conf" elif [ $apacheOn = true ] && [ $sslOn = true ];then virtualHost="./etc/apache2/sites-available/moodle-ssl.conf" elif [ $nginxOn = true ] && [ $sslOn = true ];then virtualHost="./etc/nginx/sites-available/moodle-ssl.conf" else comprobarError 1 602 fi instalarVirtualHost "/var/www/$dominioMoodle" $virtualHost $dominioMoodle unset virtualHost wwwroot else comprobarError 1 603 $dominioMoodle fi } crearDBMoodle() { # Crear base de datos para Moodle dbDir="./etc/db" if [ ! -d $dbDir ];then mkdir $dbDir 2>/dev/null comprobarError $? 603 fi dbFile=$dbDir"/moodle.sql" echo -en "CREATE DATABASE IF NOT EXISTS $nombreDBMo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n" > $dbFile echo -en "GRANT ALL PRIVILEGES ON $nombreDBMo.* TO '$userDBMo'@'localhost' IDENTIFIED BY '$sqlPasswd';\n" >> $dbFile mysql -u root --password=$sqlPasswd < $dbFile > /dev/null 2>&1 control=$? rm -f $dbFile 2>/dev/null comprobarError $? 603 comprobarError $control 603 unset control dbFile dbDir } configurarSELinux() { # Configurar SELinux which semanage >/dev/null 2>&1 if [ $? -ne 0 ];then case $ID in centos) result=$(yum -y install policycoreutils-python 2>&1) comprobarError $? 605 $result ;; fedora) result=$(yum -y install policycoreutils-python-utils 2>&1) comprobarError $? 605 $result ;; *) comprobarError 1 604 ;; esac fi semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/moodledata(/.*)?" > /dev/null 2>&1 #comprobarError $? 604 restorecon -R /var/www/ > /dev/null 2>&1 comprobarError $? 604 } instalarPHPInfo() { # Instalar fichero info.php y su VirtualHost if [ ! -f /etc/$webServerName/sites-enabled/phpinfo.conf ];then infoFile="./var/www/info.php" if [ ! -f $infoFile ];then comprobarError 1 4 "$infoFile" fi mkdir /var/www/localhost 2>/dev/null comprobarError $? 106 cp -f $infoFile /var/www/localhost/ 2>/dev/null comprobarError $? 106 chown -R $webServerUser:$webServerGroup /var/www/localhost 2>/dev/null comprobarError $? 106 unset infoFile # Instalar VirtualHost if [ $apacheOn = true ] && [ $sslOn = false ];then virtualHost="./etc/apache2/sites-available/phpinfo.conf" elif [ $nginxOn = true ] && [ $sslOn = false ];then virtualHost="./etc/nginx/sites-available/phpinfo.conf" elif [ $apacheOn = true ] && [ $sslOn = true ];then virtualHost="./etc/apache2/sites-available/phpinfo-ssl.conf" elif [ $nginxOn = true ] && [ $sslOn = true ];then virtualHost="./etc/nginx/sites-available/phpinfo-ssl.conf" else comprobarError 1 106 fi instalarVirtualHost "/var/www/localhost" $virtualHost "localhost" unset virtualHost return 0 else return 1 fi } configurarBackups() { # Instala backup-server y lo configura letsEncryptCode="" if [ ! -d "./var" ];then comprobarError 1 5 "./var" fi which backup-server > /dev/null 2>&1 if [ $? -ne 0 ];then # Descargamos backup-server curl "https://code.castanedo.es/guzman/backup-server/archive/2.1.tar.gz" 2>/dev/null | tar -xz -C "./var/" if [ $? -ne 0 ];then comprobarError 1 701 return 1 fi # Copiamos backup-server y logrotate cp -f ./var/backup-server/backup-server /usr/bin/backup-server if [ $? -ne 0 ];then comprobarError 1 701 return 1 fi cp -f ./var/backup-server/scripts/logrotate.d/backup-server /etc/logrotate.d/backup-server if [ $? -ne 0 ];then comprobarError 1 701 return 1 fi # Creamos carpeta de backups if [ ! -d /var/backup ];then mkdir /var/backup 2>/dev/null comprobarError $? 5 "/var/backup" fi # Configuramos cron.d if [ $letsEncryptOn = false ];then letsEncryptCode="--no-letsencrypt " fi echo -en "# /etc/cron.d/backup-server: crontab for $hostname\n\n" > /etc/cron.d/backup-server echo -en "# Backup every day at 4:00 am\n" >> /etc/cron.d/backup-server echo -en "0 4 * * * root [ -x /usr/bin/backup-server ] && /usr/bin/backup-server --xz -u $webServerUser -g $webServerGroup --no-encryption --sql-user root --sql-pass $sqlPasswd --nginx-dir /etc/$webServerName $letsEncryptCode--no-mail --no-gogs --no-postfix --no-dovecot --no-opendkim --no-spf --no-opendmarc --no-amavis --no-spamassassin /var/backup >> /var/log/backup-server.log 2>&1" >> /etc/cron.d/backup-server comprobarError $? 701 fi unset letsEncryptCode } # Comprobación del sistema e inicialización horaInicial=$(date +"%s") inicializarVariables OSInfo # Leer opciones which getopt >/dev/null 2>&1 if [ $? -eq 0 ] && [ $# -ne 0 ];then # Configuración por defecto (opciones de Express) instalacionExpress # Leer opciones TEMP=$(getopt -q -o hd: --longoptions help,dominio:,fqdn:,lamp,lemp,mariadb,mysql,password-sql:,max-upload-size:,letsencrypt,auto-firmados,media-wiki,no-media-wiki,nombre-mw:,dominios-mw:,password-mw:,moodle,no-moodle,nombre-mo:,nombre-corto-mo:,dominio-mo:,password-mo:,php-info,no-php-info,backup,no-backup --name $(basename $0) -- "$@") eval set -- $TEMP unset TEMP while true; do case $1 in -h|--help) ayuda exit 0 ;; -d|--dominio|--fqdn) hostname=$2 shift 2 ;; --lamp) apacheOn=true shift ;; --lemp) nginxOn=true shift ;; --mariadb) case $ID in debian) mySQLOn=true dbType="mariadb" ;; ubuntu|centos|fedora) mariaDBOn=true dbType="mariadb" esac shift ;; --mysql) if [ $ID = "ubuntu" ] && [ $VERSION = "18.04" ];then mySQLOn=true dbType="mysqli" else # No está soportado ayuda comprobarError 1 205 fi shift ;; --password-sql) sqlPasswd=$2 shift 2 ;; --max-upload-size) maxUpload=$2 shift 2 ;; --lets-encrypt) sslOn=true letsEncryptOn=true shift ;; --auto-firmados) sslOn=true letsEncryptOn=false shift ;; --media-wiki) mediaWikiOn=true shift ;; --no-media-wiki) mediaWikiOn=false shift ;; --nombre-mw) nombreMediaWiki=$2 shift 2 ;; --dominios-mw) dominioMediaWiki=$2 cont=1 serverName="" aliasMediaWiki="" for dominio in $dominioMediaWiki;do if [ $cont -eq 1 ];then # Dominio Principal (ServerName) serverName=$dominio else # Dominios Secundarios (ServerAlias) aliasMediaWiki=$aliasMediaWiki" "$dominio fi cont=$((cont + 1)) done dominioMediaWiki=$serverName unset cont serverName dominio shift 2 ;; --password-mw) passwdMediaWiki=$2 shift 2 ;; --moodle) moodleOn=true shift ;; --no-moodle) moodleOn=false shift ;; --nombre-mo) nombreMoodle=$2 shift 2 ;; --nombre-corto-mo) nombreCortoMoodle=$(echo $2 | cut -d ' ' -f 1) shift 2 ;; --dominio-mo) dominioMoodle=$2 cont=1 serverName="" aliasMoodle="" for dominio in $dominioMoodle;do if [ $cont -eq 1 ];then # Dominio Principal (ServerName) serverName=$dominio else # Dominios Secundarios (ServerAlias) aliasMoodle=$aliasMoodle" "$dominio fi cont=$((cont + 1)) done dominioMoodle=$serverName unset cont ServerName dominio aliasMoodle shift 2 ;; --password-mo) passwdMoodle=$2 shift 2 ;; --php-info) infoPHPOn=true shift ;; --no-php-info) infoPHPOn=false shift ;; --backup) backupOn=true shift ;; --no-backup) backupOn=false shift ;; --) #Ultimo shift break ;; *) # Inesperado ayuda comprobarError 1 10 $1 ;; esac done # Comprobar si los datos son correctos if [ -z "$hostname" ];then ayuda comprobarError 1 11 else hostnamectl set-hostname $hostname >/dev/null 2>&1 fi if [ -z "$sqlPasswd" ];then ayuda comprobarError 1 12 fi if [ -z "$maxUpload" ];then ayuda comprobarError 1 13 fi if [ $mediaWikiOn = true ];then if [ -z "$nombreMediaWiki" ];then ayuda comprobarError 1 14 fi if [ -z "$dominioMediaWiki" ];then ayuda comprobarError 1 15 fi if [ -z "$passwdMediaWiki" ];then ayuda comprobarError 1 16 fi fi if [ $moodleOn = true ];then if [ -z "$nombreMoodle" ];then ayuda comprobarError 1 17 fi if [ -z "$nombreCortoMoodle" ];then ayuda comprobarError 1 18 fi if [ -z "$dominioMoodle" ];then ayuda comprobarError 1 19 fi if [ -z "$passwdMoodle" ];then ayuda comprobarError 1 20 fi fi # Comprobaciones comprobarRoot comprobarDependencias else # Preguntas interactivas # Comprobaciones comprobarRoot comprobarDependencias # Bienvenida mostrarBienvenida # Selección de componentes (express vs avanzada) mostrarExpress fi # Instalación Servidor Web if [ $apacheOn = true ]; then echo -en "Instalando Servidor Web Apache..." | tee -a $logFile instalarApache echo -en " OK.\n" | tee -a $logFile elif [ $nginxOn = true ]; then echo -en "Instalando Servidor Web Nginx..." | tee -a $logFile instalarNginx echo -en " OK.\n" | tee -a $logFile fi # Instalación Base de Datos if [ $mySQLOn = true ]; then echo -en "Instalando Base de Datos MySQL..." | tee -a $logFile instalarMySQL echo -en " OK.\n" | tee -a $logFile elif [ $mariaDBOn = true ]; then echo -en "Instalando Base de Datos MariaDB..." | tee -a $logFile instalarMariaDB echo -en " OK.\n" | tee -a $logFile fi # Instalación PHP-7 if [ $phpOn = true ]; then echo -en "Instalando PHP-7..." | tee -a $logFile instalarPHP echo -en " OK.\n" | tee -a $logFile fi # Instalación Let's Encrypt if [ $letsEncryptOn = true ];then echo -en "Instalando Let's Encrypt..." | tee -a $logfile instalarLetsEncrypt echo -en " OK.\n" | tee -a $logFile fi # Configuración Web Server if [ $apacheOn = true ];then echo -en "Configurando Servidor Web Apache..." | tee -a $logFile configurarApache echo -en " OK.\n" | tee -a $logFile elif [ $nginxOn = true ]; then echo -en "Configurando Servidor Web Nginx..." | tee -a $logFile configurarNginx echo -en " OK.\n" | tee -a $logFile fi # Configuración Database (Configurar Ficheros, Arrancar Base de Datos, establecer contraseña y configuración segura) if [ $mySQLOn = true ] || [ $mariaDBOn = true ];then echo -en "Configurando Base de Datos..." | tee -a $logFile configurarSQL echo -en " OK.\n" | tee -a $logFile habilitarServicio "$sqlServerName" echo -en "Estableciendo contraseña de la Base de Datos..." | tee -a $logFile establecerSQLPasswd echo -en " OK.\n" | tee -a $logFile fi # Configuración PHP (cgi.fix_pathinfo=0 y Configurar máximo de subida de archivos) if [ $phpOn = true ];then echo -en "Configurando PHP-7..." | tee -a $logFile configurarPHP echo -en " OK.\n" | tee -a $logFile fi # Configuración SSL/TLS # Generar certificados auto-firmados if [ $sslOn = true ];then echo -en "Generando claves de intercambio Diffie-Hellman (puede llevar un largo tiempo)..." | tee -a $logFile generarDHParam echo -en " OK.\n" | tee -a $logFile echo -en "Generando Certificados Auto-Firmados..." | tee -a $logFile if [ $mediaWikiOn = true ];then generarCertAutofirmado $dominioMediaWiki fi if [ $moodleOn = true ];then generarCertAutofirmado $dominioMoodle fi if [ $infoPHPOn = true ];then generarCertAutofirmado "localhost" fi echo -en " OK.\n" | tee -a $logFile fi # Arrancar y habilitar todos los servicios (SystemD, Service o SystemV) echo -en "Habilitando todos los servicios..." | tee -a $logFile if [ $apacheOn = true ] || [ $nginxOn = true ];then habilitarServicio $webServerName fi if [ $nginxOn = true ] && [ $phpOn = true ];then habilitarServicio $phpFPMName fi echo -en " OK.\n" | tee -a $logFile # Instalar MediaWiki if [ $mediaWikiOn = true ]; then # Descargar MediaWiki echo -en "Descargando MediaWiki-1.31.0..." | tee -a $logFile descargarMediaWiki echo -en " OK.\n" | tee -a $logFile # Configurar MediWiki echo -en "Configurando MediaWiki..." | tee -a $logFile configurarMediaWiki echo -en " OK.\n" | tee -a $logFile fi # Instalar Moodle if [ $moodleOn = true ]; then # Descargar Moodle echo -en "Descargando Moodle-3.5.1..." | tee -a $logFile descargarMoodle echo -en " OK.\n" | tee -a $logFile # Configuración Moodle echo -en "Configurando Moodle (puede llevar un tiempo largo)..." | tee -a $logFile configurarMoodle echo -en " OK.\n" | tee -a $logFile fi # Instalar info.php if [ $infoPHPOn = true ];then echo -en "Configurando 'info.php'..." | tee -a $logFile instalarPHPInfo if [ $? -eq 0 ];then echo -en " OK.\n" | tee -a $logFile else echo -en " Ya se encuentra configurado.\n" | tee -a $logFile fi fi # Añadir reglas del cortafuegos echo -en "Configurando Cortafuegos..." | tee -a $logFile configurarCortafuegos echo -en " OK.\n" | tee -a $logFile # Generar certificados Let's Encrypt if [ $letsEncryptOn = true ];then echo -en "Generando Certificados Válidos Let's Encrypt..." | tee -a $logFile generarCertLetsEncrypt echo -en " OK.\n" | tee -a $logFile fi # Configurar Backup if [ $backupOn = true ]; then echo -en "Configurando Backup Automático..." | tee -a $logFile configurarBackups echo -en " OK.\n" | tee -a $logFile fi # Finalizamos horaFinal=$(date +"%s") echo -en "\n-------------------------------------------------------------\n" | tee -a $logFile echo -en "\t¡INSTALACION FINALIZADA CON EXITO! \n" | tee -a $logFile echo -en "\tDuración: "$((horaFinal-horaInicial))" seg." | tee -a $logFile echo -en "\n-------------------------------------------------------------\n" | tee -a $logFile echo -en " GUARDE LA CONFIGURACION EN UN LUGAR SEGURO\n" echo -en " LE SERÁ IMPRESCINDIBLE PARA CUALQUIER CAMBIO FUTURO\n" echo -en " Dominio: $hostname\n" echo -en " Usuarios SQL: root\n" echo -en " $userDBMW\n" echo -en " $userDBMo\n" echo -en " Contraseña SQL: $sqlPasswd\n" if [ $mediaWikiOn = true ];then echo -en " Nombre MediaWiki: $nombreMediaWiki\n" echo -en " Dominios MediaWiki: $dominioMediaWiki\n" for dominio in $aliasMediaWiki;do echo -en " $dominio\n" done echo -en " Usuario MediaWiki: admin\n" echo -en " Contraseña MediaWiki: $passwdMediaWiki\n" fi if [ $moodleOn = true ];then echo -en " Nombre Moodle: $nombreMoodle\n" echo -en " Dominio Moodle: $dominioMoodle\n" echo -en " Usuario Moodle: admin\n" echo -en " Contraseña Moodle: $passwdMoodle" fi echo -en "\n-------------------------------------------------------------\n"