#!/bin/bash ##################################################################### ####### Script instalador Ogclient ####### Autor: Luis Gerardo Romero ##################################################################### function globalSetup() { local current_dir current_dir=$(dirname "$0") PROGRAMDIR=$(readlink -e "$current_dir") PROGRAMNAME=$(basename "$0") OPENGNSYS_CLIENT_USER="ogdhcp" # Comprobar si se ha descargado el paquete comprimido (REMOTE=0) o sólo el instalador (REMOTE=1). if [ -d "$PROGRAMDIR/../installer" ]; then echo "REMOTE=0" REMOTE=0 else echo "REMOTE=1" REMOTE=1 fi BRANCH=${1:-"main"} GIT_REPO="ssh://git@ognproject.evlt.uma.es:21987/opengnsys/ogdhcp.git" # Directorios de instalación y destino de OpenGnsys. WORKDIR=/tmp/ogdhcp_installer INSTALL_TARGET=/opt/ogdhcp PATH=$PATH:$INSTALL_TARGET/bin if command -v service &>/dev/null; then STARTSERVICE="eval service \$service restart" STOPSERVICE="eval service \$service stop" else STARTSERVICE="eval /etc/init.d/\$service restart" STOPSERVICE="eval /etc/init.d/\$service stop" fi ENABLESERVICE="eval update-rc.d \$service defaults" DISABLESERVICE="eval update-rc.d \$service disable" # Variables globales DEFAULTDEV="" NGINX_TEMPLATE="$INSTALL_TARGET/etc/nginxServer.conf.tmpl" NGINX_OUTPUT="/etc/nginx/sites-available/ogdhcp.conf" NGINX_CONF_PATH="/etc/nginx/nginx.conf" PHP_FPM_CONF_PATH="/etc/php/__PHPVERSION__/fpm/pool.d/www.conf" NEW_FPM_CONF_PATH="/etc/php/__PHPVERSION__/fpm/pool.d/ogdhcp.conf" SOCKET_PATH="/run/php/php__PHPVERSION__-fpm-ogdhcp.sock" # Registro de incidencias. OGLOGFILE="$INSTALL_TARGET/var/log/${PROGRAMNAME%.sh}.log" LOG_FILE="/tmp/$(basename "$OGLOGFILE")" } function checkDependencies() { echoAndLog "Checking dependencies..." # Lista de dependencias local DEPENDENCIES=( php php-cli php-fpm php-json php-pdo php-mysql php-zip php-gd php-mbstring php-curl php-xml php-pear php-bcmath composer unzip kea-dhcp4-server kea-common kea-ctrl-agent jq net-tools nginx ) export DEBIAN_FRONTEND=noninteractive # Comprobar cada dependencia for dep in "${DEPENDENCIES[@]}"; do if ! dpkg -s "$dep" >/dev/null 2>&1; then echoAndLog "$dep is not installed. Installing..." sudo apt-get install -y --no-install-recommends "$dep" else echoAndLog "$dep is already installed." fi done sed -i '/ConditionFileNotEmpty=\/etc\/kea\/kea-api-password/d' /usr/lib/systemd/system/kea-ctrl-agent.service systemctl restart kea-ctrl-agent.service echoAndLog "Dependencies checked." } # Obtiene el código fuente del proyecto desde el repositorio de GitHub. function downloadCode() { if [ $# -ne 1 ]; then errorAndLog "${FUNCNAME}(): invalid number of parameters" exit 1 fi local url="$1" echoAndLog "${FUNCNAME}(): downloading code from '$url'..." GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new" git archive --remote="$url" --format zip --output opengnsys.zip --prefix=opengnsys/ "$BRANCH" && unzip opengnsys.zip if [ $? -ne 0 ]; then errorAndLog "${FUNCNAME}(): error getting OpenGnsys code from $url" return 1 fi rm -f opengnsys.zip echoAndLog "${FUNCNAME}(): code was downloaded" return 0 } # Crea la estructura base de la instalación de opengnsys function createDirs() { if [ $# -ne 1 ]; then errorAndLog "${FUNCNAME}(): invalid number of parameters" exit 1 fi local path_opengnsys_base="$1" # Crear estructura de directorios. echoAndLog "${FUNCNAME}(): creating directory paths in $path_opengnsys_base" mkdir -p "$path_opengnsys_base"/{bin,config,docs,public,src,etc/kea/backup,templates,var/{cache,log},vendor} if [ $? -ne 0 ]; then errorAndLog "${FUNCNAME}(): error while creating dirs. Do you have write permissions?" return 1 fi # Crear usuario ficticio. if id -u "$OPENGNSYS_CLIENT_USER" &>/dev/null; then echoAndLog "${FUNCNAME}(): user \"$OPENGNSYS_CLIENT_USER\" is already created" else echoAndLog "${FUNCNAME}(): creating OpenGnsys user" useradd "$OPENGNSYS_CLIENT_USER" 2>/dev/null if [ $? -ne 0 ]; then errorAndLog "${FUNCNAME}(): error creating OpenGnsys user" return 1 fi fi # Mover el fichero de registro de instalación al directorio de logs. echoAndLog "${FUNCNAME}(): moving installation log file" mv "$LOG_FILE" "$path_opengnsys_base/var/log" && LOG_FILE="$OGLOGFILE" chmod 777 "$LOG_FILE" sudo chmod -R 777 "$path_opengnsys_base/etc" # Mover el fichero de registro de instalación al directorio de logs. echoAndLog "${FUNCNAME}(): moving installation log file" touch "$path_opengnsys_base/var/log/dev.log" chmod 777 "$path_opengnsys_base/var/log/dev.log" echoAndLog "${FUNCNAME}(): directory paths created" return 0 # Cambiar permisos de usuario echoAndLog "Changing user permission" chown -R "$OPENGNSYS_CLIENT_USER:$OPENGNSYS_CLIENT_USER" "$INSTALL_TARGET" # Copiar .env cp -a "$WORKDIR/ogdhcp/.env" "${path_opengnsys_base}/.env" } function create_ogdhcp_project { # Crea el usuario ogdhcp si no existe local path_opengnsys_base="$1" if ! id -u ogdhcp &>/dev/null; then echoAndLog "${FUNCNAME}(): creating ogdhcp user" useradd ogdhcp 2>/dev/null if [ $? -ne 0 ]; then errorAndLog "${FUNCNAME}(): error creating ogdhcp user" return 1 fi fi # Crea el directorio path_opengnsys_base con el usuario ogdhcp echoAndLog "${FUNCNAME}(): creating directory $path_opengnsys_base with ogdhcp user" sudo mkdir -p "$path_opengnsys_base" sudo chown ogdhcp:ogdhcp $path_opengnsys_base if [ $? -ne 0 ]; then errorAndLog "${FUNCNAME}(): error while creating directory $path_opengnsys_base" return 1 fi echoAndLog "Directory $path_opengnsys_base created with ogdhcp user" } function copyServerFiles() { if [ $# -ne 1 ]; then errorAndLog "${FUNCNAME}(): invalid number of parameters" exit 1 fi local path_opengnsys_base="$1" # Lista de ficheros y directorios origen y de directorios destino. local SOURCES=( config #public src etc .env composer.json composer.lock phpunit.xml.dist symfony.lock ) local TARGETS=( config #public src etc .env composer.json composer.lock phpunit.xml.dist symfony.lock ) if [ "${#SOURCES[@]}" != "${#TARGETS[@]}" ]; then errorAndLog "${FUNCNAME}(): inconsistent number of array items" exit 1 fi # Copiar ficheros. echoAndLog "${FUNCNAME}(): copying files to server directories" pushd "$WORKDIR/ogdhcp" || return local i for (( i = 0; i < ${#SOURCES[@]}; i++ )); do if [ -f "${SOURCES[$i]}" ]; then echoAndLog "Copying ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}" cp -a "${SOURCES[$i]}" "$path_opengnsys_base/${TARGETS[$i]}" elif [ -d "${SOURCES[$i]}" ]; then echoAndLog "Copying content of ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}" cp -a "${SOURCES[$i]}"/* "$path_opengnsys_base/${TARGETS[$i]}" else warningAndLog "Unable to copy ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}" fi done echoAndLog "Changing user permission" chown -R "$OPENGNSYS_CLIENT_USER:$OPENGNSYS_CLIENT_USER" "$INSTALL_TARGET" popd || return } function runComposer() { echoAndLog "Running composer.phar to install dependencies..." local path_opengnsys_base="$1" pushd $path_opengnsys_base pwd # Ejecutar composer.phar sudo -u "$OPENGNSYS_CLIENT_USER" composer --no-interaction install # Comprobar si la ejecución fue exitosa if [ $? -ne 0 ]; then errorAndLog "Failed to run composer.phar" popd return 1 fi echoAndLog "composer.phar ran successfully and dependencies were installed" return 0 } get_first_network_interface_with_traffic() { while read -r line; do if [[ "$line" == *:* ]]; then interface=$(echo "$line" | cut -d ':' -f 1 | xargs) if [[ "$interface" != "lo" ]]; then received_bytes=$(echo "$line" | awk '{print $2}') transmitted_bytes=$(echo "$line" | awk '{print $10}') if (( received_bytes > 0 || transmitted_bytes > 0 )); then DEFAULTDEV="$interface" break fi fi fi done < /proc/net/dev } comment_auth_kea() { KEA_CTRL_AGENT_CONF="/etc/kea/kea-ctrl-agent.conf" # Verificar si el bloque de "authentication" ya está comentado if grep -q '^[^#]*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then echo "Comentando el bloque de autenticación en $KEA_CTRL_AGENT_CONF..." # Comentar solo el bloque de authentication desde la apertura hasta la línea con '},' sed -i '/"authentication": {/,/^[[:space:]]*},/ { s/^\([[:space:]]*\)\([^#]\)/\1#\2/ }' "$KEA_CTRL_AGENT_CONF" echo "Bloque de autenticación comentado correctamente." else echo "El bloque de autenticación ya está comentado." fi # Verificar si el bloque fue comentado correctamente if grep -q '^#\s*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then echo "Confirmación: Bloque de autenticación comentado correctamente." # Reiniciar el servicio de Kea Control Agent para aplicar los cambios echo "Reiniciando el agente de Kea Control Agent..." sudo systemctl restart kea-ctrl-agent.service if systemctl is-active --quiet kea-ctrl-agent.service; then echo "El agente de Kea Control Agent se ha reiniciado correctamente." else echo "Error: No se pudo reiniciar el agente de Kea Control Agent." fi else echo "Error: No se pudo comentar correctamente el bloque de autenticación." fi } # Función para obtener la dirección IP de una interfaz get_ip_address() { local interface="$1" ip -4 addr show "$interface" | grep -oP "(?<=inet\s)\d+(\.\d+){3}" } # Función para obtener la versión de PHP instalada get_php_fpm_version() { php -v | grep -oP "PHP \K\d+\.\d+" } add_write_permission_apparmor() { APPARMOR_PROFILE="/etc/apparmor.d/usr.sbin.kea-dhcp4" # Comprobar si las líneas existen if grep -q "/etc/kea/ r," "$APPARMOR_PROFILE" && grep -q "/etc/kea/** r," "$APPARMOR_PROFILE"; then echo "Modificando permisos en $APPARMOR_PROFILE..." # Modificar las líneas /etc/kea/ r, y /etc/kea/** r, añadiendo w sed -i 's#/etc/kea/ r,#/etc/kea/ rw,#g' "$APPARMOR_PROFILE" sed -i 's#/etc/kea/\*\* r,#/etc/kea/** rw,#g' "$APPARMOR_PROFILE" echo "Permisos de escritura añadidos correctamente a $APPARMOR_PROFILE." else echo "Las líneas no fueron encontradas o ya están modificadas." fi # Recargar el perfil de AppArmor para aplicar los cambios echo "Recargando el perfil de AppArmor para kea-dhcp4..." sudo apparmor_parser -r "$APPARMOR_PROFILE" if [ $? -eq 0 ]; then echo "El perfil de AppArmor se recargó correctamente." else echo "Error al recargar el perfil de AppArmor." fi } # Función para configurar Nginx setup_nginx() { get_first_network_interface_with_traffic if [[ -z "$DEFAULTDEV" ]]; then echo "Error: No se encontró una interfaz de red activa." exit 1 fi ip_address_server=$(get_ip_address "$DEFAULTDEV") php_version=$(get_php_fpm_version) if [[ -z "$php_version" ]]; then echo "Error: No se pudo obtener la versión de PHP." exit 1 fi # Leer y modificar la plantilla de configuración de nginx if [[ ! -f "$NGINX_TEMPLATE" ]]; then echo "Error: La plantilla de Nginx no se encontró." exit 1 fi nginx_content=$(<"$NGINX_TEMPLATE") nginx_content="${nginx_content//__SERVERIP__/$ip_address_server}" nginx_content="${nginx_content//__PHPVERSION__/$php_version}" # Crear el archivo de configuración de Nginx echo "$nginx_content" > "$NGINX_OUTPUT" echo "Archivo de configuración de Nginx creado en $NGINX_OUTPUT." # Crear el enlace simbólico ln -sf "$NGINX_OUTPUT" /etc/nginx/sites-enabled/ogdhcp.conf echo "Enlace simbólico creado en /etc/nginx/sites-enabled/ogdhcp.conf." # Modificar nginx.conf para ejecutar como ogdhcp sed -i 's/user www-data;/user ogdhcp;/g' "$NGINX_CONF_PATH" echo "Nginx configurado para ejecutarse como ogdhcp." # Reiniciar Nginx systemctl restart nginx.service echo "Servicio Nginx reiniciado." } # Función para modificar el archivo de configuración PHP-FPM modify_php_fpm_config() { php_version=$(get_php_fpm_version) if [[ -z "$php_version" ]]; then echo "Error: No se pudo obtener la versión de PHP." exit 1 fi php_fpm_conf_path="/etc/php/$php_version/fpm/pool.d/www.conf" new_fpm_conf_path="/etc/php/$php_version/fpm/pool.d/ogdhcp.conf" socket_path="/run/php/php$php_version-fpm-ogdhcp.sock" # Copiar el archivo www.conf a ogdhcp.conf cp "$php_fpm_conf_path" "$new_fpm_conf_path" # Modificar el archivo ogdhcp.conf sed -i 's/\[www\]/[ogdhcp]/g' "$new_fpm_conf_path" sed -i 's/user = www-data/user = ogdhcp/g' "$new_fpm_conf_path" sed -i 's/group = www-data/group = ogdhcp/g' "$new_fpm_conf_path" sed -i "s|listen =.*|listen = $socket_path|g" "$new_fpm_conf_path" sed -i 's/listen.owner = www-data/listen.owner = ogdhcp/g' "$new_fpm_conf_path" sed -i 's/listen.group = www-data/listen.group = ogdhcp/g' "$new_fpm_conf_path" # Reiniciar PHP-FPM systemctl restart php"$php_version"-fpm.service echo "PHP-FPM reiniciado." # Verificar la creación del socket if [[ -S "$socket_path" ]]; then echo "Socket PHP-FPM $socket_path creado correctamente." else echo "Error: El socket PHP-FPM $socket_path no se ha creado." exit 1 fi } ##################################################################### ####### Algunas funciones útiles de propósito general: ##################################################################### # Obtiene la fecha y hora actual en el formato especificado function getDateTime() { date "+%Y%m%d-%H%M%S" } # Escribe un mensaje en el archivo de registro y lo muestra por pantalla function echoAndLog() { local DATETIME=$(getDateTime) echo "$1" echo "$DATETIME;$SSH_CLIENT;$1" >> "$LOG_FILE" } # Escribe un mensaje de error en el archivo de registro y lo muestra por pantalla function errorAndLog() { local DATETIME=$(getDateTime) echo "ERROR: $1" echo "$DATETIME;$SSH_CLIENT;ERROR: $1" >> "$LOG_FILE" } # Escribe un mensaje de advertencia en el archivo de registro y lo muestra por pantalla function warningAndLog() { local DATETIME=$(getDateTime) echo "Warning: $1" echo "$DATETIME;$SSH_CLIENT;Warning: $1" >> "$LOG_FILE" } ########################################################################## ################################main###################################### # Sólo ejecutable por usuario root if [ "$(whoami)" != 'root' ]; then echo "ERROR: this program must run under root privileges!!" exit 1 fi globalSetup echoAndLog "OpenGnsys installation begins at $(date)" mkdir -p $WORKDIR pushd $WORKDIR checkDependencies # Si es necesario, descarga el repositorio de código en directorio temporal if [ $REMOTE -eq 1 ]; then downloadCode $GIT_REPO if [ $? -ne 0 ]; then errorAndLog "Error while getting code from the repository" exit 1 fi else ln -fs "$(dirname $PROGRAMDIR)" ogdhcp fi create_ogdhcp_project ${INSTALL_TARGET} if [ $? -ne 0 ]; then errorAndLog "Error while creating skeleton directory!" exit 1 fi # Arbol de directorios de OpenGnsys. createDirs ${INSTALL_TARGET} if [ $? -ne 0 ]; then errorAndLog "Error while creating directory paths!" exit 1 fi # Copiar ficheros de servicios OpenGnsys Server. copyServerFiles ${INSTALL_TARGET} if [ $? -ne 0 ]; then errorAndLog "Error while copying the server files!" exit 1 fi comment_auth_kea if [ $? -ne 0 ]; then errorAndLog "Error while commenting auth block!" exit 1 fi runComposer ${INSTALL_TARGET} setup_nginx $INSTALL_TARGET if [ $? -ne 0 ]; then errorAndLog "Error configuring Nginx for OpenGnsys Admin" exit 1 fi modify_php_fpm_config if [ $? -ne 0 ]; then errorAndLog "Error configuring PHP-FPM for OpenGnsys Admin" exit 1 fi add_write_permission_apparmor if [ $? -ne 0 ]; then errorAndLog "Error adding write permission to AppArmor profile" exit 1 fi # install_kea # install_php # install_composer # install_symfony # install_swagger # Ahora puedes clonar e instalar el componente ogDhcp # git clone # cd # composer install