Instalación de Redmine 3.4 en Linux CentOS 7

La idea de este artículo es documentar todo el proceso de instalación de Redmine 3.4 en la versión más estable de CentOS 7 (release 1905).

Esto se debe a que me había sido imposible hacer funcionar el procedimiento de instalación descrito en éste artículo redactado en 2017 para el sistema operativo openSUSE Leap 42.3, aún cuando en su momento no tuve mayores problemas en el proceso de instalación. Sin embargo, quizás el problema haya sido simplemente la mala configuración del entorno Ruby como veremos más adelante, en fin, comencemos sin más rodeos.


Configuración inicial del servidor

  1. Realizar una instalación del Línux CentOS 7 (release 1905) con una configuración de tipo servidor con entorno gráfico y comprobar que el servidor cuente con acceso a Internet, al menos temporalmente para instalar los paquetes requeridos más adelante para la instalación de la herramienta.

  2. Uno de los primeros pasos que se realizan es desactivar el SELinux, siendo responsabilidad del administrador evaluar si esto pone en riesgo o no la seguridad del servidor. Para ello editamos el archivo /etc/selinux/config,
    [root@testsrv ~]# vim /etc/selinux/config
    
    y le configuramos la directiva SELINUX con el valor disabled:
    # This file controls the state of SELinux on the system.
    # SELINUX= can take one of these three values:
    #     enforcing - SELinux security policy is enforced.
    #     permissive - SELinux prints warnings instead of enforcing.
    #     disabled - No SELinux policy is loaded.
    SELINUX=disabled
    # SELINUXTYPE= can take one of these two values:
    #     targeted - Targeted processes are protected,
    #     mls - Multi Level Security protection.
    SELINUXTYPE=targeted
    
    Como los cambios anteriores solo toman efecto luego de reiniciar el sistema operativo, podemos parar el SELinux en el entorno de ejecución actual con el siguiente comando:
    [root@testsrv ~]# setenforce 0
    
    O bien para asegurar la partida, reiniciar el servidor.

  3. Ahora nos toca agregar como fuente de datos para el gestor de paquetes YUM el contenido del DVD de instalación del sistema operativo. Para ello nos dirigimos al directorio de configuración /etc/yum.repos.d, hacemos una copia del seguridad del archivo public-yum-ol6.repo y lo re-nombramos a dvd.repo, para finalmente editarlo. Esto lo podemos hacer con los siguientes cuatro comandos:
    [root@testsrv ~]# cd /etc/yum.repos.d/
    [root@testsrv yum.repos.d]# cp CentOS-Media.repo CentOS-Media.repo.bkp
    [root@testsrv yum.repos.d]# vim CentOS-Media.repo
    
    Editamos el contenido dejándolo como sigue a continuación:
    [c7-media]
    name=CentOS-$releasever - Media
    baseurl=file:///mnt/CentOS_DVD/
    gpgcheck=1
    enabled=1
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
    
    Ahora el gestor de paquetes YUM ya tiene configurado la nueva fuente de datos que apunta al directorio local /media. Para que le herramienta pueda instalar paquetes a partir de dicho medio es necesario que montemos el DVD en el mencionado directorio y eso lo logramos con el siguiente comando
    [root@testsrv yum.repos.d]# mkdir /mnt/CentOS_DVD
    [root@testsrv yum.repos.d]# mount /dev/cdrom /mnt/CentOS_DVD
    
  4. Paramos y desactivamos el servicio packagekit para evitar que proceda a descargar actualizaciones en segundo plano sin nuestra autorización:
    [root@testsrv yum.repos.d]# systemctl stop packagekit
    [root@testsrv yum.repos.d]# systemctl disable packagekit
    
  5. También instalamos y activamos el repositorio EPEL (Extra Packages for Enterprise Linux) para suplir algunas dependencias.
    [root@testsrv yum.repos.d]# yum --enablerepo=extras install epel-release
    
  6. Podemos verificar los paquetes disponibles ejecutando lo siguiente, que incluye los repositorios de Extras de Internet configurados bajo el archivo CentOS-Base.repo y el repositorio EPEL agregado en el paso anterior:
    [root@testsrv ~]# yum list available
    Complementos cargados:fastestmirror, langpacks
    Loading mirror speeds from cached hostfile
    epel/x86_64/metalink                                                                                                                                                                                                  | 3.6 kB  00:00:00
     * base: mirror.facom.ufms.br
     * epel: mirror.globo.com
     * extras: mirror.facom.ufms.br
     * updates: mirror.facom.ufms.br
    ..
    
  7. Si queremos configurar un servidor ntp podemos editar el archivo chrony.conf del directorio /etc:
    [root@testsrv ~]# vim /etc/chrony.conf
    
    Donde configuramos la sección server con nuestro servidor ntp preferido
    # Use public servers from the pool.ntp.org project.
    # Please consider joining the pool (http://www.pool.ntp.org/join.html).
    #server 0.centos.pool.ntp.org iburst
    #server 1.centos.pool.ntp.org iburst
    #server 2.centos.pool.ntp.org iburst
    #server 3.centos.pool.ntp.org iburst
    server mi_servidor_ntp_local.gknet.local prefer
    
    Finalmente tenemos que reiniciar el servicio chrony para que los cambios tomen efecto:
    [root@testsrv ~]# systemctl restart chronyd
    
    Para forzar la sincronización de la hora del equipo con el servidor ntp de forma inmediata podemos ejecutar el siguiente comando:
    [root@testsrv ~]# ntpdate -u mi_servidor_ntp_local.gknet.local
    
    Para ver en tiempo real la hora en el servidor, incluyendo los segundos, podemos ejecutar el comando watch. Para salir hay que presionar las teclas CTRL+C.
    [root@testsrv ~]# watch -n 1 date
    
    Every 1,0s: date            Mon Jul  1 11:35:04 2019
    
    lun jul  1 11:35:04 -04 2019
    

Instalación de servidor Apache:

  1. Tenemos que instalar el servidor Apache.
    [root@testsrv ~]# yum install httpd mod_ssl openssl
    
  2. Para activar el service SSL en Apache primero creamos el directorio /etc/httpd/ssl para albergar certificados
    [root@testsrv ~]# mkdir /etc/httpd/ssl
    
  3. Luego pasamos a ejecutar el comando openssl para generar una nueva llave para nuestro servidor Apache. Al ejecutar el comando nos solicitará que vayamos cargando información para el certificado:
    [root@testsrv ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/httpd/ssl/apache.key -out /etc/httpd/ssl/apache.crt
    Generating a 2048 bit RSA private key
    ...............+++
    ...................+++
    writing new private key to '/etc/httpd/ssl/apache.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:PY
    State or Province Name (full name) []:It
    Locality Name (eg, city) [Default City]:HO
    Organization Name (eg, company) [Default Company Ltd]:Gabriel-Corp.
    Organizational Unit Name (eg, section) []:Informatica
    Common Name (eg, your name or your server's hostname) []:testsrv.gknet.local
    Email Address []:contacto(ARROBA)tormentadebits.com
    [root@ocssrv ~]#
    
  4. Como estamos usando OpenSSL, se recomienda crear una fuerte clave Diffie-Hellman:
    [root@testsrv ~]# openssl dhparam -out /etc/httpd/ssl/dhparam.pem 2048
    
    El hash code generado por el comando anterior lo tenemos que agregar al certificado apache.crt generado más arriba
    [root@testsrv ~]# cat /etc/httpd/ssl/dhparam.pem | tee -a /etc/httpd/ssl/apache.crt
    
  5. Luego editamos el archivo de configuración /etc/httpd/conf.d/ssl.conf
    [root@testsrv ~]# vim /etc/httpd/conf.d/ssl.conf
    
    Nos ubicamos donde se encuentran las directivas #DocumentRoot y #ServerName:
    # General setup for the virtual host, inherited from global configuration
    #DocumentRoot "/var/www/html"
    #ServerName www.example.com:443
    
    Descomentamos ambas y a la directiva ServerName le asignamos el nombre de servidor que corresponde, en este ejemplo testsrv:
    # General setup for the virtual host, inherited from global configuration
    DocumentRoot "/var/www/html"
    ServerName testsrv:443
    
    Luego pasamos a configurar la directiva SSLCertificateFile a la que le asignamos la ruta al nuevo certificado generado más arriba:
    #   Server Certificate:
    # Point SSLCertificateFile at a PEM encoded certificate.  If
    # the certificate is encrypted, then you will be prompted for a
    # pass phrase.  Note that a kill -HUP will prompt again.  A new
    # certificate can be generated using the genkey(1) command.
    SSLCertificateFile /etc/httpd/ssl/apache.crt
    
    Y finalmente también configuramos la directiva SSLCertificateKeyFile a la que le asignamos la ruta a la nueva llave generada más arriba:
    #   Server Private Key:
    #   If the key is not combined with the certificate, use this
    #   directive to point at the key file.  Keep in mind that if
    #   you've both a RSA and a DSA private key you can configure
    #   both in parallel (to also allow the use of DSA ciphers, etc.)
    SSLCertificateKeyFile /etc/httpd/ssl/apache.key
    
    Guardamos los cambios y salimos del archivo de configuración

  6. Comprobamos que la configuración de Apache esté correcta con el siguiente comando:
    [root@testsrv ~]# apachectl configtest
    Syntax OK
    #
    
  7. Finalmente activamos e iniciamos el servicio httpd (Apache2):
    [root@testsrv ~]# systemctl enable httpd
    [root@testsrv ~]# systemctl start httpd
    


Firewall:

  1. Tenemos que habilitar en el Firewall los puertos http y https para que el servidor Apache sea accesible desde equipos remotos.
    [root@testsrv ~]# firewall-cmd --get-active-zones
    public
      interfaces: ens192
    [root@testsrv ~]# firewall-cmd --zone=public --list-services
    ssh dhcpv6-client 
    [root@testsrv ~]# firewall-cmd --zone=public --permanent --add-service=http
    success
    [root@testsrv ~]# firewall-cmd --zone=public --permanent --add-service=https
    success
    [root@testsrv ~]# systemctl restart firewalld
    [root@testsrv ~]# firewall-cmd --zone=public --list-services
    ssh dhcpv6-client http https
    


Instalación y configuración de PostgreSQL

A continuación se verán los pasos para instalar y configurar de forma básica el motor de base de datos PostgreSQL:
  1. Para comenzar tenemos que instalar el motor de base de datos si aún no lo tenemos instalado:
    [root@testsrv ~]# yum install postgresql-server postgresql-contrib phpPgAdmin
    
  2. Luego tenemos que inicializar su configuración:
    [root@testsrv ~]# postgresql-setup initdb
    Initializing database ... OK
    
    #
    
  3. Activamos y arrancamos el motor de base de datos por primera vez:
    [root@testsrv ~]# systemctl enable postgresql
    [root@testsrv ~]# systemctl start postgresql
    
  4. Si queremos permitir que puedan acceder remotamente al servicio tenemos que realizar una configuración para que el motor atienda las peticiones de todas las interfaces de red del servidor (o solo algunas de ellas). Para ello crear el archivo postgresql.conf en el directorio /var/lib/pgsql/data para luego editarlo:
    [root@testsrv ~]# vim /var/lib/pgsql/data/postgresql.conf
    
    Y luego buscamos la directiva #listen_addresses, la comentamos o modificamos debiendo quedar similar a lo que sigue:
    #listen_addresses = 'localhost'
    listen_addresses = '*'
    
  5. Luego toca autorizar las redes a las que le permitiremos el acceso remoto. Pasamos a editar el archivo pg_hba.conf ubicado en el directorio /var/lib/pgsql/data como se muestra a continuación:
    [root@testsrv ~]# vim /var/lib/pgsql/data/pg_hba.conf
    
    Buscamos la siguiente sección, reemplazamos el método de autenticación ident a md5 y le agregamos la directiva necesario para permitir el acceso a los equipos ubicados en nuestra red (en este caso 192.168.1.0/24). Es importante tener en cuenta que en PostgreSQL 9.2.24 debemos dejar activa la línea relacionada a conexiones IPv6, a la cual también le tenemos que asignar el método md5.
    # TYPE  DATABASE        USER            CIDR-ADDRESS      METHOD
    # "local" is for Unix domain socket connections only
    local   all             all                               md5
    # IPv4 local connections:
    host    all             all             127.0.0.1/32      md5
    host    all             all             192.168.1.0/24    md5
    # IPv6 local connections:
    host    all             all             ::1/128           md5
    
  6. El siguiente paso consiste en cambiar la contraseña del administrador del motor de base de datos postgres, para lo cual nos conectamos a la consola sql de Postgres,
    [root@testsrv ~]# su postgres -c psql postgres
    
    Cambiamos la contraseña y salimos de la consola ejecutando la siguiente secuencia de comandos:
    postgres=# alter user postgres with password 'mi_contraseña';
    postgres=# \q
    
  7. Reiniciamos el servicio del motor de base de datos para que los cambios realizados previamente sean tomados en cuenta:
    [root@testsrv ~]# systemctl restart postgresql
    
  8. Ahora pasamos a configurar el phpPgAdmin, para lo cual a partir del archivo config.inc.php ubicado en el directorio /etc/phpPgAdmin creamos una copia con el nombre config.inc.php y luego lo editamos:
    [root@testsrv ~]# cp /etc/phpPgAdmin/config.inc.php-dist /etc/phpPgAdmin/config.inc.php
    [root@testsrv ~]# vim /etc/phpPgAdmin/config.inc.php
    
    y verificamos la configuración de las siguientes directivas cuyo contenido debería ser similar a lo sigue:
    // Configuración del servidor y puerto:
    $conf['servers'][0]['host'] = 'localhost';
    $conf['servers'][0]['port'] = 5432;
    
    // Si queremos permitir el acceso con el usuario administrador
    // (postgres) la siguiente directiva debe ser igual a false:
    $conf['extra_login_security'] = false;
    
    Guardamos los cambios y salimos del archivo de configuración para continuar con el siguiente paso.

  9. A continuación tenemos que editar el archivo phpPgAdmin.conf del directorio /etc/httpd/conf.d:
    [root@testsrv ~]# vim /etc/httpd/conf.d/phpPgAdmin.conf
    
    Y como en el servidor tenemos instalado Apache 2.4 tenemos que modificar comentar la directiva Require local y justo abajo agregar la directiva Require all granted para que funcione:
    #
    # This configuration file maps the phpPgAdmin directory into the URL space.
    # By default this application is only accessible from the local host.
    #
    
    Alias /phpPgAdmin /usr/share/phpPgAdmin
    
    <Location /phpPgAdmin>
        <IfModule mod_authz_core.c>
            # Apache 2.4
            #Require local
            Require all granted
            #Require host example.com
        </IfModule>
        <IfModule !mod_authz_core.c>
            # Apache 2.2
            Order deny,allow
            Deny from all
            Allow from 127.0.0.1
            Allow from ::1
            # Allow from .example.com
        </IfModule>
    </Location>
    
  10. Finalmente procedemos a reiniciar el servicio del Apache 2 con el siguiente comando:
    [root@testsrv ~]# systemctl restart httpd
    
  11. Con estos últimos pasos concluimos con la puesta en marcha de Apache, lo que nos permitirá acceder localmente a phpPgAdmin mediante la siguiente URL:
    http://localhost/phpPgAdmin
    
    Si carga el sitio phpPgAdmin pero tenemos problemas en loguearnos, podemos verificar que dice el archivo log de PostgreSQL, que lo podemos consultar con la siguiente directiva:
    [root@testsrv ~]# tail -f /var/lib/pgsql/data/pg_log/postgresql-Sun.log
    
    A continuación les dejo con algunas capturas de pantalla de phpPgAdmin:


  12. Con estos tres pasos anteriores hemos habilitado los puertos deseados en el cortafuego, con lo cual hemos culminado.


Instalación y configuración de Redmine

Comenzamos sin más rodeos con los pasos de instalación de la herramienta:
  1. Comenzamos por crear en el motor de base de datos PostgreSQL un nuevo usuario y la base de datos para la herramienta Redmine, esto lo podemos hacer ejecutando los siguientes comandos:
    [root@testsrv ~]# su postgres -c psql postgres
    could not change directory to "/root"
    Password:
    psql (9.2.24)
    Type "help" for help.
    postgres=# CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'redmine' NOINHERIT VALID UNTIL 'infinity';
    postgres=# CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
    postgres-# \q
    
  2. Comenzamos por instalar las dependencias que necesita la herramienta.
    [root@testsrv ~]# yum install ruby ruby-devel ImageMagick gcc gcc-c++ git curl httpd-devel ImageMagick-devel postgresql-devel mariadb-devel libcurl-devel zlib-devel
    
    Sin embargo, como he tenido problemas para instalar dependencias para la versión 2.0.0 de Ruby (ya desoportada) que viene con el DVD de instalación de CentOS 7, no me quedó otra opción que utilizar la herramienta RVM (Ruby Version Manager), que por cierto es el camino correcto y cuya falta era el problema de dependencias que he tenido en ocasiones anteriores. Antes de iniciar con el procedimiento de instalación de RVM, primero debemos instalar los siguientes paquetes:
    [root@testsrv ~]# yum install gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison iconv-devel sqlite-devel
  3. Procedemos a descargar e instalar la herramienta RVM con los siguientes pasos:
    [root@testsrv ~]# curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -
    [root@testsrv ~]# curl -sSL https://rvm.io/pkuczynski.asc | gpg2 --import -
    [root@testsrv ~]# curl -L get.rvm.io | bash -s stable
    [root@testsrv ~]# source /etc/profile.d/rvm.sh
    [root@testsrv ~]# rvm reload
    
    A continuación verificamos que se hayan cumplido con todos los requerimientos de instalación:
    [root@testsrv ~]# rvm requirements run
    Checking requirements for centos.
    Requirements installation successful.
    [root@testsrv ~]#
    
    Luego instalamos la versión 2.4.6 de Ruby..
    [root@testsrv ~]# rvm install 2.4.6
    Searching for binary rubies, this might take some time.
    No binary rubies available for: centos/7/x86_64/ruby-2.4.6.
    Continuing with compilation. Please read 'rvm help mount' to get more information on binary rubies.                                                                        
    Checking requirements for centos.
    Requirements installation successful.
    Installing Ruby from source to: /usr/local/rvm/rubies/ruby-2.4.6, this may take a while depending on your cpu(s)...
    ruby-2.4.6 - #downloading ruby-2.4.6, this may take a while depending on your connection...
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 12.0M  100 12.0M    0     0  1302k      0  0:00:09  0:00:09 --:--:-- 3127k
    ruby-2.4.6 - #extracting ruby-2.4.6 to /usr/local/rvm/src/ruby-2.4.6.....
    ruby-2.4.6 - #configuring..................................................................
    ruby-2.4.6 - #post-configuration..
    ruby-2.4.6 - #compiling..................................................................................
    ruby-2.4.6 - #installing...........................
    ruby-2.4.6 - #making binaries executable..
    ruby-2.4.6 - #downloading rubygems-3.0.6
    ruby-2.4.6 - #extracting rubygems-3.0.6......
    ruby-2.4.6 - #removing old rubygems........
    ruby-2.4.6 - #installing rubygems-3.0.6...............................................
    ruby-2.4.6 - #gemset created /usr/local/rvm/gems/ruby-2.4.6@global
    ruby-2.4.6 - #importing gemset /usr/local/rvm/gemsets/global.gems................................................................
    ruby-2.4.6 - #generating global wrappers.......
    ruby-2.4.6 - #gemset created /usr/local/rvm/gems/ruby-2.4.6
    ruby-2.4.6 - #importing gemsetfile /usr/local/rvm/gemsets/default.gems evaluated to empty gem list
    ruby-2.4.6 - #generating default wrappers.......
    ruby-2.4.6 - #adjusting #shebangs for (gem irb erb ri rdoc testrb rake).
    Install of ruby-2.4.6 - #complete 
    Ruby was built without documentation, to build it run: rvm docs generate-ri
    [root@testsrv ~]#
    
    y lo seteamos como por defecto para que sea compatible con la versión del paquete passenger instalado mediante yum.
    [root@testsrv ~]# rvm list
    [root@testsrv ~]# rvm use 2.4.6 --default
    [root@testsrv ~]# ruby --version
    
    Con la herramienta RVM también configuramos las variables de entorno correctas para el servicio crond para permitir la ejecución de scripts Ruby con la versión correcta. Dicha configuración se copia al archivo denominado redmine del directorio /etc/cron.d que más adelante se utilizará para ejecutar todos los scripts Ruby que requerirá Redmine para funcionar.
    [root@testsrv ~]# rvm cron setup
    [root@testsrv ~]# crontab -l > /etc/cron.d/redmine
    [root@testsrv ~]# chmod 644 /etc/cron.d/redmine
    
    Finalmente con el comando which comprobamos la ubicación del programa ruby instalado con la herramienta RVM:
    [root@testsrv ~]# which ruby
    ruby 2.4.6p354 (2019-04-01 revision 67394) [x86_64-linux]
    [root@testsrv ~]#
    
  4. A continuación procedemos a descargar la última versión disponible de la rama 3.4 de Redmine, que al momento de escribir el artículo correspondía a la versión 3.4.13. Es importante aclarar que se ha decido utilizar dicha rama debido a que cuando comencé a redactar este artículo solo estaba CentOS 7 cuyo paquete de Ruby más moderno que viene en el DVD corresponde a la versión 2.0.0, una versión incompatible con la rama 4.0 de Redmine. Ahora bien, ya mas tarde aprendí a usar RVM y entendí que al final el paquete oficial de la distro poco importa. Para saber más sobre la compatibilidad de las versiones de Ruby con respecto a cada rama de Redmine se puede consultar la siguiente URL:

    https://www.redmine.org/projects/redmine/wiki/RedmineInstall

    Descargamos el archivo en el directorio /opt para luego descomprimirla en el mismo directorio:
    [root@testsrv ~]# cd /opt/
    [root@testsrv opt]# wget https://www.redmine.org/releases/redmine-3.4.13.tar.gz
    [root@testsrv opt]# tar -xzf redmine-3.4.13.tar.gz
    [root@testsrv opt]# rm redmine-3.4.13.tar.gz
    [root@testsrv opt]# mv redmine-3.4.13 redmine
    [root@testsrv opt]# cd redmine/
    [root@testsrv redmine]#
    
  5. Una vez dentro del directorio raíz de la herramienta nos dirigimos a la carpeta config para crear y editar el archivo de configuración database.yml.
    [root@testsrv redmine]# cd config/
    [root@testsrv config]# cp database.yml.example database.yml
    [root@testsrv config]# vim database.yml
    
    Al cual le agregamos la configuración adecuada del motor de base de datos que utilizará Redmine
    production:
      adapter: postgresql
      database: redmine
      host: localhost
      username: redmine
      password: redmine
      encoding: utf8
    
  6. Luego, en el directorio /opt/redmine/config ejecutamos la directiva bundler con una serie de argumentos para resolver e instalar las dependencias requeridas para el entorno de producción (production) que necesita la herramienta Redmine para funcionar, las dependencias para el entorno de desarrollo y prueba (development y test respectivamente) son excluidas.
    [root@testsrv config]# bundle install --without development test
    
    El comando bundle se encargará de instalar todas las dependencias requeridas:
    Fetching gem metadata from https://rubygems.org/..............
    Fetching additional metadata from https://rubygems.org/..
    Resolving dependencies...
    Installing rake 12.3.2
    Installing i18n 0.7.0
    Installing minitest 5.11.3
    Installing thread_safe 0.3.6
    Installing tzinfo 1.2.5
    ..
    ..
    
    OBS: ruby-devel, ImageMagick-devel, postgresql-devel mysql-devel zlib-devel libMagick++-devel son paquetes del sistema operativo que tienen que estar instalados para que se puedan instalar las gemas Ruby rmagick, pg, etc. Si el comando genera una excepción indicando que no puede instalar un paquete debemos verificar si las librerías de desarrollo de Ruby (ruby-devel) y las librerías de desarrollo del paquete que se intenta instalar estén instalados en el sistema operativo.

  7. A continuación generamos una nueva llave que utiliza Rails para codificar la información de sesiones contenidas en las cookies:
    [root@testsrv config]# bundle exec rake generate_secret_token
    
  8. Una vez concluido con el paso anterior nos posicionamos en el directorio /opt/redmine y procedemos a crear el esquema de base de datos de Redmine en PostgrSQL y a cargar los registros de configuración por defecto en las tablas mediante la siguiente secuencia de comandos:
    [root@testsrv config]# cd ..
    [root@testsrv redmine]# RAILS_ENV=production bundle exec rake db:migrate
    [root@testsrv redmine]# RAILS_ENV=production bundle exec rake redmine:load_default_data
    (in /opt/redmine)
    
    Select language: bg, bs, ... en, en-GB, es, ... vi, zh, zh-TW [en] es
    ====================================
    Default configuration data loaded.
    
  9. Finalmente creamos un grupo y usuario de sistema, en ambos casos denominado redmine, y le hacemos dueño del directorio /opt/redmine:
    [root@testsrv redmine]# groupadd -r redmine
    [root@testsrv redmine]# useradd -r -g redmine redmine
    [root@testsrv redmine]# chown -Rf redmine:redmine /opt/redmine
    
  10. Ahora instalamos el módulo Passenger para permitir que Apache2 pueda ejecutar aplicaciones Ruby:
    [root@testsrv redmine]# gem install passenger
    [root@testsrv redmine]# passenger-install-apache2-module
    [root@testsrv redmine]# passenger-config validate-install
    [root@testsrv redmine]# passenger-memory-stats
    
    Ahora debemos crear en el directorio /etc/httpd/conf.d el archivo passenger.conf y luego editarlo,
    [root@testsrv redmine]# touch /etc/httpd/conf.d/passenger.conf
    [root@testsrv redmine]# vim /etc/httpd/conf.d/passenger.conf
    
    Y copiar el siguiente contenido sugerido durante la instalación de la gema:
    LoadModule passenger_module /usr/local/rvm/gems/ruby-2.4.6/gems/passenger-6.0.4/buildout/apache2/mod_passenger.so
    <IfModule mod_passenger.c>
      PassengerRoot /usr/local/rvm/gems/ruby-2.4.6/gems/passenger-6.0.4
      PassengerDefaultRuby /usr/local/rvm/gems/ruby-2.4.6/wrappers/ruby
    </IfModule>
    
    Finalmente ejecutamos la directiva para validar la instalación del módulo Passenger:
    [root@testsrv ~]# passenger-config validate-install
    What would you like to validate?
    Use  to select.
    If the menu doesn't display correctly, press '!'
    
       ⬢  Passenger itself
     ‣ ⬢  Apache
    
    -------------------------------------------------------------------------
    
    Checking whether there are multiple Apache installations...
    Only a single installation detected. This is good.
    
    -------------------------------------------------------------------------
    
     * Checking whether this Passenger install is in PATH... ✓
     * Checking whether there are no other Passenger installations... ✓
     * Checking whether Apache is installed... ✓
     * Checking whether the Passenger module is correctly configured in Apache... ✓
    
    Everything looks good. :-)
    [root@testsrv ~]#
    
    Y comprobar el uso de memoria del mencionado módulo:
    [root@testsrv ~]# passenger-memory-stats
    Version: 6.0.4
    Date   : 2019-12-15 23:04:05 -0300
    
    ---------- Apache processes ----------
    PID    PPID   VMSize    Private  Name
    --------------------------------------
    11563  1      399.3 MB  0.4 MB   /usr/sbin/httpd -DFOREGROUND
    11609  11563  401.4 MB  0.3 MB   /usr/sbin/httpd -DFOREGROUND
    11610  11563  401.4 MB  0.3 MB   /usr/sbin/httpd -DFOREGROUND
    11611  11563  401.4 MB  0.4 MB   /usr/sbin/httpd -DFOREGROUND
    11612  11563  401.4 MB  0.3 MB   /usr/sbin/httpd -DFOREGROUND
    11613  11563  401.4 MB  0.3 MB   /usr/sbin/httpd -DFOREGROUND
    11661  11563  401.4 MB  0.3 MB   /usr/sbin/httpd -DFOREGROUND
    11700  11563  401.4 MB  0.2 MB   /usr/sbin/httpd -DFOREGROUND
    11701  11563  401.4 MB  0.2 MB   /usr/sbin/httpd -DFOREGROUND
    11702  11563  401.4 MB  0.2 MB   /usr/sbin/httpd -DFOREGROUND
    11703  11563  401.4 MB  0.2 MB   /usr/sbin/httpd -DFOREGROUND
    ### Processes: 11
    ### Total private dirty RSS: 3.39 MB
    
    
    -------- Nginx processes --------
    
    ### Processes: 0
    ### Total private dirty RSS: 0.00 MB
    
    
    ------ Passenger processes ------
    PID    VMSize     Private   Name
    ---------------------------------
    11589  357.7 MB   2.1 MB    Passenger watchdog
    11592  1119.2 MB  4.2 MB    Passenger core
    11674  469.4 MB   141.5 MB  Passenger AppPreloader: /opt/redmine (forking...)
    ### Processes: 3
    ### Total private dirty RSS: 147.76 MB
    [root@testsrv ~]#
    
  11. (OPCIÓN 1) ACCESO MEDIANTE VIRTUAL HOSTS: Si deseamos que Apache sirva el sitio web de Redmine a través de un nombre de dominio totalmente cualificado (FQDN: Fully Qualified Domain Name) resuelto a través de servidores de nombres (DNS) internos o externos podemos configurar un host virtual para dicho fin. Para ello nos dirigimos al directorio /etc/httpd/conf.d y creamos un nuevo archivo llamado vredmine.conf:
    [root@testsrv ~]# cd /etc/httpd/conf.d
    [root@testsrv conf.d]# touch vredmine.conf
    Editamos el archivo con nuestro editor de texto preferido..
    [root@testsrv conf.d]# vim vredmine.conf
    
    Y luego agregamos las siguientes directivas:
    # -- ES NECESARIO DEFINIR LA DIRECTIVA NameVirtualHost CUANDO
    # SE CONFIGURAN HOSTS VIRTUALES BASADOS EN NOMBRES.
    NameVirtualHost *:80
    NameVirtualHost *:443
    
    # -- CONFIGURACION DEL HOST VIRTUAL POR DEFECTO, QUE APUNTA
    # A LA RUTA TRADICIONAL.
    <VirtualHost *:80 *:443>
        ServerName testsrv
        ServerAlias testsrv *.testsrv testsrv.gknet.local *testsrv.gknet.local
        DocumentRoot /srv/www/htdocs
    </VirtualHost>
    
    # -- CONFIGURACION DEL VIRTUAL HOST PARA REDMINE
    <VirtualHost *:80 *:443>
        Options +Indexes
        ServerAdmin nombre_usuario@gmail.com
        ServerName redminesrv
        ServerAlias redminesrv.gknet.local *.redminesrv.gknet.local redminesrv *.redminesrv
        DocumentRoot /opt/redmine/public
        RailsEnv production
    
        PassengerUser apache
        PassengerGroup apache
    
        <Directory "/opt/redmine/public">
            Options +Indexes -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch
            AllowOverride All
            # Configuracion Apache 2.2
            #Order allow,deny
            #Allow from all
    
            # Configuracion Apache 2.4 --> https://httpd.apache.org/docs/2.4/upgrading.html
            Require all granted
        </Directory>
    </VirtualHost>
    
    Con esto ya tenemos el servidor web configurado con soporte virtual host.

  12. (OPCIÓN 2) ACCESO MEDIANTE SUBDIRECTORIOS: Una opción alternativa a la configuración de host virtual de Apache para desplegar Redmine es utilizar una configuración más tradicional definiendo el acceso a dicha herramienta a través de un subdirectorio posterior al dominio o dirección IP de nuestro servidor web.

    Como primer paso nos dirigimos al directorio /etc/httpd/conf.d, para luego crear y editar un nuevo archivo llamado redmine.conf:
    [root@testsrv ~]# cd /etc/httpd/conf.d
    [root@testsrv conf.d]# touch redmine.conf
    [root@testsrv conf.d]# vim redmine.conf
    
    Al que le agregamos la siguiente configuración:
    # -- ALIAS DEL SUBDIRECTORIO APUNTANDO A LA RUTA REAL DE
    # LA HERRAMIENTA REDMINE.
    Alias /redmine /opt/redmine/public
    
    # -- DEFINICION DEL ENTORNO RAILS.
    RailsEnv production
    RailsBaseURI /redmine
    
    # -- CONFIGURACION DE PASSENGER.
    PassengerUser apache
    PassengerGroup apache
    
    # -- CONFIGURACIONES DEL DIRECTORIO DE TRABAJO.
    <Directory "/opt/redmine/public">
        Options -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch
        AllowOverride All
        # Configuracion Apache 2.2
        #Order allow,deny
        #Allow from all
        
        # Configuracion Apache 2.4 --> https://httpd.apache.org/docs/2.4/upgrading.html
        Require all granted
    </Directory>
    
    Si queremos evitar que aparezca el sitio web de bienvenida de Apache al acceder al documento root (http://ip_o_nombre_dominio_servidor), podemos hacer que automáticamente se redirija al sub-directorio redmine (http://ip_o_nombre_dominio_servidor/redmine) editando el archivo welcome.conf del directorio /etc/httpd/conf.d:
    [root@testsrv conf.d]# vim /etc/httpd/conf.d/welcome.conf
    
    Y luego agregarle antes de todo la directiva RedirectMatch de la siguiente manera:
    #
    # This configuration file enables the default "Welcome" page if there
    # is no default index page present for the root URL.  To disable the
    # Welcome page, comment out all the lines below.
    #
    # NOTE: if this file is removed, it will be restored on upgrades.
    #
    RedirectMatch ^/$ /redmine/
    
    <LocationMatch "^/+$">
        Options -Indexes
        ErrorDocument 403 /.noindex.html
    </LocationMatch>
    
    <Directory /usr/share/httpd/noindex>
        AllowOverride None
        Require all granted
    </Directory>
    
    Alias /.noindex.html /usr/share/httpd/noindex/index.html
    Alias /noindex/css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css
    Alias /noindex/css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css
    Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif
    Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png
    
  13. Asignamos el usuario apache y al grupo apach como dueños de ciertos directorios, y aplicamos algunos permisos de escritura y lectura:
    [root@testsrv conf.d]# cd /opt/redmine
    [root@testsrv conf.d]# chown -Rf apache:apache files log tmp vendor public/plugin_assets
    [root@testsrv conf.d]# chmod -Rf 755 files log tmp vendor public/plugin_assets
    
  14. Para que el módulo Passenger de Apache interprete correctamente el contenido del directorio /opt/redmine/public, tenemos que crear un enlace simbólico del mencionado directorio en el directorio /var/www/html de la siguiente manera:
    [root@testsrv conf.d]# ln -s /opt/redmine/public /var/www/html/redmine
    
  15. Finalmente reiniciamos el servicio httpd:
    [root@testsrv ~]# systemctl restart httpd
    


Acceso a Redmine

  1. Si para acceder a la herramienta Redmine hemos configurado el servicio Apache con virtual hosts, entonces debemos utilizar el nombre de dominio totalmente cualificado que hemos definido y que debe ser correctamente resuelto por algún servidor DNS o mediante alguna entrada al archivo /etc/hosts en la máquina cliente que se trata de conectar a la herramienta. Como ejemplo podríamos tener la siguiente URL:
    http://redmine.mi_dominio.local
    
  2. Si en el caso contrario hemos configurado el acceso a la herramienta Remine mediante un subdirectorio en Apache, la URL deberá ser similar a la siguiente:
    http://ip_o_nombre_dominio_servidor/redmine
    
    Por defecto la herramienta se ve así:


    OBS: El login del usuario administrador es admin y su contraseña por defecto también es admin, pero inmediatamente después la herramienta nos obligará a reemplazarla por una diferente.



    En el apartado Mi Cuenta del usuario admin, accesible desde el enlace de la esquina superior derecha, se recomienda configurar las siguientes opciones:
    - Correo electrónico
    - Idioma
    - Notificaciones por correo
    - Zona horaria



Instalación de Plugins

  1. Podemos ampliar la funcionalidad de Redmine mediante la instalación de Plugins muy interesantes. Podemos acceder a una lista detalla de plugins compatibles con la versión 3.4 de Redmine a través de éste enlace, de entre los cuales me gusta instalar los siguientes:

    Plugins libres:
    - Theme Changer
    - Attach image from clipboard
    - Lightbox Plugin 2
    - Scrum Plugin
    - Periodic Task

    Plugins de RedmineUP:
    - People
    - Checklists

    OBS: Los plugins siempre deben ser probados en una instalación de prueba, nunca en el servidor de producción, ya que algunos suelen fallar dependiendo de la versión de Redmine, Ruby, etc.

  2. Para proceder con la instalación de un plugin, lo que tenemos que hacer es dirigimos al directorio de plugins de Redmine:
    [root@testsrv ~]# cd /opt/redmine/plugins/
    
    Luego descargarlo mediante la URL que sugiere el desarrollador del plugin y asignarle los permisos correspondientes. Si la URL permite descargar un archivo con formato tar.gz, tgz, zip, etc. podemos utilizar wget para descargar el paquete como se muestra a continuación:
    [root@testsrv plugins]# wget https://github.com/haru/redmine_theme_changer/releases/download/0.3.1/redmine_theme_changer-0.3.1.zip
    [root@testsrv plugins]# unzip redmine_theme_changer-0.3.1.zip
    [root@testsrv plugins]# rm redmine_theme_changer-0.3.1.zip
    [root@testsrv plugins]# chown -Rf redmine:redmine redmine_theme_changer/
    
    Una vez descargado y descompactado el plugin ejecutamos el siguiente comando que implementa las modificaciones requeridas por el plugin en la base de datos y en la aplicación.
    [root@testsrv plugins]# bundle exec rake redmine:plugins:migrate RAILS_ENV=production
    
  3. Si el proyecto se encuentra disponible en algún repositorio Git en la web podemos descargar el complemento clonando en repositorio remoto y lo instalamos de la siguiente manera:
    [root@testsrv plugins]# git clone https://github.com/peclik/clipboard_image_paste.git
    [root@testsrv plugins]# chown -Rf redmine:redmine clipboard_image_paste/
    [root@testsrv plugins]# bundle exec rake redmine:plugins:migrate RAILS_ENV=production
    
  4. A continuación instalamos el plugin redmine_lightbox2:
    [root@testsrv plugins]# wget https://github.com/paginagmbh/redmine_lightbox2/archive/v0.4.4.zip
    [root@testsrv plugins]# unzip v0.4.4.zip
    [root@testsrv plugins]# rm v0.4.4.zip
    [root@testsrv plugins]# mv redmine_lightbox2-0.4.4 redmine_lightbox2
    [root@testsrv plugins]# chown -Rf redmine:redmine redmine_lightbox2
    [root@testsrv plugins]# bundle exec rake redmine:plugins NAME=redmine_lightbox2 RAILS_ENV=production
    
    El plugin scrum-plugin:
    [root@testsrv plugins]# wget https://redmine.ociotec.com/attachments/download/476/scrum-v0.18.0.tar.gz
    [root@testsrv plugins]# tar -xzvf scrum-v0.18.0.tar.gz
    [root@testsrv plugins]# rm scrum-v0.18.0.tar.gz
    [root@testsrv plugins]# chown -Rf redmine:redmine scrum
    [root@testsrv plugins]# bundle exec rake redmine:plugins NAME=scrum RAILS_ENV=production
    
  5. Para instalar el plugin Redmine-Periodic-Task primero también debemos tener instalados algunos gemas adicionales:
    [root@testsrv plugins]# gem install activesupport -v 5.2.4.1
    [root@testsrv plugins]# gem install business_time
    [root@testsrv plugins]# gem install protected_attributes_continued -v 1.4.0
    [root@testsrv plugins]# gem install activemodel -v 4.2.11.1
    [root@testsrv plugins]# wget https://www.redmine.org/attachments/download/22557/Redmine-Periodic-Task-4.1.0.zip
    [root@testsrv plugins]# unzip Redmine-Periodic-Task-4.1.0.zip
    [root@testsrv plugins]# rm Redmine-Periodic-Task-4.1.0.zip
    [root@testsrv plugins]# mv Redmine-Periodic-Task-4.1.0 periodictask
    [root@testsrv plugins]# chown -Rf redmine:redmine periodictask
    [root@testsrv plugins]# bundle exec rake redmine:plugins NAME=periodictask RAILS_ENV=production
    
    El plugin Redmine-Periodic-Task también necesita que se ejecute un Crontab que verifique periódicamente la generación de las tareas periódicas registradas, para lo cual editamos el archivo llamado redmine dentro del directorio /etc/cron.d:
    [root@testsrv ~]# vim /etc/cron.d/redmine
    
    Archivo en el cual agregamos al final el siguiente contenido para que cada 10 minutos verifique la generación de una tarea preconfigurada:
    # Ejecucion periodica para la generacion automatica de tareas mediante el complemento periodictasks.
    */10 * * * * root rake -f /opt/redmine/Rakefile redmine:check_periodictasks RAILS_ENV="production" LOCALE="de"
    
    Finalmente reiniciamos el servicio crond:
    [root@testsrv plugins]# systemctl restart crond
    
    Para mas información consultar el apartado CONFIGURATION del archivo README.md del repositorio GitHub del autor del plugin.

  6. Para instalar los pluggins People y Plugin Checklists antes se tienen que instalar algunas dependencias de la siguiente forma:
    [root@testsrv plugins]# gem install vcard
    [root@testsrv plugins]# gem install redmine_crm
    
    Ahora si ya podemos instalar el pluggin People en su versión ligera (Ligth) descargada desde www.redmineup.com:
    [root@testsrv plugins]# unzip redmine_people-1_4_1-light.zip
    [root@testsrv plugins]# chown -Rf redmine:redmine redmine_people
    [root@testsrv plugins]# bundle exec rake redmine:plugins NAME=redmine_people RAILS_ENV=production
    
    Así como el plugin Plugin Checklists:
    [root@testsrv plugins]# unzip redmine_checklists-3_1_16-light.zip
    [root@testsrv plugins]# chown -Rf redmine:redmine redmine_checklists
    [root@testsrv plugins]# bundle exec rake redmine:plugins NAME=redmine_checklists RAILS_ENV=production
    
  7. Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:
    [root@testsrv ~]# systemctl restart httpd
    


Actualización de temas (themes)

Podemos agregar nuevos themes para personalizar el look & feel de la herramienta, los pasos para agregarlos van a continuación.
  1. Lo primero es descargar el nuevo tema que deseamos instalar desde el sitio web que sigue a continuación:
    URL: http://www.redmine.org/projects/redmine/wiki/Theme_List
    
    De mi parte les recomiendo probar los siguientes themes disponibles:
    - A1
    - Circle
    - Dwarf

  2. Si el archivo está empaquetado bajo los formatos tar.gz, tgz, zip, etc, entonces tenemos que copiar el archivo en la carpeta /opt/redmine/public/themes, descomprimirlo y asignarle el nuevo dueño:
    [root@testsrv ~]# cd /opt/redmine/public/themes
    [root@testsrv themes]# unzip a1_theme-2_0_0.zip
    [root@testsrv themes]# rm a1_theme-2_0_0.zip
    [root@testsrv themes]# chown -Rf redmine:redmine a1
    
    Si el theme se encuentra en un repositorio git lo podemos instalar siguiendo los siguientes pasos (El theme Dwarf se tiene que mover de una sub-carpeta a /opt/redmine/public/themes, en los demás themes esto no suele ser necesario):
    [root@testsrv ~]# cd /opt/redmine/public/themes
    [root@testsrv themes]# git clone https://github.com/themondays/Dwarf.git
    [root@testsrv themes]# cd Dwarf/production/
    [root@testsrv production]# mv dwarf/ ../../
    [root@testsrv production]# cd ../../
    [root@testsrv themes]# chown -Rf redmine:redmine dwarf
    [root@testsrv themes]# rm -Rf Dwarf
    
    También recomendamos instalar y probar el siguiente theme:
    
    [root@testsrv themes]# git clone https://bitbucket.org/dkuk/redmine_alex_skin.git
    [root@testsrv themes]# chown -Rf redmine:redmine redmine_alex_skin
    
    Finalmente es necesario reiniciar el servicio httpd para que los nuevos themes sean tomados en cuenta:
    root@testsrv themes]# systemctl restart httpd
    
  3. Con eso ya está, ya podremos seleccionar los nuevos temas agregados en la pestaña Mostrar (Show) de la sección de Administración de la herramienta, y si tenemos instalado el plugin Theme Changer cada usuario podrá personalizar su theme directamente desde la página de su perfil.


Configuración para envío de correos

Para que la herramienta pueda generar notificaciones vía email se tiene que definir como mínimo un servidor smtp que nos permita enviar los correos. Los pasos van a continuación:
  1. Primeramente nos dirigimos al directorio /opt/redmine/config y creamos el archivo configuration.yml a partir del archivo plantilla del mismo directorio.
    [root@testsrv ~]# cd /opt/redmine/config/
    [root@testsrv config]# cp configuration.yml.example configuration.yml
    
  2. Luego editamos el archivo configuration.yml,
    [root@testsrv config]# vim configuration.yml
    
    y lo configuramos similar a lo que sigue en el caso de que tengamos un servidor de correo local:
    default:
      email_delivery:
        delivery_method: :smtp
        smtp_settings:
          address: ip_servidor_local
          port: 25
          domain: midominio.com
          authentication: :none
          openssl_verify_mode: none
    
    Para una cuenta de Gmail la configuración podría ser similar a lo que sigue:
    default:
      email_delivery:
        delivery_method: :smtp
        smtp_settings:
          enable_starttls_auto: true
          address: "smtp.gmail.com"
          port: 587
          domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
          authentication: :plain
          user_name: "your_email@gmail.com"
          password: "your_password"
    
    OBS: Recuerda que si usas Gmail tendrás que habilitar en el correo los servicios de IMAP y activar el acceso a aplicaciones menos seguras. Referencias:
    - Leer mensajes de Gmail desde otros clientes de correo mediante IMAP
    - Permitir que las aplicaciones menos seguras accedan a tu cuenta

  3. Reiniciamos el servicio Apache para que la configuración anterior tome efecto:
    [root@testsrv config]# systemctl restart httpd
    
  4. Y finalmente realizamos las configuraciones faltantes en la interfaz Web. Primeramente realizamos algunos cambios en la sección de configuración Administración-->Configuración-->General, en la cual debemos configurar el Nombre y la ruta del servidor y el Protocolo, además de otras configuraciones interesantes como el título de la aplicación, el mensaje de bienvenida, la cantidad de objetos por página, etc.


    Luego seguimos con cambios en la opción de configuración Administración-->Configuración-->Notificaciones por correo de la interfaz web de Redmine.


    En este apartado se recomienda configurar las opciones:
    - Correo desde el que enviar mensajes
    - Opción de notificación por defecto
    - Pie de mensajes

    Una vez concluida con las configuraciones guardamos los cambios con el botón Guardar y luego probamos el funcionamiento de envío de correos haciendo clic en el enlace Enviar un correo de prueba, que intentará enviar un correo de prueba a la cuenta definida en el apartado Mi Cuenta del usuario admin, que previamente había configurado como contacto(ARROBA).tormentadebits.com.


Registro de tareas a partir de correos electrónicos

En esta parte de la guía se van a abarcar las configuraciones y modificaciones que se necesitan realizar para implementar la generación de tareas (peticiones) a partir de correos electrónicos, su correspondiente identificación y la generación de notificaciones automáticas para la cuenta de correo que haya enviado la tarea.
  1. Para recibir los correos entrantes primero necesitamos tener una cuenta de correo definida en algún servidor local o proveedor de correo electrónico externo que permita el acceso mediante los protocolos POP3 o IMAP.

  2. Una vez resuelto el paso anterior podemos generar las tareas a partir de los correos que se encuentran en la bandeja de entrada dirigiéndonos al directorio /opt/redmine,
    [root@testsrv ~]# cd /opt/redmine
    
    y ejecutando el siguiente comando que lo tenemos que adecuar a nuestras necesidades:
    [root@testsrv redmine]# bundle exec rake redmine:email:receive_imap RAILS_ENV="production" host=imap.gmail.com port=993 username=mi_cuenta@gmail.com password=contraseña_de_cuenta_gmail ssl=1 folder=INBOX project=prueba tracker=Soporte allow_override=project,tracker,priority unknown_user=accept no_permission_check=1 move_on_failure=INBOX move_on_success=INBOX -r 'openssl' -E 'OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE'
    
    En este caso se utiliza de ejemplo una cuenta de correo Gmail con acceso IMAP. Las directivas de configuración relacionadas al protocolo IMAP son las siguientes:
    • host=imap.gmail.com: IMAP server host (default: 127.0.0.1)
    • port=993: IMAP server port (default: 143)
    • ssl=1: Usa SSL? El valor 1 indica que si se usa SSL (default: false)
    • username=USERNAME: IMAP account
    • password=PASSWORD: IMAP password
    • folder=INBOX: Directorio IMAP a leer (default: INBOX)
    • move_on_success=INBOX: Deja en la carpeta INBOX los correos que fueron recibidos exitosamente en Redmine en vez de borrar los correos. Se podría crear una carpeta REDMINESUCCESS en nuestro Gmail para almacenar todos los correos procesados exitosamente por la herramienta.
    • move_on_failure=INBOX: Deja en la carpeta INBOX los ignorados por Redmine en vez de borrarlos. Se podría crear una carpeta REDMINEFAILURES en nuestro Gmail para almacenar todos los correos ignorados por la herramienta.
    • -r 'openssl' -E 'OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE: En CentOS se agregan las directivas para forzar a que ignore la verificación del certificado SSL del protocolo IMAP en el puerto 993, ya que sin dicha directiva la ejecución del comando generaba la siguiente excepción:
      rake aborted! OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
      
      Referencia: Receiving emails from imap ssl

    También podemos controlar la forma en que se agrega una nueva tarea en Redmine incluyendo los siguientes argumentos en el cuerpo del correo:
    • project=PROJECT: Identifier of the target project
    • tracker=TRACKER: Name of the target tracker
    • category=CATEGORY: Name of the target category
    • priority=PRIORITY: Name of the target priority
    • allow_override=ATTRS: Allow email content to override attributes specified by previous options ATTRS is a comma separated list of attributes
    • unknown_user=ACTION
    • no_permission_check=[0|1]
    Según como se haya definido la directiva unknown_user se puede aceptar o no correos de usuarios no registrados en Redmine para crear tareas o peticiones a partir de ellos. En nuestro comando anterior hemos utilizado la opción unknown_user=accept, que permite generar tareas a partir de correos cuyas cuentas de usuario no corresponden a un usuario de Redmine debidamente registrado.

    A continuación se muestran todas las opciones disponibles para la directiva unknown_user:
    unknown_user=ACTION     how to handle emails from an unknown user where ACTION can be one of the following
    values:
    - ignore: the email is ignored (default)
    - accept: the sender is considered as an anonymous user and the email is accepted
    - create: a user account is created for the sender (username/password are sent back to the user) and the email is accepted
    
    Para que los usuarios no registrados puedan agregar tareas vía e-mail sin problemas no basta con solo agregar la directiva unknown_user=accept, también debemos agregar la directiva no_permission_check=1 que evitará que redmine:email:receive_imap verifique los permisos relacionados al usuario Anonymous, que es el usuario de Redmine al cual serán asociadas las nuevas tareas generadas.

    Ahora bien, es importante aclarar que si queremos utilizar la directiva unknown_user=accept sin especificar la directiva no_permission_check=1 será necesario configurar los permisos del rol Anonymous, al cual tendremos que agregar el permiso "notificaciones" (add issues), y dependiendo si los proyectos son públicos o privados también habrá que configurar la "Visibilidad de las peticiones" (Issues visibility), configuraciones que además darán permisos a los usuarios anónimos para que puedan registrar tareas mediante la interfaz web de Redmine.

    Por último y para no olvidar, como le hemos especificado el valor Soporte al argumento tracker del comando anterior, es importante agregar la opción Soporte a la lista de Actividades, que es configurable accediendo al menú Administración-->Listas de valores como se observa a continuación:


    El comando utiliza el argumento tracker para saber bajo que tipo de actividad debe registrar el tiempo dedicado en una tarea cuando dicha información se especifica en el cuerpo del mensaje al subir una revisión al servidor como se detalla en la siguiente captura:


  3. El siguiente paso consiste en registrar una nueva tarea programada que se encargue de buscar los correos periódicamente. Para ello editamos el archivo redmine del directorio /etc/cron.d:
    [root@testsrv ~]# vim /etc/cron.d/redmine
    
    Una vez abierto el archivo le agregamos la siguiente directiva que ejecuta cada minuto una versión derivada del script tratado en el paso anterior, que realizará la búsqueda de nuevos correos entrantes y creará nuevas peticiones (issues) a partir de ellos.
    # Generacion de tareas a partir de correos entrantes.
    * * * * * root rake -f /opt/redmine/Rakefile --silent redmine:email:receive_imap RAILS_ENV="production" host=imap.gmail.com port=993 username=mi_cuenta@gmail.com password=contraseña_de_cuenta_gmail ssl=1 folder=INBOX project=prueba tracker=Soporte allow_override=project,tracker,priority unknown_user=accept no_permission_check=1 move_on_failure=INBOX move_on_success=INBOX -r 'openssl' -E 'OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE' > /dev/null 2>&1
    
    OBS: En CentOS se agrega al final las directivas "-r 'openssl' -E 'OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE'" para forzar a que ignore la verificación del certificado SSL del protocolo IMAP en el puerto 993, ya que sin dicha directiva la ejecución del comando generaba la siguiente excepción:
    rake aborted! OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
    
    Referencia: Receiving emails from imap ssl

    Finalmente reiniciamos el servicio cron para activar la tarea.
    [root@testsrv ~]# systemctl restart crond
    
  4. Si hemos utilizado las directivas unknown_user=accept y no_permission_check=1, las nuevas peticiones recibidas mediante correos serán registradas en Redmine con el usuario Anónimo como titular de la tarea, con lo cual ya no sabremos quien ha sido el real emisor del correo/tarea.

    Para evitar esto podemos realizar algunas modificaciones para que la cuenta de correo del emisor sea agregada en el título y en el cuerpo de la tarea. Para lograr esto vamos a modificar parte del código en el archivo mail_handler.rb ubicado en el directorio /opt/redmine/app/models, que se encarga de procesar los correos entrantes:
    [root@testsrv ~]# vim /opt/redmine/app/models/mail_handler.rb
    
    Una vez abierto el archivo tenemos que buscar la siguiente sección en la cual procedemos a comentar el código que aparece en las líneas 12 y 17. Luego agregamos debajo de las líneas comentadas el código que aparece en las líneas 13 y 18 respectivamente.
    # Creates a new issue
      def receive_issue
        project = target_project
        # check permission
        unless handler_options[:no_permission_check]
          raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
        end
    
        issue = Issue.new(:author => user, :project => project)
        attributes = issue_attributes_from_keywords(issue)
        if handler_options[:no_permission_check]
          issue.tracker_id = attributes['tracker_id']
          if project
            issue.tracker_id ||= project.trackers.first.try(:id)
          end
        end
        issue.safe_attributes = issue_attributes_from_keywords(issue)
        issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
        #issue.subject = cleaned_up_subject
        issue.subject = cleaned_up_subject  + " (#{email.from.to_a.first.to_s.strip.gsub(/@.*$/, '').strip})"
        if issue.subject.blank?
          issue.subject = '(no subject)'
        end
        #issue.description = cleaned_up_text_body
        issue.description = "ENVIADO POR: #{email.from.to_a.first.to_s.strip}\r\n\r\n" + cleaned_up_text_body
        issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?
        issue.is_private = (handler_options[:issue][:is_private] == '1')
    
        # add To and Cc as watchers before saving so the watchers can reply to Redmine
        add_watchers(issue)
        issue.save!
        add_attachments(issue)
        logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
        issue
    end
    
  5. Para hacer que aquellos usuarios que envíen sus correos a soporte y que no se encuentren registrados en la herramienta Redmine reciban una notificación por cada actualización que se realice a la tarea, yo recomiendo utilizar el plugin CC Address Plugin for Redmine, un fork del proyecto original redmine_cc_addresses que ya no es compatible con las últimas versiones de Redmine. Este plugin permite a ciertos usuarios de Redmine (según los permisos del usuario) asociar cuentas de correos a una tarea, a fin de que la herramienta envíe automáticamente notificaciones a dichas cuentas para mantener informado al interesado ante cualquier cambio que pueda sufrir la mencionada petición, como ser una asignación de técnico, cierre de tarea, etc.

    Para implementar el plugin nos dirigimos al directorio de plugins de Redmine, lo descargamos de Github, le asignamos los permisos correspondientes y ejecutamos un comando que implementa las modificaciones requeridas por el plugin en la base de datos y en la aplicación:
    [root@testsrv ~]# cd /opt/redmine/plugins/
    [root@testsrv plugins]# git clone https://github.com/ageis/redmine_cc_addresses.git
    [root@testsrv plugins]# chown -Rf redmine:redmine redmine_cc_addresses/
    [root@testsrv plugins]# bundle exec rake redmine:plugins:migrate RAILS_ENV=production
    
    Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:
    [root@testsrv ~]# systemctl restart httpd
    
    Hay que tener en cuenta que en la sección de Configuración -> Módulo de cada proyecto hay que activar el módulo CC addresses para que la sección CC Addresses aparezca en cada una de las peticiones (issues). Aparte de ello no tenemos que olvidarnos de definir los permisos correspondientes en los perfiles de usuario que podrán ver, agregar y eliminar las cuentas de correo de la lista, esto se personaliza en Administración -> Perfiles y permisos -> Perfil X.

  6. En las tareas generadas a partir de correos electrónicos, sería interesante agregar automáticamente a la lista de direcciones CC implementadas mediante el plugin redmine_cc_addresses las cuentas de correo del emisor y de los destinatarios con copia (CC), para que los mismos puedan mantenerse informados de los cambios que vayan surgiendo en la tarea.

    Para implementar esta funcionalidad tenemos que volver a modificar el código del archivo mail_handler.rb
    [root@testsrv ~]# vim /opt/redmine/app/models/mail_handler.rb
    
    Luego nos tenemos que posicionar entre los métodos add_attachments y add_accept_attachment? para agregar un nuevo método llamado add_cc_addresses, método que se encargará de registrar los correos del emisor y de los asociados como CC a la lista de direcciones CC de la tarea. El código va resaltado a continuación:
    def add_attachments(obj)
        ...
      end
    
      # Metodo que agrega a la lista de correo CC de la peticion las cuentas del emisor
      # y de los asociados como copia (CC).
      def add_cc_addresses(obj)
        addresses = [email.from, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
        unless addresses.empty?
          addresses.each do |address|
            # Agrega a la tabla cc_addresses los correos.
            addr = CcAddress.create(:mail => address, :issue_id => obj.id)
          end
        end
      end
    
      # Returns false if the +attachment+ of the incoming email should be ignored
      def accept_attachment?(attachment)
        .....
      end
    
    A continuación buscamos el método receive_issue y agregamos el código necesario para que por cada nuevo correo entrante que se procese se ejecute el método add_cc_addresses:
    # Creates a new issue
      def receive_issue
        project = target_project
        # check permission
        unless handler_options[:no_permission_check]
          raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
        end
    
        issue = Issue.new(:author => user, :project => project)
        attributes = issue_attributes_from_keywords(issue)
        if handler_options[:no_permission_check]
          issue.tracker_id = attributes['tracker_id']
          if project
            issue.tracker_id ||= project.trackers.first.try(:id)
          end
        end
        issue.safe_attributes = attributes
        issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
        #issue.subject = cleaned_up_subject
        issue.subject = cleaned_up_subject  + " (#{email.from.to_a.first.to_s.strip.gsub(/@.*$/, '').strip})"
        if issue.subject.blank?
          issue.subject = '(no subject)'
        end
        #issue.description = cleaned_up_text_body
        issue.description = "ENVIADO POR: #{email.from.to_a.first.to_s.strip}\r\n\r\n" + cleaned_up_text_body
        issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?
        issue.is_private = (handler_options[:issue][:is_private] == '1')
    
        # add To and Cc as watchers before saving so the watchers can reply to Redmine
        add_watchers(issue)
        issue.save!
        add_cc_addresses(issue)
        add_attachments(issue)
        logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger
        issue
      end
    
    Y con esto ya se agregan automáticamente por cada correo recibido las cuentas del emisor y CC a la lista de notificación de la petición o tarea de Redmine generada por el script mail_handler.rb.

    OBS: Es importante tener en cuenta que no se van a enviar correos si probamos modificar una tarea con el usuario Admin, a menos que dicho usuario esté registrado como miembro del proyecto. He perdido buen tiempo tratando de realizar pruebas de envío de correos automáticos y el motivo finalmente fue que lo estaba haciendo con el usuario Admin, que puede hacer cualquier modificación en un proyecto sin ser miembro del mismo.


Configuración SCM (Subversion)

Si bien Redmine soporta la integración de varias herramientas SCM como Subversion, CVS, Git, Bazaar, Mercurial y Darcs, en esta sección solo se abarcarán los pasos necesarios para integrar repositorios Subversion a la herramienta.
  1. Lo primero que tenemos que hacer es crear un directorio dentro del directorio home de Redmine para almacenar los proyectos y repositorios de Subversion:
    [root@testsrv ~]# mkdir /opt/redmine/svn
    [root@testsrv ~]# chown -Rf apache:apache /opt/redmine/svn
    [root@testsrv ~]# chmod -Rf 750 /opt/redmine/svn
    
  2. Luego tenemos que instalar en openSUSE los paquetes relacionados a Subversion y otros requisitos más:
    [root@testsrv ~]# yum install subversion curl mod_perl perl-DBI perl-DBD-Pg perl-Digest-SHA mod_dav_svn
    
    También instalamos las gemas activesupport, rails-observers y activeresource en sus respectivas versiones compatibles con la versión Ruby 2.4.6:
    [root@testsrv ~]# gem install activesupport -v 5.2.4.1
    [root@testsrv ~]# gem install rails-observers -v 0.1.5
    [root@testsrv ~]# gem install activeresource -v 5.1.0
    
  3. Verificamos que en el directorio /etc/httpd/conf.modules.d se encuentren activos los módulos dav, perl y subversion para Subversion.
    #[root@testsrv ~]# cat /etc/httpd/conf.modules.d/00-dav.conf
    LoadModule dav_module modules/mod_dav.so
    LoadModule dav_fs_module modules/mod_dav_fs.so
    LoadModule dav_lock_module modules/mod_dav_lock.so
    [root@testsrv ~]# cat /etc/httpd/conf.modules.d/02-perl.conf
    #
    # Mod_perl incorporates a Perl interpreter into the Apache web server,
    # so that the Apache web server can directly execute Perl code.
    # Mod_perl links the Perl runtime library into the Apache web server
    # and provides an object-oriented Perl interface for Apache's C
    # language API.  The end result is a quicker CGI script turnaround
    # process, since no external Perl interpreter has to be started.
    #
    
    LoadModule perl_module modules/mod_perl.so
    [root@testsrv ~]# cat /etc/httpd/conf.modules.d/10-subversion.conf
    LoadModule dav_svn_module     modules/mod_dav_svn.so
    LoadModule authz_svn_module   modules/mod_authz_svn.so
    LoadModule dontdothat_module  modules/mod_dontdothat.so
    #
    
  4. Necesitamos crear un enlace simbólico en el directorio /usr/lib64/perl5/vendor_perl/Apache2 a partir del archivo Redmine.pm que se encuentra ubicado en la ruta /opt/redmine/extra/svn:
    [root@testsrv ~]# ln -s /opt/redmine/extra/svn/Redmine.pm /usr/lib64/perl5/vendor_perl/Apache2/
    
  5. Tenemos que agregar la configuración requerida para Apache, para ello creamos y editamos posteriormente el archivo redmine_svn.conf dentro del directorio /etc/httpd/conf.d.
    [root@testsrv ~]# touch /etc/httpd/conf.d/redmine_svn.conf
    [root@testsrv ~]# vim /etc/httpd/conf.d/redmine_svn.conf
    
    A dicho archivo le agregamos la siguiente configuración:
    PerlLoadModule Apache2::Redmine
    <location /svn>
        DAV svn
        SVNParentPath "/opt/redmine/svn"
    
        PerlAccessHandler Apache::Authn::Redmine::access_handler
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
        AuthType Basic
        AuthName "Redmine Subversion Repository"
        Require valid-user
    
        ## For mysql
        # RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"
        ## For postgresql
        RedmineDSN "DBI:Pg:dbname=redmine;host=localhost"
        RedmineDbUser "redmine"
        RedmineDbPass "redmine"
    
        ## Optional where clause (fulltext search would be slow and
        ## database dependant).
        # RedmineDbWhereClause "and members.role_id IN (1,2)"
        ## Optional credentials cache size
        # RedmineCacheCredsMax 50
    </location>
    
    Finalmente reiniciamos el servicio Apache.
    [root@testsrv ~]# systemctl restart httpd
    
  6. El siguiente paso consiste en dirigirnos a la pestaña Administration -> Configuración –> Repositorios en la herramienta Redmine donde habilitamos la opción WS for repository management (Habilitar SW para la gestión del repositorio), para luego generar la API key que a mi me salió X9YEsWGYUbevDmX4u5ep. Es importante aclarar que la llave API generada anteriormente será utilizada desde la línea de comandos para crear los repositorios Subversion en Redmine.


    En este ventana también se recomienda configurar las siguientes opciones:
    - Desmarcar todos los tipos de servicios SCM a excepción de los que deseamos utilizar.
    - Marcar la opción Habilitar registro de horas.

    Una vez realizado lo anterior tenemos que guardar los cambios.

  7. Para habilitar y crear el repositorio Subversion para un proyecto de Redmine primero debemos seleccionar nuestro proyecto, dirigirnos a la pestaña Módulos en la sección Configuración del proyecto y activar la opción Repositorio. Luego tenemos que pasar a la línea de comandos donde tenemos que ejecutar el siguiente comando para generar y activar la accesibilidad del repositorio en el proyecto deseado:
    [root@testsrv ~]# ruby /opt/redmine/extra/svn/reposman.rb --redmine IP_SERVIDOR/redmine --scm Subversion --svn-dir /opt/redmine/svn --owner apache --url file:///opt/redmine/svn --verbose --key=X9YEsWGYUbevDmX4u5ep
    
    Es en el comando anterior donde utilizamos la llave API generada en el paso anterior. Si al acceder a las pestaña Repositorio del proyecto les llega a salir el siguiente error:
    404
    
    La entrada y/o la revisión no existe en el repositorio.
    
    Pueden probar cambiar el dueño y grupo de usuario a apache apache del archivo environment.rb ubicado en la carpeta config,
    [root@testsrv ~]# chown -Rf apache:apache /opt/redmine/config/environment.rb
    
    reiniciando posteriormente el servicio Apache como se muestra a continuación:
    [root@testsrv ~]# systemctl restart httpd
    
  8. Podemos automatizar la creación de un repositorio subversion cuando al administrador de Redmine registre un nuevo proyecto con el módulo Repositorio activado. Para ello se tiene que editar nuevamente el archivo /etc/cron.d/redmine:
    [root@testsrv ~]# vim /etc/cron.d/redmine
    
    Al final del cual agregamos una nueva tarea programada que se encargue de realizar cada minuto la comprobación correspondiente:
    # Generacion automatica de repositorios subversion.
    * * * * * root ruby /opt/redmine/extra/svn/reposman.rb --redmine IP_SERVIDOR/redmine --scm Subversion --svn-dir /opt/redmine/svn --owner apache --url file:///opt/redmine/svn --verbose --key=X9YEsWGYUbevDmX4u5ep >> /dev/null 2>&1
    
    Además de la tarea anterior, agregamos otra tarea programada más que se encargará de sincronizar cada minuto los comentarios de los commits que estén referenciados a una petición/tarea.
    # Sincronizacion de comentarios de commits asociados a tareas.
    * * * * * root curl "http://IP_SERVIDOR/redmine/sys/fetch_changesets?key=X9YEsWGYUbevDmX4u5ep" > /dev/null 2>&1
    
    Finalmente reiniciamos el servicio cron.
    [root@testsrv ~]# systemctl restart crond
    
  9. Con los pasos anteriores ya podremos utilizar el repositorio, su integración en la herramienta quedaría como sigue:


ACLARACIONES SOBRE EL MÓDULO REPOSITORIO DE REDMINE:

  1. El proyecto tiene que tener activo el módulo Repositorio para que la aplicación reposman.rb pueda crear el repositorio svn físico en el directorio /opt/redmine/svn.

  2. Con la configuración anterior, si el proyecto es público se podrá realizar descargas sin autenticación del repositorio, pero para subir un cambio el usuario deberá estar registrado en el proyecto. Si el proyecto es privado, tanto para hacer el checkout como para subir algún cambio se tendrá que utilizar si o sí un usuario de la herramienta Redmine.

  3. Para que un usuario de Redmine pueda acceder al repositorio éste deberá estar agregado como miembro del proyecto. Para realizar cambios en el repositorio deberá tener el perfil Jefe de proyecto o Desarrollador, porque si tiene asignado el perfil Informador solo podrá descargar el repositorio pero no subir actualizaciones.

  4. Si se ha migrado un repositorio Subversion antiguo a un nuevo repositorio creado en Redmine, los usuarios utilizados para realizar los commits en el viejo repositorio pueden ser referenciados a los usuarios de la herramienta Redmine en la opción Usuarios de la pestaña Configuración --> Repositorio del proyecto en cuestión.


Realización de copias de seguridad

Debido a que la información almacenada en Redmine es de mucho valor, es de importancia incluir en ésta guía un procedimiento para realizar una copia de seguridad completa de la herramienta.
  1. En principio necesitamos definir un directorio en donde ubicar las copias de seguridad realizadas, en mi caso voy a crear una carpeta llamada backups en el directorio raíz.
    [root@testsrv ~]# mkdir /backups
    
  2. Luego pasamos a crear los directorios backups y backups/svndumps dentro de /opt/redmine para almacenar las copias de seguridad en bruto de la base de datos y de los repositorios subversion que tenemos agregados:
    [root@testsrv ~]# mkdir -p /opt/redmine/backups/svndumps
    
  3. A continuación accedemos al directorio /opt/redmine/script y creamos el archivo backup que contendrá el script que realizará la copia de seguridad, además se le asignará los permisos correspondientes:
    [root@testsrv ~]# cd /opt/redmine/script/
    [root@testsrv script]# touch backup
    [root@testsrv script]# chmod 750 backup
    
  4. Luego editamos el archivo backup,
    [root@testsrv script]# vim backup
    
    y le agregamos el siguiente script bash:
    #!/bin/bash
    # Realiza una copia de seguridad completa de la herramienta Redmine.
    DIA=`date +"%Y%m%d"`
    HORA=`date +"%H%M"`
    BACKUP_PATH=/backups
     
    # -- REDMINE
    REDMINE_HOME=/opt/redmine
    REDMINE_DB_TYPE=pg #[pg|mysql]
    REDMINE_DB_NAME=redmine
    REDMINE_DB_USER=redmine
    REDMINE_DB_PASS=redmine
    REDMINE_DB_BACKUP=$REDMINE_HOME/backups/redmine_db.sql
    REDMINE_BACKUP_NAME="redmine_"$DIA"_"$HORA".tar.gz"
    REDMINE_BACKUP_HISTO="histo_redmine_"$DIA"_"$HORA".tar.gz"
    REDMINE_BACKUP_LIVE_TIME=30
    REDMINE_BACKUP_HISTO_LIVE_TIME=365
     
    # -- SVN
    SVN_REPOS_PATH=$REDMINE_HOME/svn
    SVN_BACKUP_PATH=$REDMINE_HOME/backups/svndumps
     
    # -- PATRON LIMPIEZA
    PATRON_BKP_DIARIO=redmine_*.tar.gz
    PATRON_BKP_HISTO=histo_redmine_*.tar.gz
     
    # -- FTP
    FTP_COPIAR="N" #[S|N]
    FTP_SERVER=ip_servidor_backup_ftp
    FTP_USER=usuario_ftp
    FTP_PASS=password_ftp
    FTP_REMOTE_CD=remote_backups
    FTP_LOCAL_CD=$BACKUP_PATH
     
    # Backup de Proyectos SVN
    echo
    echo "-->BACKUP DE REPOSITORIOS SVN"
    echo "===================================================================="
    cd $SVN_REPOS_PATH
    for SVN_REPO_NAME in *
    do
        echo "---------- Iniciando exportacion del repositorio '$SVN_REPO_NAME' ----------"
        /usr/bin/svnadmin dump $SVN_REPOS_PATH/$SVN_REPO_NAME > $SVN_BACKUP_PATH/$SVN_REPO_NAME.dump
        echo "------------- Fin exportacion del repositorio '$SVN_REPO_NAME' -------------"
        echo
    done
     
    # Segun el motor de base de datos especificado se procede a exportar la base de datos de Redmine.
    echo
    echo "-->BACKUP DE LA BASE DE DATOS DE REDMINE"
    echo "===================================================================="
    if [ $REDMINE_DB_TYPE == "mysql" ]; then
        echo "Exportando la base de datos de Redmine a partir de MySQL. Aguarde un momento..."
        mysqldump -v -u $REDMINE_DB_USER -p$REDMINE_DB_PASS --database $REDMINE_DB_NAME > $REDMINE_DB_BACKUP
        echo "Fin del proceso de exportacion."
        echo
    elif [ $REDMINE_DB_TYPE == "pg" ]; then
        echo "Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento..."
        export PGUSER=$REDMINE_DB_USER
        export PGPASSWORD=$REDMINE_DB_PASS
        pg_dump -b -F p --column-inserts $REDMINE_DB_NAME > $REDMINE_DB_BACKUP
        unset PGUSER
        unset PGPASSWORD
        echo "Fin del proceso de exportacion."
    fi
     
    # Se generan los archivos con todas las copias de seguridad para ser enviadas a una unidad de cinta.
    echo
    echo "-->CREANDO FULL BACKUP DE REDMINE"
    echo "===================================================================="
    tar -czf $BACKUP_PATH/$REDMINE_BACKUP_NAME $REDMINE_HOME
     
    # Almacenando una copia de seguridad alternativa si la fecha corresponde a fin de mes.
    TOMORROW=`date --date=tomorrow +%d`
    if [ $TOMORROW -eq "1" ]; then
        echo
        echo "-->CREANDO BACKUP HISTORICO POR SER FIN DE MES"
        echo "===================================================================="
        cp $BACKUP_PATH/$REDMINE_BACKUP_NAME $BACKUP_PATH/$REDMINE_BACKUP_HISTO
    fi
     
    # Para no llenar el disco duro con backups, se eliminan todos los backups diarios pasados la cantidad
    # de dias especificados en la variable REDMINE_BACKUP_LIVE_TIME, lo backups historicos se eliminan luego 
    # de la cantidad de dias expecificados en la variable REDMINE_BACKUP_HISTO_LIVE_TIME.
    echo
    echo "-->LIMPIEZA DE BACKUPS ANTIGUOS"
    echo "===================================================================="
    find $BACKUP_PATH/$PATRON_BKP_DIARIO -mtime +$REDMINE_BACKUP_LIVE_TIME -exec rm {} \;
    find $BACKUP_PATH/$PATRON_BKP_HISTO -mtime +$REDMINE_BACKUP_HISTO_LIVE_TIME -exec rm {} \;
     
    # Se copia el full backup a un servidor de respaldo.
    if [ $FTP_COPIAR == "S" ]; then
        echo
        echo "-->COPIANDO EL FULL BACKUP DE REDMINE A UN SERVIDOR DE RESPALDO"
        echo "===================================================================="
        /usr/bin/ftp -n <<EOD
        open $FTP_SERVER
        quote USER $FTP_USER
        quote PASS $FTP_PASS
        bin
        cd $FTP_REMOTE_CD
        lcd $FTP_LOCAL_CD
        put $REDMINE_BACKUP_NAME
        bye
    EOD
    else
        echo
        echo "-->COPIA FTP INHABILITADA!"
        echo
    fi
    
    Este script se encarga de realizar una copia de seguridad de la base de datos de la herramienta y de los repositorios subversion agregados. Genera copias de seguridad periódicas y mensuales compresas en tar.gz de todo el directorio /opt/redmine, elimina las copias de seguridad muy antiguas y de forma opcional permite transferir la última copia de seguridad a un equipo remoto mediante el protocolo ftp.

    En este punto ya podemos probar la ejecución del script de la siguiente manera
    [root@testsrv ~]# /opt/redmine/script/backup
    
    -->BACKUP DE REPOSITORIOS SVN
    ====================================================================
    ---------- Iniciando exportacion del repositorio 'prueba' ----------
    * Dumped revision 0.
    * Dumped revision 1.
    * Dumped revision 2.
    * Dumped revision 3.
    * Dumped revision 4.
    * Dumped revision 5.
    ------------- Fin exportacion del repositorio 'prueba' -------------
    
    ---------- Iniciando exportacion del repositorio 'test' ----------
    * Dumped revision 0.
    ------------- Fin exportacion del repositorio 'test' -------------
    
    
    -->BACKUP DE LA BASE DE DATOS DE REDMINE
    ====================================================================
    Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento...
    Fin del proceso de exportacion.
    
    -->CREANDO FULL BACKUP DE REDMINE
    ====================================================================
    tar: Removing leading `/' from member names
    
    -->LIMPIEZA DE BACKUPS ANTIGUOS
    ====================================================================
    find: ‘/backups/histo_redmine_*.tar.gz’: No such file or directory
    
    -->COPIA FTP INHABILITADA!
    
    #
    
  5. Para programar la ejecución periódica del script debemos agregar una tarea programada. Para ello editamos nuevamente el archivo /etc/cron.d/redmine:
    [root@testsrv ~]# vim /etc/cron.d/redmine
    
    Para luego agregarle al final del mismo el siguiente contenido:
    # Backup Redmine
    30 22 * * * root /opt/redmine/script/backup > /opt/redmine/log/backup.log 2>&1
    
    Finalmente reiniciamos el servicio cron para que la tarea programada sea funcional.
    [root@testsrv ~]# systemctl restart crond
    


Otras capturas de pantalla



Información técnica

  • CentOS 7 (release 1905)
  • PostgreSQL 9.2.24
  • Apache 2.4.6
  • Ruby 2.4.6
  • Redmine 3.4.13
  • Perl 5.16.3


Fuentes

Comentarios