Instalación de Redmine 3.4 en Linux openSUSE Leap 42.3

La idea de este artículo es documentar todo el proceso de instalación de Redmine 3.4 en openSUSE Leap 42.3, basándome en éste artículo del 2012.

Actualmente llevo usando hace ya varios años en producción la versión 1.3 de Redmine en un openSUSE que sigue batallando, y es hora de poner a punto una nueva versión que se adapte a las necesidades de mi entorno de trabajo. En fin, comenzamos con los pasos sin más rodeos.

Instalación y configuración básica

  1. Para comenzar debemos instalar y configurar de forma básica el motor de base de datos PostgreSQL, que ya ha sido tratado en este blog y que lo pueden encontrar aquí.

  2. Mediante el comando zypper instalamos algunas de las dependencias que necesita la herramienta.
    testsrv:~ # zypper in apache2 apache2-prefork ImageMagick gcc gcc-c++ git ruby ruby2.4 curl apache2-devel ImageMagick-devel ruby-devel ruby2.4-devel postgresql-devel libmysqld-devel libcurl-devel
  3. Ahora toca 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
    testsrv:~ # su postgres -c psql postgres
    postgres=# CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'redmine' NOINHERIT VALID UNTIL 'infinity';
    postgres=# CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
    postgres-# \q

  4. A continuación procedemos a descargar la última versión de la herramienta Redmine, en este ejemplo la 3.4.1, desde su sitio web en el directorio /opt para luego descomprimirla en el mismo directorio:
    testsrv:~ # cd /opt/
    testsrv:/opt # wget http://www.redmine.org/releases/redmine-3.4.2.tar.gz
    testsrv:/opt # tar -xzf redmine-3.4.2.tar.gz
    testsrv:/opt # rm redmine-3.4.2.tar.gz
    testsrv:/opt # mv redmine-3.4.2 redmine
    testsrv:/opt # cd redmine/
    testsrv:/opt/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.
    testsrv:/opt/redmine # cd config/
    testsrv:/opt/redmine/config # cp database.yml.example database.yml
    testsrv:/opt/redmine/config # vi 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, con el gestor de paquetes gem de Ruby 2.4 instalamos el paquete bundler, y ejecutamos en el directorio /opt/redmine/config la directiva que permite resolver las dependencias 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.
    testsrv:/opt/redmine/config # gem.ruby2.4 install bundler rdoc
    testsrv:/opt/redmine/config # bundle.ruby2.4 install --without development test

    El comando bundle se encargará de instalar todas las dependencias requeridas:
    Fetching gem metadata from https://rubygems.org/..........
    Fetching version metadata from https://rubygems.org/..
    Fetching dependency metadata from https://rubygems.org/.
    Resolving dependencies...
    Fetching rake 12.0.0
    Installing rake 12.0.0
    ..
    ..
    OBS: ruby-devel, ImageMagick-devel, postgresql-devel mysql-devel son paquetes del sistema operativo que tienen que estar instalados para que se puedan instalar las gemas Ruby rmagick, pg y mysql2. 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:
    testsrv:/opt/redmine/config # bundle.ruby2.4 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:
    testsrv:/opt/redmine/config # cd ..
    testsrv:/opt/redmine # RAILS_ENV=production bundle.ruby2.4 exec rake db:migrate
    testsrv:/opt/redmine # RAILS_ENV=production bundle.ruby2.4 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:
    testsrv:/opt/redmine # groupadd -r redmine
    testsrv:/opt/redmine # useradd -r -g redmine redmine
    testsrv:/opt/redmine # chown -Rf redmine:redmine /opt/redmine



Configuración de Apache

  1. En cuanto a la configuración de Apache, lo primero que debemos hacer es dirigirnos al directorio /etc/sysconfig y editar el archivo apache2.
    testsrv:~ # vi /etc/sysconfig/apache2
    Una vez en el archivo nos dirigimos a la sección APACHE_MODULES para verificar que el módulo ssl esté debidamente definido (para las conexiones https):
    APACHE_MODULES="actions alias auth_basic authn_file authz_host authz_groupfile authz_default authz_user autoindex cgi dir env expires include log_config mime negotiation setenvif ssl userdir php5 perl"
    También, en el mismo archivo tenemos que asignar a la directiva APACHE_SERVER_FLAGS el valor SSL, quedando como se muestra a continuación:
    APACHE_SERVER_FLAGS="SSL"
  2. El siguiente paso consiste en verificar que Apache esté correctamente configurado para que escuche en los puertos indicados, tanto en el puerto por defecto que es el 80 como así también para las conexiones seguras que normalmente es el 443, para ello nos vamos al directorio /etc/apache2/ y ahí abrimos el archivo llamado listen.conf,
    testsrv:~ # vi /etc/apache2/listen.conf
    debiendo tener la siguiente sección similar a lo que sigue:
    Listen 80

    <IfDefine SSL>
    <IfDefine !NOSSL>
    <IfModule mod_ssl.c>

    Listen 443

    </IfModule>
    </IfDefine>
    </IfDefine>

  3. Generación de certificado no personalizado: Existen varias formas para generar un certificado para las conexiones https, una de ellas y el método más simple es generar un certificado sin información adicional, para ello hay que ejecutar el siguiente comando:
    testsrv:~ # gensslcert
    Este comando sobre-escribirá los siguientes archivos:
    /etc/apache2/ssl.crt/ca.crt
    /etc/apache2/ssl.key/server.key
    /etc/apache2/ssl.crt/server.crt
    /etc/apache2/ssl.csr/server.csr

    También creará un nuevo archivo CA.crt en el directorio /srv/www/htdocs/ para ser descargado por los clientes que se conectan bajo el protocolo https.

    Generación de certificado personalizado: Si queremos generar un certificado con información personalizada de nuestra organización podemos indicarle al comando gensslcert varios argumentos para enriquecer el contenido del certificado como se muestra a continuación:
    testsrv:~ # gensslcert -C "tormentadebits" -N "Este es un Certificado de Ejemplo" -c PY -s It -l HO -o "Gabriel-Corp." -u "Informatica" -n "www.tormentadebits.com" -e "contacto(ARROBA)tormentadebits.com" -y 60
    Al ejecutar el comando se crearán una serie de archivos inicialmente llamados con el nombre tormentadebits- en los siguientes directorios:
    /etc/apache2/ssl.crt/tormentadebits-ca.crt
    /etc/apache2/ssl.crt/tormentadebits-server.crt
    /etc/apache2/ssl.csr/tormentadebits-server.csr
    /etc/apache2/ssl.key/tormentadebits-ca.key
    /etc/apache2/ssl.key/tormentadebits-server.key
    /srv/www/htdocs/TORMENTADEBITS-CA.crt

  4. Luego hay que crear una copiar del archivo /etc/apache2/vhosts.d/vhost-ssl.template y renombrarlo a vhost-ssl.conf.
    testsrv:~ # cd /etc/apache2/vhosts.d
    testsrv:/etc/apache2/vhosts.d # cp vhost-ssl.template vhost-ssl.conf

    Si hemos creado un certificado personalizado y queremos que sea éste el certificado utilizado para la autenticación tendremos que editar el archivo vhost-ssl.conf en el directorio /etc/apache2/vhosts.d/,
    testsrv:~ # vi /etc/apache2/vhosts.d/vhost-ssl.conf
    y modificar las directivas que se citan a continuación con los nombres de los archivos (certificados) generados anteriormente:
    SSLCertificateFile /etc/apache2/ssl.crt/tormentadebits-server.crt
    SSLCertificateKeyFile /etc/apache2/ssl.key/tormentadebits-server.key

    Con esto hemos creado un host virtual exclusivo para las conexiones seguras.

  5. Ahora continuemos con la configuración para Redmine, debemos instalar el módulo passenger para Apache con el gestor de paquetes gem.ruby2.4 de Ruby 2.4, donde luego lo compilamos e instalamos en el sistema operativo siguiendo los pasos que nos indica la ejecución del script passenger-install-apache2-module.ruby2.4:
    testsrv:~ # gem.ruby2.4 install passenger
    testsrv:~ # exec passenger-install-apache2-module.ruby2.4

    This installer will guide you through the entire installation process. It
    shouldn't take more than 3 minutes in total.

    Here's what you can expect from the installation process:

    1. The Apache 2 module will be installed for you.
    2. You'll learn how to configure Apache.
    3. You'll learn how to deploy a Ruby on Rails application.

    Don't worry if anything goes wrong. This installer will advise you on how to
    solve any problems.

    Press Enter to continue, or Ctrl-C to abort.


    --------------------------------------------

    Which languages are you interested in?

    Use <space> to select.
    If the menu doesn't display correctly, press '!'

    >⬢ Ruby
    ⬡ Python
    ⬡ Node.js
    ⬡ Meteor
    ...
    ...
    cd 'buildout/ruby/ruby-2.4.1-x86_64-linux/' && make
    compiling /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8/src/ruby_native_extension/passenger_native_support.c
    linking shared-object passenger_native_support.so

    --------------------------------------------
    Almost there!

    Please edit your Apache configuration file, and add these lines:

    LoadModule passenger_module /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8/buildout/apache2/mod_passenger.so

    PassengerRoot /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8
    PassengerDefaultRuby /usr/bin/ruby.ruby2.4


    After you restart Apache, you are ready to deploy any number of web
    applications on Apache, with a minimum amount of configuration!

    Press ENTER when you are done editing.

    --------------------------------------------

    Validating installation...
    ...
    ...
    Detected 0 error(s), 2 warning(s).
    Press ENTER to continue.
  6. Ahora debemos dirigirnos al directorio /etc/apache2/conf.d,
    testsrv:~ # cd /etc/apache2/conf.d
    Agregar y editar un nuevo archivo llamado passenger.conf:
    testsrv:/etc/apache2/conf.d # touch passenger.conf
    testsrv:/etc/apache2/conf.d # vi passenger.conf

    Y agregarle un contenido similar a lo que sigue para que Apache levante el módulo correspondiente:
    # Carga del modulo passenger en Apache.
    LoadModule passenger_module /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8/buildout/apache2/mod_passenger.so
    PassengerRoot /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8
    PassengerDefaultRuby /usr/bin/ruby.ruby2.4

  7. (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/apache2/vhosts.d y creamos un nuevo archivo llamado vhost.conf:
    testsrv:~ # cd /etc/apache2/vhosts.d
    testsrv:/etc/apache2/vhosts.d # touch vhost.conf
    Editamos el archivo con nuestro editor de texto preferido..
    testsrv:/etc/apache2/vhosts.d # vi vhost.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 wwwrun
    PassengerGroup www

    <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.

  8. (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/apache2/conf.d, para luego crear y editar un nuevo archivo llamado redmine.conf:
    testsrv:~ # cd /etc/apache2/conf.d
    testsrv:/etc/apache2/conf.d # touch redmine.conf
    testsrv:/etc/apache2/conf.d # vi 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 wwwrun
    PassengerGroup www


    # -- 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>
    OBS: Una vez afuera del archivo anterior creamos un enlace simbólico del directorio /opt/redmine/public al directorio /srv/www/htdocs:
    testsrv:/etc/apache2/conf.d # ln -s /opt/redmine/public/ /srv/www/htdocs/redmine
  9. Asignamos el usuario wwwrun y al grupo www como dueños de ciertos directorios, y aplicamos algunos permisos de escritura y lectura:
    testsrv:/opt/redmine # chown -Rf wwwrun:www /opt/redmine/files /opt/redmine/log /opt/redmine/tmp /opt/redmine/public/plugin_assets
    testsrv:/opt/redmine # chmod -Rf 755 /opt/redmine/files /opt/redmine/log /opt/redmine/tmp /opt/redmine/public/plugin_assets

  10. Finalmente activamos los niveles de ejecución y luego iniciamos (o reiniciamos si ya se estaba ejecutando) el servicio apache2:
    testsrv:~ # systemctl enable apache2.service
    testsrv:~ #
    systemctl restart apache2.service


Configuración del cortafuegos

  1. Para que podamos acceder a la herramienta desde otro equipo remoto necesitamos abrir los puertos HTTP (80) y HTTPS (443) en el firewall del servidor, para ello editamos el archivo SuSEfirewall2 del directorio /etc/sysconfig:
    testsrv:~ # vi /etc/sysconfig/SuSEfirewall2
    y le asignamos los servicios apache2 y apache2-ssl a la directiva FW_CONFIGURATIONS_EXT como se muestra a continuación:
    FW_CONFIGURATIONS_EXT="sshd apache2 apache2-ssl"
  2. Luego reiniciamos el cortafuegos para que la nueva configuración tome efecto, lo realizamos con el siguiente comando:
    testsrv:~ # rcSuSEfirewall2 restart


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:

    - Local Avatars
    - Theme Changer
    - Attach image from clipboard
    - 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:
    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:
    testsrv:/opt/redmine/plugins # wget https://github.com/haru/redmine_theme_changer/releases/download/0.3.0/redmine_theme_changer-0.3.0.zip
    testsrv:/opt/redmine/plugins # unzip redmine_theme_changer-0.3.0.zip
    testsrv:/opt/redmine/plugins # rm redmine_theme_changer-0.3.0.zip
    testsrv:/opt/redmine/plugins # chown -Rf redmine:redmine redmine_theme_changer/

    Si el proyecto se encuentra disponible en algún repositorio Git en la web podemos descargar el complemento clonando en repositorio remoto de la siguiente manera:
    testsrv:/opt/redmine/plugins # git clone https://github.com/peclik/clipboard_image_paste.git
    testsrv:/opt/redmine/plugins # chown -Rf redmine:redmine clipboard_image_paste/

  3. Una vez descargado el plugin debemos volver al directorio raíz de Redmine y ejecutar un comando que implementa las modificaciones requeridas por el plugin en la base de datos y en la aplicación.
    testsrv:/opt/redmine/plugins # cd /opt/redmine
    testsrv:/opt/redmine # bundle.ruby2.4 exec rake redmine:plugins:migrate RAILS_ENV=production

  4. Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:
    testsrv:~ # systemctl restart apache2


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:
    testsrv:~ # cd /opt/redmine/public/themes
    testsrv:/opt/redmine/public/themes # unzip a1_theme-2_0_0.zip
    testsrv:/opt/redmine/public/themes # rm a1_theme-2_0_0.zip
    testsrv:/opt/redmine/public/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 subcarpeta a /opt/redmine/public/themes, en los demás themes esto no suele ser necesario):
    testsrv:~ # cd /opt/redmine/public/themes
    testsrv:/opt/redmine/public/themes # git clone https://github.com/themondays/Dwarf.git
    testsrv:/opt/redmine/public/themes # cd Dwarf/production/
    testsrv:/opt/redmine/public/themes/Dwarf/production # mv dwarf/ ../../
    testsrv:/opt/redmine/public/themes/Dwarf/production # cd ../../
    testsrv:/opt/redmine/public/themes # chown -Rf redmine:redmine dwarf
    testsrv:/opt/redmine/public/themes # rm -Rf Dwarf

  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.
    testsrv:~ # cd /opt/redmine/config/
    testsrv:/opt/redmine/config # cp configuration.yml.example configuration.yml

  2. Luego editamos el archivo configuration.yml,
    testsrv:/opt/redmine/config # vi 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

    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:
    testsrv:/opt/redmine/config # systemctl restart apache2.service
  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,
    testsrv:~ # cd /opt/redmine
    y ejecutando el siguiente comando que lo tenemos que adecuar a nuestras necesidades:
    testsrv:/opt/redmine # bundle.ruby2.4 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=SSL 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
    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=SSL: 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.
    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 creamos un archivo llamado redmine dentro del directorio /etc/cron.d y luego lo editamos:
    testsrv:~ # touch /etc/cron.d/redmine
    testsrv:~ # vi /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=SSL 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
    Finalmente reiniciamos el servicio cron para activar la tarea.
    testsrv:~ # systemctl restart cron.service
  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:
    testsrv:~ # vi /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 pluggin 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 y le asignamos los permisos correspondientes de la siguiente manera:
    testsrv:~ # cd /opt/redmine/plugins/
    testsrv:/opt/redmine/plugins # git clone https://github.com/ageis/redmine_cc_addresses.git
    testsrv:/opt/redmine/plugins # chown -Rf redmine:redmine redmine_cc_addresses/

    Una vez descargado el plugin debemos volver al directorio raíz de Redmine y ejecutar un comando que implementa las modificaciones requeridas por el plugin en la base de datos y en la aplicación.
    testsrv:/opt/redmine/plugins # cd /opt/redmine
    testsrv:/opt/redmine # bundle.ruby2.4 exec rake redmine:plugins:migrate RAILS_ENV=production

    Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:
    testsrv:~ # systemctl restart apache2.service
    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
    testsrv:~ # vi /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:
    testsrv:~ # mkdir /opt/redmine/svn
    testsrv:~ # chown -Rf wwwrun:www /opt/redmine/svn
    testsrv:~ # chmod -Rf 750 /opt/redmine/svn

  2. Luego tenemos que instalar en openSUSE los paquetes relacionados a Subversion y otros requisitos más:
    testsrv:~ # zypper in subversion-server curl apache2-mod_perl perl-Apache-DBI perl-DBD-Pg
    También instalamos las gemas activesupport y activeresource:
    testsrv:~ # gem.ruby2.4 install activesupport activeresource
  3. Verificamos que en el archivo /etc/sysconfig/apache2 se encuentren activos los módulos perl, dav y dav_svn para Subversion.
    testsrv:~ # vi /etc/sysconfig/apache2
    APACHE_MODULES="actions alias ... passenger perl dav dav_svn"
  4. Necesitamos crear un enlace simbólico en el directorio /usr/lib/perl5/vendor_perl/5.18.2/Apache a partir del archivo Redmine.pm que se encuentra ubicado en la ruta /opt/redmine/extra/svn:
    testsrv:~ # ln -s /opt/redmine/extra/svn/Redmine.pm /usr/lib/perl5/vendor_perl/5.18.2/Apache/
  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/apache2/conf.d.
    testsrv:~ # touch /etc/apache2/conf.d/redmine_svn.conf
    testsrv:~ # vi /etc/apache2/conf.d/redmine_svn.conf

    A dicho archivo le agregamos la siguiente configuración:
    PerlLoadModule Apache::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.
    testsrv:~ # systemctl restart apache2.service
  6. El siguiente paso consiste en dirigirnos a la pestaña Administration – Settings – Repositories 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:
    testsrv:~ # ruby.ruby2.4 /opt/redmine/extra/svn/reposman.rb --redmine IP_SERVIDOR/redmine --scm Subversion --svn-dir /opt/redmine/svn --owner wwwrun --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 wwwrun www del archivo environment.rb ubicado en la carpeta config,
    testsrv:~ # chown -Rf wwwrun:www /opt/redmine/config/environment.rb
    reiniciando posteriormente el servicio Apache como se muestra a continuación:
    testsrv:~ # systemctl restart apache2.service
  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:
    testsrv:~ # vi /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.ruby2.4 /opt/redmine/extra/svn/reposman.rb --redmine IP_SERVIDOR/redmine --scm Subversion --svn-dir /opt/redmine/svn --owner wwwrun --url file:///opt/redmine/svn --verbose --key=X9YEsWGYUbevDmX4u5ep >> /dev/null
    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.
    # Sincronización 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.
    testsrv:~ # systemctl restart cron
  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.
    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:
    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:
    testsrv:~ # cd /opt/redmine/script/
    testsrv:/opt/redmine/script # touch backup
    testsrv:/opt/redmine/script # chmod 750 backup

  4. Luego editamos el archivo backup,
    testsrv:/opt/redmine/script # vi 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
    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!

    testsrv:~ #
  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:
    testsrv:~ # vi /etc/cron.d/redmine
    Para luego agregarle al final del mismo el siguiente contenido:
    # Backup Redmine
    30 22 * * * root /opt/redmine/script/backup >> /dev/null
    Finalmente reiniciamos el servicio cron para que la tarea programada sea funcional.
    testsrv:~ # systemctl restart cron


Otras capturas de pantalla









Información técnica

  • openSUSE Leap 42.3 x64
  • Apache 2.4
  • Ruby 2.4.1
  • Redmine 3.4.2
  • Perl 5.18.2


Fuentes

Comentarios