tag:blogger.com,1999:blog-10359032162495925642024-03-12T19:30:54.922-03:00Tormenta de BitsNueva era que a nadie le importa..GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.comBlogger84125tag:blogger.com,1999:blog-1035903216249592564.post-59284344597324000722022-10-20T00:54:00.000-03:002022-10-20T00:54:04.857-03:00Blog migrado<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00062.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="390" data-original-width="800" height="312" src="http://files.tormentadebits.com/covers/portada-00062.png" width="640" /></a></div>Luego de mucho trabajo, y muchas pausas entre medio, finalmente pude concluir con la migración de la información del Blog <b>Tormenta de Bits</b> a esta nueva cuenta. <div><br /></div><div>En un principio pensaba que el proceso sería mucho más fácil, ya que se trataba de migrar datos de una cuenta Blogger a otra cuenta Blogger, sin embargo Google no lo puso fácil, es más, en cierto modo lo hizo mucho más difícil de lo que debería ser, como lo veremos a continuación.</div><span><a name='more'></a></span><h2 style="text-align: left;">Migración de artículos con URL's personalizadas</h2><div>El principal problema que tuve fue con las URL personalizadas que tenía configuradas para casi cada uno de los artículos del blog, ya que en su momento pensé que tener URL's cortas con palabras puntuales ayudarían en las búsquedas. </div><div><br /></div><div>Todo muy bien, el problema fue que al importar los artículos del blog en la nueva cuenta Blogger pasó totalmente por alto las URL's personalizadas y asignó URL's automáticas a su antojo. Para corregir este desastre tuve que acceder a cada artículo, pasarlo a borrador, tocar la fecha (para que Blogger se diera cuenta que tenía que asignar el año y el mes correctos en el que se había publicado el artículo en su momento y no poner la fecha del día en que se hacía el cambio), y luego volver a transcribir la URL del antiguo blog al nuevo.</div><div><br /></div><div>Este problema generó un gran inconveniente al blog, ya que afectó totalmente la indexación de los artículos en los buscadores, que seguían teniendo registrados las URL viejas y que al acceder al link mostraba el error 404.</div><div><br /></div><div>La corrección llevó demasiado tiempo, y eso que el blog tenía apenas un poco más de artículos publicados.</div><h2 style="text-align: left;">Cambios de URL's de las imágenes del Blog</h2><div>Otro cambio que llevó su tiempo fue cambiar la forma en que se alojaban y se accedían a las imágenes del blog. En el blog anterior las imágenes estaban alojadas en Blogger, lo que facilitaba mucho su gestión y evitaba costos extras de almacenamiento, sin embargo, lo malo es que las mismas dependían directamente de la cuenta de Google en donde fue creado el blog, no se podían migrar a otra cuenta de Google y tenían unas URL's que no llevaban relación con el dominio del blog, solo servían para esa cuenta.</div><div><br /></div><div>Blogger (o sea, Google) no ofrece ninguna opción o herramienta para migrar esas imágenes a otra cuenta de Blogger (Google), y como los enlaces a las URL's de las imágenes en los artículos se iban a romper de todas formas al importar el blog en otra cuenta de Google, decidí que iba a ser una buena oportunidad (no había otra salida) para alojar las imágenes en un portal que me permita acceder a ellas a través de una URL personalizada http://files.tormentadebits.com.</div><div><br /></div><div>La opción elegida fue crear un Bucket público en Amazon AWS S3 que coincida con la URL files.tormentadadebits.com para acceder al mismo con la URL de mi dominio y alojar en él todos los archivos (principalmente las imágenes). Si hay otra opción mejor no lo sé, no tenía tiempo para seguir investigando más.</div><div><br /></div><div>Lo siguiente fue modificar cada uno de los artículos para reemplazar las URL's odiosas de Blogger por las URL's de las imágenes alojadas en AWS. Como los nombres de las imágenes se mantuvieron iguales en AWS, lo que se tenía que cambiar era todo el resto de la URL, o lo que es lo mismo, las partes resaltadas en rojo de los siguientes ejemplos:</div><div><br /></div><div><pre class="a-b-r-La" style="background-color: white; font-family: "Courier New", Courier, monospace, arial, sans-serif; font-size: 14px; margin-bottom: 0px; margin-top: 0px; overflow-wrap: break-word; user-select: text; white-space: pre-wrap;"><span style="color: red;">https://4.bp.blogspot.com/-F_IkIR13Q-E/Wbs4ge7QcVI/AAAAAAAAByM/NOYI8psZfwMgf7_x3Kw4AZFWRUedseLowCKgBGAs/s320/</span><b>portada-00057.png</b></pre><pre class="a-b-r-La" style="background-color: white; font-family: "Courier New", Courier, monospace, arial, sans-serif; font-size: 14px; margin-bottom: 0px; margin-top: 0px; overflow-wrap: break-word; user-select: text; white-space: pre-wrap;"><span style="color: red;">https://4.bp.blogspot.com/-F_IkIR13Q-E/Wbs4ge7QcVI/AAAAAAAAByM/NOYI8psZfwMgf7_x3Kw4AZFWRUedseLowCKgBGAs/s1600/</span><b>portada-00057.png</b></pre><pre class="a-b-r-La" style="background-color: white; font-family: "Courier New", Courier, monospace, arial, sans-serif; font-size: 14px; margin-bottom: 0px; margin-top: 0px; overflow-wrap: break-word; user-select: text; white-space: pre-wrap;"><span style="color: red;">https://3.bp.blogspot.com/-MxzdE8C9ijM/Wbstwbmdt4I/AAAAAAAABwM/ZfTqH3Q_9SYvokkxYXBM-_hJk6DATroYQCLcBGAs/s1600/</span><b>00025-redmine-06.png</b></pre><pre class="a-b-r-La" style="background-color: white; font-family: "Courier New", Courier, monospace, arial, sans-serif; font-size: 14px; margin-bottom: 0px; margin-top: 0px; overflow-wrap: break-word; user-select: text; white-space: pre-wrap;"><span style="color: red;">http://1.bp.blogspot.com/-88io9hE_rkU/UNcGB3MA1RI/AAAAAAAAAmc/TWZRfViAx7k/s1600/</span><b>00014-phpPgAdmin-01.png</b></pre></div><div><br /></div><div>Como se puede observar más arriba, las URL's de las imágenes alojadas en Blogger tienen muchas variaciones, como por ejemplo el uso de diferentes protocolos (http o https), diferentes sub dominios (3.bp.blogspot.com, 4.bp.blogspot.com), con hash's que vaya uno a saber con qué criterio fueron generados (Wbs4ge7QcVI, AAAAAAAAByM, NOYI8psZfwMgf7_x3Kw...), con rutas por el tamaño que indican el tamaño del thumbnail o de la imagen (s1600, s320). Para reemplazarlas me tuve que poner bastante creativo para que el procedimiento fuese práctico y más o menos rápido (o bien absurdo).</div><div><br /></div><div>El procedimiento de cambio de las URL's elegido fue modificar cada artículo, copiar la redacción en su formato HTML al Notepad++ y utilizar la herramienta de búsqueda y reemplazo para reemplazar las URLs del texto por las nuevas corregidas, por último el texto corregido se volvía a copiar al editor de Blogger y se publican los cambios realizados</div><div><br /></div><div>Para agilizar la búsqueda y el reemplazo tuve que experimentar con varias expresiones regulares, la versión más avanzada que permitía encontrar casi todas las cadenas de texto de las URL's arriba mencionadas fue la siguiente:</div><div><pre class="a-b-r-La" style="background-color: white; font-family: "Courier New", Courier, monospace, arial, sans-serif; font-size: 14px; margin-bottom: 0px; margin-top: 0px; overflow-wrap: break-word; user-select: text; white-space: pre-wrap;"><b>(http)(s)?(://)([0-9])(.bp.blogspot.com).+?(/).+?(/).+?(/).+?(/).+?(/)</b></pre></div><div><br /></div><div>Las URL's encontradas eran luego reemplazadas con URL personalizadas similares a las que siguen:</div><div><pre class="a-b-r-La" style="background-color: white; font-family: "Courier New", Courier, monospace, arial, sans-serif; font-size: 14px; margin-bottom: 0px; margin-top: 0px; overflow-wrap: break-word; user-select: text; white-space: pre-wrap;"><b>http://files.tormentadebits.com/covers/
http://files.tormentadebits.com/images/</b></pre></div><div><br /></div><div>Quizás el cambio se podría haber realizado de otra forma, quizás reemplazando las URL's en el archivo de exportación de Blogger antes de importar el contenido de los artículos a la nueva cuenta de Blogger, pero bueno, se hizo lo que pasó por la mente en ese momento.</div><h2 style="text-align: left;">¿Otros problemas?</h2><div>No entiendo como configurar el blog para que en portada me muestren más artículos, solo me trae los más recientes, tampoco me interesa invertir tiempo en ello, no aporta nada.</div><h2 style="text-align: left;">¿Futuro del blog?</h2><div>Mantener los artículos existentes hasta que Google decida dar de baja el servicio de Blogger, que viendo cómo opera Google puede ser en cualquier momento, luego de eso, si todavía esté con ganas quizás lo migraré a Wordpress.com, o tal vez lo dejaré desvanecer en el olvido como fue el destino de tantos otros, solo el futuro lo dirá, será hasta entonces.</div><div><br /></div><div><br /></div>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-92075240832328526232022-07-20T23:41:00.005-04:002022-08-08T23:05:52.172-04:00Migración del blog de Blogger a Blogger<div class="separator" style="clear: both;"><a href="http://files.tormentadebits.com/covers/portada-00001.png" style="clear: left; display: block; float: left; padding: 1em 0px; text-align: center;"><img border="0" data-original-height="300" data-original-width="615" height="157" src="http://files.tormentadebits.com/covers/portada-00001.png" width="320" /></a></div>Luego de tanto tiempo vuelvo a escribir una nueva entrada en este fatídico blog, para comentar que tuve que cambiar el contenido del blog de mi cuenta gratuita que tenía en <b>GSuite</b> a una cuenta personal nueva de Google.<div><br /></div><div>Todo ello debido a que Google me recomendó obligadamente a cambiar mi cuenta gratuita y desoportada de "<b>GSuite</b>" a la solución renovada de <b>Google Workspace</b>. Eso si, por un precio de unos cuantos dólares, que quizás para algunos no sea gran cosa, pero viendo las "visitas" y las "ganacias" que me deja el blog, que son nulas obviamente, no tenía el menor interés de pagar ni siquiera la tarifa más básica de Google Workspace.
</div><span><a name='more'></a></span><h2 style="text-align: left;">Problemas, no podía ser de otra manera</h2><div>Luego de reimportar los artículos del blog en el Blogger de mi nueva cuenta de Google, me di cuenta que las URL's personalizadas que utilizaba en los artículos habían cambiado a URL's generadas de forma automática, y que si las intentaba corregir también se modificaba la fecha histórica que forma parte de la url, rompiendo todo lo poco que estaba indexado en Google y algún otro buscador. Al final me dio igual y las dejé así como están, si se rompió algo indexado que algún robot de Google lo vuelva a reparar, total pocas visitas había.</div><div><br /></div><div>Ahora bien, lo anterior es pasable, pero el problema más grande está con las imágenes enlazadas en los artículos. Todas las imágenes de los artículos fueron alojadas dentro de la plataforma de Blogger de mi cuenta de Google GSuite, y si elimino esa cuenta las URL a dichas imágenes quedarán rotas, y como no hay forma de migrar las imágenes de una cuenta Blogger a otra cuenta Blogger, me di cuenta de la necesidad de tener un repositorio propio y personalizado para alojar los assets de cualquier sitio y poder acceder a ellos mediante una URL personalizada que pueda controlar (ya se que es lo obvio, les recuerdo no soy programador web, solo quise ser un simple bloggero).</div><div><br /></div><div>Podría volver a subir las imágenes a Blogger y corregir manualmente los enlaces a las imágenes en los pocos artículos que tengo, pero no sería una solución muy adecuada, teniendo en cuenta que Google podría cerrar Blogger en cualquier momento, y no quisiera volver a repetir el mismo trabajo en la próxima migración de plataforma que tengo que hacer.</div><div><br /></div><div>Pero bueno, hay que verle el lado bueno a todo, estaré probando el servicio de <b>Amazon S3</b> para alojar las imágenes, configurar el acceso a las mismas mediante un dominio personalizado y veré que tal funciona en el blog.. y el costo mensual que posteriormente me generará eso..</div><div><br /></div><div>Pues será hasta entonces, creo..</div>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-87977537348804993212020-08-30T22:28:00.003-04:002022-10-04T23:06:10.453-03:00Crear nuestra propia distribución Linux openSUSE con KIWI NG<p style="background-color: white; border: 0px; font-family: "open sans", "dejavu sans", verdana, sans-serif; font-size: 16px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 10px 0px 0px; padding: 0px; position: relative; vertical-align: baseline; z-index: 2;"></p><div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/covers/portada-00061.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1230" src="http://files.tormentadebits.com/covers/portada-00061.png" width="320" /></a></div>Como bien lo dice su wiki, <a href="https://osinside.github.io/kiwi/" target="_blank"><b>KIWI</b></a> es una herramienta de línea de comandos que permite construir imágenes de sistemas operativos Linux aplicados para hardware físico, como así también para entornos virtuales.<div><br /></div><div>Permite crear una distribución Linux con el mínimo sistema operativo y software necesario para tareas específicas (<span face="" style="color: #222222;">JeOS, J</span><span face="" style="color: #222222;">ust enough </span><b style="color: #222222; font-family: arial, sans-serif;">Operating System</b>), o bien crear y personalizar una distribución Linux a nuestro propio antojo. <p></p><p style="background-color: white; border: 0px; font-family: "open sans", "dejavu sans", verdana, sans-serif; font-size: 16px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 10px 0px 0px; padding: 0px; position: relative; vertical-align: baseline; z-index: 2;"> <span></span></p><a name='more'></a>Este artículo estará basado en la versión <b>KIWI NG 9</b>, y buscará documentar todos los conocimientos adquiridos durante el difícil proceso de aprendizaje por el cual tuve que pasar para aprender a utilizar esta herramienta a fin de continuar creando y actualizando mis propias distribuciones <b>openSUSE Linux</b> corporativas. <p></p><p style="background-color: white; border: 0px; font-family: "open sans", "dejavu sans", verdana, sans-serif; font-size: 16px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 10px 0px 0px; padding: 0px; position: relative; vertical-align: baseline; z-index: 2;"> Y digo para continuar creando y actualizando mis propias distribuciones porque previamente utilizaba la herramienta web <a href="https://en.wikipedia.org/wiki/SUSE_Studio" target="_blank"><b>SUSE Studio</b></a> para dicho fin, que básicamente era un frontend web que abstraía muchos de los pasos necesarios para crear y empaquetar una distribución Linux con todo el software requerido. Cuando <b>SUSE Studio</b> se descontinuó y finalmente su portal web dejó de funcionar el 15 de febrero del 2018, estaba en una posición en la que ya no podía seguir actualizando mis versiones Linux personalizadas con versiones de software y kernel más recientes, motivo por el cual comencé a investigar sobre la herramienta <b>KIWI</b> que sabía era la herramienta que <b>SUSE Studio</b> utilizaba en el backend para construir las imágenes del sistema operativo. </p><p style="background-color: white; border: 0px; font-family: "open sans", "dejavu sans", verdana, sans-serif; font-size: 16px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 10px 0px 0px; padding: 0px; position: relative; vertical-align: baseline; z-index: 2;"> Por último quisiera aclarar que conozco <a href="https://studioexpress.opensuse.org/" target="_blank">SUSE Studio Express</a>, publicitada en principio como la alternativa a <b>SUSE Studio</b>, pero que hasta el momento no es más que una landing page con enlaces al sitio de <a href="http://openbuildservice.org" target="_blank">Open Build Service</a>, sitio web que por cierto tengo que reconocer que me ha espantado de lo complejo y difícil de usar que era para el propósito que yo estaba necesitando. </p><p style="background-color: white; border: 0px; font-family: "open sans", "dejavu sans", verdana, sans-serif; font-size: 16px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin: 10px 0px 0px; padding: 0px; position: relative; vertical-align: baseline; z-index: 2;"> <br /></p><br /><h3>Instalación de Kiwi:</h3><ol style="text-align: left;"> <li>Como el objetivo de esta guía es personalizar una distribución basada en <b>SUSE Leap 15.2</b>, lo primero que tenemos que hacer es obtener e instalar el sistema operativo <b>openSUSE Leap 15.2 x86_64</b>, ya que de esta forma podremos utilizar sus archivos de configuración originales como ejemplos o modelos de configuración para la construcción de la imagen personalizada.<br /><br /></li><li>Luego procedemos a instalar los paquetes <b>KIWI NG,</b> <b>Git y YaST2 Firstboot</b>:<br /> <pre><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span> zypper in python3-kiwi git yast2-firstboot</pre> </li> <li> Podemos ver la versión instalada de la herramienta ejecutando el siguiente comando:<br /> <pre><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span> kiwi -v<br />KIWI (next generation) version 9.18.16<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span></pre> </li> <li> Para facilitar la creación de nuestro primer proyecto <b>Kiwi</b> procedemos a clonar un repositorio <b>Git</b> que ya tiene proyectos pre-configurados a partir de los cuales podremos iniciar nuestro proyecto:<br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> git clone https://github.com/OSInside/kiwi-descriptions</span><br />Clonando en 'kiwi-descriptions'...<br />remote: Enumerating objects: 2028, done.<br />remote: Total 2028 (delta 0), reused 0 (delta 0), pack-reused 2028<br />Recibiendo objetos: 100% (2028/2028), 457.11 KiB | 354.00 KiB/s, listo.<br />Resolviendo deltas: 100% (978/978), listo.<br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span></pre> </li> <li> Si verificamos el directorio <b>kiwi-descriptions</b> podremos observar varios proyectos pre-configurados:<br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> ls -l kiwi-descriptions/</span><br />total 80<br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">archlinux</span><br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">centos</span><br />drwxr-xr-x 6 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">custom_boot</span><br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">debian</span><br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">fedora</span><br />drwxr-xr-x 8 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">.git</span><br />-rw-r--r-- 1 root root 15 jul 14 00:45 .gitignore<br />-rw-r--r-- 1 root root 35141 jul 14 00:45 LICENSE<br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">mageia</span><br />-rw-r--r-- 1 root root 173 jul 14 00:45 README.md<br />drwxr-xr-x 4 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse</span><br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">ubuntu</span><br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span></pre></li> <li>A partir de esos proyectos pre-configurados veremos como construir nuestro proyecto inicial en la siguiente sección.</li></ol> <br /><h3>Configuración y construcción de un proyecto básico:</h3><ol style="text-align: left;"> <li> Si nos ponemos a mirar dentro de cada sub directorio de la carpeta <b>kiwi-descriptions</b>, como por ejemplo <b>suse/x86_64</b>, podremos observar varias versiones de <b>SUSE Leap</b> y <b>Tumbleweed</b> pre-configuradas como JeOS y para Docker:<br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> ls -l kiwi-descriptions/suse/x86_64/<br /></span>total 32<br />drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-leap-15.0-JeOS</span><span style="background-color: white;"><br /></span>drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-leap-15.1-JeOS</span><span style="background-color: white;"><br /></span>drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-leap-15.1-JeOS-vagrant</span><span style="background-color: white;"><br /></span>drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-leap-15.2-JeOS</span><span style="background-color: white;"><br /></span>drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-leap-42.2-JeOS</span><span style="background-color: white;"><br /></span>drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-leap-42.3-JeOS</span><span style="background-color: white;"><br /></span>drwxr-xr-x 2 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-tumbleweed-docker</span><span style="background-color: white;"><br /></span>drwxr-xr-x 3 root root 4096 jul 14 00:45 <span style="background-color: white; color: #5454ff; font-weight: bold;">suse-tumbleweed-JeOS</span><span style="background-color: white;"><br /></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span></pre> </li> <li>Creamos una copia del directorio <b>suse-leap-15.2-JeOS</b> en el home del usuario root renombrada como <b>mysuseleap-15.2</b> y finalmente accedemos a la misma:<br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> cp -R ~/kiwi-descriptions/suse/x86_64/suse-leap-15.2-JeOS ~/mysuseleap-15.2</span><br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> cd mysuseleap-15.2</span></pre> </li> <li> Una vez dentro del directorio <b>mysuseleap-15.2</b> ejecutamos el comando <b>ls -l</b>, donde deberíamos ver lo siguiente:<br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span><span style="background-color: white;"> ls -l</span><br />total 12<br />-rwxr-xr-x 1 root root 1182 jul 14 21:25 <span style="background-color: white; color: #18b218;">config.sh</span><span style="background-color: white;"><br /></span>-rw-r--r-- 1 root root 3836 jul 14 21:25 config.xml<br />lrwxrwxrwx 1 root root 10 jul 14 21:25 <span style="background-color: white; color: #18b2b2;">leap-15.2-JeOS.kiwi</span><span style="background-color: white;"> -> config.xml</span><br />drwxr-xr-x 3 root root 4096 jul 14 21:25 <span style="background-color: white; color: #5454ff; font-weight: bold;">root</span><span style="background-color: white;"></span><br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span></pre> A continuación me gustaría explicar el propósito de cada uno de los archivos y del directorio <b>root</b> que se pueden observar mas arriba.<br /><br />El archivo <b>config.xml</b> permite definir <i><b>la configuración de la imagen Linux</b></i> que deseamos construir (nombre del sistema operativo, versión, repositorios, paquetes que se deben instalar, etc.), por su parte, el archivo <b>config.sh</b> es un script bash opcional cuyas directivas se ejecutan justo luego de que el proceso de construcción de la imagen haya terminado de empaquetar nuestra distro Linux, como veremos más adelante, yo haré bastante uso de ese archivo. En cuanto al archivo <b>leap-15.2-JeOS.kiwi</b>, pueden observar que es solo un enlace simbólico al archivo config.xml que en realidad no es en absoluto necesario, pero como no molesta lo dejamos ahí.<br /><br />En cuanto a la carpeta <b>root</b>, todo lo que pongamos ahí adentro será lo que <b>conformará la estructura de directorio dentro de la raíz / de nuestra distribución Linux</b> una vez que haya sido construida. De hecho, si verificamos su contenido veremos que ya existe la carpeta "<b>etc</b>", que luego de construir la imagen e instalar nuestro Linux personalizado pasará a ser su directorio <b>/etc</b>: <br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span><span style="background-color: white;"> ls -l root</span><br />total 4<br />drwxr-xr-x 4 root root 4096 jul 14 21:25 <span style="background-color: white; color: #5454ff; font-weight: bold;">etc</span><br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span></pre>Pero no nos preocupemos tanto por eso ahora y avancemos al siguiente paso.<br /><br /> </li> <li>Vamos a comenzar por editar el archivo <b>config.xml</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span><span style="background-color: white;"> vim </span>config.xml</pre>Y dejar el contenido del mismo similar a lo que sigue, en el cual he resaltado los cambios que he realizado a partir de la configuración por defecto que venía:<br /><pre><?xml version="1.0" encoding="utf-8"?><br /><br /><image schemaversion="6<span style="background-color: white;">.8</span>" name="<span style="background-color: #ffe599;">tdb-openSU<span>S</span></span><span style="background-color: #ffe599;">E-Leap-15.2</span>"><br /> <description type="system"><br /> <author><span style="background-color: #ffe599;">Gabriel</span></author><br /> <contact><span style="background-color: #ffe599;">contacto(arroba)tormentadebits(dot)com</span></contact><br /> <specification><br /> <span style="background-color: #ffe599;">TDB openSU<span>S</span></span><span style="background-color: #ffe599;">E Leap 15.2 es una distro Linux corporativa basada en openSUSE.</span><br /> </specification><br /> </description><br /> <preferences><br /> <type image="iso" primary="true" flags="overlay" hybrid="true" firmware="efi" kernelcmdline="splash" hybridpersistent_filesystem="ext4" hybridpersistent="true" mediacheck="true"/><br /> <version><span style="background-color: #ea9999;">1.0.0</span></version><br /> <packagemanager>zypper</packagemanager><br /> <locale><span style="background-color: #ea9999;">es_ES</span></locale><br /> <keytable><span style="background-color: #ea9999;">es</span></keytable><br /> <timezone><span style="background-color: #ea9999;">America/Asuncion</span></timezone><br /> <rpm-excludedocs><span style="background-color: #ea9999;">false</span></rpm-excludedocs><br /> <rpm-check-signatures>false</rpm-check-signatures><br /> <bootsplash-theme><span style="background-color: white;">bgrt</span></bootsplash-theme><br /> <bootloader-theme>openSUSE</bootloader-theme><br /> </preferences><br /> <preferences><br /> <type image="vmx" filesystem="ext4" bootloader="grub2" kernelcmdline="splash" firmware="efi"/><br /> <type image="oem" filesystem="ext4" initrd_system="dracut" installiso="true" bootloader="grub2" kernelcmdline="splash" firmware="efi"><br /> <oemconfig><br /> <span style="background-color: #b4a7d6;"><!--oem-systemsize>2048</oem-systemsize--></span><br /> <oem-swap>true</oem-swap><br /> <oem-device-filter>/dev/ram</oem-device-filter><br /> <oem-multipath-scan>false</oem-multipath-scan><br /> </oemconfig><br /> <machine memory="512" guestOS="suse" HWversion="4"><br /> <vmdisk id="0" controller="ide"/><br /> <vmnic driver="e1000" interface="0" mode="bridged"/><br /> </machine><br /> </type><br /> </preferences><br /> <users><br /> <user password="<span style="background-color: #f9cb9c;">$1$randomte$hVK3OIJW75TkyaZ.i7Kh20</span>" home="/root" name="root" groups="root"/><br /> </users><br /> <repository type="rpm-md" alias="kiwi" priority="1"><br /> <source path="obs://Virtualization:Appliances:Builder/openSUSE_Leap_15.2"/><br /> </repository><br /> <repository type="rpm-md" alias="Leap_15_2" imageinclude="true"><br /> <source path="obs://openSUSE:Leap:15.2/standard"/><br /> </repository><br /><span style="background-color: #9fc5e8;"> <repository type="rpm-md" alias="repo-update" imageinclude="true" priority="1"><br /> <source path="http://download.opensuse.org/update/leap/15.2/oss"/><br /> </repository><br /> <repository type="rpm-md" alias="repo-update-non-oss" imageinclude="true" priority="2"><br /> <source path="http://download.opensuse.org/update/leap/15.2/non-oss"/><br /> </repository><br /> <repository type="rpm-md" alias="repo-oss" imageinclude="true" priority="3"><br /> <source path="http://download.opensuse.org/distribution/leap/15.2/repo/oss"/><br /> </repository><br /> <repository type="rpm-md" alias="repo-non-oss" imageinclude="true" priority="4"><br /> <source path="http://download.opensuse.org/distribution/leap/15.2/repo/non-oss"/><br /> </repository><br /> <repository type="rpm-md" alias="google-chrome" imageinclude="true" priority="5"><br /> <source path="http://dl.google.com/linux/chrome/rpm/stable/x86_64"/><br /> </repository><br /> <repository type="rpm-md" alias="download.nvidia.com-leap" imageinclude="true" priority="6"><br /> <source path="https://download.nvidia.com/opensuse/leap/15.2"/><br /> </repository><br /> <repository type="rpm-md" alias="repo-oss" imageinclude="true" priority="7"><br /> <source path="http://packman.inode.at/suse/openSUSE_Leap_15.2"/><br /> </repository><br /> <repository type="rpm-md" alias="snappy" imageinclude="true" priority="8"><br /> <source path="http://download.opensuse.org/repositories/system:/snappy/openSUSE_Leap_15.2"/><br /> </repository></span><br /> <packages type="image" <span style="background-color: #b6d7a8;">patternType="plusRecommended"</span>><br /> <package name="checkmedia"/><br /> <package name="plymouth-theme-bgrt"/><br /> <package name="plymouth-dracut"/><br /> <package name="grub2-branding-openSUSE"/><br /> <package name="ifplugd"/><br /> <package name="iputils"/><br /> <package name="vim"/><br /> <package name="grub2"/><br /> <package name="grub2-x86_64-efi" arch="x86_64"/><br /> <package name="grub2-i386-pc"/><br /> <package name="syslinux"/><br /> <package name="lvm2"/><br /> <package name="plymouth"/><br /> <package name="fontconfig"/><br /> <package name="fonts-config"/><br /> <package name="tar"/><br /> <package name="parted"/><br /> <package name="openssh"/><br /> <package name="iproute2"/><br /> <package name="less"/><br /> <package name="bash-completion"/><br /> <package name="dhcp-client"/><br /> <package name="which"/><br /> <package name="shim"/><br /> <package name="kernel-default"/><br /> <package name="timezone"/><br /><span style="background-color: #b6d7a8;"> <package name="ntp"/><br /> <package name="man-pages"/><br /> <package name="man-pages-posix"/><br /> <package name="x11vnc"/><br /> <package name="krfb"/><br /> <package name="xinetd"/><br /> <package name="bzip2"/><br /> <package name="unrar"/><br /> <package name="yast2-alternatives"/><br /> <package name="yast2-firstboot"/><br /> <package name="yast2-trans-es"/><br /> <package name="pidgin"/><br /> <package name="gajim"/><br /> <package name="kwrite"/><br /> <package name="firewalld"/><br /> <package name="firewall-config"/><br /> <package name="telnet"/><br /> <package name="vncmanager"/><br /> <package name="OpenPrintingPPDs"/><br /> <package name="hplip"/><br /> <package name="manufacturer-PPDs"/><br /> <package name="epson-inkjet-printer-escpr"/><br /> <package name="gutenprint"/><br /> <package name="myspell-es"/><br /> <package name="myspell-es_PY"/><br /> <package name="aspell-es"/><br /> <package name="ispell-spanish"/><br /> <package name="nmap"/><br /> <package name="rsync"/><br /> <package name="tcpdump"/><br /> <package name="libreoffice-writer-extensions"/><br /> <package name="libreoffice-calc-extensions"/><br /> <package name="libreoffice-l10n-es"/><br /> <package name="gcc"/><br /> <package name="gcc-c++"/><br /> <package name="cups-backends"/><br /> <package name="net-tools-deprecated"/><br /> <package name="perl-Net-IP"/><br /> <package name="perl-Net-IPv4Addr"/><br /> <package name="snapd"/><br /> <package name="virtualbox-kmp-default"/><br /> <package name="virtualbox-guest-tools"/><br /> <package name="virtualbox-guest-x11"/><br /> <package name="sane-backends"/><br /> <package name="xf86-video-amdgpu"/><br /> <package name="xf86-video-ati"/><br /> <package name="xf86-video-nouveau"/><br /> <package name="xf86-video-nv"/><br /> <package name="xf86-video-r128"/><br /> <package name="xf86-video-intel"/><br /> <namedCollection name="apparmor"/><br /> <namedCollection name="apparmor_opt"/><br /> <namedCollection name="base"/><br /> <namedCollection name="basesystem"/><br /> <namedCollection name="enhanced_base"/><br /> <namedCollection name="enhanced_base_opt"/><br /> <namedCollection name="fonts"/><br /> <namedCollection name="fonts_opt"/><br /> <namedCollection name="imaging"/><br /> <namedCollection name="imaging_opt"/><br /> <namedCollection name="kde"/><br /> <namedCollection name="kde_imaging"/><br /> <namedCollection name="kde_internet"/><br /> <namedCollection name="kde_multimedia"/><br /> <namedCollection name="kde_office"/><br /> <namedCollection name="kde_plasma"/><br /> <namedCollection name="kde_utilities"/><br /> <namedCollection name="kde_utilities_opt"/><br /> <namedCollection name="kde_yast"/><br /> <namedCollection name="laptop"/><br /> <namedCollection name="minimal_base"/><br /> <namedCollection name="multimedia"/><br /> <namedCollection name="multimedia_opt"/><br /> <namedCollection name="office"/><br /> <namedCollection name="sw_management"/><br /> <namedCollection name="x11"/><br /> <namedCollection name="x11_enhanced"/><br /> <namedCollection name="x11_opt"/><br /> <namedCollection name="x11_yast"/><br /> <namedCollection name="yast2_basis"/></span><br /> </packages><br /><span style="background-color: #d5a6bd;"> <packages type="delete"><br /> <!--package name="PackageKit"/--><br /> <!--package name="PackageKit-backend-zypp"/--><br /> <!--package name="PackageKit-lang"/--><br /> <!--package name="PackageKit-branding-openSUSE"/--><br /> <package name="discover"/><br /> <package name="discover-lang"/><br /> <package name="tigervnc"/><br /> <package name="kpat"/><br /> <package name="kpat-lang"/><br /> <package name="kdegames-carddecks-default"/><br /> <package name="kmahjongg"/><br /> <package name="kmahjongg-lang"/><br /> <package name="kmines"/><br /> <package name="kmines-lang"/><br /> <package name="kreversi"/><br /> <package name="kreversi-lang"/><br /> <package name="ksudoku"/><br /> <package name="ksudoku-lang"/><br /> <namedCollection name="patterns-games-games"/><br /> <namedCollection name="patterns-kde-kde_games"/><br /> </packages></span><br /> <packages type="iso"><br /> <package name="gfxboot-branding-openSUSE"/><br /> <package name="dracut-kiwi-live"/><br /> </packages><br /> <packages type="oem"><br /> <package name="gfxboot-branding-openSUSE"/><br /> <package name="dracut-kiwi-oem-repart"/><br /> <package name="dracut-kiwi-oem-dump"/><br /> </packages><br /> <packages type="bootstrap"><br /> <package name="udev"/><br /> <package name="filesystem"/><br /> <package name="glibc-locale"/><br /> <package name="cracklib-dict-full"/><br /> <package name="ca-certificates"/><br /> <package name="openSUSE-release"/><br /> </packages><br /></image></pre> Todos los cambios resaltados más arriba a excepción de los muy obvios los iré detallado a continuación:<br />- <b style="background-color: #ffe599;">name="tdb-openSUSE-Leap-15.2"</b>: Permite nombrar a nuestro proyecto, nombre con el cual se generará la imagen.<br /><br />- <b style="background-color: #ea9999;"><version>1.0.0</version></b>: Permite especificar la versión del proyecto de la imagen que estamos desarrollando, y que formará parte del nombre del archivo final.<br /><br />- <b style="background-color: #ea9999;"><locale>es_ES</locale></b>: Nos permite configurar el idioma por defecto para el sistema operativo.<br /><br />- <b style="background-color: #ea9999;"><keytable>es</keytable></b>: Nos permite configurar el idioma del teclado por defecto para el sistema operativo.<br /><br />- <b style="background-color: #ea9999;"><timezone>America/Asuncion</timezone></b>: Permite especificar la zona horaria por defecto para el sistema operativo, en el ejemplo especifico la zona horaria de mi país, si quieren conocer las zonas horarias disponibles pueden visitar <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones" target="_blank">este link</a>.<br /><br />- <b style="background-color: #ea9999;"><rpm-excludedocs>false</rpm-excludedocs></b>: Es importante setear el valor <b>false</b> a esta directiva, ya que si la dejamos con el valor por defecto no nos incluirá ningún documento <b>man</b> de ayuda. A mi me ha pasado que he pasado horas tratando de entender porqué no había documentos <b>man</b> en el sistema operativo una vez generada la imagen, y se debía a esta directiva que tenía el valor por defecto <b>true</b>.<br /><br />- <b style="background-color: #b4a7d6;"><!--oem-systemsize>2048</oem-systemsize--></b>: Esta directiva la recomiendo comentar o directamente eliminar para que el sistema de archivos auto asigne los tamaños de las particiones durante la instalación de la imagen, caso contrario creará una partición para la raíz de apenas 2 GB, algo que a toda costa es insuficiente a menos que nuestro proyecto lo requiera.<br /><br />- <b><span style="background-color: #f9cb9c;"><user password=</span></b>: Permite especificar la contraseña por defecto que se le asignará al usuario <b>root</b> apenas instalemos nuestra imagen Linux personalizada. La misma es básicamente un hash code que lo recomiendo reemplazar por una nueva contraseña encriptada que la podemos generar de la siguiente directiva:<br /> <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> openssl passwd -1 -salt 'randomtext', tdbpass</span><br />$1$randomte$hVK3OIJW75TkyaZ.i7Kh20<br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span></pre><br />- <b style="background-color: #9fc5e8;"><a href="https://osinside.github.io/kiwi/concept_and_workflow/repository_setup.html" target="_blank"><repository type="rpm-md"</a></b>: En esta sección vamos configurando los repositorios que la herramienta Kiwi podrá disponer para obtener los paquetes e incorporarlos en la construcción de la imagen del sistema operativo, y si le agregamos la directiva <b>imageinclude="true"</b> como se observa en el ejemplo ya estarán configurados automáticamente en nuestro imagen. En este ejemplo se agregan como fuente de datos los repositorios repo-update, repo-update-non-oss, repo-oss, repo-non-oss, google-chrome, download.nvidia.com-leap, repo-oss y snappy.<br /><br />- <b style="background-color: #b6d7a8;"><packages type="image" patternType="plusRecommended"></b>: En esta sección es importante resaltar la directiva patternType="plusRecommended" que permite que durante la creación de la imagen no solo se incorporen los paquetes estrictamente necesarios, sino también aquellos recomendados para el buen funcionamiento y compatibilidad del sistema operativo final. Dentro de dicha sección de configuración podemos especificar la directiva <b><b>"</b>package name</b><b>"</b> para indicar nombres de paquetes específicos y la directiva <b>"namedCollection name"</b> para especificar nombres de colecciones de paquetes. Todos las directivas <span style="background-color: #b6d7a8;">resaltadas en verde</span> son justamente paquetes y colecciones de paquetes agregadas de forma adicional que no viene con la configuración por defecto.<br /><br />- <b style="background-color: #d5a6bd;"><packages type="delete"></b>: En esta sección de configuración podemos especificar los nombres de paquetes y de las colecciones de paquetes que queremos que se excluyan durante la construcción de la imagen de nuestra distribución Linux personalizada.<br /><br /></li><li>Para nuestro proyecto básico también tenemos que realizar un cambio menor al archivo <b>config.sh</b>. Procedemos a editarlo:<pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span><span style="background-color: white;"> vim </span>config.sh</pre>Una vez adentro buscamos la sección <b>baseSetRunlevel</b> y reemplazamos el <b>nivel de ejecución 3</b> (Multiusuario con soporte de red sin interfaz gráfica, solo consola) por el <b>nivel de ejecución 5</b> (Multiusuario con soporte de red y entorno gráfico):<br /><pre><b><font color="#3d85c6"><span style="background-color: white;">#======================================</span><span style="background-color: white;"><br /></span><span style="background-color: white;"># Setup default target, multi-user</span><span style="background-color: white;"><br /></span><span style="background-color: white;">#--------------------------------------</span></font><span style="background-color: white;"><br /></span>baseSetRunlevel <font color="#ff54ff"><span style="background-color: white;">5</span></font></b><br /></pre></li><li>En el directorio home del usuario root creamos la carpeta <b>kiwi-builds</b> para albergar las imágenes que generará el comando de construcción de la imagen:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span><span style="background-color: white;"> cd ..<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span> mkdir kiwi-builds<br /></span></pre></li><li>Llegados hasta este punto ya estamos listos para proceder con la ejecución del comando que se encargará de construir la imagen de nuestra distribución Linux personalizada con una configuración básica inicial. Damos inicio al proceso de construcción ejecutando el siguiente comando:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span>kiwi --type oem system build --description ~/mysuseleap-15.2 --target-dir ~/kiwi-builds</pre>La salida completa de la ejecución del comando anterior se puede observar a continuación:<br /><pre>[ INFO ]: 22:04:17 | Loading XML description<br />[ INFO ]: 22:04:17 | --> loaded /root/mysuseleap-15.2/config.xml<br />[ INFO ]: 22:04:17 | --> Selected build type: oem<br />[ INFO ]: 22:04:17 | Preparing new root system<br />[ INFO ]: 22:04:17 | Setup root directory: /root/kiwi-builds/build/image-root<br />[ INFO ]: 22:04:18 | Setting up repository obs://Virtualization:Appliances:Builder/openSUSE_Leap_15.2<br />[ INFO ]: 22:04:18 | --> Type: rpm-md<br />[ INFO ]: 22:04:18 | --> Priority: 1<br />[ INFO ]: 22:04:19 | --> Translated: http://download.opensuse.org/repositories/Virtualization:/Appliances:/Builder/openSUSE_Leap_15.2/<br />[ INFO ]: 22:04:19 | --> Alias: kiwi<br />[ INFO ]: 22:04:19 | Setting up repository obs://openSUSE:Leap:15.2/standard<br />[ INFO ]: 22:04:19 | --> Type: rpm-md<br />[ INFO ]: 22:04:20 | --> Translated: http://download.opensuse.org/distribution/leap/15.2/repo/oss/<br />[ INFO ]: 22:04:20 | --> Alias: Leap_15_2<br />[ INFO ]: 22:04:20 | Setting up repository http://download.opensuse.org/update/leap/15.2/oss<br />[ INFO ]: 22:04:20 | --> Type: rpm-md<br />[ INFO ]: 22:04:20 | --> Priority: 1<br />[ INFO ]: 22:04:20 | --> Translated: http://download.opensuse.org/update/leap/15.2/oss<br />[ INFO ]: 22:04:20 | --> Alias: repo-update<br />[ INFO ]: 22:04:20 | Setting up repository http://download.opensuse.org/update/leap/15.2/non-oss<br />[ INFO ]: 22:04:20 | --> Type: rpm-md<br />[ INFO ]: 22:04:20 | --> Priority: 2<br />[ INFO ]: 22:04:20 | --> Translated: http://download.opensuse.org/update/leap/15.2/non-oss<br />[ INFO ]: 22:04:20 | --> Alias: repo-update-non-oss<br />[ INFO ]: 22:04:20 | Setting up repository http://download.opensuse.org/distribution/leap/15.2/repo/oss<br />[ INFO ]: 22:04:20 | --> Type: rpm-md<br />[ INFO ]: 22:04:20 | --> Priority: 3<br />[ INFO ]: 22:04:20 | --> Translated: http://download.opensuse.org/distribution/leap/15.2/repo/oss<br />[ INFO ]: 22:04:20 | --> Alias: repo-oss<br />[ INFO ]: 22:04:20 | Setting up repository http://download.opensuse.org/distribution/leap/15.2/repo/non-oss<br />[ INFO ]: 22:04:20 | --> Type: rpm-md<br />[ INFO ]: 22:04:20 | --> Priority: 4<br />[ INFO ]: 22:04:20 | --> Translated: http://download.opensuse.org/distribution/leap/15.2/repo/non-oss<br />[ INFO ]: 22:04:20 | --> Alias: repo-non-oss<br />[ INFO ]: 22:04:21 | Setting up repository http://dl.google.com/linux/chrome/rpm/stable/x86_64<br />[ INFO ]: 22:04:21 | --> Type: rpm-md<br />[ INFO ]: 22:04:21 | --> Priority: 5<br />[ INFO ]: 22:04:21 | --> Translated: http://dl.google.com/linux/chrome/rpm/stable/x86_64<br />[ INFO ]: 22:04:21 | --> Alias: google-chrome<br />[ INFO ]: 22:04:21 | Setting up repository http://download.nvidia.com/opensuse/leap/15.2<br />[ INFO ]: 22:04:21 | --> Type: rpm-md<br />[ INFO ]: 22:04:21 | --> Priority: 6<br />[ INFO ]: 22:04:21 | --> Translated: http://download.nvidia.com/opensuse/leap/15.2<br />[ INFO ]: 22:04:21 | --> Alias: download.nvidia.com-leap<br />[ INFO ]: 22:04:21 | Setting up repository http://packman.inode.at/suse/openSUSE_Leap_15.2<br />[ INFO ]: 22:04:21 | --> Type: rpm-md<br />[ INFO ]: 22:04:21 | --> Priority: 7<br />[ INFO ]: 22:04:21 | --> Translated: http://packman.inode.at/suse/openSUSE_Leap_15.2<br />[ INFO ]: 22:04:21 | --> Alias: repo-oss<br />[ INFO ]: 22:04:21 | Setting up repository http://download.opensuse.org/repositories/system:/snappy/openSUSE_Leap_15.2<br />[ INFO ]: 22:04:21 | --> Type: rpm-md<br />[ INFO ]: 22:04:21 | --> Priority: 8<br />[ INFO ]: 22:04:21 | --> Translated: http://download.opensuse.org/repositories/system:/snappy/openSUSE_Leap_15.2<br />[ INFO ]: 22:04:21 | --> Alias: snappy<br />[ INFO ]: 22:04:21 | Using package manager backend: zypper<br />[ INFO ]: 22:04:21 | Installing bootstrap packages<br />[ INFO ]: 22:04:21 | --> collection type: onlyRequired<br />[ INFO ]: 22:04:21 | --> package: ca-certificates<br />[ INFO ]: 22:04:21 | --> package: cracklib-dict-full<br />[ INFO ]: 22:04:21 | --> package: filesystem<br />[ INFO ]: 22:04:21 | --> package: glibc-locale<br />[ INFO ]: 22:04:21 | --> package: openSUSE-release<br />[ INFO ]: 22:04:21 | --> package: udev<br />[ INFO ]: 22:04:21 | --> package: zypper<br />[ INFO ]: Processing: [########################################] 100%<br />[ INFO ]: 22:09:46 | Installing system (chroot) for build type: oem<br />[ INFO ]: 00:25:38 | --> collection type: plusRecommended<br />[ INFO ]: 00:25:38 | --> package: OpenPrintingPPDs<br />[ INFO ]: 00:25:38 | --> package: aspell-es<br />[ INFO ]: 00:25:38 | --> package: bash-completion<br />[ INFO ]: 00:25:38 | --> package: bzip2<br />[ INFO ]: 00:25:38 | --> package: checkmedia<br />[ INFO ]: 00:25:38 | --> package: cups-backends<br />[ INFO ]: 00:25:38 | --> package: dhcp-client<br />[ INFO ]: 00:25:38 | --> package: dracut-kiwi-oem-dump<br />[ INFO ]: 00:25:38 | --> package: dracut-kiwi-oem-repart<br />[ INFO ]: 00:25:38 | --> package: epson-inkjet-printer-escpr<br />[ INFO ]: 00:25:38 | --> package: firewall-config<br />[ INFO ]: 00:25:38 | --> package: firewalld<br />[ INFO ]: 00:25:38 | --> package: fontconfig<br />[ INFO ]: 00:25:38 | --> package: fonts-config<br />[ INFO ]: 00:25:38 | --> package: gajim<br />[ INFO ]: 00:25:38 | --> package: gcc<br />[ INFO ]: 00:25:38 | --> package: gcc-c++<br />[ INFO ]: 00:25:38 | --> package: gfxboot-branding-openSUSE<br />[ INFO ]: 00:25:38 | --> package: grub2<br />[ INFO ]: 00:25:38 | --> package: grub2-branding-openSUSE<br />[ INFO ]: 00:25:38 | --> package: grub2-i386-pc<br />[ INFO ]: 00:25:38 | --> package: grub2-x86_64-efi<br />[ INFO ]: 00:25:38 | --> package: gutenprint<br />[ INFO ]: 00:25:38 | --> package: hplip<br />[ INFO ]: 00:25:38 | --> package: ifplugd<br />[ INFO ]: 00:25:38 | --> package: iproute2<br />[ INFO ]: 00:25:38 | --> package: iputils<br />[ INFO ]: 00:25:38 | --> package: ispell-spanish<br />[ INFO ]: 00:25:38 | --> package: kernel-default<br />[ INFO ]: 00:25:38 | --> package: krfb<br />[ INFO ]: 00:25:38 | --> package: kwrite<br />[ INFO ]: 00:25:38 | --> package: less<br />[ INFO ]: 00:25:38 | --> package: libreoffice-calc-extensions<br />[ INFO ]: 00:25:38 | --> package: libreoffice-l10n-es<br />[ INFO ]: 00:25:38 | --> package: libreoffice-writer-extensions<br />[ INFO ]: 00:25:38 | --> package: lvm2<br />[ INFO ]: 00:25:38 | --> package: man-pages<br />[ INFO ]: 00:25:38 | --> package: man-pages-posix<br />[ INFO ]: 00:25:38 | --> package: manufacturer-PPDs<br />[ INFO ]: 00:25:38 | --> package: myspell-es<br />[ INFO ]: 00:25:38 | --> package: myspell-es_PY<br />[ INFO ]: 00:25:38 | --> package: net-tools-deprecated<br />[ INFO ]: 00:25:38 | --> package: nmap<br />[ INFO ]: 00:25:38 | --> package: ntp<br />[ INFO ]: 00:25:38 | --> package: openssh<br />[ INFO ]: 00:25:38 | --> package: parted<br />[ INFO ]: 00:25:38 | --> package: perl-Net-IP<br />[ INFO ]: 00:25:38 | --> package: perl-Net-IPv4Addr<br />[ INFO ]: 00:25:38 | --> package: pidgin<br />[ INFO ]: 00:25:38 | --> package: plymouth<br />[ INFO ]: 00:25:38 | --> package: plymouth-dracut<br />[ INFO ]: 00:25:38 | --> package: plymouth-theme-bgrt<br />[ INFO ]: 00:25:38 | --> package: rsync<br />[ INFO ]: 00:25:38 | --> package: sane-backends<br />[ INFO ]: 00:25:38 | --> package: shim<br />[ INFO ]: 00:25:38 | --> package: snapd<br />[ INFO ]: 00:25:38 | --> package: syslinux<br />[ INFO ]: 00:25:38 | --> package: tar<br />[ INFO ]: 00:25:38 | --> package: tcpdump<br />[ INFO ]: 00:25:38 | --> package: telnet<br />[ INFO ]: 00:25:38 | --> package: timezone<br />[ INFO ]: 00:25:38 | --> package: unrar<br />[ INFO ]: 00:25:38 | --> package: vim<br />[ INFO ]: 00:25:38 | --> package: virtualbox-guest-tools<br />[ INFO ]: 00:25:38 | --> package: virtualbox-guest-x11<br />[ INFO ]: 00:25:38 | --> package: virtualbox-kmp-default<br />[ INFO ]: 00:25:38 | --> package: vncmanager<br />[ INFO ]: 00:25:38 | --> package: which<br />[ INFO ]: 00:25:38 | --> package: x11vnc<br />[ INFO ]: 00:25:38 | --> package: xf86-video-amdgpu<br />[ INFO ]: 00:25:38 | --> package: xf86-video-ati<br />[ INFO ]: 00:25:38 | --> package: xf86-video-intel<br />[ INFO ]: 00:25:38 | --> package: xf86-video-nouveau<br />[ INFO ]: 00:25:38 | --> package: xf86-video-nv<br />[ INFO ]: 00:25:38 | --> package: xf86-video-r128<br />[ INFO ]: 00:25:38 | --> package: xinetd<br />[ INFO ]: 00:25:38 | --> package: yast2-alternatives<br />[ INFO ]: 00:25:38 | --> package: yast2-firstboot<br />[ INFO ]: 00:25:38 | --> package: yast2-trans-es<br />[ INFO ]: 00:25:38 | --> collection: apparmor<br />[ INFO ]: 00:25:38 | --> collection: apparmor_opt<br />[ INFO ]: 00:25:38 | --> collection: base<br />[ INFO ]: 00:25:38 | --> collection: basesystem<br />[ INFO ]: 00:25:38 | --> collection: enhanced_base<br />[ INFO ]: 00:25:38 | --> collection: enhanced_base_opt<br />[ INFO ]: 00:25:38 | --> collection: fonts<br />[ INFO ]: 00:25:38 | --> collection: fonts_opt<br />[ INFO ]: 00:25:38 | --> collection: imaging<br />[ INFO ]: 00:25:38 | --> collection: imaging_opt<br />[ INFO ]: 00:25:38 | --> collection: kde<br />[ INFO ]: 00:25:38 | --> collection: kde_imaging<br />[ INFO ]: 00:25:38 | --> collection: kde_internet<br />[ INFO ]: 00:25:38 | --> collection: kde_multimedia<br />[ INFO ]: 00:25:38 | --> collection: kde_office<br />[ INFO ]: 00:25:38 | --> collection: kde_plasma<br />[ INFO ]: 00:25:38 | --> collection: kde_utilities<br />[ INFO ]: 00:25:38 | --> collection: kde_utilities_opt<br />[ INFO ]: 00:25:38 | --> collection: kde_yast<br />[ INFO ]: 00:25:38 | --> collection: laptop<br />[ INFO ]: 00:25:38 | --> collection: minimal_base<br />[ INFO ]: 00:25:38 | --> collection: multimedia<br />[ INFO ]: 00:25:38 | --> collection: multimedia_opt<br />[ INFO ]: 00:25:38 | --> collection: office<br />[ INFO ]: 00:25:38 | --> collection: sw_management<br />[ INFO ]: 00:25:38 | --> collection: x11<br />[ INFO ]: 00:25:38 | --> collection: x11_enhanced<br />[ INFO ]: 00:25:38 | --> collection: x11_opt<br />[ INFO ]: 00:25:38 | --> collection: x11_yast<br />[ INFO ]: 00:25:38 | --> collection: yast2_basis<br />[ INFO ]: Processing: [########################################] 100%<br />[ INFO ]: 23:41:14 | Creating .profile environment<br />[ INFO ]: 23:41:14 | Importing Image description to system tree<br />[ INFO ]: 23:41:14 | --> Importing state XML description as image/config.xml<br />[ INFO ]: 23:41:14 | --> Importing config.sh script as image/config.sh<br />[ INFO ]: 23:41:14 | --> Importing script helper functions<br />[ INFO ]: 23:41:14 | Copying user defined files to image tree<br />[ INFO ]: 23:41:14 | Setting up user root<br />[ INFO ]: 23:41:14 | --> Modifying user: root [root]<br />[ INFO ]: 23:41:14 | Setting up keytable: es<br />[ INFO ]: 23:41:14 | Setting up locale: en_ES<br />[ INFO ]: 23:41:14 | Setting up timezone: America/Asuncion<br />[ INFO ]: 23:41:14 | Check/Fix File Permissions<br />[ INFO ]: 23:41:16 | Setting up image repository obs://openSUSE:Leap:15.2/standard<br />[ INFO ]: 23:41:16 | --> Type: rpm-md<br />[ INFO ]: 23:41:16 | --> Translated: http://download.opensuse.org/distribution/leap/15.2/repo/oss/<br />[ INFO ]: 23:41:16 | --> Alias: Leap_15_2<br />[ INFO ]: 23:41:17 | Calling config.sh script<br />[ INFO ]: 23:41:17 | Force deleting system packages (chroot)<br />[ INFO ]: 23:41:17 | Using package manager backend: zypper<br />[ INFO ]: 23:41:17 | --> package: discover<br />[ INFO ]: 23:41:17 | --> package: discover-lang<br />[ INFO ]: 23:41:17 | --> package: kdegames-carddecks-default<br />[ INFO ]: 23:41:17 | --> package: kmahjongg<br />[ INFO ]: 23:41:17 | --> package: kmahjongg-lang<br />[ INFO ]: 23:41:17 | --> package: kmines<br />[ INFO ]: 23:41:17 | --> package: kmines-lang<br />[ INFO ]: 23:41:17 | --> package: kpat<br />[ INFO ]: 23:41:17 | --> package: kpat-lang<br />[ INFO ]: 23:41:17 | --> package: kreversi<br />[ INFO ]: 23:41:17 | --> package: kreversi-lang<br />[ INFO ]: 23:41:17 | --> package: ksudoku<br />[ INFO ]: 23:41:17 | --> package: ksudoku-lang<br />[ INFO ]: 23:41:17 | --> package: tigervnc<br />[ INFO ]: 23:41:17 | Force deleting system packages (chroot)<br />[ INFO ]: Processing: [########################################] 100%<br />[ INFO ]: 23:41:18 | Cleaning up SystemPrepare instance<br />[ INFO ]: 23:41:19 | Creating system image<br />[ INFO ]: 23:41:19 | Preparing boot system<br />[ INFO ]: 23:41:19 | Creating .profile environment<br />[ INFO ]: 23:41:19 | Precalculating required disk size<br />[ INFO ]: 23:41:41 | --> system data with filesystem overhead needs 9788 MB<br />[ INFO ]: 23:41:41 | --> legacy bios boot partition adding 2 MB<br />[ INFO ]: 23:41:41 | --> EFI partition adding 20 MB<br />[ INFO ]: 23:41:41 | Using calculated disk size: 9810 MB<br />[ INFO ]: 23:41:41 | Creating raw disk image /root/kiwi-builds/tdb-openSUSE-Leap-15.2.x86_64-1.0.0.raw<br />[ INFO ]: 23:41:43 | --> creating EFI CSM(legacy bios) partition<br />[ INFO ]: 23:41:45 | --> creating EFI partition<br />[ INFO ]: 23:41:47 | --> creating root partition<br />[ INFO ]: 23:41:50 | Creating EFI(fat16) filesystem on /dev/mapper/loop0p2<br />[ INFO ]: 23:41:50 | Creating root(ext4) filesystem on /dev/mapper/loop0p3<br />[ INFO ]: 23:41:51 | Creating config.partids in boot system<br />[ INFO ]: 23:41:51 | Export modprobe configuration<br />[ INFO ]: 23:41:51 | Creating image identifier: 0x3cfb4ea2<br />[ INFO ]: 23:41:51 | Creating generic system etc/fstab<br />[ INFO ]: 23:41:51 | Creating generic dracut initrd archive<br />[ INFO ]: 23:44:23 | --> initrd archive as initrd-5.3.18-lp152.33-default<br />[ INFO ]: 23:44:23 | Creating grub2 bootloader configuration<br />[ INFO ]: 23:44:23 | Creating grub2 bootloader images<br />[ INFO ]: 23:44:23 | --> Using prebuilt unsigned efi image<br />[ INFO ]: 23:44:23 | Creating grub2 config file from template<br />[ INFO ]: 23:44:23 | --> Using hybrid boot disk template<br />[ INFO ]: 23:44:23 | Writing grub.cfg file<br />[ INFO ]: 23:44:23 | Writing grub2 defaults file<br />[ INFO ]: 23:44:23 | --> GRUB_CMDLINE_LINUX_DEFAULT:"splash root=UUID=458f7faa-e741-405b-ba75-d11a6616cacd rw "<br />[ INFO ]: 23:44:23 | --> GRUB_THEME:/boot/grub2/themes/openSUSE/theme.txt<br />[ INFO ]: 23:44:23 | --> GRUB_TIMEOUT:10<br />[ INFO ]: 23:44:23 | --> GRUB_USE_INITRDEFI:true<br />[ INFO ]: 23:44:23 | --> GRUB_USE_LINUXEFI:true<br />[ INFO ]: 23:44:23 | Writing sysconfig bootloader file<br />[ INFO ]: 23:44:23 | --> DEFAULT_APPEND:"splash root=UUID=458f7faa-e741-405b-ba75-d11a6616cacd rw "<br />[ INFO ]: 23:44:23 | --> FAILSAFE_APPEND:"splash root=UUID=458f7faa-e741-405b-ba75-d11a6616cacd rw ide=nodma apm=off noresume edd=off nomodeset 3 "<br />[ INFO ]: 23:44:23 | --> LOADER_LOCATION:none<br />[ INFO ]: 23:44:23 | --> LOADER_TYPE:grub2-efi<br />[ INFO ]: 23:44:23 | Creating config.bootoptions<br />[ INFO ]: 23:44:23 | Syncing system to image<br />[ INFO ]: 23:44:23 | --> Syncing EFI boot data to EFI partition<br />[ WARNING ]: 23:44:24 | Extended attributes not supported for target: /tmp/kiwi_mount_manager.hr6ebggl<br />[ INFO ]: 23:44:24 | --> Syncing root filesystem data<br />[ INFO ]: 23:49:57 | Installing grub2 on disk /dev/loop0<br />[ INFO ]: 23:50:01 | Cleaning up BootLoaderInstallGrub2 instance<br />[ INFO ]: 23:50:01 | Saving boot image instance to file<br />[ INFO ]: 23:50:01 | Export rpm packages metadata<br />[ INFO ]: 23:50:05 | Export rpm verification metadata<br />[ INFO ]: 23:55:02 | Cleaning up FileSystemExt4 instance<br />[ INFO ]: 23:55:02 | Cleaning up FileSystemFat16 instance<br />[ INFO ]: 23:55:02 | Cleaning up Disk instance<br />[ INFO ]: 23:55:02 | Cleaning up LoopDevice instance<br />[ INFO ]: 23:55:02 | Creating hybrid ISO installation image<br />[ INFO ]: 23:55:02 | Creating disk image checksum<br />[ INFO ]: 23:55:53 | Creating squashfs embedded disk image<br />[ INFO ]: 01:25:51 | Setting up install image bootloader configuration<br />[ INFO ]: 01:25:51 | Creating grub2 bootloader images<br />[ INFO ]: 01:25:51 | --> Creating identifier file 0x5bdd7555<br />[ INFO ]: 01:25:52 | --> Creating bios image<br />[ INFO ]: 01:25:52 | --> Using prebuilt unsigned efi image<br />[ INFO ]: 01:25:53 | Creating grub2 install config file from template<br />[ WARNING ]: 01:25:53 | root=UUID=<uuid> setup requested, but uuid is not provided<br />[ INFO ]: 01:25:53 | --> Using standard boot install template<br />[ INFO ]: 01:25:53 | Writing grub.cfg file<br />[ INFO ]: 01:25:53 | Writing /root/kiwi-builds/kiwi_install_media.fvec9t0_/EFI/BOOT/grub.cfg file to be found by EFI firmware<br />[ INFO ]: 01:25:53 | Writing grub2 defaults file<br />[ INFO ]: 01:25:53 | --> GRUB_CMDLINE_LINUX_DEFAULT:"splash"<br />[ INFO ]: 01:25:53 | --> GRUB_THEME:/boot/grub2/themes/openSUSE/theme.txt<br />[ INFO ]: 01:25:53 | --> GRUB_TIMEOUT:10<br />[ INFO ]: 01:25:53 | --> GRUB_USE_INITRDEFI:true<br />[ INFO ]: 01:25:53 | --> GRUB_USE_LINUXEFI:true<br />[ INFO ]: 01:25:53 | Writing sysconfig bootloader file<br />[ INFO ]: 01:25:53 | --> DEFAULT_APPEND:"splash"<br />[ INFO ]: 01:25:53 | --> FAILSAFE_APPEND:"splash ide=nodma apm=off noresume edd=off nomodeset 3"<br />[ INFO ]: 01:25:53 | --> LOADER_LOCATION:none<br />[ INFO ]: 01:25:53 | --> LOADER_TYPE:grub2-efi<br />[ INFO ]: 01:25:53 | Creating install image boot image<br />[ INFO ]: 01:25:53 | Creating generic dracut initrd archive<br />[ INFO ]: 01:28:35 | Creating ISO filesystem<br />[ INFO ]: 01:29:14 | Cleaning up InstallImageBuilder instance<br />[ INFO ]: 01:29:14 | Cleaning up BootImageDracut instance<br />[ INFO ]: 01:29:14 | Cleaning up BootImageDracut instance<br />[ INFO ]: 01:29:14 | Cleaning up BootImageDracut instance<br />[ INFO ]: 01:29:14 | Result files:<br />[ INFO ]: 01:29:14 | --> disk_image: /root/kiwi-builds/tdb-openSUSE-Leap-15.2.x86_64-1.0.0.raw<br />[ INFO ]: 01:29:14 | --> image_packages: /root/kiwi-builds/tdb-openSUSE-Leap-15.2.x86_64-1.0.0.packages<br />[ INFO ]: 01:29:14 | --> image_verified: /root/kiwi-builds/tdb-openSUSE-Leap-15.2.x86_64-1.0.0.verified<br />[ INFO ]: 01:29:14 | --> installation_image: /root/kiwi-builds/tdb-openSUSE-Leap-15.2.x86_64-1.0.0.install.iso<br />[ INFO ]: 01:29:14 | Cleaning up BootImageDracut instance<br /></pre>Una vez concluida la construcción de la imagen, podemos verificar el contenido del directorio <b>~/</b><b>kiwi-builds</b> donde lo que importa es el archivo <b>tdb-openSUSE-Leap-15.2.x86_64-1.0.0.install.iso</b>, que es la imagen ISO personalizada de nuestro propio sistema operativo:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> ls -l ~/kiwi-builds<br /></span><span style="background-color: white;">total 9605896<br /></span>drwxr-xr-x 3 root root 4096 jul 29 01:17 <span style="background-color: white; color: #5454ff; font-weight: bold;">build</span><span style="background-color: white;"><br /></span><span style="background-color: #b6d7a8;">-rw-r--r-- 1 root root 2321940480 jul 29 01:29 tdb-openSUSE-Leap-15.2.x86_64-1.0.0.install.iso</span><br />-rw-r--r-- 1 root root 421891 jul 28 23:50 tdb-openSUSE-Leap-15.2.x86_64-1.0.0.packages<br />-rw-r--r-- 1 root root 10286530560 jul 28 23:50 tdb-openSUSE-Leap-15.2.x86_64-1.0.0.raw<br />-rw-r--r-- 1 root root 4979 jul 28 23:55 tdb-openSUSE-Leap-15.2.x86_64-1.0.0.verified<br />-rw-r--r-- 1 root root 16863 jul 29 01:29 kiwi.result<br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><br /></pre></li><li>Como podrán darse cuenta el proceso tardará bastante, ya que el proceso abarca desde la descarga de los paquetes requeridos para la construcción de la imagen en el directorio temporal <b>/var/cache/kiwi/packages</b>, la construcción de la estructura del sistema de archivos del sistema operativo, el empaquetamiento y la construcción de la imagen ISO final.<br /><br />Ahora bien, los paquetes que se descargan en el directorio <b>/var/cache/kiwi/packages</b> ya no se volverán a descargar durante la próxima compilación, ya estarán cacheados. De hecho, si queremos actualizar las versiones de los paquetes en posteriores compilaciones es recomendable renombrar la carpeta <b>/var/cache/kiwi</b> por <b>/var/cache/kiwi-v1.0.0</b> y durante la próxima compilación dejar que el proceso vuelva a crear el directorio y descargar en él todos los paquetes actualizados a partir de los repositorios en línea.<br /><br /></li><li>Un problema que suele presentarse cuando <b>volvemos a ejecutar el comando kiwi</b> luego de que haya fallado durante la primera ejecución, es que el comando nos informará que no puede avanzar debido a que <b>ya existe una construcción en curso</b> en el directorio <b>~/</b><b>kiwi-builds</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">kiwi --type oem system build --description ~/mysuseleap-15.2 --target-dir ~/kiwi-builds<br /></span>[ INFO ]: 22:03:25 | Loading XML description<br />[ INFO ]: 22:03:26 | --> loaded /root/mysuseleap-15.2/config.xml<br />[ INFO ]: 22:03:26 | --> Selected build type: oem<br />[ INFO ]: 22:03:26 | Preparing new root system<br />[ INFO ]: 22:03:26 | Setup root directory: /root/kiwi-builds/build/image-root<br /><span style="background-color: #e06666;">[ ERROR ]: 22:03:26 | KiwiRootDirExists: Root directory /root/kiwi-builds/build/image-root already exists</span><br />[ INFO ]: 22:03:26 | Cleaning up SystemPrepare instance<br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span></pre>Para solucionar este problema simplemente procedemos a eliminar la carpeta <b>kiwi-builds</b> con todo su contenido del proyecto de construcción que quedó a medio terminar y la volvemos a crear:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> rm -Rf <span style="background-color: transparent;">~/kiwi-builds</span><br /></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ # </span>mkdir kiwi-builds</pre>Si no nos permite eliminar la carpeta <b>kiwi-builds</b> es posible que existan <b>unidades montadas</b> por el sistema operativo dentro de dicha carpeta, requeridos para el proceso de construcción de la imagen. Para ver si existen unidades montadas podemos ejecutar el comando <b>mount</b>, identificar cual es la unidad que se encuentra montada dentro del directorio <b>~/</b><b>kiwi-builds</b> y desmontarla con el comando <b>umount</b>, con lo cual ya nos debería permitir eliminar y volver a crear la carpeta <b>kiwi-builds</b> para que el comando <b>kiwi</b> detallado en el paso 7 se ejecute sin problemas. </li></ol><br /><h2 style="text-align: left;">Configuración avanzada de un proyecto Kiwi:</h2>Lo que hemos logrado con los pasos anteriores fue especificarle a <b>Kiwi</b> que deseamos que genere un sistema operativo con cierta configuración preliminar, con varios paquetes y repositorios predefinidos, una contraseña personalizada para el usuario root y poco más, nada demasiado especial.<br /><br />Sin embargo, utilizando la posibilidad de agregar paquetes, instaladores, scripts, archivos de configuración, etc. dentro de la carpeta <b>root</b> (/) de nuestro proyecto <b>kiwi</b>, y de ejecutar comandos de consola durante la construcción de la imagen del sistema operativo mediante el script de configuración <b>config.sh</b>, podremos hacer cambios muy profundos al sistema operativo que estamos personalizando, algunos de los cuales veremos en este apartado.</div><div><br />Lo primero que es importante entender es que el script <b>config.sh</b> ya contiene algunas pocas directivas de configuración para la imagen del sistema operativo. Si lo editamos con el siguiente comando:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> cd mysuseleap-15.2</span><br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2 #</span><span style="background-color: white;"> vim config.sh</span></pre>Vemos que ya tiene secciones de configuración, como por ejemplo la sección "<i><b>Setup baseproduct link</b></i>" donde se ejecuta el script <b>suseSetupProduct</b>, la sección "<i><b>Activate services</b></i>" donde especifica la directiva para indicarle a <b>kiwi</b> que el servicio <b>sshd</b> debe estar activado e iniciado por defecto apenes termine la instalación del sistema operativo, o la sección "<b><i>Setup default target, multi-user</i></b>" donde se configura en que nivel de ejecución se debe iniciar el sistema operativo, opción que por cierto ya hemos modificado en los pasos previos. <pre><b><font color="#3d85c6">#======================================<br /># Functions...<br />#--------------------------------------</font><br />test -f /.kconfig && . /.kconfig<br />test -f /.profile && . /.profile<br /><br /><font color="#3d85c6">#======================================<br /># Greeting...<br />#--------------------------------------</font><br />echo "Configure image: [$kiwi_iname]..."<br /><br /><font color="#3d85c6">#======================================<br /># Setup baseproduct link<br />#--------------------------------------</font><br />suseSetupProduct<br /><br /><font color="#3d85c6">#======================================<br /># Activate services<br />#--------------------------------------</font><br />suseInsertService sshd<br /><br /><font color="#3d85c6">#======================================<br /># Setup default target, multi-user<br />#--------------------------------------</font><br />baseSetRunlevel <span style="background-color: white; color: #ff54ff;">5</span></b></pre></div><div>Para facilitar la comprensión de los cambios que le estaremos haciendo a los archivos de configuración de nuestro sistema operativo y a las aplicaciones que vamos a instalar, me gusta agrupar todos los cambios dentro de una estructura de directorios dentro de la carpeta <b>root</b> de nuestro proyecto. A continuación agregaremos la carpeta <b>kiwifiles</b> que estará en el directorio raíz de nuestro sistema operativo y dentro de ella las carpetas <b>os</b> y <b>user</b> para agrupar los cambios que le haremos al sistema operativo en si y al entorno de los usuarios respectivamente:</div><div><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> cd mysuseleap-15.2/root<br /></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2/root </span><span style="background-color: white; color: #ff5454; font-weight: bold;"># </span>mkdir kiwifiles<br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2/root #</span><span style="background-color: white;"> mkdir kiwifiles/os</span><br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~/mysuseleap-15.2/root #</span><span style="background-color: white;"> mkdir </span>kiwifiles/user</pre>Pues bien, ya estamos listos para comenzar a ver diferentes ejemplos de como modificar nuestro sistema operativo durante el proceso de construcción de la imagen, a fin de ayudarnos a entender la cantidad de cambios que podemos hacer a nuestro sistema operativo sabiendo un poco de script bash y entiendo la estructura de los sistemas operativos basados en Linux.</div><div><br /></div><div><h3 style="text-align: left;">Personalización del sistema operativo:</h3><ol><li><b>RPMs</b>: A veces tenemos que instalar archivos rpms manualmente para instalar aplicaciones que no suelen estar disponibles en los repositorios, como es el caso del instalador oficial de Java. Para ello lo que podemos hacer es crear el directorio <b>rpms</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él copiar el archivo rpm <b>jre-8u261-linux-x64.rpm</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/rpms<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp ~/Downloads/jre-8u261-linux-x64.rpm ~/mysuseleap-15.2/root/kiwifiles/os/rpms</span><br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y bien al final del script le agregamos las siguiente directiva para instalar automáticamente el paquete rpm <b>jre-8u261-linux-x64.rpm</b>:<div><pre><font color="#3d85c6"><b># ==================================================================<br /># OS Configuration<br /># ==================================================================<br /><br /># --> Instalación de <Java><br /></b></font>zypper --non-interactive --no-gpg-checks in --allow-unsigned-rpm /kiwifiles/os/rpms/jre-8u261-linux-x64.rpm<b><br /></b></pre></div><div>Si tendríamos más paquetes rpm que instalar solo bastaría con copiarlos en el misma carpeta y agregar más directivas como la anterior por cada paquete que deseamos instalar.</div><br /></li><li><b>CUPS</b>: Si queremos que nuestro sistema operativo esté personalizado con impresoras por defecto, recomiendo crear el directorio <b>cups</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> en el cual estaríamos copiando nuestros archivos de configuración personalizados de CUPS incluyendo los archivos de definición de las impresoras (.ppd). En este ejemplo dentro del host <b>kiwi</b> ya hemos configurado y probado una impresora, cuyos archivos de configuración se copian en la carpeta cups creada previamente:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/cups<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/cups/cupsd.conf</span></span> ~/mysuseleap-15.2/root/kiwifiles/os/cups<br /><span style="background-color: white;"><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/cups/</span></span>printers.conf ~/mysuseleap-15.2/root/kiwifiles/os/cups<br /><span style="background-color: white;"><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/cups/ppd/testprinter.ppd</span></span> ~/mysuseleap-15.2/root/kiwifiles/os/cups<br /></pre>Como anécdota quisiera mencionar que para la versión <b>2.2.7</b> de <b>CUPS</b> de openSUSE 15.0 tuvimos que agregar configuraciones relacionadas con el protocolo USB para que ciertas impresoras de la marca <b>Zebra</b> funcionaran adecuadamente, configuraciones que no eran necesarias en versiones previas de CUPS. Por un lado se tuvo que agregar las directivas "Option usb-no-reattach true" y "Option usb-unidir true" en la sección de la impresora en el archivo de configuración <b>printers.conf</b>, y por el otro se tuvo que modificar la configuración de las impresoras en el archivo <b>org.cups.usb-quirks</b> presente normalmente en el directorio <b>/usr/share/cups/usb</b>, donde en la sección correspondiente a la marca Zebra (0x0a5f) se le agregó a la directiva"0x0a5f unidir" la directiva "no-reattach", quedando "0x0a5f unidir no-reattach", en fin, estas cosas suelen pasar entre cambios de versiones, lo que para una versión funcionaba quizás para la siguiente ya no, lo que a veces puede ser frustrante. <br /><br />Volviendo al tema procedemos a editar el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las siguientes directivas para copiar los archivos de configuración:<div><pre><font color="#3d85c6"><b># --> <b>Configuración</b><b> de <CUPS></b><br /></b></font>cp /kiwifiles/os/cups/cupsd.conf /etc/cups/<br />cp /kiwifiles/os/cups/printers.conf /etc/cups/<br />cp /kiwifiles/os/cups/testprinter.ppd /etc/cups/ppd/<br />chmod 640 /etc/cups/cupsd.conf<br />chmod 600 /etc/cups/printers.conf<br />chmod 644 /etc/cups/ppd/testprinter.ppd<br />chown root:lp /etc/cups/cupsd.conf<br />chown root:lp /etc/cups/printers.conf<br />chown root:lp /etc/cups/ppd/testprinter.ppd</pre></div></li> <li><b>SAMBA</b>: El paso sería básicamente el mismo que los anteriores, creamos el directorio <b>samba</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él copiar el archivo personalizado <b>smb.conf</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/samba<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/samba/smb.conf ~/mysuseleap-15.2/root/kiwifiles/os/samba</span><br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las siguiente directiva para copiar el archivo <b>smb.conf</b> a ubicación correspondiente:<div><pre><font color="#3d85c6"><b># --> <b>Configuración</b><b> de <Samba></b><br /></b></font>cp /kiwifiles/os/samba/smb.conf /etc/samba/<br />chmod 644 /etc/samba/smb.conf<br />chown root:root /etc/samba/smb.conf</pre></div></li><li><b>HALT.LOCAL</b>: A veces tenemos la necesidad de ejecutar comandos bash durante el apagado de la computadora para realizar ciertas tareas, como era mi caso donde al apagar la máquina solía ejecutar comandos para limpiar las órdenes de impresión colgadas que se enviaban a impresoras remotas a través del protocolo SAMBA.<br /><br />Para ello antes usaba al archivo <b>halt.local</b> que solía estar ubicado en el directorio <b>/etc/init.d</b>, sin embargo, desde la implementación de <b>systemd</b> ese archivo desapareció. Sin embargo, si verificamos el contenido del archivo <b>/usr/lib/systemd/system/halt-local.service</b> podremos comprobar que aún existe un servicio de <b>systemd</b> que utiliza y permite ejecutar directivas desde el archivo <b>/etc/init.d/halt.local</b>, solo falta crearlo. Pero como me gusta ordenarlo todo creamos el directorio <b>services</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él creamos el archivo <b>halt.local</b> y luego lo editamos:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/services<br /><span><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>touch ~/mysuseleap-15.2/root/kiwifiles/os/</span></span>services/halt.local<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>vim ~/mysuseleap-15.2/root/kiwifiles/os/</span></span>services/halt.local</pre>Y le agregamos un contenido similar a lo que sigue:<div><pre><font color="#3d85c6"><b>#! /bin/sh<br />#<br /># La ejecucion del script halt.local se llama desde el servicio de <br /># systemd ubicado en /usr/lib/systemd/system/halt-local.service.<br /><br /># Se agrega el comando para la limpieza de las bases<br /># de datos de impresoras samba al apagar el host.</b><b><br /></b></font>/bin/rm -f /var/lib/samba/printing/*.tdb</pre></div>Ahora ya podemos volver a editar el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y bien al final le agregamos las directivas que ubiquen el archivo <b>halt.local</b> en su posición correcta durante la construcción de la imagen del sistema operativo:<div><pre><font color="#3d85c6"><b># --> Configuración de <Services><br /></b></font>cp /kiwifiles/os/services/halt.local /etc/init.d/<br />chmod 744 /etc/init.d/halt.local<br />chown root:root /etc/init.d/halt.local</pre></div></li><li><b>FIREWALL</b>: Algunos servicios como Samba, CUPS y VNC los suelo habilitar de forma adicional en el Firewall, como se puede apreciar en la configuración del archivo <b>public.xml</b> del directorio <b>/etc/firewalld/zones</b>:<br /><pre><span><span style="background-color: white;"><?xml version="</span><span style="background-color: white; color: #ff00fe;">1.0</span><span style="background-color: white;">" encoding="</span><span style="background-color: white; color: #ff00fe;">utf-8</span><span style="background-color: white;">"?><br /><zone><br /> <short></span><span style="background-color: white; color: #666666;">Public</span><span style="background-color: white;"></short><br /> <description></span><span style="background-color: white; color: #666666;">For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</span><span style="background-color: white;"></description><br /> <service name="</span><span style="background-color: white; color: #ff00fe;">ssh</span><span style="background-color: white;">"/><br /> <service name="</span><span style="background-color: white; color: #ff00fe;">dhcpv6-client</span><span style="background-color: white;">"/><br /></span><span style="background-color: white;"> <service name="<span style="color: #ff00fe;">vnc-server</span>"/><br /> <service name="<span style="color: #ff00fe;">samba-client</span>"/><br /> <service name="<span style="color: #ff00fe;">samba</span>"/></span><span style="background-color: white;"><br /></zone></span></span></pre>Para mantener todo organizado podemos crear el directorio <b>firewalld</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él copiar todos los archivos de configuración de las zonas que deseamos:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/firewalld<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/firewalld/zones/public.xml ~/mysuseleap-15.2/root/kiwifiles/os/firewalld</span><br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las directiva para copiar el archivo de configuración del servicio Firewalld a la ubicación correspondiente:<div><pre><font color="#3d85c6"><b># --> Configuración de <Firewalld><br /></b></font>cp /kiwifiles/os/firewalld/public.xml /etc/firewalld/zones/<br />chmod 644 /etc/firewalld/zones/public.xml<br />chown root:root /etc/firewalld/zones/public.xml</pre></div></li><li><b>TIME SYNC & NTP</b>: Para que nuestra distribución Linux personalizada sincronice automáticamente la fecha y la hora con servidores NTP remotos y corra como un servidor NTP local, procedemos a creamos el directorio <b>ntp</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él copiar todos los archivos de configuración modificados a nuestro gusto para dicho fin:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/ntp<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/adjtime/chrony.conf ~/mysuseleap-15.2/root/kiwifiles/os/ntp<br /></span></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">cp /etc/adjtime ~/mysuseleap-15.2/root/kiwifiles/os/ntp<br /></span><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/sysconfig/clock ~/mysuseleap-15.2/root/kiwifiles/os/ntp<br /></span><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/ntp.conf ~/mysuseleap-15.2/root/kiwifiles/os/ntp<br /></span><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/sysconfig/ntp ~/mysuseleap-15.2/root/kiwifiles/os/ntp</span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las siguientes directivas:<div><pre><font color="#3d85c6"><b># --> Configuración de <NTP<b>></b><br /></b></font>cp /kiwifiles/os/ntp/chrony.conf /etc<br />cp /kiwifiles/os/ntp/adjtime /etc<br />cp /kiwifiles/os/ntp/clock /etc/sysconfig/<br />cp /kiwifiles/os/ntp/ntp.conf /etc/<br />cp /kiwifiles/os/ntp/ntp /etc/sysconfig/<br />chmod 640 /etc/chrony.conf<br />chmod 644 /etc/adjtime<br />chmod 644 /etc/sysconfig/clock<br />chmod 640 /etc/ntp.conf<br />chmod 644 /etc/sysconfig/ntp<br />chown root:chrony /etc/chrony.conf<br />chown root:root /etc/adjtime<br />chown root:root /etc/sysconfig/clock<br />chown root:root /etc/ntp.conf<br />chown root:root /etc/sysconfig/ntp<br /></pre></div></li><li><b>NETWORK</b>: Una configuración de red que suelo pre-configurar en la imagen es la relacionada con el IP Forwarding, que en openSUSE la encontramos en el archivo <b>sysctl.conf</b> del directorio <b>/etc</b> (la configuración de la dirección IP y demás la veremos más adelante). Siguiendo la tradición de organizar todo bajo el directorio <b>kiwifiles</b>, creamos la carpeta <b>network</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él copiamos el mencionado archivo:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/network<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/sysctl.conf ~/mysuseleap-15.2/root/kiwifiles/os/network</span><br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las directivas de copiado y seteo de siempre:<div><pre><font color="#3d85c6"><b># --> Configuración de <Network><br /></b></font>cp /kiwifiles/os/network/sysctl.conf /etc/<br />chmod 644 /etc/sysctl.conf<br />chown root:root /etc/sysctl.conf</pre></div></li><li><b>SYSCONFIG</b>: Creamos la carpeta <b>sysconfig</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> :<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/sysconfig</span></pre>Y en él copiamos los archivos de configuración del directorio <b>/etc/sysconfig</b> que necesitamos, que en mi caso suelo incluir el archivo de configuración <b>displaymanager</b> que lleva seteado de forma personalizada las siguientes directivas:<br /><pre><b>DISPLAYMANAGER_REMOTE_ACCESS="yes"<br />DISPLAYMANAGER_ROOT_LOGIN_REMOTE="yes"<br />DISPLAYMANAGER_AUTOLOGIN="gabriel"</b></pre>y el archivo <b>keyboard</b> que lleva personalizada la directiva <b>KBD_NUMLOCK</b> como se observa a continuación:<br /><pre><span style="background-color: white;"><b>KBD_NUMLOCK="yes"</b></span><br /></pre>Podemos copiar los archivos del directorio <b>/etc/sysconfig</b> a partir del servidor que usamos para construir la imagen:<br /><pre><span style="background-color: white;"><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/sysconfig/displaymanager ~/mysuseleap-15.2/root/kiwifiles/os/sysconfig</span><br /></span><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>cp /etc/sysconfig/keyboard ~/mysuseleap-15.2/root/kiwifiles/os/sysconfig</span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las directivas de copiado y seteos correspondientes:<div><pre><font color="#3d85c6"><b># --> Configuración de <Sysconfig><br /></b></font>cp /kiwifiles/os/sysconfig/displaymanager /etc/sysconfig/<br />cp /kiwifiles/os/sysconfig/keyboard /etc/sysconfig/<br />chmod 644 /etc/sysconfig/displaymanager<br />chmod 644 /etc/sysconfig/keyboard<br />chown root:root /etc/sysconfig/displaymanager<br />chown root:root /etc/sysconfig/keyboard</pre></div></li><li><b>ARTWORK</b>: A un sistema operativo personalizado no le puede faltar un <b>artwork</b> que no sea personalizado. Yo he llegado a crear <b>iconos</b> (en formato png), así como <b>fondos de pantalla</b> y <b>fondos para la ventana de logueo</b> personalizados. Si creamos fondos de pantallas (wallpapers) es importante crear diferentes tamaños de imagen para que se adapten automáticamente a la resolución de nuestro monitor, deberían tener las extensión <b>jpg</b> con nombres similar a los siguientes: 1024x768.jpg, 1280x1024.jpg, 1280x800.jpg, 1366x768.jpg, 1440x900.jpg, 1600x1200.jpg, 1638x1024.jpg, 1680x1050.jpg, 1920x1080.jpg, 1920x1200.jpg, 2560x1440.jpg, 2560x1600.jpg, 3200x1800.jpg, 3200x2000.jpg y 3840x2160.jpg.<br /><br />La estructura que utilicé para organizar todo fue crear la carpeta <b>artwork</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él crear otras tres subcarpetas: <b>icons</b>, <b>loginscreen</b> y <b>wallpapers</b>. En la subcarpeta <b>icons</b> van los iconos con extensión png, en la subcarpeta <b>loginscreen</b> las imagen personalizada con extensión jpg para la pantalla de logueo, y en la subcarpeta <b>wallpapers</b> todas las imágenes jpg diseñados para dicho fin:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/artwork<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>mkdir ~/mysuseleap-15.2/root/kiwifiles/os/artwork/icons<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>mkdir ~/mysuseleap-15.2/root/kiwifiles/os/artwork/loginscreen<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>mkdir ~/mysuseleap-15.2/root/kiwifiles/os/artwork/wallpapers</span></span></span><br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las directivas de copiado y seteos similares a lo que sigue:<div><pre><font color="#3d85c6"><b># --> Configuración de <Artwork><br /></b></font>mkdir -p /usr/share/icons/tdbsuse/<br />cp -f /kiwifiles/os/artwork/wallpapers/*.jpg /usr/share/wallpapers/openSUSEdefault/contents/images/<br />cp /kiwifiles/os/artwork/loginscreen/login-screen.jpg /usr/share/sddm/themes/breeze-openSUSE<br />cp /kiwifiles/os/artwork/icons/*.png /usr/share/icons/tdbsuse/<br />chmod 644 /usr/share/wallpapers/openSUSEdefault/contents/images/*.jpg<br />chmod 644 /usr/share/sddm/themes/breeze-openSUSE/login-screen.jpg<br />chmod 644 /usr/share/icons/tdbsuse/*.png<br />chown root:root /usr/share/wallpapers/openSUSEdefault/contents/images/*.jpg<br />chown root:root /usr/share/sddm/themes/breeze-openSUSE/login-screen.jpg<br />chown root:root /usr/share/icons/tdbsuse/*.png</pre></div></li><li><b>SDDM</b>: Podemos realizar algunos cambios al gestor de pantallas (Simple Desktop Display Manager). A continuación vamos a configurar el fondo de pantalla de la pantalla de desbloqueo de usuarios, para lo cual creamos la carpeta <b>sddm</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b> y en él creamos el archivo <b>theme.conf.user</b> para luego editarlo:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/sddm<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>touch </span></span>~/mysuseleap-15.2/root/kiwifiles/os/sddm/theme.conf.user<br /><span style="background-color: white;"><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>vim </span></span>~/mysuseleap-15.2/root/kiwifiles/os/sddm/theme.conf.user</pre>Una vez abierto el archivo <b>theme.conf.user</b> le agregamos el siguiente contenido, donde se destaca la directiva <b>background</b> a la que se le asigna el nombre del archivo de imagen <b>login-screen.jpg</b> que se usará como fondo del SDDM, y que en el paso anterior ya habíamos copiado al directorio <b>/usr/share/sddm/themes/breeze-openSUSE</b>:<div><pre>[General]<br />background=login-screen.jpg<br />type=image</pre></div>Ahora solo nos resta guardar los cambios y editar el archivo <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Al cual le agregamos las siguientes directivas de configuración:<div><pre><font color="#3d85c6"><b># --> Configuración de <SDDM><br /></b></font>mkdir -p /usr/share/sddm/themes/breeze-openSUSE<br />cp /kiwifiles/os/sddm/theme.conf.user /usr/share/sddm/themes/breeze-openSUSE<br />chmod 644 /usr/share/sddm/themes/breeze-openSUSE/theme.conf.user<br />chown root:root /usr/share/sddm/themes/breeze-openSUSE/theme.conf.user</pre></div></li><li><b>FIRSTBOOT</b>: Esta funcionalidad nos permite personalizar el primer arranque de nuestro sistema operativo luego de que se haya instalado en una PC o en una máquina virtual. Comenzamos por crear la carpeta <b>firstboot</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b>, para luego copiar en él el archivo <b>firstboot.xml</b> y crear el archivo nuevo <b>customs-after-firstboot</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/os/firstboot<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> cp /etc/YaST2/firstboot.xml</span><span> ~/mysuseleap-15.2/root/kiwifiles/os/firstboot/firstboot.xml<br /><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>touch ~/mysuseleap-15.2/root/kiwifiles/os/firstboot</span></span></span>/customs-after-firstboot</pre>Comenzamos por editar el archivo <b>firstboot.xml</b>:<br /><pre><span style="background-color: white;"><span style="color: #ff5454; font-weight: bold;">kiwi:~ #</span><span> </span><span>vim ~/mysuseleap-15.2/root/kiwifiles/os/firstboot/firstboot.xml</span></span></pre>La configuración del archivo <b>firstboot.xml</b> permite indicarle al <b>módulo firstboot de YaST</b> que interfaces de configuración deben mostrarse durante el primer arranque del sistema operativo. La configuración debería quedar similar a lo que sigue (para más información pueden consultar <a href="https://en.opensuse.org/YaST_Firstboot" target="_blank">éste enlace</a>):<br /><pre><b><?xml </b>version="1.0"?<b>><br /><productDefines <span style="color: #38761d;">xmlns=</span><span style="color: red;">"http://www.suse.com/1.0/yast2ns"</span><br /> <span style="color: #38761d;">xmlns:config=</span><span style="color: red;">"http://www.suse.com/1.0/configns"</span>><br /><br /></b><span style="color: #666666;"><span style="font-weight: bold;"> </span> <!--<br /> $Id$<br /> Work around for the text domain<br /> textdomain="firstboot"<br /> --></span><br /><br /> <b> <textdomain></b>firstboot<b></textdomain><br /><br /> <globals></b><br /><br /><span style="background-color: white;"><span style="color: #666666;"><b style="color: black;"> </b><!--<br /><b style="color: black;"> </b>If a variable root_password_as_first_user is present in globals section,<br /><b style="color: black;"> </b>inst_user step will have the check box<br /><b style="color: black;"> </b> "Use this password for system administrator"<br /><b style="color: black;"> </b>so you don't need to include root password step (fate#306297).<br /><b style="color: black;"> </b>If the variable is missing (commented), the check box won't appear.<br /><br /><b style="color: black;"> </b>The value of the variable (true/false) will set the default value for the check box.<br /><b style="color: black;"> </b><root_password_as_first_user config:type="boolean">true</root_password_as_first_user><br /><b style="color: black;"> </b> --><br /><br /><b style="color: black;"> </b><!-- The default value of "Automatic Login" checkbox --></span></span><br /><b><b> </b><enable_autologin <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span>></b>false<b></enable_autologin></b><br /><br /><span style="color: #666666;"><b style="color: black;"> </b><!--<br /><b style="color: black;"> </b>For more variables that can be in this section, look into the control file<br /><b style="color: black;"> </b>(/etc/YaST2/control.xml or root directory of installation media)<br /><b style="color: black;"> </b>--><br /><br /><b style="color: black;"> </b><!--<br /><b style="color: black;"> </b>Definition of Automatic Configuration Steps follows - each step<br /><b style="color: black;"> </b>runs non-interactive configuration. To enable steps defined in<br /><b style="color: black;"> </b>Automatic Configuration, enable inst_automatic_configuration in the<br /><b style="color: black;"> </b>workflow.<br /><b style="color: black;"> </b>--></span><br /><b><b> </b><automatic_configuration <b><span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span></b><b>></b><br /></b><b> </b> <span style="color: #666666;"><!-- Configure network --></span><br /><b><b> </b> <ac_step><br /><b> </b><b> </b><b><text_id></b>ac_label_1<b></text_id></b><br /></b><b><b> </b><b> </b><b><icon></b>yast-lan<b></icon></b><br /></b><b><b> </b><b> </b><b><type></b>proposals<b></type></b><br /></b><b><b><b> </b> </b><b><ac_items <b><span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span></b><b>></b></b><br /><b><b> </b> </b><b> <ac_item></b>lan<b></ac_item></b><br /></b><b><b><b> </b> </b><b></ac_items></b><br /><b> </b> </ac_step></b><br /><b> </b> <span style="color: #666666;"><!--<br /><b style="color: black;"> </b> Configure printer (needs configured network for net-detection)<br /><b style="color: black;"> </b> --></span><br /><b> </b> <b> <ac_step><br /><b> </b><b> </b><b><text_id></b>ac_label_2<b></text_id></b><br /></b><b><b> </b><b> </b><b><icon></b>yast-hwinfo<b></icon></b><br /></b><b><b><b> </b> </b><b><type></b>proposals<b></type></b><br /></b><b><b><b> </b> </b><b><ac_items <b><span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span></b><b>></b></b><br /><b> </b><b> </b><b> <ac_item></b>printer<b></ac_item></b><br /></b><b><b> </b><b> </b><b></ac_items></b><br /><b> </b> </ac_step><br /><b> </b></automatic_configuration><br /> </globals><br /> <proposals <b><span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span></b><b>></b><br /> <proposal><br /> <name></b>firstboot_hardware<b></name><br /> <mode></b>installation<b></mode><br /> <stage></b>firstboot<b></stage><br /> <label></b>Hardware Configuration<b></label><br /> <proposal_modules <b><span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span></b><b>></b><br /> <proposal_module></b>printer<b></proposal_module><br /> </proposal_modules><br /> </proposal><br /> </proposals><br /> <workflows <b><span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span></b><b>></b><br /> <workflow><br /> <defaults><br /> <enable_back></b>yes<b></enable_back><br /> <enable_next></b>yes<b></enable_next><br /> <archs></b>all<b></archs><br /> </defaults><br /> <stage></b>firstboot<b></stage><br /> <label></b>Configuration<b></label><br /> <mode></b>installation<b></mode><br /> <modules <span style="color: #38761d;">config:type=</span><span style="color: red;">"list"</span>></b><br /><span style="color: #666666;"> <!-- <module><br /> <label>Network Autosetup</label><br /> <name>firstboot_setup_dhcp</name><br /> </module> --></span><br /><b style="font-weight: bold;"> <module><br /> <label></b>Language and Keyboard<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /></b> <span style="color: #666666;"><!-- step for configuration of both language and keyboard layout (fate#306296) --></span><br /> <b style="font-weight: bold;"> <name></b>firstboot_language_keyboard<b style="font-weight: bold;"></name><br /> </module><br /> <module><br /> <label></b>Language<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b style="font-weight: bold;"><br /> <name></b>firstboot_language<b style="font-weight: bold;"></name><br /> </module><br /> <module><br /> <label></b>Keyboard Layout<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> <name></b>firstboot_keyboard<b></name><br /> </module></b><br /> <span style="color: #666666;"> <!-- <module><br /> <label>Welcome</label><br /> <name>firstboot_welcome</name><br /> </module> --></span><br /> <b style="font-weight: bold;"> <module><br /> <label></b>License Agreement<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b style="font-weight: bold;"><br /> <name></b>firstboot_licenses<b style="font-weight: bold;"></name><br /> </module></b><b><br /> <module></b><br /> <span><span style="color: #666666;"><!-- Rutina firstboot no compatible en openSUSE 15.2 --><br /> </span><b><label></b>Host Name<b></label></b></span><b style="font-weight: bold;"><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> <name></b>firstboot_hostname<b></name><br /> </module><br /> <module><br /> <label></b>Network<b></label></b><br /> <span style="color: #666666;"><!-- this step only restarts service 'network' --></span><br /> <b> <name></b>firstboot_network_write<b></name><br /> <enabled </b><b style="font-weight: bold;"><span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> </module><br /> <module><br /> <enabled </b><b style="font-weight: bold;"><span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> <name></b>firstboot_ssh<b></name><br /> </module><br /> <module><br /></b><span style="color: #666666;"> <!-- <label>Network</label> --></span><b><br /> <label></b>Configuración de Red<b></label><br /> <name></b>inst_lan<b></name><br /> <enabled </b><b style="font-weight: bold;"><span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>true<b style="font-weight: bold;"></enabled><br /></b><b> <span style="background-color: #fcff01;"><arguments></span><br /> <span style="background-color: #fcff01;"> <skip_detection></span></b><span style="background-color: #fcff01;">true</span><b><span style="background-color: #fcff01;"></skip_detection></span><br /> <span style="background-color: #fcff01;"></arguments></span><br /> </module><br /> <module><br /> <label></b>Automatic Configuration<b style="font-weight: bold;"></label><br /> <name></b>inst_automatic_configuration<b style="font-weight: bold;"></name><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b style="font-weight: bold;"><br /> </module><br /> <module><br /> <label></b>Time and Date<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b style="font-weight: bold;"><br /> <name></b>firstboot_timezone<b style="font-weight: bold;"></name><br /> </module><br /> <module><br /> <label></b>NTP Client<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b style="font-weight: bold;"><br /> <name></b>firstboot_ntp<b style="font-weight: bold;"></name><br /> </module><br /> <module><br /> <label></b>Desktop<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> <name></b>firstboot_desktop<b></name><br /> </module></b><br /> <span style="color: #666666;"> <!-- <module><br /> <label>Network</label><br /> <name>inst_lan</name><br /> <enabled config:type="boolean">false</enabled><br /> </module> --></span><br /><b style="font-weight: bold;"> <module><br /> <label></b>Users<b style="font-weight: bold;"></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> <name></b>firstboot_user<b></name><br /> </module></b><br /><span><b><span style="color: #666666;"> </span> <module><br /> <label></b>Root Password<b></label><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span>></b>false<b></enabled><br /> <name></b>firstboot_root<b></name><br /> </module></b></span><br /> <b> <module><br /> <label></b>Customer Center<b></label><br /> <name></b>registration<b style="font-weight: bold;"></name><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span></b><b style="font-weight: bold;">></b>false<b style="font-weight: bold;"></enabled></b><b><br /> </module><br /> <module><br /> <label></b>Hardware<b></label><br /> <name></b>inst_proposal<b></name><br /> <enabled <span style="color: #38761d;">config:type=</span><span style="color: red;">"boolean"</span>></b>false<b></enabled><br /> <proposal></b>firstboot_hardware<b></proposal><br /> </module><br /> <module></b><br /> <span style="color: #666666;"><!-- <label>Finish Setup</label> --></span><br /> <b> <label></b>Configuración Final<b></label><br /> <name></b>firstboot_write<b></name><br /> <enable_back></b>no<b></enable_back><br /> <enable_next></b>no<b></enable_next><br /> </module></b><br /><span style="color: #666666;"> <!-- <module><br /> <label>Finish Setup</label><br /> <name>inst_congratulate</name><br /> <enable_back>yes</enable_back><br /> <enable_next>yes</enable_next><br /> </module> --></span><br /><b><br /> </modules><br /> </workflow><br /> </workflows><br /><b> </b><texts></b><br /><span style="color: #666666;"><b style="color: black;"> </b><!--<br /><b style="color: black;"> </b>Labels used during Automatic Configuration: use "text_id" from "ac_step"<br /><b style="color: black;"> </b>--></span><br /><b><b> </b><ac_label_1><label></b>Configuring network...<b></label></ac_label_1></b><br /><b><b> </b><ac_label_2><label></b>Configuring hardware...<b></label></ac_label_2></b><br /><b><b><b> </b></b></texts><br /></productDefines></b><br /></pre><b>OBS:</b> En la sección de la rutina <b>inst_lan</b> (<span style="background-color: #fcff01;">resaltada en amarillo</span>) se le tuvo que agregar el argumento <b><skip_detection>true</skip_detection></b> para permitir que el usuario pueda <b>realizar la configuración manual de la red</b> durante el primer arranque del sistema operativo, algo que en las versiones previas de openSUSE no era requerido y que tampoco se menciona como una observación en el archivo original <b>firstboot.xml</b> del directorio <b>/etc/YaST2</b> de cualquier instalación oficial de openSUSE 15.2.<br /><br />Para identificar cual era la causa del porque la rutina<b> inst_lan</b> del archivo <b>firstboot.xml</b> no funcionaba como yo esperaba, tuve que verificar el código del programa <b>inst_lan.rb</b> de YaST2 ubicado en el directorio <b>/usr/share/YaST2/clients</b> (donde también están los programas de las demás rutinas), código que a su vez hacía referencia al archivo <span style="background-color: white;"><b>inst_lan.rb</b> pero del directorio </span><span style="background-color: white;"><b>/usr/share/YaST2/lib/network/clients</b>. Dentro de este último archivo los programadores pusieron la siguiente aclaración que trajo la luz luego de <b>varias semanas de pruebas:</b></span> <pre><span style="color: #666666;"> # Client for configuring the network during installation.<br /> #<br /> # If the network configuration is managed by NetworkManager or some<br /> # connection config is already present the client skip the configuration<br /> # sequence.<br /> #<br /> # The configuration sequence can be forced passing the 'skip_detection'<br /> # argument.<br /> #<br /> # @example calling the client forcing the configuration sequence<br /> # Yast::WFM.CallFunction("inst_lan", [args.merge("skip_detection" => true)])<br /> #<br /> # @example firsboot xml forcing the configuration sequence<br /> # <module><br /> # <label>Network</label><br /> # <name>inst_lan</name><br /> # <arguments><br /> # <skip_detection>true</skip_detection><br /> # </arguments><br /> # </module></span></pre>En fin, volviendo al tema pasamos a editar el archivo <b>customs-after-firstboot:<br /></b><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> vim </span><span style="background-color: white;"><span><span>~/mysuseleap-15.2/root/kiwifiles/os/firstboot</span></span></span>/customs-after-firstboot</pre>Al que le podemos agregar un script bash similar al que sigue, que se ejecutará una sola vez durante el primer arranque del sistema operativo:<div><pre><span style="color: #666666;">#!/bin/bash</span><br /><br /><b>echo ""<br />echo "============================================"<br />echo "STARTING CUSTOMS SCRIPT AFTER FIRSTBOOT!!"<br />echo "============================================"</b><br /><br /><span style="color: #666666;"># Creación del usuario gabriel y expiración de contraseña inicial gabrielpass.</span><br /><b>/usr/sbin/useradd --create-home --comment Gabriel -g users -G dialout -p $(/usr/bin/perl -e'print crypt("gabrielpass", "SALT_text")') gabriel</b><br /><span style="background-color: white;"><b><br /></b><span style="color: #666666;"># Expira la contraseña por defecto del y solicita el cambio (Opción no soportada por SDDM)<b><br />#/usr/bin/passwd </b></span></span><span style="background-color: white; color: #666666; font-weight: bold;">--expire gabriel</span><br /><br /><span style="color: #666666;"># Configuracion del servicio xinetd.</span><br /><b>systemctl enable xinetd.service<br />systemctl start xinetd.service</b><br /><br /><span style="color: #666666;"># Configuración del fecha y hora</span><br /><b>systemctl enable chronyd.service<br />systemctl restart chronyd.service</b><br /><br /><span style="background-color: white; color: #666666;"># Configuracion del servicio Cups.</span><br /><b>systemctl enable cups.service<br />systemctl start cups.service</b><br /><br /><span style="background-color: white;"><span style="color: #666666;"># Configuracion del servicio Samba.</span></span><br /><b>systemctl enable smb.service<br />systemctl enable nmb.service<br />systemctl start smb.service<br />systemctl start nmb.service</b><br /><br /><span style="color: #666666;"># Configuración del firewall</span><br /><b>systemctl enable firewalld.service<br />systemctl start firewalld.service</b><br /><br /><span style="color: #666666;"># Se agregan entradas al archivo /etc/hosts para los sistemas.</span><br /><b>/bin/echo "192.168.1.222 miServidor" >> /etc/hosts</b><br /><br /><span style="color: #666666;"># Se comenta la linea de la IP local 127.0.0.2</span><br /><b>/bin/sed -i "s/127.0.0.2/#127.0.0.2/g" /etc/hosts</b><br /><br /><span style="color: #666666;"># Configuracion de prioridades del JRE (Oracle).</span><br /><b>/usr/sbin/update-alternatives --remove-all java<br />/usr/sbin/update-alternatives --install /usr/bin/java java /usr/java/jre1.8.0_261-amd64/bin/java 100<br />/usr/sbin/update-alternatives --install /usr/lib64/browser-plugins/libjavaplugin.so libjavaplugin.so.x86_64 /usr/java/jre1.8.0_261-amd64/lib/amd64/libnpjp2.so 20000</b><br /><br /><span style="color: #666666;"># Se cambia el grub a español y luego se cambia el timeout a solo 1 segundo.</span><br /><b>LANG=es_ES grub2-mkconfig -o /boot/grub2/grub.cfg<br />/bin/sed -i 's/timeout=10/timeout=1/g' /boot/grub2/grub.cfg</b><br /><br /><span style="color: #666666;"># Finalmente se elimina el script customs-after-firstboot.</span><br /><b>/bin/rm -f /usr/share/firstboot/scripts/customs-after-firstboot</b><br /><br /><b>echo "============================================"<br />echo "FINISH CUSTOMS SCRIPT AFTER FIRSTBOOT!!"<br />echo "============================================"<br />echo ""</b></pre></div><b>OBS:</b> El motivo por el cual los servicios como <b>samba</b>, <b>cups</b>, <b>xinetd</b>, etc. se activan e inician desde el script <b>customs-after-firstboot</b> y no desde el script <b>config.sh</b> se debe al orden de ejecución de las directivas del archivo <b>config.sh</b>, primero se estarían arrancando los servicios y luego se estarían configurando, por lo que las configuraciones no estarían activas hasta tanto se reinicie el sistema operativo. Si bien existe la posibilidad de modificar el orden en que se realizan las configuraciones dentro del script <b>config.sh</b>, es interesante mostrar el potencial que permite la utilización del script <b>customs-after-firstboot</b>.<br /><br />Finalmente haremos la última edición al script <b>config.sh</b> en este apartado:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script le agregamos las directivas de copiado y seteos similares a lo que sigue:<div><pre><font color="#3d85c6"><b># --> Configuración de <Firstboot><br /></b></font>cp /etc/YaST2/firstboot.xml /etc/YaST2/firstboot.xml.orig<br />cp /kiwifiles/os/firstboot/firstboot.xml /etc/YaST2/<br />cp /kiwifiles/os/firstboot/customs-after-firstboot /usr/share/firstboot/scripts<br />touch /var/lib/YaST2/reconfig_system<br />chmod 644 /etc/YaST2/firstboot.xml<br />chmod 755 /usr/share/firstboot/scripts/customs-after-firstboot<br />chown root:root /etc/YaST2/firstboot.xml<br />chown root:root /usr/share/firstboot/scripts/customs-after-firstboot<br /></pre></div></li><li>Y con esto terminamos el apartado de personalizaciones relacionadas con configuraciones del sistema operativo.</li></ol><div><br /></div> <div><h3>Personalización del entorno de usuario:</h3>En mis primeros intentos solía hacer cambios a archivos de configuraciones del entorno de uno de los usuarios ya creados previamente, pero el inconveniente de este enfoque es que al momento de crear un nuevo usuario desde la línea de comandos o desde YaST ninguna de estas configuraciones se pasaban al nuevo usuario.</div><div><br /></div><div>Investigando más sobre el tema pude averiguar que la <b>configuración inicial de cualquier usuario</b> que se crea está basado en la estructura de directorios y de configuración del directorio <b>/etc/skel</b>, entre otros directorios que veremos a continuación:</div><div><ol><li><b>Configuraciones de x11vnc en /etc/skel</b>: Todo lo que agreguemos bajo este directorio se agregará automáticamente al <b>home</b> de un usuario al crearlo. Me gusta que al crear un usuario ya esté la configuración del servicio VNC, para lo cual suelo crear el directorio <b>vnc</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/user </b>y copiar adentro los archivos de configuración requeridos por la aplicación <b>x11vnc</b>: <b>passwd</b>, <b>x11vnc.desktop</b> y <b>x11vncrc</b><br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/user/vnc<br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y bien al final del script le agregamos las siguientes directivas que crean las subcarpetas requeridas dentro del directorio <b>/etc/skel</b>, copian los archivos de configuración y configuran los permisos y el dueño de los archivos, que dentro de <b>skel</b> es <b>root</b>.<div><pre><font color="#3d85c6"><b># ==================================================================<br /># User Configuration<br /># ==================================================================<br /><br /># --> Configuración de <VNC><br /></b></font>mkdir -p /etc/skel/.config/autostart/<br />mkdir -p /etc/skel/.vnc<br />cp /kiwifiles/user/vnc/passwd /etc/skel/.vnc<br />cp /kiwifiles/user/vnc/x11vncrc /etc/skel/.x11vncrc<br />cp /kiwifiles/user/vnc/x11vnc.desktop /etc/skel/.config/autostart/<br />chmod -Rf 700 /etc/skel/.vnc<br />chmod -Rf 600 /etc/skel/.vnc/passwd<br />chmod 644 /etc/skel/.x11vncrc<br />chmod 755 /etc/skel/.config/autostart/x11vnc.desktop<br />chown -Rf root:root /etc/skel/.vnc<br />chown root:root /etc/skel/.x11vncrc<br />chown -Rf root:root /etc/skel/.config/autostart</pre></div></li><li><b><b>Configuraciones de Java en </b>/etc/skel</b>: A veces necesitamos que nuestro entorno Java ya esté pre configurado para cualquier usuario, para ello podemos almacenar todos los archivos de configuración y certificados en la carpeta <b>java</b> creada dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/user</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/user/java<br /></span></pre>Editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y bien al final le agregamos las directivas para crear nuevas subcarpetas en <b>/etc/skel</b> requeridas por Java, en las cuales luego se copian los archivos de configuración de Java:<div><pre><font color="#3d85c6"><b># --> Configuración de <Java><br /></b></font>mkdir -p /etc/skel/.java/deployment/security<br />cp /kiwifiles/user/java/deployment.properties /etc/skel/.java/deployment/<br />cp /kiwifiles/user/java/exception.sites /etc/skel/.java/deployment/security<br />cp /kiwifiles/user/java/trusted.cacerts /etc/skel/.java/deployment/security<br />cp /kiwifiles/user/java/trusted.certs /etc/skel/.java/deployment/security<br />chmod -Rf 755 /etc/skel/.java<br />chmod 644 /etc/skel/.java/deployment/deployment.properties<br />chmod 644 /etc/skel/.java/deployment/security/exception.sites<br />chmod 644 /etc/skel/.java/deployment/security/trusted.cacerts<br />chmod 644 /etc/skel/.java/deployment/security/trusted.certs<br />chown -Rf root:root /etc/skel/.java</pre></div></li><li><b><b><b>Configuraciones de Konsole en</b> </b>/etc/skel</b>: Muchas cosas podemos personalizar en la aplicación Konsole, podemos agregar un nuevo perfil de usuario que configure las funciones por defectos de teclas, esquema de colores, etc. Todos estos archivos los metemos en la carpeta <b>konsole</b> creada dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/user</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/user/konsole<br /></span></pre>Editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span>vim ~/mysuseleap-15.2/config.sh</pre>Y bien al final le agregamos las directivas para crear subcarpetas y copiar los archivos de configuración en los directorios correspondientes:<div><pre><font color="#3d85c6"><b># --> Configuración de <Konsole<b>></b><br /></b></font>mkdir -p /etc/skel/.local/share/konsole/<br />cp /kiwifiles/user/konsole/konsoleui.rc /etc/skel/.local/share/konsole/<br />cp /kiwifiles/user/konsole/myprofile.keytab /etc/skel/.local/share/konsole/<br />cp /kiwifiles/user/konsole/myprofile.profile /etc/skel/.local/share/konsole/<br />cp /kiwifiles/user/konsole/WhiteOnBlack.colorscheme /etc/skel/.local/share/konsole/<br />cp /kiwifiles/user/konsole/konsolerc /etc/skel/.config<br />chmod -Rf 700 /etc/skel/.local<br />chmod 644 /etc/skel/.local/share/konsole/konsoleui.rc<br />chmod 644 /etc/skel/.local/share/konsole/myprofile.keytab<br />chmod 644 /etc/skel/.local/share/konsole/myprofile.profile<br />chmod 644 /etc/skel/.local/share/konsole/WhiteOnBlack.colorscheme<br />chmod 600 /etc/skel/.config/konsolerc<br />chown -Rf root:root /etc/skel/.local<br />chown root:root /etc/skel/.config/konsolerc</pre></div></li><li><b><b>Configuraciones de <b>KDE en</b> </b>/etc/skel</b>: En los entornos de usuario de mis sistemas operativos personalizados me gusta inhabilitar Kwallet (no hay peor molestia) y configurar el bloqueo automático de la pantalla por inactividad del usuario. Para ello dentro de la carpeta <b>kde</b> creada dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/user</b> ubicamos los archivos de configuración personalizados <b>kwalletrc</b> y <b>kscreenlockerrc</b>. <pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/user/kde<br /></span></pre>Editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y bien al final le agregamos las directivas que copian los archivos de configuración <b>kwalletrc </b>y <b>kscreenlockerrc</b> a sus debidos directorios dentro del directorio esqueleto.<div><pre><font color="#3d85c6"><b># --> Configuración de <Kde<b>></b><br /></b></font>cp /kiwifiles/user/kde/kwalletrc /etc/skel/.config<br />cp /kiwifiles/user/kde/kscreenlockerrc /etc/skel/.config</pre></div></li><li><b>Configuraciones de PLASMA en /usr/share/plasma</b>: ¿Que tal si nos gustaría pre configurar la altura de la barra de KDE? ¿Agregar y quitar widgets del escritorio? Para ello hay que modificar los archivos .js de Plasma <b>layout.js</b> y <b>org.kde.plasma.desktop-layout.js</b>, donde el primero permite configurar el aspecto del escritorio, como la altura de la barra (panel en términos de KDE) y su composición, agregando, reemplazando y/o quitando widgets:<br /><pre><span style="background-color: white;"><span style="color: #666666;">// -- OBS: Aumento del tamaño del panel inferior a 2.5.<br />//panel.height = gridUnit * 2<br /></span><b>panel.height = gridUnit * 2.5<br /><br /></b><span style="color: #666666;">// -- OBS: Se ha reemplazado el tipo de lanzador del menú de aplicaciones<br />// predefinido "kickoff" por el más sencillo "kicker".<br />//var kickoff = panel.addWidget("org.kde.plasma.kickoff")</span><br /><b>var kickoff = panel.addWidget("org.kde.plasma.kicker")<br />kickoff.currentConfigGroup = ["Shortcuts"]<br />kickoff.writeConfig("global", "Alt+F1")<br /></b><br /><span style="color: #666666;">// -- OBS: Se comenta la directiva que agrega el widget <br />// Activity Manager que es poco útil para la mayoría.<br />//panel.addWidget("org.kde.plasma.showActivityManager")</span><br /><b>panel.addWidget("org.kde.plasma.pager")<br />panel.addWidget("org.kde.plasma.taskmanager")</b><br /></span></pre>Y el segundo bloquear por defecto la modificación de los mismo agregando el código que sigue a continuación:<br /><pre><span style="background-color: white;"><span style="color: #666666;">// -- OBS: Bloqueo automático de widgets.</span><b><br />sleep(2);<br />locked = true;</b><br /></span></pre>Una vez personalizados dichos archivos .js lo mejor es ubicarlos dentro del directorio <b>plasma</b> previamente creado dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/user</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/user/plasma<br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y al final del script agregamos las directivas de copiado y seteo correspondientes:<div><pre><font color="#3d85c6"><b># --> Instalación de <Plasma><br /></b></font>cp -b /kiwifiles/user/plasma/layout.js /usr/share/plasma/layout-templates/org.opensuse.desktop.defaultPanel/contents/<br />cp -b /kiwifiles/user/plasma/org.kde.plasma.desktop-layout.js /usr/share/plasma/look-and-feel/org.openSUSE.desktop/contents/layouts/<br />chmod 644 /usr/share/plasma/layout-templates/org.opensuse.desktop.defaultPanel/contents/layout.js<br />chmod 644 /usr/share/plasma/look-and-feel/org.openSUSE.desktop/contents/layouts/org.kde.plasma.desktop-layout.js<br />chown root:root /usr/share/plasma/layout-templates/org.opensuse.desktop.defaultPanel/contents/layout.js<br />chown root:root /usr/share/plasma/look-and-feel/org.openSUSE.desktop/contents/layouts/org.kde.plasma.desktop-layout.js</pre></div></li><li><b>Configuraciones de accesos directos en /usr/share/kio_desktop</b>: A mi me gusta que el usuario ya cuente con una serie de accesos directos a aplicaciones importantes y útiles en su escritorio. Si hemos creado nuestros propios accesos directos lo mejor sería colocarlos en la carpeta <b>desktop</b>, que la podemos crear dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles/os</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">mkdir ~/mysuseleap-15.2/root/kiwifiles/user/desktop<br /></span></pre>Luego editamos el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y bien al final del script <b>config.sh</b> agregamos las siguientes directivas para que al crear un nuevo usuario automáticamente aparezcan en su escritorio nuestros accesos personalizados (en el ejemplo cups.desktop y tdb.desktop) y aquellos ya existentes dentro del OS como suelen ser los accesos directos de Konsole, Calc y Writer de Libre Office, Firefox, entre otros.<div><pre><font color="#3d85c6"><b># --> Instalación de <Desktop App Links><br /></b></font>cp /kiwifiles/user/desktop/tdb.desktop /usr/share/kio_desktop/DesktopLinks<br />cp /kiwifiles/user/desktop/cups.desktop /usr/share/kio_desktop/DesktopLinks<br />cp /usr/share/applications/org.kde.konsole.desktop /usr/share/kio_desktop/DesktopLinks/konsole.desktop<br />cp /usr/share/applications/org.kde.kwrite.desktop /usr/share/kio_desktop/DesktopLinks/kwrite.desktop<br />cp /usr/share/applications/org.kde.kcalc.desktop /usr/share/kio_desktop/DesktopLinks/kcalc.desktop<br />cp /usr/share/applications/calc.desktop /usr/share/kio_desktop/DesktopLinks<br />cp /usr/share/applications/writer.desktop /usr/share/kio_desktop/DesktopLinks<br />cp /usr/share/applications/firefox.desktop /usr/share/kio_desktop/DesktopLinks<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/tdb.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/cups.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/konsole.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/kwrite.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/kcalc.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/calc.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/writer.desktop<br />chmod 744 /usr/share/kio_desktop/DesktopLinks/firefox.desktop<br />chown root:root /usr/share/kio_desktop/DesktopLinks/tdb.desktop<br />chown root:root /usr/share/kio_desktop/DesktopLinks/cups.desktop</pre></div></li><li>Y eso es todo por el momento en esta sección, ya dependerá de cada quien adaptar los ejemplos anteriores a sus propias necesidades.</li></ol></div><div><div><h3><br /></h3><h3>Personalizaciones adicionales:</h3></div><div><ol><li><b>Rehashing SSL Certificates</b>: Esta configuración proviene de la herramienta web SUSE Studio, que al final del archivo <b>config.sh</b> agregaba la llamada al comando <b>c_rehash</b>, que en teoría sirve para actualizar los enlaces simbólicos de cada archivo .pem, .crt, .cer, o .crl presentes en la imagen empaquetada del OS.<br /><br />Para agregar la llamada a dicho comando comenzamos por editar el script <b>config.sh</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.sh</span></pre>Y agregar el siguiente script:<br /><div><pre><font color="#3d85c6"><b># ==================================================================<br /># SSL Certificates Configuration<br /># ==================================================================<br /></b></font>echo '** Rehashing SSL Certificates...'<br />c_rehash</pre></div></li><li><b>motd</b>: Si cada vez que nos conectemos por <b>ssh</b> al equipo queremos que en pantalla nos muestre un mensaje de bienvenida luego de loguearnos, podemos editar el archivo <b>motd</b> ubicado en el directorio <b>~/mysuseleap-15.2/root/etc</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/root/etc/motd</span></pre>Al que por ejemplo le podríamos agregar un mensaje de bienvenida similar al que sigue:<br /><div><pre>+-------------------------------------------------------------+<br />| Bienvenido a la distribucion Linux TDB openSUSE 15.2 x86_64 |<br />| personalizada para el blog tormentadebits(dot)com |<br />+-------------------------------------------------------------+</pre></div></li><li>Y eso es todo lo que tenía pensado comentar bajo esta sección.</li></ol></div></div><div><h3><br /></h3><h3>Comandos útiles para personalizar un sistema operativo:</h3></div><div><ol style="text-align: left;"><li>Comando para buscar los últimos archivos modificados en el sistema operativo Linux desde hace 15 minutos atrás. Útil para identificar archivos de configuración recientemente modificados:<br /><div><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">find /etc -type f -mmin -15</span></pre></div></li><li>Comando para buscar texto en el contenido de los archivos de un directorio:<br /><div><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">grep -rnw /usr/share/plasma -e loadTemplate</span></pre></div></li><li>Comando para hallar los diez directorios con mayor tamaño de archivos:<br /><div><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">du -Sh | sort -rh | head -10</span></pre></div></li><li>Comando para generar el hash code de una cadena de texto que deseamos encriptar:<br /><div><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">openssl passwd -1 -salt 'salt_text', cadenta_de_texto_a_encriptar</span></pre></div></li></ol></div><div><div><h3><br class="Apple-interchange-newline" />Construcción de la imagen del sistema operativo personalizado de forma avanzada:</h3></div><div><ol><li>Llegados hasta este punto ya estamos listos para volver a repetir la construir de la imagen de nuestra distribución Linux personalizada de forma avanzada, pero antes de seguir sería recomendable <b>cambiar la versión de nuestro proyecto</b> editando el archivo <b>config.xml</b> del directorio <b>~/mysuseleap-15.2</b>:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span><span style="background-color: white;">vim ~/mysuseleap-15.2/config.xml</span></pre>Donde en la línea resaltada en verde cambiamos a la <b>versión 1.1.0</b> que separarla de la compilación anterior:<br /><pre><?xml version="1.0" encoding="utf-8"?><br /><br /><span style="background-color: white;"><image schemaversion="6<span>.8</span>" name="<span>tdb-openSUSE-Leap-15.2</span>"><br /> <description type="system"><br /> <author><span>Gabriel</span></author><br /> <contact><span>contacto(arroba)tormentadebits(dot)com</span></contact><br /> <specification><br /> TDB open<span>SUSE Leap 15.2 es una distro Linux corporativa basada en openSUSE.</span><br /> </specification></span><br /> </description><br /> <preferences><br /> <type image="iso" primary="true" flags="overlay" hybrid="true" firmware="efi" kernelcmdline="splash" hybridpersistent_filesystem="ext4" hybridpersistent="true" mediacheck="true"/><br /><span style="background-color: #04ff00;"> <version><span>1.1.0</span></version></span></pre></li><li>También sería interesante crear un archivo denominado <b>Changelog.txt</b> dentro del directorio <b>~/mysuseleap-15.2/root/kiwifiles</b>, editarlo:<br /><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> touch</span><span style="background-color: white;"> ~/mysuseleap-15.2/root/kiwifiles/Changelog.txt<br /></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> vim</span><span style="background-color: white;"> ~/mysuseleap-15.2/root/kiwifiles/Changelog.txt</span></pre>Para agregarle todos los cambios que vamos incorporando en cada versión de nuestra distribución Linux personalizada:<br /><pre><span style="background-color: white;">=================<br />CHANGELOG<br />=================<br /><br />Versión 1.1.0:<br />---------------<br />- Incorporación de modificaciones avanzadas mediante el script config.sh.<br /><br /><br />Versión 1.0.0:<br />--------------<br />- Personalización de nombre de la distribución, repositorios, paquetes, etc.<br />mediante el archivo config.xml.</span></pre></li><li>Finalmente borramos la construcción anterior y volvemos a ejecutar el comando que se encargará de construir la nueva versión de la imagen:<br /><div><pre><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> rm -Rf <span style="background-color: transparent;">~/kiwi-builds<br /></span></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ # </span>mkdir ~/kiwi-builds<br /><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> </span>kiwi --type oem system build --description ~/mysuseleap-15.2 --target-dir ~/kiwi-builds</pre></pre></div></li><li>Si queremos copiar la imagen en un pendrive para facilitar su arranque e instalación en otra computadora, podemos instalar la aplicación <b>imagewriter</b>, que al ejecutarla nos desplegará una ventana gráfica que detecta el pendrive conectado ,y a la cual podemos arrastrar el archivo .iso y posteriormente presionar el botón <b>Write</b> para iniciar el proceso de escritura:<br /><div><pre><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ #</span><span style="background-color: white;"> zypper in imagewriter<span style="background-color: transparent;"><br /></span></span><span style="background-color: white; color: #ff5454; font-weight: bold;">kiwi:~ # </span>imagewriter</pre></div></li><li>Y con eso finalizamos este extenso manual, a continuación les dejo con una serie de capturas de la distribución Linux personalizada <span style="background-color: white;"><b>tdb-openSUSE-Leap-15.2</b>, espero que las disfruten:</span></li></ol></div></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-01.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="799" height="480" src="http://files.tormentadebits.com/images/00061-kiwisuse-01.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-02.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="799" height="482" src="http://files.tormentadebits.com/images/00061-kiwisuse-02.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-03.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="799" height="480" src="http://files.tormentadebits.com/images/00061-kiwisuse-03.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-04.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="799" height="150" src="http://files.tormentadebits.com/images/00061-kiwisuse-04.png" width="200" /></a><a href="http://files.tormentadebits.com/images/00061-kiwisuse-05.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="800" height="150" src="http://files.tormentadebits.com/images/00061-kiwisuse-05.png" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-06.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="799" height="151" src="http://files.tormentadebits.com/images/00061-kiwisuse-06.png" width="200" /></a><a href="http://files.tormentadebits.com/images/00061-kiwisuse-07.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="795" data-original-width="1223" height="130" src="http://files.tormentadebits.com/images/00061-kiwisuse-07.png" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-08.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="793" data-original-width="1225" height="414" src="http://files.tormentadebits.com/images/00061-kiwisuse-08.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-09.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="799" data-original-width="1226" height="418" src="http://files.tormentadebits.com/images/00061-kiwisuse-09.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-10.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="793" data-original-width="1223" height="416" src="http://files.tormentadebits.com/images/00061-kiwisuse-10.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-11.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1228" height="418" src="http://files.tormentadebits.com/images/00061-kiwisuse-11.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-12.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="799" data-original-width="1225" height="418" src="http://files.tormentadebits.com/images/00061-kiwisuse-12.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-13.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="788" data-original-width="1225" height="412" src="http://files.tormentadebits.com/images/00061-kiwisuse-13.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-14.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="791" data-original-width="1227" height="414" src="http://files.tormentadebits.com/images/00061-kiwisuse-14.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-15.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="786" data-original-width="1224" height="129" src="http://files.tormentadebits.com/images/00061-kiwisuse-15.png" width="200" /></a> <a href="http://files.tormentadebits.com/images/00061-kiwisuse-16.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="788" data-original-width="1225" height="129" src="http://files.tormentadebits.com/images/00061-kiwisuse-16.png" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-17.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="801" data-original-width="1228" height="131" src="http://files.tormentadebits.com/images/00061-kiwisuse-17.png" width="200" /></a><a href="http://files.tormentadebits.com/images/00061-kiwisuse-18.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="797" data-original-width="1221" height="131" src="http://files.tormentadebits.com/images/00061-kiwisuse-18.png" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-19.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="796" data-original-width="1224" height="416" src="http://files.tormentadebits.com/images/00061-kiwisuse-19.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-20.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="797" data-original-width="1223" src="http://files.tormentadebits.com/images/00061-kiwisuse-20.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00061-kiwisuse-21.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="799" data-original-width="1225" src="http://files.tormentadebits.com/images/00061-kiwisuse-21.png" width="640" /></a></div><br /><div><br /></div><div><h2 style="text-align: left;">Nota final del autor:</h2></div><div>Para finalizar quisiera mencionar que me ha llevado mucho tiempo y esfuerzo estructurar la idea y redactar este manual. Ciertamente por la red no se encuentra mucha información respecto al tema, y por ello para mi ha sido casi una obligación redactarlo, como si fuese un hito para mi carrera, o todo lo contrario, como si fuese una barrera que no me dejara avanzar a nuevos proyectos hasta tanto la haya superado.</div><div><br /></div><div>Y es que al final sentía que todo ese conocimiento que había adquirido con mucho sacrificio para crear un sistema operativo personalizado no debía quedar en el olvido, en especial para mí que muy ocupado y olvidadizo me encuentro durante estos en estos tiempo.</div><h3><br /></h3><h2 style="text-align: left;">Referentes y enlaces de utilidad:</h2><ul style="text-align: left;"> <li> <a href="https://osinside.github.io/kiwi/index.html" target="_blank">Wiki sobre KIWI NG (Versión 9 vigente)</a> </li> <li> <a href="https://doc.opensuse.org/projects/kiwi/doc/" target="_blank">Wiki sobre la versión anterior de KIWI 7 (Desoportada)</a> </li> <li> <a href="https://en.wikipedia.org/wiki/SUSE_Studio" target="_blank">Sobre SUSE Studio en Wikipedia</a><br /> </li><li><a href="https://en.opensuse.org/YaST_Firstboot">https://en.opensuse.org/YaST_Firstboot</a></li><li><span color="" face=""><a href="https://groups.google.com/forum/#!topic/kiwi-images/td1b_HxNJaQ" target="_blank">Creating passwd compatible hashes for Kiwi</a></span></li><li><a href="https://userbase.kde.org/KDE_System_Administration/PlasmaDesktopScripting#Look_and_Feel_dependent_default_setup_for_applets" target="_blank">KDE Userbase - Look and Feel dependent default setup for applets</a></li></ul></div>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com8tag:blogger.com,1999:blog-1035903216249592564.post-62357492880274426642020-07-05T18:44:00.004-04:002022-10-04T23:03:51.602-03:00Instalación de Agentes OCS Inventory en Windows y distros Linux<div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/covers/portada-00060.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1230" height="156" src="http://files.tormentadebits.com/covers/portada-00060.png" width="320" /></a></div>Éste artículo es la continuación del artículo publicado hace ya un tiempo referente a la <a href="https://www.blogger.com/2020/04/ocs-inventory-server-en-centos8.html" target="_blank"><b>instalación del servidor OCS Inventory</b></a>, herramienta que como ya sabrán sirve para inventariar nuestro parque de equipos informáticos.<br /><br />A continuación veremos como empaquetar y configurar el instalador del agente para <b>Windows</b>, la instalación del agente para <b>CentOS Linux</b> desde repositorios y la creación de un script bash que facilite la instalación del agente para los sistemas operativos <b>openSUSE Linux</b>.<br /><a name='more'></a><br /><h3>Descarga de Agentes OCS</h3><ol> <li> Lo primero que tenemos que hacer es conseguir las versiones de los agentes compatibles para nuestros Sistemas Operativos, para lo cual tenemos que acceder al apartado de descargas del sitio web de la herramienta <b>OCS Inventory</b>:<br /> <br /> <a href="https://ocsinventory-ng.org/?page_id=1548&lang=en" target="_blank"><b>https://ocsinventory-ng.org/?page_id=1548&lang=en</b></a><br /> <br /> </li> <li> Luego nos dirigimos donde se encuentran los links a las diferentes versiones de Agentes según el sistema operativo en el cual deseamos instalarlo:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-downloads-1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="464" data-original-width="886" height="209" src="http://files.tormentadebits.com/images/00060-ocs-downloads-1.png" width="400" /></a> </div> </li> <li> Hacemos clic en cualquiera de los <b>links</b>, ya que en cualquier caso nos llevará a un formulario donde debemos especificar nuestra cuenta de correo y descomentar el botón de selección si no desean recibir promociones de sus productos. Al presionar el botón <b>Send</b> nos enviarán un correo con los links de descarga de los agentes y demás software que componen la herramienta:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-downloads-2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="693" data-original-width="663" height="400" src="http://files.tormentadebits.com/images/00060-ocs-downloads-2.png" width="383" /></a> </div> </li> <li> El correo que nos debería llegar es similar al siguiente:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-downloads-3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1054" data-original-width="600" height="640" src="http://files.tormentadebits.com/images/00060-ocs-downloads-3.png" width="364" /></a> </div> </li> <li> En las siguientes secciones veremos los procedimientos de instalación de los agentes para los diferentes sistemas operativos. </li></ol><div><br /></div><div> <h3>Preparación e instalación de Agentes para Windows 7 o superior</h3></div><ol> <li> En este tutorial solo se abarcará la instalación en <b>Windows 7 o superior </b>con arquitecturas <b>64 bits </b>utilizando una versión pre-configurada del agente que facilite la instalación del agente ya sea de forma manual como a través de políticas de <b>Active Directory</b>. Para comenzar<b> </b>procedemos a descargar la versión 2.6 del Agente y del Packager mediante sus correspondientes enlaces:<br /> - <a href="https://github.com/OCSInventory-NG/WindowsAgent/releases/download/2.6.0.0/OCS-Windows-Agent-2.6.0.0.zip"><b>OCS Windows Agent 2.6.0.0 (64 bits only)</b></a><br /> - <a href="https://github.com/OCSInventory-NG/Packager-for-Windows/releases/download/2.6/OCS-Windows-Packager-2.6.zip"><b>OCS Windows Packager 2.6 (64 bits only)</b></a><br /> <br />También necesitamos descargar el paquete de herramientas <b>PSTools</b>, de entre las cuales estaremos necesitando la herramienta <b>PsExec</b> que permite la ejecución de procesos desde la línea de comandos y que es un requerimiento para el programa <b>OCS Windows Packager</b>:<br /> - <a href="https://download.sysinternals.com/files/PSTools.zip"><b>PsTools</b></a><br /><br />Una vez descargadas los programas arriba mencionados a nuestra máquina <b>Windows</b>, procedemos a des-compactarlos. <br /><br /> </li> <li> Abrimos una consola <b>CMD</b> y ejecutamos el comando <b>ping testsrv.gknet.local</b> para comprobar que desde la máquina Windows podemos conectarnos al servidor sin especificar la dirección IP, ya que debería resolverlo nuestro servidor <b>DNS</b> local. Caso contrario podemos agregar una entrada en el archivo <b>hosts</b> del directorio <b>C:\Windows\System32\drivers\etc</b>.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="340" data-original-width="674" height="323" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-1.png" width="640" /></a> </div> </li> <li> De nuestro servidor <b>testsrv</b> descargamos el archivo <b>apache.crt</b> del directorio <b>/etc/httpd/ssl</b> a nuestra máquina Windows y lo renombramos como <b>cacert.pem</b>.<br /><br /> </li> <li> Una vez que tengamos todos los programas y archivos anteriores, procedemos a copiar el programa <b>PsExec.exe</b> de la carpeta <b>PSTools</b> y el archivo <b>cacert.pem</b> dentro de la carpeta del programa <b>OCS-Windows-Packager-2.6</b> junto al programa <b>OcsPackager.exe</b>.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="529" data-original-width="786" height="430" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-2.png" width="640" /></a> </div> </li> <li> A continuación ejecutamos el programa <b>OcsPackager.exe</b> para empaquetar el instalador y asignamos los siguientes valores en cada campo: <ul> <li> <b>Agent Setup File</b>: Especificamos la ruta al instalador del agente <b>OCS-NG-Windows-Agent-Setup.exe</b> </li> <li> <b>Certificate file</b>: Especificamos la ruta al certificado <b>cacert.pem</b> </li> <li> <b>Command line options</b>: Se le agregan los parámetros que el empaquetador luego utiliza para instalar el agente. Las directivas que se recomiendan cargar como ser la url del servidor, activar la conexión SSL, usuario, contraseña de autenticación, ejecución en modo silencioso entre otros: <b>/server=https://testsrv.gknet.local/ocsinventory /USER=ocsagentes /PWD=passwagentes /SSL=1 /S /NOW /NO_SYSTRAY</b> </li> <li> <b>User</b>: Para especificar la cuenta del administrador de dominio <b>admin@gknet.local</b>. </li> <li> <b>Password</b>: Para especificar la contraseña del usuario de dominio.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="389" data-original-width="502" height="496" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-3.png" width="640" /></a> </div> </li> </ul> </li> <li> En el siguiente paso el asistente nos permite seleccionar el directorio en donde se va a generar el instalador empaquetado del agente, dejamos todo por defecto para que genere el archivo en el escritorio y presionamos el botón <b>OK</b> para iniciar el procedimiento de generación del instalador.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="387" data-original-width="503" height="308" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-4.png" width="400" /></a> </div> </li> <li> Al finalizar el asistente presionamos el botón <b>Close</b> para finalizar el proceso.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="389" data-original-width="503" height="309" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-5.png" width="400" /></a> </div> </li> <li> A continuación ya podemos proceder con la instalación del agente, pero antes cambiamos su nombre de <b>OcsPackage.exe</b> a <b>OcsAgentPackage-Win7.exe</b> y con clic derecho lo <b>ejecutamos como administrador</b>, ya que sino la instalación no funcionará de forma adecuada:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-6.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="244" data-original-width="438" height="223" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-6.png" width="400" /></a> </div> </li> <li> Una vez ejecutado el instalador lo único que nos aparecerá en pantalla será un banner que diga <b>OCS Inventory NG</b>, que nos permite saber que el asistente se está instalando de forma silenciosa. Para corroborar que el agente se haya instalado correctamente tenemos que verificar que el servicio <b>OCS Inventory Service</b> esté iniciado.<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-8.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="598" data-original-width="981" height="390" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-8.png" width="640" /></a> </div> </li> <li> Podemos verificar el archivo de configuración <b>ocsinventory.ini</b> o los archivos <b>logs</b> del Agente especificando la siguiente dirección en el explorador de Windows: <pre><b>%programdata%\OCS Inventory NG\Agent</b><br /></pre> </li> <li> Con la herramienta <b>WinSCP</b> procedemos a subir el Agente instalador <b>OcsAgentPackage-Win7.exe</b> al directorio <b>/srv/ocsinventory/agents/Windows</b> de nuestro servidor <b>OCS Inventory</b> (testsrv.gknet.local) a fin de facilitar la distribución y descarga del agente de instalación de Windows. <br /><br /> </li> <li> Para facilitar la instalación desde una política <b>GPO</b> de <b>Active Directory</b> nos conectamos por consola al servidor <b>testsrv.gknet.local</b> y nos ubicamos en el directorio <b>/srv/ocsinventory/agents/Windows</b>, en donde creamos un archivo llamado <b>ocsinstallgpo.bat</b> y luego lo editamos. <pre><b>[root@testsrv ~]# cd /srv/ocsinventory/agents/Windows<br />[root@testsrv Windows]# touch ocsinstallgpo.bat<br />[root@testsrv Windows]# vim ocsinstallgpo.bat</b><br /></pre> Al mismo le agregamos las siguientes directivas shell de Windows que permiten la instalación del agente previa verificación si ya se encuentra instalado o no en el equipo: <pre><b>@echo off</b><br /><br /><i>rem Script que permite la instalación del Agente desde recursos compartidos.<br /><br />rem Se verifica que el agente aún no esté instalado.</i><br /><b>if exist "%programfiles(x86)%\OCS Inventory Agent\OCSInventory.exe" goto end<br />if exist "%programfiles%\OCS Inventory Agent\OCSInventory.exe" goto end</b><br /><br /><i>rem Se procede a ejecutar el instalador desde el recurso compartido.</i><br /><b>start \\testsrv.gknet.local\ocsagents\Windows\OcsAgentPackage-Win7.exe<br /><br />:end</b><br /></pre> Además, aprovechamos la ocasión para crear un archivo Readme.txt: <pre><b>[root@testsrv Windows]# touch Readme.txt<br />[root@testsrv Windows]# vim Readme.txt</b><br /></pre> Al cual le agregamos el siguiente contenido para recordarnos los pasos importantes que debemos seguir para que la instalación del agente se realice de forma adecuada: <pre><b>README:<br />=======<br /><br />El instalador se tiene que ejecutar como "Administrador", ya que <br />se requiere dicho nivel de acceso para poder instalar y registrar<br />la aplicacion OCS Inventory como un servicio que corre en segundo<br />plano.</b><br /></pre> </li> <li> Solo resta mencionar que con los pasos anteriores ya dispondremos de un instalador pre-configurado del <b>Agente OCS Inventory</b> para nuestros equipos <b>Windows 7 o superior</b>, disponible para ser descargado desde nuestro servidor OCS Inventory colocando la URL <b>\\testsrv.gknet.local\ocsagents\Windows</b> en el explorador de Windows:<br /> <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-agent-win-9.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="531" data-original-width="788" height="432" src="http://files.tormentadebits.com/images/00060-ocs-agent-win-9.png" width="640" /></a> </div> </li></ol><br /><br /><h3>Instalación del Agente OCS en equipos con openSUSE Linux</h3>Para automatizar y agilizar la instalación, he decidido crear un <b>script</b> que se almacene en la carpeta de agentes del servidor <b>testsrv</b>, y que desde los equipos con <b>openSUSE Linux</b> se pueda descargar y ejecutar para proceder con la instalación del agente. A continuación veremos la creación del script y el proceso de instalación del Agente con el mencionado script:<br /><ol> <li> Nos conectamos al servidor <b>testsrv</b> con el usuario <b>root</b> y nos dirigimos al directorio <b>/srv/ocsinventory/agents/openSUSE</b> en el cual descargamos desde Github el archivo <b>Ocsinventory-Unix-Agent-2.6.1.tar.gz</b> con los fuentes para instalar el agente:<br /> <pre><b>[root@testsrv ~]# cd /srv/ocsinventory/agents/openSUSE<br />[root@testsrv openSUSE]# wget https://github.com/OCSInventory-NG/UnixAgent/releases/download/v2.6.1/Ocsinventory-Unix-Agent-2.6.1.tar.gz --no-proxy</b><br /></pre> Para este ejemplo se va a utilizar la versión del agente <b>2.6.1</b> (Que no aparece sugerido como opción de descarga en el correo), sin embargo, pueden verificar en <a href="https://github.com/OCSInventory-NG/UnixAgent/releases" target="_blank"><b>éste enlace</b></a> para obtener las últimas versiones disponibles.<br /> <br /> </li> <li> Luego creamos el archivo <b>ocsinstaller-opensuse-agent.sh</b>, le asignamos los permisos correspondientes y lo editamos:<br /> <pre><b>[root@testsrv openSUSE]# touch ocsinstaller-opensuse-agent.sh<br />[root@testsrv openSUSE]# chmod 644 ocsinstaller-opensuse-agent.sh<br />[root@testsrv openSUSE]# vim ocsinstaller-opensuse-agent.sh</b><br /></pre> Y le agregamos el siguiente script bash:<br /> <pre><i>#/bin/bash<br /># REFS: http://wiki.ocsinventory-ng.org/03.Basic-documentation/Setting-up-the-UNIX-agent-on-client-computers/ <br /><br /># Verificacion que el operador haya pasado la contrasenia<br /># de conexión del usuario OCS_USER.</i><br />if [ -z "$1" ]; then<br /> echo ""<br /> echo "ATENCION: Debe pasar como argumento la contraseña del usuario $OCS_USER"<br /> echo ""<br /> exit 1<br />fi<br /><br /><i># Definicion de la ruta de descarga de los instaladores. </i><br />OCS_BIN_FILE="/usr/bin/ocsinventory-agent"<br />OCS_LOG_FILE="/var/log/ocsinventory-agent.log"<br />OCS_CFG_FILE="/etc/ocsinventory-agent/ocsinventory-agent.cfg"<br />OCS_SRV_NAME="<span style="color: red;"><b>testsrv.gknet.local</b></span>"<br />OCS_HTTP_USER="<span style="color: red;"><b>ocsagentes</b></span>"<br />OCS_HTTP_REALM="<span style="color: red;"><b>OCS Inventory agent area</b></span>"<br />TEMP_DIR=/tmp/ocsinstaller<br /><br /><i># Encriptamos el nombre de usuario y la contrasenia en Base64, ya que seran guardados en el archivo de<br /># configuracion del agente y ademas es un requisito para que el metodo de autenticacion Apache Basic<br /># del servidor no genere errores tipo "AH01618: user \xa6\xbb\x9em not found"</i>.<br />OCS_HTTP_USER_ENCRYP=$(echo -n $OCS_HTTP_USER | base64)<br />OCS_HTTP_PASS_ENCRYP=$(echo -n $1 | base64)<br /><br /><i># Verificacion del nombre de la version y distribucion Linux. </i><br />arch=$(uname -m) <br />kernel=$(uname -r) <br />if [ -n "$(command -v lsb_release)" ]; then <br /> distroname=$(lsb_release -s -d | tr -d '="') <br />elif [ -f "/etc/os-release" ]; then <br /> distroname=$(grep PRETTY_NAME /etc/os-release | sed 's/PRETTY_NAME=//g' | tr -d '="') <br />elif [ -f "/etc/debian_version" ]; then <br /> distroname="Debian $(cat /etc/debian_version)" <br />elif [ -f "/etc/redhat-release" ]; then <br /> distroname=$(cat /etc/redhat-release) <br />elif [ -f "/etc/SuSE-release" ]; then <br /> distroname=$(cat /etc/SuSE-release | grep openSUSE) <br />else <br /> distroname="$(uname -s) $(uname -r)" <br />fi <br /><br /><i># Verifica si la distribucion de linux en la que se ejecuta el script corresponde con la version de <br /># openSUSE para el cual fue desarrollado el script. </i><br />if [ "$distroname" == "openSUSE Leap 15.0" ] || [ "$distroname" == "openSUSE Leap 15.1" ]; then<br /> <i># Instalacion de paquetes requeridos mediante zypper:</i><br /> zypper -n in -l gcc pciutils dmidecode nmap perl-App-cpanminus perl-XML-Simple perl-Net-IP perl-Digest-MD5 perl-Net-SSLeay perl-IO-Socket-SSL perl-Crypt-SSLeay perl-LWP-Protocol-https perl-Net-SNMP perl-Net-Netmask<br /><br /> <i># Instalacion de dependencias PERL con la herramienta CPAN MINUS:</i> <br /> cpanm Compress::Zlib<br /> cpanm LWP::UserAgent<br /> cpanm Data::UUID <br /> cpanm Proc::Daemon <br /> cpanm Proc::PID::File<br /> <br /> <i># Instalacion de dependencias PERL opcionales con la herramienta CPAN MINUS:</i><br /> cpanm Nmap::Parser<br /> cpanm Module::Install<br /> cpanm Net::CUPS<br /> cpanm Parse::EDID<br />else<br /> echo "Este instalador no funciona con la distribucion de Linux '$distroname'." <br /> exit 1<br />fi<br /><br /><i># Creacion del directorio de instalacion y ubicacion en el mismo:</i><br />mkdir $TEMP_DIR <br />cd $TEMP_DIR <br /><br /><i># Descarga del Agente OCS Inventory del servidor:</i> <br />wget http://$OCS_SRV_NAME/ocsagents/openSUSE/Ocsinventory-Unix-Agent-2.6.1.tar.gz --no-proxy <br /><br /><i># Descompactado de los paquetes de instalacion:</i><br />tar -xzf Ocsinventory-Unix-Agent-2.6.1.tar.gz <br /><br /><i># Instalacion del paquete Perl Ocinventory::Unix::Agent</i><br />cd $TEMP_DIR/Ocsinventory-Unix-Agent-2.6.1 <br />env PERL_AUTOINSTALL=1 perl Makefile.PL && make && make install && perl postinst.pl --nowizard --server=https://$OCS_SRV_NAME/ocsinventory --nossl --logfile=$OCS_LOG_FILE --user="$OCS_HTTP_USER_ENCRYP" --password="$OCS_HTTP_PASS_ENCRYP" --proxy="" --crontab <br /><br /><i># Como en el comando de compilacion anterior no podemos pasar un realm con <br /># espacios en la cadena de texto usando la directiva --realm="", y por ende <br /># tampoco la directiva --now, procederemos a continuación a agregar la directiva<br /># realm de forma manual al archivo de configuración y a ejecutar el agente por<br /># primera vez con las siguientes dos comandos:</i><br />echo 'realm="'$OCS_HTTP_REALM'"' >> $OCS_CFG_FILE<br />$OCS_BIN_FILE<br /><br /><i># Eliminacion de la carpeta temporal:</i><br />cd /tmp <br />rm -Rf ocsinstaller/ <br /><br /><i># Salida:</i><br />exit 0<br /></pre> Como se puede observar más arriba el script se encuentra desarrollado de forma preliminar para que sea compatible solo con <b>openSUSE 15.0</b> y <b>15.1</b>. <br /><br /></li> <li> En el mismo directorio creamos el archivo <b>Readme.txt</b>, asignamos los permisos, lo editamos:<br /> <pre><b>[root@testsrv openSUSE]# touch Readme.txt<br />[root@testsrv openSUSE]# chmod 644 Readme.txt<br />[root@testsrv openSUSE]# vim Readme.txt</b><br /></pre> Y le agregamos el siguiente contenido que permitirá recordar en el futuro como proceder con la instalación del agente pre-configurado en una máquina cliente con la distro <b>openSUSE</b>:<br /> <pre>README:<br /><br />1)- Para instalar el Agente OCS Inventory en una openSUSE Linux<br />tenemos que abrir una consola o conectarnos desde PuTTY a la pc<br />openSUSE, conectarnos al equipo con el usuario root y<br />verificamos la version de openSUSE que tiene instalado el equipo:<br /><br /> opensusecli:~ # cat /etc/os-release<br /><br /><br />2)- Descargamos el script ocsinstaller-opensuse-agent.sh desde<br />el servidor testsrv.gknet.local con el siguiente comando:<br /><br /> opensusecli:~ # wget -N http://testsrv.gknet.local/ocsagents/openSUSE/ocsinstaller-opensuse-agent.sh --no-proxy<br /><br /><br />3)- Ejecutamos el script instalador del Agente OCS y pasamos<br />como argumento la contrasenia del usuario de conexion con el<br />siguiente comando:<br /><br /> opensusecli:~ # sh ocsinstaller-opensuse-agent.sh password_ocsagents<br /><br /><br />4)- Con estos pasos al finalizar el agente ya deberia estar<br />instalado correctamente y haber informado al servidor sobre<br />el estado del equipo en donde se instalo el agente.<br /></pre> </li> <li> A continuación solo nos resta seguir los pasos del archivo <b>Readme.txt</b> para instalar el agente en una pc con la distro <b>openSUSE 15.0</b> o <b>15.1</b>. Comenzamos por conectarnos con el usuario <b>root</b> y verificar la versión:<br /> <pre><b><span style="color: red;">opensusecli:~ #</span> cat /etc/os-release</b><br />NAME="openSUSE Leap"<br />VERSION="15.1"<br />ID="opensuse-leap"<br />ID_LIKE="suse opensuse"<br />VERSION_ID="15.1"<br />PRETTY_NAME="openSUSE Leap 15.1"<br />ANSI_COLOR="0;32"<br />CPE_NAME="cpe:/o:opensuse:leap:15.1"<br />BUG_REPORT_URL="https://bugs.opensuse.org"<br />HOME_URL="https://www.opensuse.org/"<br /><b><span style="color: red;">opensusecli:~ #</span></b><br /></pre> Descargamos el script de instalación <b>ocsinstaller-opensuse-agent.sh</b>: <br /> <pre><b><span style="color: red;">opensusecli:~ #</span> wget -N http://testsrv.gknet.local/ocsagents/openSUSE/ocsinstaller-opensuse-agent.sh --no-proxy</b><br />--2020-04-27 00:36:34-- http://testsrv.gknet.local/ocsagents/openSUSE/ocsinstaller-opensuse-agent.sh<br />Resolviendo testsrv.gknet.local (testsrv.gknet.local)... 192.168.1.10<br />Conectando con testsrv.gknet.local (testsrv.gknet.local)[192.168.1.10]:80... conectado.<br />Petición HTTP enviada, esperando respuesta... 200 OK<br />Longitud: 2269 (2,2K) [application/x-sh]<br />Grabando a: “ocsinstaller-opensuse-agent.sh”<br /><br />ocsinstaller-opensuse-agent.sh 100%[========================================================>] 2,22K --.-KB/s en 0s <br /><br />2020-04-27 00:36:34 (265 MB/s) - “ocsinstaller-opensuse-agent.sh” guardado [2269/2269]<br /><br /><b><span style="color: red;">opensusecli:~ #</span></b><br /></pre> Y finalmente lo ejecutamos para instalar el agente:<br /> <pre><b><span style="color: red;">opensusecli:~ #</span> sh ocsinstaller-opensuse-agent.sh passwagentes</b><br />Cargando datos del repositorio...<br />...<br />...<br />Setting OCS Inventory NG server address... <br />Looking for OCS Invetory NG Unix Unified agent installation... <br />ocsinventory agent presents: /usr/bin/ocsinventory-agent <br />Setting crontab... <br />Creating /etc/ocsinventory-agent directory... <br />Writing OCS Inventory NG Unix Unified agent configuration <br />Creating /var/lib/ocsinventory-agent/https:__testsrv.gknet.local_ocsinventory directory... <br />Copying SNMP MIBs XML files... <br />Activating modules if needed...<br />New settings written! Thank you for using OCS Inventory <br />Can't open display<br /><b><span style="color: red;">opensusecli:~ #</span></b><br /></pre> </li> <li> Una vez finalizado la instalación recomendamos revisar la hora en que está programada la ejecución diaria del agente OCS Inventory, ya que suele asignar horarios aleatorios que pueden caer a media noche donde probablemente el equipo esté apagado. Para ello editamos el archivo <b>ocsinventory-agent</b> ubicado en el directorio <b>/etc/cron.d</b>:<br /> <pre><b><span style="color: red;">opensusecli:~ #</span> vim /etc/cron.d/ocsinventory-agent</b><br /></pre> Y verificamos que la hora programada (resaltada en rojo) sea correcta, si figura un horario en que el equipo probablemente esté apagado (medianoche, madrugada, etc.) cambiamos a una hora en que el equipo normalmente se encuentra encendido.<br /> <pre><b>PATH=/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/usr/bin:/bin:/usr/lib/mit/sbin<br />0 <span style="color: red;">15</span> * * * root /usr/bin/ocsinventory-agent --lazy > /dev/null 2>&1</b><br /></pre> Si hemos realizado un cambio al archivo cron <b>ocsinventory-agent</b> reiniciamos el servicio <b>crontab</b>:<br /> <pre><b><span style="color: red;">opensusecli:~ #</span> systemctl restart cron</b><br /></pre> </li> <li> Por otro lado, si queremos ejecutar el agente de forma manual podemos ejecutar desde la línea de comandos la siguiente directiva:<br /> <pre><b><span style="color: red;">opensusecli:~ #</span> /usr/bin/ocsinventory-agent<br />Can't open display <br /><span style="color: red;">opensusecli:~ #</span></b><br /></pre> </li> <li> Finalmente podemos verificar en la consola de administración <b>OCS Inventory</b> del servidor <b>testsrv</b> donde ya debería aparecer la entrada para el equipo <b>opensusecli</b>:<br /> </li></ol><br /><br /><h3>Instalación del Agente OCS en equipos con CentOS 8 Linux</h3><ol> <li> Para las distribución Linux <b>CentOS 8</b> podemos instalar los paquetes a partir del repositorio oficial, para lo cual comenzamos por conectarnos a nuestro equipo cliente e instalamos y activamos el repositorio <b>EPEL</b> (Extra Packages for Enterprise Linux) requerido para suplir algunas dependencias.<br /> <pre><b>[root@centoscli ~]# yum --enablerepo=extras install epel-release</b><br /></pre> </li> <li> Luego procedemos a descargar e instalar el repositorio <b>ocsinventory-release-latest</b> que contiene los paquetes requeridos para instalar el agente OCS Inventory:<br /> <pre><b>[root@centoscli ~]# wget https://rpm.ocsinventory-ng.org/ocsinventory-release-latest.el8.ocs.noarch.rpm<br />[root@testsrv ~]# yum install ocsinventory-release-latest.el8.ocs.noarch.rpm</b><br /></pre> </li> <li> Para la instalación del <b>Agente OCS Inventory</b> debemos ejecutar el siguiente comando:<br /> <pre><b>[root@centoscli ~]# dnf --enablerepo=PowerTools --enablerepo=epel-playground install ocsinventory-agent</b></pre> </li> <li> A continuación tenemos que agregar en el archivo de configuración <b>ocsinventory-agent.cfg</b> del directorio <b>/etc/ocsinventory</b> las directivas de configuración del usuario y la contraseña de autenticación HTTP requerida por el servidor OCS Inventory, que deben ir <b>encriptados en Base64</b> para que el servidor no los rechace: <pre><b>[root@centoscli ~]# echo user=$(echo -n 'ocsagentes' | base64) >> /etc/ocsinventory/ocsinventory-agent.cfg<br />[root@centoscli ~]# echo password=$(echo -n 'passwagentes' | base64) >> /etc/ocsinventory/ocsinventory-agent.cfg</b><br /></pre> Luego editamos el archivo <b>ocsinventory-agent.cfg</b>: <pre><b>[root@centoscli ~]# vim /etc/ocsinventory/ocsinventory-agent.cfg</b><br /></pre> Y comentamos la directiva <b>local</b> (<span style="background-color: #f4c7c3;">resaltada en rojo</span>), descomentamos la directiva <b>server</b> que debe tener asignada la URL del servidor (<span style="background-color: #fce8b2;">resaltado en amarillo</span>) y al final le agregamos las directivas adicionales <b>ssl</b> y <b>realm</b> (<span style="background-color: #b7e1cd;">resaltadas en verde</span>). Debería quedar similar a lo que sigue: <pre><b><i># <br /># OCS Inventory "Unix Unified Agent" Configuration File<br />#<br /># options used by cron job overides this (see /etc/sysconfig/ocsinventory-agent)<br />#</i><br /><br /><i># Server URL, unconmment if needed</i><br /><span style="background-color: #fce8b2;">server = https://testsrv.gknet.local/ocsinventory</span><br /><i style="background-color: #f4c7c3;">#local = /var/lib/ocsinventory-agent</i><br /><br /><i># Administrative TAG (optional, must be filed before first inventory)<br /># tag = your_tag</i><br /><br /><i># How to log, can be File,Stderr,Syslog</i><br />logger = Stderr<br />logfile = /var/log/ocsinventory-agent/ocsinventory-agent.log<br /><br /><span style="background-color: #b7e1cd;"><i># Server HTTP Basic Auth data:</i><br />user=b2NzYWdlbnRlcw==<br />password=cGFzc3dhZ2VudGVz<br />ssl = 0<br />realm = "OCS Inventory agent area"</span></b><br /></pre> <b>OBS</b>: Es importante recordar que la directiva <b>realm</b> es muy importante y debe tener el mismo texto a la directiva <b>AuthName</b> configurada en la sección de <b>Apache Auth Basic</b> del servidor <b>OCS Inventory</b>, caso contrario el servidor generará un error 401 Unauthorized.<br /><br /> </li> <li> A continuación ya podemos probar la ejecución del agente: <pre><b>[root@centoscli ~]# /usr/sbin/ocsinventory-agent</b><br /></pre> </li> <li> Si bien ya existe una tarea programada configurada para el servicio OCS Inventory en el directorio <b>/etc/cron.hourly</b>, la misma solo funciona si se activa en el archivo de configuración <b>/etc/sysconfig/ocsinventory-agent</b>. En vez de eso yo prefiero configurar una tarea programada con una configuración personalizada para que el agente se ejecute por día, para lo cual primero creamos el archivo <b>ocsinventory-agent</b> en el directorio <b>/etc/cron.d</b> y luego lo editamos: <pre><b>[root@centoscli ~]# touch /etc/cron.d/ocsinventory-agent<br />[root@centoscli ~]# vim /etc/cron.d/ocsinventory-agent</b><br /></pre> Y una vez adentro agregamos la siguiente directiva para que cada tarde a las 15:30 horas se ejecute el agente:<br /> <pre><i># Tarea programada para la ejecucion diaria del agente OCS Inventory.</i><br /><b>30 15 * * * root /usr/sbin/ocsinventory-agent --lazy > /dev/null 2>&1</b><br /></pre> Realizado lo anterior salimos del archivo y reiniciamos el servicio <b>crontab</b> para que los cambios tomen efecto: <pre><b>[root@centoscli ~]# systemctl restart crond</b><br /></pre> Y con eso ya tenemos el agente funcionando para la distribución <b>Linux CentOS 8.</b> </li></ol><br /><br /><h3>Captura de la información recopilada por el servidor OCS Inventory</h3>Para finalizar quisiera compartir unas capturas de la interfaz de administración del servidor OCS Inventory con los registros de inventario de las computadores que fueron reportadas por los agentes instalados en los pasos previos. <div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-server-web-interface-1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="901" data-original-width="1213" height="476" src="http://files.tormentadebits.com/images/00060-ocs-server-web-interface-1.png" width="640" /></a><br /><br /></div><div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-server-web-interface-2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="502" data-original-width="1217" height="264" src="http://files.tormentadebits.com/images/00060-ocs-server-web-interface-2.png" width="640" /></a><br /><br /></div><div class="separator" style="clear: both; text-align: center;"> <a href="http://files.tormentadebits.com/images/00060-ocs-server-web-interface-3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="883" data-original-width="1209" height="468" src="http://files.tormentadebits.com/images/00060-ocs-server-web-interface-3.png" width="640" /></a></div><div><br /></div><div> Como se puede observar en las capturas previas, la información de los tres sistemas operativos fueron reportados adecuadamente al servidor por los agentes, un hito con el cual puedo dar por finalizado el artículo. </div><div> <br /> <h3>Referentes y enlaces útiles:</h3> <ol> <li> <a href="https://github.com/OCSInventory-NG/WindowsAgent/releases" target="_blank">OCS Inventory WindowsAgent Releases (Github)</a> </li> <li> <a href="https://github.com/OCSInventory-NG/Packager-for-Windows/releases" target="_blank">OCS Inventory OCSPackager Releases (Github)</a> </li> <li> <a href="https://docs.microsoft.com/en-us/sysinternals/downloads/psexec" target="_blank">https://docs.microsoft.com/en-us/sysinternals/downloads/psexec</a><br /> </li> <li> <a href="https://github.com/OCSInventory-NG/UnixAgent/releases" target="_blank">OCS Inventory UnixAgent Releases (Github)</a><br /> </li> <li> <a href="https://wiki.ocsinventory-ng.org/03.Basic-documentation/Setting-up-the-Windows-Agent-2.x-on-client-computers/">Setting up the Windows Agent 2.x on client computers/</a> </li> <li> <a href="https://wiki.ocsinventory-ng.org/03.Basic-documentation/Setting-up-the-UNIX-agent-on-client-computers/">Setting up the UNIX agent on client computers</a> </li> <li> <a href="https://serverfault.com/a/844649" target="_blank">Referente a problemas con el protocolo de autenticación Apache Auth Basic (Server Fault)</a><br /> </li> <li> <a href="http://ebarrova.blogspot.com/2014/02/despliegue-del-agente-de-ocsinventory.html" target="_blank">http://ebarrova.blogspot.com/2014/02/despliegue-del-agente-de-ocsinventory.html</a><br /> </li> <li> <a href="https://allysonsaraiva.blogspot.com/2015/12/dicas-instalando-agent-ocs-via-gpo.html" target="_blank">https://allysonsaraiva.blogspot.com/2015/12/dicas-instalando-agent-ocs-via-gpo.html</a><br /> </li> <li> <a href="https://www.tecmint.com/password-protect-apache-web-directories-using-htaccess/" target="_blank">https://www.tecmint.com/password-protect-apache-web-directories-using-htaccess/</a><br /> </li> </ol></div>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-40268043491213578282020-04-19T21:09:00.005-04:002022-10-04T23:02:25.237-03:00Instalación del servidor OCS Inventory NG 2.7 en CentOS 8<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00060.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1230" height="156" src="http://files.tormentadebits.com/covers/portada-00060.png" width="320" /></a></div><b>OCS Inventory NG</b> es una herramienta que permite inventariar nuestro parque de equipos informáticos.<br /><br />Permite recopilar mediante agentes que se instalan en los equipos clientes información referente al sistema operativo, software instalado, componentes de hardware, etc.<br /><a name='more'></a><br />El servidor <b>OCS Inventory NG</b> está compuesta de los siguientes 4 componentes básicos:<br /><ol><li><b>Database server</b>: Motor de base de datos que almacena la información del inventario.<br /></li><li><b>Communication server</b>: Servidor que gestiona la comunicación entre el motor de base de datos y agentes remotos mediante el protocolo HTTP.<br /></li><li><b>Administration console</b>: La consola de administración es la herramienta Web que nos permitirá administrar y consultar los datos recopilados por la herramienta.<br /></li><li><b>Deployment server</b>: Servidor para configurar la implementación de paquetes, que requiere el protocolo HTTPS para funcionar.<br /></li></ol>En este tutorial nos centraremos en los tres primeros componentes del servidor. La instalación y configuración de los agente remotos que recopilan y reportan la información al servidor serán tratados en un post independiente.<br /><br /><br /><h3>Configuración inicial del sistema operativo</h3><ol><li>Instalar el sistema operativo <b>Linux CentOS 8</b> con una configuración de <b>tipo servidor con entorno gráfico</b> 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.<br /><br /></li><li>Ahora nos toca agregar como fuente de datos al contenido del DVD de instalación del sistema operativo como nuevo origen al gestor de paquetes <b>YUM</b>. Para ello nos dirigimos al directorio de configuración <b>/etc/yum.repos.d</b>, hacemos una copia del seguridad del archivo <b>CentOS-Media.repo</b> y lo editamos con los siguientes comandos:<br /><pre><b>[root@testsrv ~]# cd /etc/yum.repos.d/<br />[root@testsrv yum.repos.d]# cp CentOS-Media.repo CentOS-Media.repo.bkp<br />[root@testsrv yum.repos.d]# vim CentOS-Media.repo</b><br /></pre>Editamos el contenido dejándolo como sigue a continuación:<br /><pre>[c8-media-BaseOS]<br />name=CentOS-BaseOS-$releasever - Media<br /><b>baseurl=file:///media/BaseOS</b><br />gpgcheck=1<br /><b>enabled=1</b><br />gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial<br /></pre>Ahora el gestor de paquetes <b>YUM</b> ya tiene configurado la nueva fuente de datos que apunta al directorio local <b>/media</b>. 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:<br /><pre><b>[root@testsrv yum.repos.d]# mount /dev/cdrom /media</b><br /></pre>Podemos verificar los paquetes disponibles ejecutando lo siguiente:<br /><pre><b>[root@testsrv yum.repos.d]# cd<br />[root@testsrv ~]# yum list available</b><br /></pre></li><li>Paramos y desactivamos el servicio <b>packagekit</b> para evitar que proceda a descargar actualizaciones en segundo plano sin nuestra autorización:<br /><pre><b>[root@testsrv ~]# systemctl stop packagekit<br />[root@testsrv ~]# systemctl disable packagekit</b><br /></pre></li><li>Para este tutorial voy a deshabilitar el módulo de seguridad <b>SELinux</b> y si esto pone en riesgo o no la seguridad del servidor queda bajo la responsabilidad de cada administrador. Para avanzar con esto procedemos a editar el archivo <b>/etc/selinux/config</b>,<br /><pre><b>[root@testsrv ~]# vim /etc/selinux/config</b><br /></pre>y le configuramos la directiva <b>SELINUX</b> con el valor <b>disabled</b>:<br /><pre><i># This file controls the state of SELinux on the system.<br /># SELINUX= can take one of these three values:<br /># enforcing - SELinux security policy is enforced.<br /># permissive - SELinux prints warnings instead of enforcing.<br /># disabled - No SELinux policy is loaded.</i><br />SELINUX=<b>disabled</b><br /><i># SELINUXTYPE= can take one of these two values:<br /># targeted - Targeted processes are protected,<br /># mls - Multi Level Security protection.</i><br />SELINUXTYPE=targeted<br /></pre>Una de las formas para que los cambios anteriores toman efecto es reiniciar el sistema operativo, sin embargo también podemos parar el <b>SELinux</b> en el entorno de ejecución actual con el siguiente comando:<br /><pre><b>[root@testsrv ~]# setenforce 0</b><br /></pre></li><li>Si queremos configurar un servidor <b>ntp</b> específico a partir de donde deseamos sincronizar la fecha y hora del servidor, podemos editar el archivo <b>chrony.conf</b> del directorio <b>/etc</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/chrony.conf</b><br /></pre>Donde configuramos la sección <b>server</b> con nuestro servidor <b>ntp</b> preferido:<br /><pre><i># Use public servers from the pool.ntp.org project.<br /># Please consider joining the pool (http://www.pool.ntp.org/join.html).<br />#server 2.centos.pool.ntp.org iburst</i><br /><b>server mi_servidor_ntp_local.gknet.local prefer</b><br /></pre>Finalmente tenemos que reiniciar el servicio <b>chrony</b> para que los cambios tomen efecto:<br /><pre><b>[root@testsrv ~]# systemctl restart chronyd</b><br /></pre>Para forzar la sincronización de la hora del equipo con el servidor <b>ntp</b> de forma inmediata podemos ejecutar el siguiente comando:<br /><pre><b>[root@testsrv ~]# ntpdate -u mi_servidor_ntp_local.gknet.local</b><br /></pre>Para ver en tiempo real la hora en el servidor, incluyendo los segundos, podemos ejecutar el comando <b>watch</b>. Para salir hay que presionar las teclas CTRL+C.<br /><pre><b>[root@testsrv ~]# watch -n 1 date</b><br /><br />Every 1,0s: date Mon Jul 1 11:35:04 2019<br /><br />lun jul 1 11:35:04 -04 2019<br /></pre></li></ol><br /><br /><h3>Instalación de servidor Apache:</h3><ol><li>Tenemos que instalar el servidor <b>Apache</b>.<br /><pre><b>[root@testsrv ~]# yum install httpd<br />[root@testsrv ~]# yum install mod_ssl openssl</b><br /></pre></li><li>Para activar el servicio <b>SSL</b> en <b>Apache</b> primero creamos el directorio <b>/etc/httpd/ssl</b> para albergar certificados:<br /><pre><b>[root@testsrv ~]# mkdir /etc/httpd/ssl</b><br /></pre></li><li>Luego pasamos a ejecutar el comando <b>openssl</b> para generar una nueva llave para nuestro servidor Apache. Al ejecutar el comando nos solicitará que vayamos cargando información para el certificado:<br /><pre><b>[root@testsrv ~]# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/httpd/ssl/apache.key -out /etc/httpd/ssl/apache.crt</b><br />Generating a 2048 bit RSA private key<br />...............+++<br />...................+++<br />writing new private key to '/etc/httpd/ssl/apache.key'<br />-----<br />You are about to be asked to enter information that will be incorporated<br />into your certificate request.<br />What you are about to enter is what is called a Distinguished Name or a DN.<br />There are quite a few fields but you can leave some blank<br />For some fields there will be a default value,<br />If you enter '.', the field will be left blank.<br />-----<br />Country Name (2 letter code) [XX]:<b>PY</b><br />State or Province Name (full name) []:<b>It</b><br />Locality Name (eg, city) [Default City]:<b>HO</b><br />Organization Name (eg, company) [Default Company Ltd]:<b>Gabriel-Corp.</b><br />Organizational Unit Name (eg, section) []:<b>Informatica</b><br />Common Name (eg, your name or your server's hostname) []:<b>testsrv.gknet.local</b><br />Email Address []:<b>contacto(ARROBA)tormentadebits.com</b><br /><b>[root@testsrv ~]#</b><br /></pre></li><li>Como estamos usando <b>OpenSSL</b>, se recomienda crear una fuerte clave <b>Diffie-Hellman</b>:<br /><pre><b>[root@testsrv ~]# openssl dhparam -out /etc/httpd/ssl/dhparam.pem 2048</b><br /></pre>El <b>hash code</b> generado por el comando anterior lo tenemos que agregar al certificado <b>apache.crt</b> generado más arriba:<br /><pre><b>[root@testsrv ~]# cat /etc/httpd/ssl/dhparam.pem | tee -a /etc/httpd/ssl/apache.crt</b><br /></pre></li><li>Luego editamos el archivo de configuración <b>/etc/httpd/conf.d/ssl.conf</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/ssl.conf</b><br /></pre>Y nos ubicamos donde se encuentran las directivas <b>#DocumentRoot</b> y <b>#ServerName</b>:<br /><pre><i># General setup for the virtual host, inherited from global configuration<br />#DocumentRoot "/var/www/html"<br />#ServerName www.example.com:443</i><br /></pre>Descomentamos ambas y a la directiva <b>ServerName</b> le asignamos el nombre de servidor que corresponde, en este ejemplo <b>testsrv</b>:<br /><pre><i># General setup for the virtual host, inherited from global configuration</i><br /><b>DocumentRoot "/var/www/html"<br />ServerName testsrv:443</b><br /></pre>Luego pasamos a configurar la directiva <b>SSLCertificateFile</b> a la que le asignamos la ruta al nuevo certificado generado más arriba:<br /><pre><i># Server Certificate:<br /># Point SSLCertificateFile at a PEM encoded certificate. If<br /># the certificate is encrypted, then you will be prompted for a<br /># pass phrase. Note that a kill -HUP will prompt again. A new<br /># certificate can be generated using the genkey(1) command.</i><br /><b>SSLCertificateFile /etc/httpd/ssl/apache.crt</b><br /></pre>Y finalmente también configuramos la directiva <b>SSLCertificateKeyFile</b> a la que le asignamos la ruta a la nueva llave generada más arriba:<br /><pre><i># Server Private Key:<br /># If the key is not combined with the certificate, use this<br /># directive to point at the key file. Keep in mind that if<br /># you've both a RSA and a DSA private key you can configure<br /># both in parallel (to also allow the use of DSA ciphers, etc.)</i><br /><b>SSLCertificateKeyFile /etc/httpd/ssl/apache.key</b><br /></pre>Guardamos los cambios y salimos del archivo de configuración.<br /><br /></li><li>Comprobamos que la configuración de <b>Apache</b> esté correcta con el siguiente comando:<br /><pre><b>[root@testsrv ~]# apachectl configtest</b><br />Syntax OK<br /><b>[root@testsrv ~]#</b><br /></pre></li><li>Terminada la configuración de nuestro servidor <b>Apache</b>, tenemos que habilitar en el <b>Firewall</b> los puertos <b>http</b> y <b>https</b> para que el servidor Apache sea accesible desde equipos remotos.<br /><pre><b>[root@testsrv ~]# firewall-cmd --get-active-zones</b><br />libvirt<br /> interfaces: virbr0<br />public<br /> interfaces: enp0s3<br /><b>[root@testsrv ~]# firewall-cmd --zone=public --list-services</b><br />cockpit dhcpv6-client ssh<br /><b>[root@testsrv ~]# firewall-cmd --zone=public --permanent --add-service=http</b><br />success<br /><b>[root@testsrv ~]# firewall-cmd --zone=public --permanent --add-service=https</b><br />success<br /><b>[root@testsrv ~]# systemctl restart firewalld</b><br /><b>[root@testsrv ~]# firewall-cmd --zone=public --list-services</b><br />cockpit dhcpv6-client http https ssh<br /><b>[root@testsrv ~]#</b><br /></pre></li><li>Habilitamos y arrancamos el servidor de <b>Apache</b>:<br /><pre><b>[root@testsrv ~]# systemctl enable httpd<br />[root@testsrv ~]# systemctl start httpd</b><br /></pre></li><li>Y finalmente probamos si podemos acceder al servicio <b>Apache</b> del servidor introduciendo la URL que corresponde en el navegador de otro equipo de nuestra red local:<br /><pre><b>http://ip_del_servidor</b><br /></pre></li></ol><br /><br /><h3>Configuración de MariaDB</h3><ol><li>Tenemos que instalar el motor de base de datos <b>MariaDB</b>.<br /><pre><b>[root@testsrv ~]# yum install mariadb mariadb-server</b><br /></pre></li><li>Abrimos el archivo de configuración del motor de base de datos <b>my.cnf</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/my.cnf.d/mariadb-server.cnf</b><br /></pre>Y agregamos a la sección de configuración <b>[mysqld]</b> la siguiente directiva:<br /><pre><i># Habilita paquetes de hasta 20 MB.</i><br /><b>max_allowed_packet=20M</b><br /></pre></li><li>Habilitamos y arrancamos el servidor de <b>MariaDB</b>:<br /><pre><b>[root@testsrv ~]# systemctl enable mariadb<br />[root@testsrv ~]# systemctl start mariadb</b><br /></pre></li><li>Nos conectamos al motor de base de datos con el usuario <b>root</b> y le asignamos una contraseña inicial:<br /><pre><b>[root@testsrv ~]# mysql -u root</b><br />Welcome to the MariaDB monitor. Commands end with ; or \g.<br />Your MariaDB connection id is 2<br />Server version: 5.5.60-MariaDB MariaDB Server<br /><br />Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.<br /><br />MariaDB [(none)]> <b>SET PASSWORD FOR 'root'@'localhost' = PASSWORD('yourpassword');</b><br />Query OK, 0 rows affected (0.00 sec)<br /><br />MariaDB [(none)]><br /></pre></li><li>Sin desconectarnos pasamos a crear la base de datos que será utilizada desde el mismo servidor:<br /><pre>MariaDB [(none)]> <b>CREATE DATABASE ocsweb;</b><br />Query OK, 1 row affected (0.00 sec)<br /><br />MariaDB [(none)]><br /></pre></li><li>Creamos un nuevo usuario denominado <b>ocs</b> y le asignamos los <b>privilegios</b> necesarios para acceder a la base de datos <b>ocsweb</b> creada en el punto anterior.<br /><pre>MariaDB [(none)]> <b>CREATE USER 'ocs'@'localhost' IDENTIFIED BY 'ocspass';</b><br />Query OK, 0 rows affected (0.00 sec)<br /><br />MariaDB [(none)]> <b>GRANT ALL PRIVILEGES ON ocsweb.* TO 'ocs'@'localhost' WITH GRANT OPTION;</b><br />Query OK, 0 rows affected (0.00 sec)<br /><br />MariaDB [(none)]><br /></pre></li><li>Finalmente ejecutamos la siguiente directiva para aplicar los parámetros y salimos del intérprete de comandos de <b>MariaDB</b> ejecutando el comando <b>exit</b>:<br /><pre>MariaDB [(none)]> <b>FLUSH PRIVILEGES;</b><br />Query OK, 0 rows affected (0.00 sec)<br /><br />MariaDB [(none)]> <b>exit</b><br />Bye<br /><b>[root@testsrv ~]#</b><br /></pre></li><li>Por último también es importante ejecutar la directiva <b>mysql_secure_installation</b> y seguir las instrucciones para realizar configuraciones de seguridad adicionales al motor de base de datos. A continuación dejo resaltado en rojo las interacciones realizadas con la herramienta para definir ciertas configuraciones de seguridad:<br /><pre><b>[root@testsrv ~]# mysql_secure_installation</b><br /><br />NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB<br /> SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!<br /><br />In order to log into MariaDB to secure it, we'll need the current<br />password for the root user. If you've just installed MariaDB, and<br />you haven't set the root password yet, the password will be blank,<br />so you should just press enter here.<br /><br />Enter current password for root (enter for none): <br />OK, successfully used password, moving on...<br /><br />Setting the root password ensures that nobody can log into the MariaDB<br />root user without the proper authorisation.<br /><br />You already have a root password set, so you can safely answer 'n'.<br /><br /><b>Change the root password? [Y/n]</b> <span style="color: red;"><b>N</b></span><br /> ... skipping.<br /><br />By default, a MariaDB installation has an anonymous user, allowing anyone<br />to log into MariaDB without having to have a user account created for<br />them. This is intended only for testing, and to make the installation<br />go a bit smoother. You should remove them before moving into a<br />production environment.<br /><br /><b>Remove anonymous users? [Y/n]</b> <span style="color: red;"><b>Y</b></span><br /> ... Success!<br /><br />Normally, root should only be allowed to connect from 'localhost'. This<br />ensures that someone cannot guess at the root password from the network.<br /><br /><b>Disallow root login remotely? [Y/n]</b> <span style="color: red;"><b>Y</b></span><br /> ... Success!<br /><br />By default, MariaDB comes with a database named 'test' that anyone can<br />access. This is also intended only for testing, and should be removed<br />before moving into a production environment.<br /><br /><b>Remove test database and access to it? [Y/n]</b> <span style="color: red;"><b>Y</b></span><br /> - Dropping test database...<br /> ... Success!<br /> - Removing privileges on test database...<br /> ... Success!<br /><br />Reloading the privilege tables will ensure that all changes made so far<br />will take effect immediately.<br /><br /><b>Reload privilege tables now? [Y/n]</b> <span style="color: red;"><b>Y</b></span><br /> ... Success!<br /><br />Cleaning up...<br /><br />All done! If you've completed all of the above steps, your MariaDB<br />installation should now be secure.<br /><br />Thanks for using MariaDB!<br /><b>[root@testsrv ~]#</b><br /></pre></li></ol><br /><br /><h3>Instalación del servidor OCS Inventory desde RPM</h3><ol><li>Instalamos y activamos el repositorio <b>EPEL</b> (Extra Packages for Enterprise Linux) requerido para suplir algunas dependencias.<br /><pre><b>[root@testsrv yum.repos.d]# yum --enablerepo=extras install epel-release</b><br /></pre></li><li>Luego procedemos a descargar e instalar los repositorios <b>ocsinventory-release-latest</b> y <b>remi-release-8</b> que contienen paquetes requeridos para instalar la nueva herramienta en pasos posteriores:<br /><pre><b>[root@testsrv ~]# wget https://rpm.ocsinventory-ng.org/ocsinventory-release-latest.el8.ocs.noarch.rpm<br />[root@testsrv ~]# wget https://rpms.remirepo.net/enterprise/remi-release-8.rpm<br />[root@testsrv ~]# yum install ocsinventory-release-latest.el8.ocs.noarch.rpm remi-release-8.rpm</b><br /></pre></li><li>Para la instalación del servidor <b>OCS Inventory</b> debemos ejecutar la siguiente secuencia de comandos:<br /><pre><b>[root@testsrv ~]# dnf install yum-utils<br />[root@testsrv ~]# yum-config-manager --enable remi<br />[root@testsrv ~]# dnf module reset php<br />[root@testsrv ~]# dnf module install php:remi-7.3<br />[root@testsrv ~]# dnf install --enablerepo=PowerTools ocsinventory</b><br /></pre></li><li>Luego editamos el archivo <b>ocsinventory-server.conf</b> del directorio <b>/etc/httpd/conf.d</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/ocsinventory-server.conf</b><br /></pre>Y una vez abierto el archivo buscamos la siguiente directiva:<br /><pre><i># Password for user</i><br /> PerlSetVar OCS_DB_PWD ocs<br /></pre>Y le asignamos la misma contraseña que le asignamos al usuario <b>osc</b> del motor de base de datos <b>MariaDB</b>:<br /><pre><i># Password for user</i><br /> PerlSetVar OCS_DB_PWD <b>ocspass</b><br /></pre>La misma configuración también tenemos que realizar en el archivo <b>ocsinventory-restapi.conf</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/ocsinventory-restapi.conf</b><br /></pre></li><li>Si queremos <b>evitar que aparezca el sitio web de bienvenida de Apache</b> al acceder al <b>documento root</b> (http://ip_o_nombre_dominio_servidor), podemos hacer que automáticamente se redirija al sub-directorio <b>ocsreports</b> (http://ip_o_nombre_dominio_servidor/ocsreports) editando el archivo <b>welcome.conf</b> del directorio <b>/etc/httpd/conf.d</b>:<br /><pre><b>[root@testsrv conf.d]# vim /etc/httpd/conf.d/welcome.conf</b><br /></pre>Y luego agregarle antes de todo la directiva <b>RedirectMatch</b> de la siguiente manera:<br /><pre><i>#<br /># This configuration file enables the default "Welcome" page if there<br /># is no default index page present for the root URL. To disable the<br /># Welcome page, comment out all the lines below.<br />#<br /># NOTE: if this file is removed, it will be restored on upgrades.<br />#</i><br /><b>RedirectMatch ^/$ /ocsreports/</b><br /><br /><LocationMatch "^/+$"><br /> Options -Indexes<br /> ErrorDocument 403 /.noindex.html<br /></LocationMatch><br /><br /><Directory /usr/share/httpd/noindex><br /> AllowOverride None<br /> Require all granted<br /></Directory><br /><br />Alias /.noindex.html /usr/share/httpd/noindex/index.html<br />Alias /noindex/css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css<br />Alias /noindex/css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css<br />Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif<br />Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png<br /></pre></li><li>A continuación necesitamos editar el archivo <b>php.ini</b> ubicado en el directorio <b>/etc</b> para realizar una serie de configuraciones:<br /><pre><b>[root@testsrv ~]# vim /etc/php.ini</b><br /></pre>Y una vez abierto buscamos y modificamos el valor de la directiva <b>post_max_size</b> como sigue:<br /><pre><i>; Maximum size of POST data that PHP will accept.<br />; Its value may be 0 to disable the limit. It is ignored if POST data reading<br />; is disabled through enable_post_data_reading.<br />; http://php.net/post-max-size<br />;post_max_size = 8M</i><br /><b>post_max_size = 201M</b><br /></pre>y también de la directiva <b>upload_max_filesize</b>:<br /><pre><i>; Maximum allowed size for uploaded files.<br />; http://php.net/upload-max-filesize<br />;upload_max_filesize = 2M</i><br /><b>upload_max_filesize = 200M</b><br /></pre></li><li>Procedemos a activar e iniciar el servicio requerido <b>php-fpm</b>:<br /><pre><b>[root@testsrv ~]# systemctl enable php-fpm<br />[root@testsrv ~]# systemctl start php-fpm</b><br /></pre></li><li>El siguiente paso consiste en reiniciar el servidor <b>Apache</b>:<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre></li><li>Si todo ha funcionado como corresponde desde nuestro navegador Web favorito colocamos una URL similar a la que sigue (reemplazar el nombre del servidor testsrv por el suyo o bien la dirección IP que hayan usado para el mismo):<br /><pre><b>https://testsrv/ocsreports/</b><br /></pre>Que debería lanzar la siguiente interfaz de usuario para avanzar con la configuración del servidor OCS Inventory. Como se puede observar, se tiene que introducir los datos de conexión del motor de base de datos:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-1.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="828" data-original-width="1043" height="507" src="http://files.tormentadebits.com/images/00060-ocs-inventory-1.JPG" width="640" /></a></div>Una vez cargado los datos que corresponden en cada campo procedemos a presionar el botón <b>Send</b>.<br /><br /></li><li>A continuación el asistente web de configuración nos indicará que la instalación ha concluido y que hagamos clic en el enlace asociado al texto "<b>Click here to enter OCS-NG GUI</b>".<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-2.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="824" data-original-width="1044" height="505" src="http://files.tormentadebits.com/images/00060-ocs-inventory-2.JPG" width="640" /></a></div><br /></li><li>A continuación el asistente web nos informa que se puede actualizar el contenido de la base de datos de una versión anterior a la versión más reciente. Para avanzar presionamos el botón <b>Perform the update</b>:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-3.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="826" data-original-width="1041" height="508" src="http://files.tormentadebits.com/images/00060-ocs-inventory-3.JPG" width="640" /></a></div><br /></li><li>Luego del paso anterior el asistente nos confirmará que la actualización fue realizada exitosamente y que hagamos clic nuevamente en el link "<b>Click here to enter OCS-NG GUI</b>" para acceder a la consola de administración de la herramienta.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-4.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="824" data-original-width="1042" height="506" src="http://files.tormentadebits.com/images/00060-ocs-inventory-4.JPG" width="640" /></a></div><br /></li><li>En el siguiente paso ya estamos en la interfaz de conexión de la consola de administración de <b>OCS Inventory</b>. Debemos especificar el usuario <b>admin</b> que es el administrador de la herramienta y cuya contraseña por defecto también es la palabra <b>admin</b>:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-5.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="826" data-original-width="1044" height="506" src="http://files.tormentadebits.com/images/00060-ocs-inventory-5.JPG" width="640" /></a></div><br /></li><li>Autorizada la conexión, la herramienta nos llevará al dashboard donde se muestra una alerta de seguridad que nos informa que el archivo <b>install.php</b> sigue existiendo en el directorio <b>ocsreports</b>:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-6.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="824" data-original-width="1163" height="453" src="http://files.tormentadebits.com/images/00060-ocs-inventory-6.JPG" width="640" /></a></div><br />La alerta anterior se debe a que alguien podría volver a ejecutar el archivo <b>install.php</b> especificando la URL completa. Para evitar eso nos dirigimos al directorio <b>/usr/share/ocsinventory-reports/ocsreports</b> desde donde movemos el archivo al directorio <b>/etc/ocsinventory</b> y de paso lo renombramos:<br /><pre><b>[root@testsrv ~]# cd /usr/share/ocsinventory-reports/ocsreports<br />[root@testsrv ocsreports]# mv install.php /etc/ocsinventory/install.php.bkp</b><br /></pre></li><li>Si volvemos a refrescar nuestro navegador podremos observar que el mensaje de advertencia desaparece, dejándonos la consola de administración lista para ser utilizada.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00060-ocs-inventory-7.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="819" data-original-width="1155" height="454" src="http://files.tormentadebits.com/images/00060-ocs-inventory-7.JPG" width="640" /></a></div><br />Como no dispongo de mucho tiempo no daré ninguna introducción sobre las opciones de configuración y utilización que ofrece la consola de administración de la herramienta <b>OCS Inventory NG</b>. Además, aún no tengo instalado un agente remoto que suministre información al servidor que se pueda mostrar de ejemplo.<br /></li></ol><h3><br /></h3><h3>Adecuación del servidor para distribución de Agentes</h3>Es necesario realizar algunas configuraciones para adecuar nuestro servidor OCS Inventory para que pueda servir de plataforma de descarga de los agentes OCS a través de distintos protocolos y así facilitar su instalación en los equipos que deseamos inventariar.<br /><ol> <li> Lo primero que tenemos que hacer es crear un directorio en donde podamos ubicar los agentes para su descarga remota, para ello creamos el siguiente directorio:<br /> <pre><b>[root@testsrv ~]# mkdir -p /srv/ocsinventory/agents</b><br /></pre> Dentro del directorio <b>/srv/ocsinventory/agents</b> recomendamos crear varios directorios para los agentes cuyo configuración y versión dependen para el sistema operativo para el cual fueron preparados. En este ejemplo estaremos abarcando la instalación de agentes para los sistemas operativos <b>Windows</b> y <b>openSUSE</b>:<br /> <pre><b>[root@testsrv ~]# mkdir /srv/ocsinventory/agents/Windows<br />[root@testsrv ~]# mkdir /srv/ocsinventory/agents/openSUSE</b><br /></pre> Finalmente asignamos los permisos correspondientes a la estructura del directorio <b>/srv/ocsinventory</b>:<br /> <pre><b>[root@testsrv ~]# chown -Rf apache:root /srv/ocsinventory</b><br /></pre> </li> <li> El siguiente paso consistirá en configurar el servicio <b>Apache</b> para permitir que los agentes puedan ser descargados remotamente a través del protocolo <b>http</b>. Para ello editamos el archivo de configuración <b>ocsinventory-reports.conf</b> del directorio <b>/etc/httpd/conf.d</b>:<br /> <pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/ocsinventory-reports.conf</b><br /></pre> Y al final del archivo le agregamos la siguiente configuración:<br /> <pre><i># Path para descargas de instaladores de agentes.</i><br />Alias /ocsagents /srv/ocsinventory/agents<br /><Directory /srv/ocsinventory/agents><br /> Options Indexes FollowSymLinks<br /> AllowOverride All<br /> Order allow,deny<br /> Allow from all<br /> Require all granted<br /></Directory><br /></pre>Como medida de seguridad adicional, también procederemos a configurar un archivo de autenticación <b>htpasswd</b> en el servidor OCS Inventory para que exija a los agentes remotos autenticarse con un usuario y contraseña antes de que puedan enviar información alguna. Para ello comenzamos por editar el archivo <b>ocsinventory-server.conf</b> del directorio <b>/etc/httpd/conf.d</b>: <pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/ocsinventory-server.conf</b><br /></pre>Y en la sección que sigue a continuación descomentamos las líneas correspondientes a las directivas <b>AuthType</b>, <b>AuthName</b>, <b>AuthUserFile</b> y <b>Require</b> (<span style="background-color: #fce8b2;">resaltadas en amarillo</span>), y nos aseguramos de <b>comentar la línea</b> relacionada a la directiva <b>Require all granted</b> (<span style="background-color: #f4c7c3;">resaltada en rojo</span>) para evitar que el servidor Apache tome ésta directiva como la principal en vez de la directiva <b>Require valid-user</b>: <pre><i> # Engine apache settings<br /> # "Virtual" directory for handling OCS Inventory NG agents communications<br /> # Be careful, do not create such directory into your web server root document !</i><br /> <Location /ocsinventory><br /> <IfModule mod_authz_core.c><br /> <i># Apache 2.4</i><br /><b style="background-color: #f4c7c3;"> <i>#Require all granted</i></b><br /> </IfModule><br /> <IfModule !mod_authz_core.c><br /> <i># Apache 2.2</i><br /> order deny,allow<br /> allow from all<br /> </IfModule><br /> <i># If you protect this area you have to deal with http_auth_* agent's parameters</i><br /><b style="background-color: #fce8b2;"> AuthType Basic<br /> AuthName "OCS Inventory agent area"<br /> AuthUserFile "/etc/ocsinventory/ocsinventory-server/htpasswd"<br /> Require valid-user</b><br /> SetHandler perl-script<br /> PerlHandler Apache::Ocsinventory<br /> </Location><br /></pre>Con el siguiente comando actualizamos el archivo <b>htpasswd</b> del directorio <b>/etc/ocsinventory/ocsinventory-server</b> (o bien lo crearemos si no existe) con el nombre del usuario genérico "<b>ocsagentes</b>" y su correspondiente contraseña de ejemplo "<b>passwagentes</b>" que deberán usar todos los agentes para conectarse al servidor: <pre><b>[root@testsrv ~]# htpasswd -c /etc/ocsinventory/ocsinventory-server/htpasswd ocsagentes</b><br />New password: <br />Re-type new password: <br />Adding password for user ocsagentes<br /><b>[root@testsrv ~]#b</b><br /></pre>Finalmente verificamos la configuración del servicio <b>Apache</b> y lo reiniciamos para que los cambios tomen efecto: <pre><b>[root@testsrv ~]# apachectl configtest<br />[root@testsrv ~]# systemctl restart httpd</b><br /></pre> </li> <li> Otro medio para facilitar la descarga remota de los agentes, especialmente en equipos que tienen instalado el sistema operativo <b>Windows</b>, es compartir el directorio <b>/srv/ocsinventory/agents</b> a través de <b>Samba</b>. Comenzamos por instalar las dependencias requeridas para hacer funcionar el servicio <b>Samba</b>:<br /> <pre><b>[root@testsrv ~]# yum install samba samba-client samba-common</b><br /></pre> A continuación habilitamos en el <b>Firewall</b> los puertos que utiliza el servicio <b>Samba</b>: <pre><b>[root@testsrv ~]# firewall-cmd --permanent --zone=public --add-service=samba<br />[root@testsrv ~]# firewall-cmd --reload</b><br /></pre> A continuación editamos el archivo de configuración de Samba <b>smb.conf</b> ubicado en el directorio <b>/etc/samba</b>:<br /> <pre><b>[root@testsrv ~]# vim /etc/samba/smb.conf</b><br /></pre> En el cual configuramos las directivas <b>workgroup</b> y <b>netbios name</b>, comentamos con puntos y comas las secciones <b>homes</b>, <b>printers</b> y <b>print$</b>, y al final del archivo agregamos la sección <b>ocsagents</b>:<br /> <pre><i># See smb.conf.example for a more detailed config file or<br /># read the smb.conf manpage.<br /># Run 'testparm' to verify the config is correct after<br /># you modified it.</i><br /><br />[global]<br /> <b>workgroup = gknet.local</b><br /> server string = Samba Server %v<br /> <b>netbios name = testsrv</b><br /> security = user<br /> map to guest = bad user<br /> passdb backend = tdbsam<br /><br /> printing = cups<br /> printcap name = cups<br /> load printers = yes<br /> cups options = raw<br /><br /><i>;[homes]<br />; comment = Home Directories<br />; valid users = %S, %D%w%S<br />; browseable = No<br />; read only = No<br />; inherit acls = Yes<br /><br />;[printers]<br />; comment = All Printers<br />; path = /var/tmp<br />; printable = Yes<br />; create mask = 0600<br />; browseable = No<br /><br />;[print$]<br />; comment = Printer Drivers<br />; path = /var/lib/samba/drivers<br />; write list = @printadmin root<br />; force group = @printadmin<br />; create mask = 0664<br />; directory mask = 0775</i><br /><br /><b>[ocsagents]<br /> comment = OCS Inventory Agents Repository<br /> path = /srv/ocsinventory/agents<br /> browseable = yes<br /> writable = no<br /> guest ok = yes</b><br /></pre>Luego ya podemos habilitar e iniciar los servicios Samba <b>smb</b> y <b>nmb</b> con los siguientes comandos: <pre><b>[root@testsrv ~]# systemctl enable smb.service<br />[root@testsrv ~]# systemctl enable nmb.service<br />[root@testsrv ~]# systemctl start smb.service<br />[root@testsrv ~]# systemctl start nmb.service</b><br /></pre></li><li>Con el paso anterior hemos finalizado la adecuación de nuestro servidor OCS Inventory para que funcione como plataforma de distribución de los instaladores de los agentes OCS y mejorar la seguridad de las conexiones de los agentes.</li></ol> <h2><br /></h2><h2>Realización de copias de seguridad</h2><ol><li>En principio necesitamos definir un directorio en donde ubicar las copias de seguridad realizadas, en mi caso voy a crear una estructura de directorios <b>backups/ocsinventory</b> en el directorio raíz.<br /><pre><b>[root@testsrv ~]# mkdir -p /backups/ocsinventory</b><br /></pre></li><li>A continuación creamos el archivo <b>bkpocsinventory.sh</b> en el directorio <b>/backups/ocsinventory</b> que contendrá el script que realizará la copia de seguridad, además se le asignará los permisos correspondientes y luego lo editamos:<br /><pre><b>[root@testsrv ~]# touch /backups/ocsinventory/bkpocsinventory.sh<br />[root@testsrv ~]# chmod 750 /backups/ocsinventory/bkpocsinventory.sh<br />[root@testsrv ~]# vim /backups/ocsinventory/bkpocsinventory.sh</b><br /></pre>y le agregamos el siguiente script bash:<br /><pre><i>#!/bin/bash<br /># Realiza una copia de seguridad completa de la herramienta OCS Inventory.</i><br />DIA=`date +"%Y%m%d"`<br />HORA=`date +"%H%M"`<br />BACKUP_PATH=/backups/ocsinventory<br /> <br /><i># -- OCS</i><br />OCS_REPORTS_WEB=/usr/share/ocsinventory-reports<br />OCS_REPORTS_TOOLS=/var/lib/ocsinventory-reports<br />OCS_AGENTS_INSTALLERS=/srv/ocsinventory/agents<br />OCS_DB_NAME=ocsweb<br />OCS_DB_USER=ocs<br />OCS_DB_PASS=ocspass<br />OCS_DB_BACKUP=$OCS_REPORTS_WEB/ocsinventory-db-bkp.sql<br />OCS_APACHE_CONF_PATH=/etc/httpd/conf.d<br />OCS_BACKUP_NAME="ocsinventory-bkp-"$DIA"_"$HORA".tgz"<br />OCS_BACKUP_LIVE_TIME=30<br /><br /><i># -- PATRON LIMPIEZA</i><br />PATRON_BKP_DIARIO=ocsinventory-bkp-*.tgz<br /> <br /><i># Se procede a exportar la base de datos de OCS Inventory.</i><br />echo<br />echo "-->BACKUP DE LA BASE DE DATOS DE OCS INVENTORY"<br />echo "===================================================================="<br />echo "Exportando la base de datos de OCS Inventory a partir de MySQL. Aguarde un momento..."<br />mysqldump -v -u $OCS_DB_USER -p$OCS_DB_PASS --database $OCS_DB_NAME > $OCS_DB_BACKUP<br />echo "Fin del proceso de exportacion."<br />echo<br /> <br /><i># Se generan los archivos con todas las copias de seguridad para ser enviadas a una unidad de cinta.</i><br />echo<br />echo "-->CREANDO FULL BACKUP DE OCS INVENTORY"<br />echo "===================================================================="<br />tar -czf $BACKUP_PATH/$OCS_BACKUP_NAME $OCS_REPORTS_WEB $OCS_REPORTS_TOOLS $OCS_AGENTS_INSTALLERS $OCS_APACHE_CONF_PATH/ocsinventory-*<br /> <br /><i># Para no llenar el disco duro con backups, se eliminan todos los backups diarios pasados la cantidad<br /># de dias especificados en la variable OCS_BACKUP_LIVE_TIME.</i><br />echo<br />echo "-->LIMPIEZA DE BACKUPS ANTIGUOS"<br />echo "===================================================================="<br />find $BACKUP_PATH/$PATRON_BKP_DIARIO -mtime +$OCS_BACKUP_LIVE_TIME -exec rm {} \;<br /><br /><i># Mensaje de finalizacion:</i><br />echo<br />echo "-->FIN DE BACKUP"<br />echo<br /></pre>En este punto ya podemos probar la ejecución del script de la siguiente manera:<br /><pre><b>[root@testsrv ~]# /backups/ocsinventory/bkpocsinventory.sh</b><br /><span style="background-color: white;"> </span><br />-->BACKUP DE LA BASE DE DATOS DE OCS INVENTORY <br />==================================================================== <br />Exportando la base de datos de OCS Inventory a partir de MySQL. Aguarde un momento... <br />Info: Using unique option prefix 'database' is error-prone and can break in the future. Please use the full name <br />'databases' instead. <br />-- Connecting to localhost... <br />-- Retrieving table structure for table accesslog... <br />-- Sending SELECT query... <br />-- Retrieving rows... <br />....<br />....<br />-- Retrieving rows... <br />-- Disconnecting from localhost... <br />Fin del proceso de exportacion. <br /><br />-->CREANDO FULL BACKUP DE OCS INVENTORY <br />==================================================================== <br />tar: Eliminando la `/' inicial de los nombres <br />tar: Eliminando la `/' inicial de los objetivos de los enlaces <br /><br />-->LIMPIEZA DE BACKUPS ANTIGUOS <br />==================================================================== <br /><br />-->FIN DE BACKUP <br /><br /><b>[root@testsrv ~]#</b><br /></pre>Y al finalizar ya podríamos ver la copia de seguridad generada en el directorio <b>/backups/ocsinventory</b>:<br /><pre><b>[root@testsrv ~]# ls -l /backups/ocsinventory</b><br />total 2732<br />-rwxr-x---. 1 root root 1749 abr 19 01:42 bkpocsinventory.sh<br />-rw-r--r--. 1 root root 2793315 abr 19 01:43 ocsinventory-bkp-20200419_0143.tgz<br /><b>[root@testsrv ~]#</b><br /></pre></li><li>Para programar la ejecución periódica del script debemos agregar una tarea programada. Para ello creamos el archivo <b>ocsinventory</b> en el directorio <b>/etc/cron.d</b>:<br /><pre><b>[root@testsrv ~]# touch /etc/cron.d/ocsinventory<br />[root@testsrv ~]# vim /etc/cron.d/ocsinventory</b><br /></pre>Para luego agregarle el siguiente contenido:<br /><pre><i># Backup OCS Inventory</i><br /><b>30 22 * * * root /backups/ocsinventory/bkpocsinventory.sh > /backups/ocsinventory/bkpocsinventory.log 2>&1</b><br /></pre>Finalmente reiniciamos el servicio <b>cron</b> para que la tarea programada sea funcional.<br /><pre><b>[root@testsrv ~]# systemctl restart crond</b><br /></pre>Y hasta aquí va el artículo de hoy, veremos cuando sale el artículo sobre la instalación de los agentes.<br /></li></ol><br /><br /><h3>Referencias y enlaces útiles:</h3><ol><li><a href="http://wiki.ocsinventory-ng.org/03.Basic-documentation/Setting-up-a-OCS-Inventory-Server-with-rpm/" target="_blank">http://wiki.ocsinventory-ng.org/03.Basic-documentation/Setting-up-a-OCS-Inventory-Server-with-rpm/</a><br /></li><li><a href="https://kifarunix.com/install-ocs-ng-inventory-on-centos-8/" target="_blank">https://kifarunix.com/install-ocs-ng-inventory-on-centos-8/</a><br /></li><li><a href="http://wiki.ocsinventory-ng.org/03.Basic-documentation/Updating-the-server/" target="_blank">http://wiki.ocsinventory-ng.org/03.Basic-documentation/Updating-the-server/</a><br /></li><li><a href="http://wiki.ocsinventory-ng.org/10.Plugin-engine/Using-plugins-installer/" target="_blank">http://wiki.ocsinventory-ng.org/10.Plugin-engine/Using-plugins-installer/</a><br /></li><li><a href="http://wiki.ocsinventory-ng.org/02.Basic-documentation/Deploying-database-server/" target="_blank">http://wiki.ocsinventory-ng.org/02.Basic-documentation/Deploying-database-server/</a><br /></li><li><a href="http://wiki.ocsinventory-ng.org/02.Basic-documentation/Setting-up-a-OCS-Inventory-Server/#under-linux-operating-system" target="_blank">http://wiki.ocsinventory-ng.org/02.Basic-documentation/Setting-up-a-OCS-Inventory-Server/#under-linux-operating-system</a></li><li><a href="https://plugins.ocsinventory-ng.org/" target="_blank">https://plugins.ocsinventory-ng.org</a><br /></li><li><a href="https://proyectosbeta.net/2015/05/instalar-httpd-con-ssl-en-centos-7/" target="_blank">https://proyectosbeta.net/2015/05/instalar-httpd-con-ssl-en-centos-7</a><br /></li><li><a href="https://www.digitalocean.com/community/tutorials/how-to-create-an-ssl-certificate-on-apache-for-centos-7" target="_blank">https://www.digitalocean.com/community/tutorials/how-to-create-an-ssl-certificate-on-apache-for-centos-7</a><br /></li><li><a href="https://www.esquis.net/instalacion-y-configuracion-de-servidor-ocs-inventory-ng-en-ubuntu-17-04/" target="_blank">https://www.esquis.net/instalacion-y-configuracion-de-servidor-ocs-inventory-ng-en-ubuntu-17-04</a><br /></li><li><a href="http://ocsinventory.blogspot.com/2014/11/crear-certificado-autofirmado-pa-ocs.html" target="_blank">http://ocsinventory.blogspot.com/2014/11/crear-certificado-autofirmado-pa-ocs.html</a><br /></li></ol> <b><div><b><br /></b></div><span style="background-color: #c6dafc;">ACTUALIZACIÓN 28/06/2020</span></b>: Se ha agregado la nueva sección <b>"Adecuación del servidor para distribución de Agentes"</b> y se ha modificado de forma menor el script de backup para incorporar la ruta al repositorio de agentes <b>/srv/ocsinventory/agents</b>.GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com6tag:blogger.com,1999:blog-1035903216249592564.post-59846621691036731112019-12-29T13:29:00.004-03:002022-10-04T23:00:53.221-03:00Instalación de Redmine 3.4 en Linux CentOS 7<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00057.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1230" height="156" src="http://files.tormentadebits.com/covers/portada-00057.png" width="320" /></a></div>La idea de este artículo es documentar todo el proceso de instalación de <b>Redmine 3.4</b> en la versión más estable de <b>CentOS 7 (release 1905)</b>.<br /><br />Esto se debe a que me había sido imposible hacer funcionar el procedimiento de instalación descrito en <a href="https://www.blogger.com/2017/09/instalacion-de-redmine-3.4-en-linux-opensuse.html" target="_blank"><b>éste artículo redactado en 2017</b></a> para el sistema operativo <b>openSUSE Leap 42.3</b>, 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.<br /><a name='more'></a><br /><br /><h2>Configuración inicial del servidor</h2><ol><li>Realizar una instalación del <b>Línux CentOS 7 (release 1905)</b> con una configuración de <b>tipo servidor con entorno gráfico</b> 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.<br /><a name='more'></a><br /></li><li>Uno de los primeros pasos que se realizan es desactivar el <b>SELinux</b>, siendo responsabilidad del administrador evaluar si esto pone en riesgo o no la seguridad del servidor. Para ello editamos el archivo <b>/etc/selinux/config</b>,<br /><pre><b>[root@testsrv ~]# vim /etc/selinux/config</b><br /></pre>y le configuramos la directiva <b>SELINUX</b> con el valor <b>disabled</b>:<br /><pre><i># This file controls the state of SELinux on the system.<br /># SELINUX= can take one of these three values:<br /># enforcing - SELinux security policy is enforced.<br /># permissive - SELinux prints warnings instead of enforcing.<br /># disabled - No SELinux policy is loaded.</i><br /><b>SELINUX=disabled</b><br /><i># SELINUXTYPE= can take one of these two values:<br /># targeted - Targeted processes are protected,<br /># mls - Multi Level Security protection.</i><br /><b>SELINUXTYPE=targeted</b><br /></pre>Como los cambios anteriores solo toman efecto luego de reiniciar el sistema operativo, podemos parar el <b>SELinux</b> en el entorno de ejecución actual con el siguiente comando:<br /><pre><b>[root@testsrv ~]# setenforce 0</b><br /></pre>O bien para asegurar la partida, reiniciar el servidor.<br /><br /></li><li>Ahora nos toca agregar como fuente de datos para el gestor de paquetes <b>YUM</b> el contenido del DVD de instalación del sistema operativo. Para ello nos dirigimos al directorio de configuración <b>/etc/yum.repos.d</b>, hacemos una copia del seguridad del archivo <b>public-yum-ol6.repo</b> y lo re-nombramos a <b>dvd.repo</b>, para finalmente editarlo. Esto lo podemos hacer con los siguientes cuatro comandos:<br /><pre><b>[root@testsrv ~]# cd /etc/yum.repos.d/<br />[root@testsrv yum.repos.d]# cp CentOS-Media.repo CentOS-Media.repo.bkp<br />[root@testsrv yum.repos.d]# vim CentOS-Media.repo</b><br /></pre>Editamos el contenido dejándolo como sigue a continuación:<br /><pre>[c7-media]<br />name=CentOS-$releasever - Media<br />baseurl=file:///mnt/CentOS_DVD/<br />gpgcheck=1<br />enabled=1<br />gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7<br /></pre>Ahora el gestor de paquetes YUM ya tiene configurado la nueva fuente de datos que apunta al directorio local <b>/media</b>. 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<br /><pre><b>[root@testsrv yum.repos.d]# mkdir /mnt/CentOS_DVD<br />[root@testsrv yum.repos.d]# mount /dev/cdrom /mnt/CentOS_DVD</b><br /></pre></li><li>Paramos y desactivamos el servicio <b>packagekit</b> para evitar que proceda a descargar actualizaciones en segundo plano sin nuestra autorización:<br /><pre><b>[root@testsrv yum.repos.d]# systemctl stop packagekit<br />[root@testsrv yum.repos.d]# systemctl disable packagekit</b><br /></pre></li><li>También instalamos y activamos el repositorio <b>EPEL</b> (Extra Packages for Enterprise Linux) para suplir algunas dependencias.<br /><pre><b>[root@testsrv yum.repos.d]# yum --enablerepo=extras install epel-release</b><br /></pre></li><li>Podemos verificar los paquetes disponibles ejecutando lo siguiente, que incluye los repositorios de Extras de Internet configurados bajo el archivo <b>CentOS-Base.repo</b> y el repositorio <b>EPEL</b> agregado en el paso anterior:<br /><pre><b>[root@testsrv ~]# yum list available</b><br />Complementos cargados:fastestmirror, langpacks<br />Loading mirror speeds from cached hostfile<br />epel/x86_64/metalink | 3.6 kB 00:00:00<br /> * base: mirror.facom.ufms.br<br /> * epel: mirror.globo.com<br /> * extras: mirror.facom.ufms.br<br /> * updates: mirror.facom.ufms.br<br />..<br /></pre></li><li>Si queremos configurar un servidor <b>ntp</b> podemos editar el archivo <b>chrony.conf</b> del directorio <b>/etc</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/chrony.conf</b><br /></pre>Donde configuramos la sección <b>server</b> con nuestro servidor <b>ntp</b> preferido<br /><pre><i># Use public servers from the pool.ntp.org project.<br /># Please consider joining the pool (http://www.pool.ntp.org/join.html).<br />#server 0.centos.pool.ntp.org iburst<br />#server 1.centos.pool.ntp.org iburst<br />#server 2.centos.pool.ntp.org iburst<br />#server 3.centos.pool.ntp.org iburst</i><br /><b>server mi_servidor_ntp_local.gknet.local prefer</b><br /></pre>Finalmente tenemos que reiniciar el servicio <b>chrony</b> para que los cambios tomen efecto:<br /><pre><b>[root@testsrv ~]# systemctl restart chronyd</b><br /></pre>Para forzar la sincronización de la hora del equipo con el servidor <b>ntp</b> de forma inmediata podemos ejecutar el siguiente comando:<br /><pre><b>[root@testsrv ~]# ntpdate -u mi_servidor_ntp_local.gknet.local</b><br /></pre>Para ver en tiempo real la hora en el servidor, incluyendo los segundos, podemos ejecutar el comando <b>watch</b>. Para salir hay que presionar las teclas CTRL+C.<br /><pre><b>[root@testsrv ~]# watch -n 1 date</b><br /><br />Every 1,0s: date Mon Jul 1 11:35:04 2019<br /><br />lun jul 1 11:35:04 -04 2019<br /></pre></li></ol><br /><h2>Instalación de servidor Apache:</h2><ol><li>Tenemos que instalar el servidor <b>Apache</b>.<br /><pre><b>[root@testsrv ~]# yum install httpd mod_ssl openssl</b><br /></pre></li><li>Para activar el service <b>SSL</b> en <b>Apache</b> primero creamos el directorio <b>/etc/httpd/ssl</b> para albergar certificados<br /><pre><b>[root@testsrv ~]# mkdir /etc/httpd/ssl</b><br /></pre></li><li>Luego pasamos a ejecutar el comando <b>openssl</b> para generar una nueva llave para nuestro servidor Apache. Al ejecutar el comando nos solicitará que vayamos cargando información para el certificado:<br /><pre><b>[root@testsrv ~]# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/httpd/ssl/apache.key -out /etc/httpd/ssl/apache.crt</b><br />Generating a 2048 bit RSA private key<br />...............+++<br />...................+++<br />writing new private key to '/etc/httpd/ssl/apache.key'<br />-----<br />You are about to be asked to enter information that will be incorporated<br />into your certificate request.<br />What you are about to enter is what is called a Distinguished Name or a DN.<br />There are quite a few fields but you can leave some blank<br />For some fields there will be a default value,<br />If you enter '.', the field will be left blank.<br />-----<br />Country Name (2 letter code) [XX]:<b><span style="color: red;">PY</span></b><br />State or Province Name (full name) []:<b><span style="color: red;">It</span></b><br />Locality Name (eg, city) [Default City]:<b><span style="color: red;">HO</span></b><br />Organization Name (eg, company) [Default Company Ltd]:<b><span style="color: red;">Gabriel-Corp.</span></b><br />Organizational Unit Name (eg, section) []:<b><span style="color: red;">Informatica</span></b><br />Common Name (eg, your name or your server's hostname) []:<b><span style="color: red;">testsrv.gknet.local</span></b><br />Email Address []:<b><span style="color: red;">contacto(ARROBA)tormentadebits.com</span></b><br /><b>[root@ocssrv ~]#</b><br /></pre></li><li>Como estamos usando <b>OpenSSL</b>, se recomienda crear una fuerte clave <b>Diffie-Hellman</b>:<br /><pre><b>[root@testsrv ~]# openssl dhparam -out /etc/httpd/ssl/dhparam.pem 2048</b><br /></pre>El <b>hash code</b> generado por el comando anterior lo tenemos que agregar al certificado <b>apache.crt</b> generado más arriba<br /><pre><b>[root@testsrv ~]# cat /etc/httpd/ssl/dhparam.pem | tee -a /etc/httpd/ssl/apache.crt</b><br /></pre></li><li>Luego editamos el archivo de configuración <b>/etc/httpd/conf.d/ssl.conf</b><br /><pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/ssl.conf</b><br /></pre>Nos ubicamos donde se encuentran las directivas <b>#DocumentRoot</b> y <b>#ServerName</b>:<br /><pre><i># General setup for the virtual host, inherited from global configuration<br />#DocumentRoot "/var/www/html"<br />#ServerName www.example.com:443</i><br /></pre>Descomentamos ambas y a la directiva <b>ServerName</b> le asignamos el nombre de servidor que corresponde, en este ejemplo <b>testsrv</b>:<br /><pre><i># General setup for the virtual host, inherited from global configuration</i><br /><b>DocumentRoot "/var/www/html"<br />ServerName testsrv:443</b><br /></pre>Luego pasamos a configurar la directiva <b>SSLCertificateFile</b> a la que le asignamos la ruta al nuevo certificado generado más arriba:<br /><pre><i># Server Certificate:<br /># Point SSLCertificateFile at a PEM encoded certificate. If<br /># the certificate is encrypted, then you will be prompted for a<br /># pass phrase. Note that a kill -HUP will prompt again. A new<br /># certificate can be generated using the genkey(1) command.</i><br /><b>SSLCertificateFile /etc/httpd/ssl/apache.crt</b><br /></pre>Y finalmente también configuramos la directiva <b>SSLCertificateKeyFile</b> a la que le asignamos la ruta a la nueva llave generada más arriba:<br /><pre><i># Server Private Key:<br /># If the key is not combined with the certificate, use this<br /># directive to point at the key file. Keep in mind that if<br /># you've both a RSA and a DSA private key you can configure<br /># both in parallel (to also allow the use of DSA ciphers, etc.)</i><br /><b>SSLCertificateKeyFile /etc/httpd/ssl/apache.key</b><br /></pre>Guardamos los cambios y salimos del archivo de configuración<br /><br /></li><li>Comprobamos que la configuración de Apache esté correcta con el siguiente comando:<br /><pre><b>[root@testsrv ~]# apachectl configtest</b><br />Syntax OK<br /><b>#</b><br /></pre></li><li>Finalmente activamos e iniciamos el servicio <b>httpd</b> (Apache2):<br /><pre><b>[root@testsrv ~]# systemctl enable httpd<br />[root@testsrv ~]# systemctl start httpd</b><br /></pre></li></ol><br /><br /><h2>Firewall:</h2><ol><li>Tenemos que habilitar en el <b>Firewall</b> los puertos <b>http</b> y <b>https</b> para que el servidor <b>Apache</b> sea accesible desde equipos remotos.<br /><pre><b>[root@testsrv ~]# firewall-cmd --get-active-zones</b><br />public<br /> interfaces: ens192<br /><b>[root@testsrv ~]# firewall-cmd --zone=public --list-services</b><br />ssh dhcpv6-client <br /><b>[root@testsrv ~]# firewall-cmd --zone=public --permanent --add-service=http</b><br />success<br /><b>[root@testsrv ~]# firewall-cmd --zone=public --permanent --add-service=https</b><br />success<br /><b>[root@testsrv ~]# systemctl restart firewalld<br />[root@testsrv ~]# firewall-cmd --zone=public --list-services</b><br />ssh dhcpv6-client http https<br /></pre></li></ol><br /><br /><h2>Instalación y configuración de PostgreSQL</h2>A continuación se verán los pasos para instalar y configurar de forma básica el motor de base de datos <b>PostgreSQL</b>: <br /><ol><li>Para comenzar tenemos que instalar el motor de base de datos si aún no lo tenemos instalado:<br /><pre><b>[root@testsrv ~]# yum install postgresql-server postgresql-contrib phpPgAdmin</b><br /></pre></li><li>Luego tenemos que inicializar su configuración:<br /><pre><b>[root@testsrv ~]# postgresql-setup initdb</b><br />Initializing database ... OK<br /><br /><b>#</b><br /></pre></li><li>Activamos y arrancamos el motor de base de datos por primera vez:<br /><pre><b>[root@testsrv ~]# systemctl enable postgresql<br />[root@testsrv ~]# systemctl start postgresql</b><br /></pre></li><li>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 <b>postgresql.conf</b> en el directorio <b>/var/lib/pgsql/data</b> para luego editarlo:<br /><pre><b>[root@testsrv ~]# vim /var/lib/pgsql/data/postgresql.conf</b><br /></pre>Y luego buscamos la directiva <b>#listen_addresses</b>, la comentamos o modificamos debiendo quedar similar a lo que sigue:<br /><pre><i>#listen_addresses = 'localhost'</i><br />listen_addresses = '*'<br /></pre></li><li>Luego toca autorizar las redes a las que le permitiremos el acceso remoto. Pasamos a editar el archivo <b>pg_hba.conf</b> ubicado en el directorio <b>/var/lib/pgsql/data</b> como se muestra a continuación:<br /><pre><b>[root@testsrv ~]# vim /var/lib/pgsql/data/pg_hba.conf</b><br /></pre>Buscamos la siguiente sección, reemplazamos el método de autenticación <b>ident</b> a <b>md5</b> 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 <b>PostgreSQL 9.2.24</b> debemos dejar activa la línea relacionada a conexiones IPv6, a la cual también le tenemos que asignar el método <b>md5</b>.<br /><pre><i># TYPE DATABASE USER CIDR-ADDRESS METHOD<br /># "local" is for Unix domain socket connections only</i><br />local all all <span style="background-color: #fff2cc;">md5</span><br /><i># IPv4 local connections:</i><br />host all all 127.0.0.1/32 <span style="background-color: #fff2cc;">md5</span><br /><span style="background-color: #fff2cc;">host all all 192.168.1.0/24 md5</span><br /><i># IPv6 local connections:</i><br />host all all ::1/128 <span style="background-color: #fff2cc;">md5</span><br /></pre></li><li>El siguiente paso consiste en cambiar la contraseña del administrador del motor de base de datos <b>postgres</b>, para lo cual nos conectamos a la consola sql de Postgres,<br /><pre><b>[root@testsrv ~]# su postgres -c psql postgres</b><br /></pre>Cambiamos la contraseña y salimos de la consola ejecutando la siguiente secuencia de comandos:<br /><pre><b>postgres=# alter user postgres with password 'mi_contraseña';<br />postgres=# \q</b><br /></pre></li><li>Reiniciamos el servicio del motor de base de datos para que los cambios realizados previamente sean tomados en cuenta:<br /><pre><b>[root@testsrv ~]# systemctl restart postgresql</b><br /></pre></li><li>Ahora pasamos a configurar el <b>phpPgAdmin</b>, para lo cual a partir del archivo <b>config.inc.php</b> ubicado en el directorio <b>/etc/phpPgAdmin</b> creamos una copia con el nombre <b>config.inc.php</b> y luego lo editamos:<br /><pre><b>[root@testsrv ~]# cp /etc/phpPgAdmin/config.inc.php-dist /etc/phpPgAdmin/config.inc.php<br />[root@testsrv ~]# vim /etc/phpPgAdmin/config.inc.php</b><br /></pre>y verificamos la configuración de las siguientes directivas cuyo contenido debería ser similar a lo sigue:<br /><pre><i>// Configuración del servidor y puerto:</i><br /><b>$conf['servers'][0]['host'] = 'localhost';<br />$conf['servers'][0]['port'] = 5432;</b><br /><br /><i>// Si queremos permitir el acceso con el usuario administrador<br />// (postgres) la siguiente directiva debe ser igual a false:</i><br /><b>$conf['extra_login_security'] = false;</b><br /></pre>Guardamos los cambios y salimos del archivo de configuración para continuar con el siguiente paso.<br /><br /></li><li>A continuación tenemos que editar el archivo <b>phpPgAdmin.conf</b> del directorio <b>/etc/httpd/conf.d</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/httpd/conf.d/phpPgAdmin.conf</b><br /></pre>Y como en el servidor tenemos instalado <b>Apache 2.4</b> tenemos que modificar comentar la directiva <b>Require local</b> y justo abajo agregar la directiva <b>Require all granted</b> para que funcione:<br /><pre><i>#<br /># This configuration file maps the phpPgAdmin directory into the URL space.<br /># By default this application is only accessible from the local host.<br />#</i><br /><br />Alias /phpPgAdmin /usr/share/phpPgAdmin<br /><br /><Location /phpPgAdmin><br /> <IfModule mod_authz_core.c><br /> <i># Apache 2.4<br /> #Require local</i><br /> Require all granted<br /> <i>#Require host example.com</i><br /> </IfModule><br /> <IfModule !mod_authz_core.c><br /> <i># Apache 2.2</i><br /> Order deny,allow<br /> Deny from all<br /> Allow from 127.0.0.1<br /> Allow from ::1<br /> <i># Allow from .example.com</i><br /> </IfModule><br /></Location><br /></pre></li><li>Finalmente procedemos a reiniciar el servicio del <b>Apache 2</b> con el siguiente comando:<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre></li><li>Con estos últimos pasos concluimos con la puesta en marcha de Apache, lo que nos permitirá acceder localmente a phpPgAdmin mediante la siguiente <b>URL</b>:<br /><pre><a href="http://localhost/phpPgAdmin" target="_blank"><b>http://localhost/phpPgAdmin</b></a><br /></pre>Si carga el sitio <b>phpPgAdmin</b> pero tenemos problemas en loguearnos, podemos verificar que dice el archivo log de PostgreSQL, que lo podemos consultar con la siguiente directiva:<br /><pre><b>[root@testsrv ~]# tail -f /var/lib/pgsql/data/pg_log/postgresql-Sun.log</b><br /></pre>A continuación les dejo con algunas capturas de pantalla de <b>phpPgAdmin</b>:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00014-phpPgAdmin-01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://files.tormentadebits.com/images/00014-phpPgAdmin-01.png" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00014-phpPgAdmin-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="http://files.tormentadebits.com/images/00014-phpPgAdmin-02.png" width="400" /></a></div><br /></li><li>Con estos tres pasos anteriores hemos habilitado los puertos deseados en el cortafuego, con lo cual hemos culminado.<br /></li></ol><br /><br /><h2>Instalación y configuración de Redmine</h2>Comenzamos sin más rodeos con los pasos de instalación de la herramienta: <br /><ol><li>Comenzamos por crear en el motor de base de datos PostgreSQL un nuevo usuario y la base de datos para la herramienta <b>Redmine</b>, esto lo podemos hacer ejecutando los siguientes comandos:<br /><pre><b>[root@testsrv ~]# su postgres -c psql postgres</b><br />could not change directory to "/root"<br /><b>Password:</b><br />psql (9.2.24)<br />Type "help" for help.<br /><b>postgres=# CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'redmine' NOINHERIT VALID UNTIL 'infinity';<br />postgres=# CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;<br />postgres-# \q</b><br /></pre></li><li>Comenzamos por instalar las dependencias que necesita la herramienta.<br /><pre><b>[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</b><br /></pre>Sin embargo, como he tenido problemas para instalar dependencias para la versión <b>2.0.0</b> de <b>Ruby</b> (ya desoportada) que viene con el DVD de instalación de CentOS 7, no me quedó otra opción que utilizar la herramienta <b>RVM</b> (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 <b>RVM</b>, primero debemos instalar los siguientes paquetes:<br /><pre><b>[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</b></pre></li><li>Procedemos a descargar e instalar la herramienta <b>RVM</b> con los siguientes pasos:<br /><pre><b>[root@testsrv ~]# curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -<br />[root@testsrv ~]# curl -sSL https://rvm.io/pkuczynski.asc | gpg2 --import -<br />[root@testsrv ~]# curl -L get.rvm.io | bash -s stable<br />[root@testsrv ~]# source /etc/profile.d/rvm.sh<br />[root@testsrv ~]# rvm reload</b><br /></pre>A continuación verificamos que se hayan cumplido con todos los requerimientos de instalación:<br /><pre><b>[root@testsrv ~]# rvm requirements run</b><br />Checking requirements for centos.<br />Requirements installation successful.<br /><b>[root@testsrv ~]#</b><br /></pre>Luego instalamos la versión <b>2.4.6</b> de <b>Ruby</b>..<br /><pre><b>[root@testsrv ~]# rvm install 2.4.6</b><br />Searching for binary rubies, this might take some time.<br />No binary rubies available for: centos/7/x86_64/ruby-2.4.6.<br />Continuing with compilation. Please read 'rvm help mount' to get more information on binary rubies. <br />Checking requirements for centos.<br />Requirements installation successful.<br />Installing Ruby from source to: /usr/local/rvm/rubies/ruby-2.4.6, this may take a while depending on your cpu(s)...<br />ruby-2.4.6 - #downloading ruby-2.4.6, this may take a while depending on your connection...<br /> % Total % Received % Xferd Average Speed Time Time Time Current<br /> Dload Upload Total Spent Left Speed<br />100 12.0M 100 12.0M 0 0 1302k 0 0:00:09 0:00:09 --:--:-- 3127k<br />ruby-2.4.6 - #extracting ruby-2.4.6 to /usr/local/rvm/src/ruby-2.4.6.....<br />ruby-2.4.6 - #configuring..................................................................<br />ruby-2.4.6 - #post-configuration..<br />ruby-2.4.6 - #compiling..................................................................................<br />ruby-2.4.6 - #installing...........................<br />ruby-2.4.6 - #making binaries executable..<br />ruby-2.4.6 - #downloading rubygems-3.0.6<br />ruby-2.4.6 - #extracting rubygems-3.0.6......<br />ruby-2.4.6 - #removing old rubygems........<br />ruby-2.4.6 - #installing rubygems-3.0.6...............................................<br />ruby-2.4.6 - #gemset created /usr/local/rvm/gems/ruby-2.4.6@global<br />ruby-2.4.6 - #importing gemset /usr/local/rvm/gemsets/global.gems................................................................<br />ruby-2.4.6 - #generating global wrappers.......<br />ruby-2.4.6 - #gemset created /usr/local/rvm/gems/ruby-2.4.6<br />ruby-2.4.6 - #importing gemsetfile /usr/local/rvm/gemsets/default.gems evaluated to empty gem list<br />ruby-2.4.6 - #generating default wrappers.......<br />ruby-2.4.6 - #adjusting #shebangs for (gem irb erb ri rdoc testrb rake).<br />Install of ruby-2.4.6 - #complete <br />Ruby was built without documentation, to build it run: rvm docs generate-ri<br /><b>[root@testsrv ~]#</b><br /></pre>y lo seteamos como <b>por defecto</b> para que sea compatible con la versión del paquete <b>passenger</b> instalado mediante <b>yum</b>.<br /><pre><b>[root@testsrv ~]# rvm list<br />[root@testsrv ~]# rvm use 2.4.6 --default<br />[root@testsrv ~]# ruby --version</b><br /></pre>Con la herramienta <b>RVM</b> también configuramos las variables de entorno correctas para el servicio <b>crond</b> para permitir la ejecución de scripts Ruby con la versión correcta. Dicha configuración se copia al archivo denominado <b>redmine</b> del directorio <b>/etc/cron.d</b> que más adelante se utilizará para ejecutar todos los scripts Ruby que requerirá Redmine para funcionar.<br /><pre><b>[root@testsrv ~]# rvm cron setup<br />[root@testsrv ~]# crontab -l > /etc/cron.d/redmine<br />[root@testsrv ~]# chmod 644 /etc/cron.d/redmine</b><br /></pre>Finalmente con el comando <b>which</b> comprobamos la ubicación del programa <b>ruby</b> instalado con la herramienta <b>RVM</b>:<br /><pre><b>[root@testsrv ~]# which ruby</b><br />ruby 2.4.6p354 (2019-04-01 revision 67394) [x86_64-linux]<br /><b>[root@testsrv ~]#</b><br /></pre></li><li>A continuación procedemos a descargar la última versión disponible de la <b>rama 3.4</b> de <b>Redmine</b>, que al momento de escribir el artículo correspondía a la <b>versión 3.4.13</b>. Es importante aclarar que se ha decido utilizar dicha rama debido a que cuando comencé a redactar este artículo solo estaba <b>CentOS 7</b> cuyo paquete de <b>Ruby</b> más moderno que viene en el DVD corresponde a la <b>versión 2.0.0</b>, una versión incompatible con la <b>rama 4.0</b> de <b>Redmine</b>. Ahora bien, ya mas tarde aprendí a usar <b>RVM</b> 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:<br /><br /><a href="https://www.redmine.org/projects/redmine/wiki/RedmineInstall" target="_blank"><b>https://www.redmine.org/projects/redmine/wiki/RedmineInstall</b></a><br /><br />Descargamos el archivo en el directorio <b>/opt</b> para luego descomprimirla en el mismo directorio:<br /><pre><b>[root@testsrv ~]# cd /opt/<br />[root@testsrv opt]# wget https://www.redmine.org/releases/redmine-3.4.13.tar.gz<br />[root@testsrv opt]# tar -xzf redmine-3.4.13.tar.gz<br />[root@testsrv opt]# rm redmine-3.4.13.tar.gz<br />[root@testsrv opt]# mv redmine-3.4.13 redmine<br />[root@testsrv opt]# cd redmine/<br />[root@testsrv redmine]#</b><br /></pre></li><li>Una vez dentro del directorio raíz de la herramienta nos dirigimos a la carpeta <b>config</b> para crear y editar el archivo de configuración <b>database.yml</b>.<br /><pre><b>[root@testsrv redmine]# cd config/<br />[root@testsrv config]# cp database.yml.example database.yml<br />[root@testsrv config]# vim database.yml</b><br /></pre>Al cual le agregamos la configuración adecuada del motor de base de datos que utilizará Redmine<br /><pre><b>production:<br /> adapter: postgresql<br /> database: redmine<br /> host: localhost<br /> username: redmine<br /> password: redmine<br /> encoding: utf8</b><br /></pre></li><li>Luego, en el directorio <b>/opt/redmine/config</b> ejecutamos la directiva <b>bundler</b> con una serie de argumentos para resolver e instalar las dependencias requeridas para el entorno de producción (production) que necesita la herramienta <b>Redmine</b> para funcionar, las dependencias para el entorno de desarrollo y prueba (development y test respectivamente) son excluidas.<br /><pre><b>[root@testsrv config]# bundle install --without development test</b><br /></pre>El comando bundle se encargará de instalar todas las dependencias requeridas:<br /><pre>Fetching gem metadata from https://rubygems.org/..............<br />Fetching additional metadata from https://rubygems.org/..<br />Resolving dependencies...<br />Installing rake 12.3.2<br />Installing i18n 0.7.0<br />Installing minitest 5.11.3<br />Installing thread_safe 0.3.6<br />Installing tzinfo 1.2.5<br />..<br />..<br /></pre><b>OBS:</b> 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 <b>rmagick</b>, <b>pg</b>, 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.<br /><br /></li><li>A continuación generamos una nueva llave que utiliza <b>Rails</b> para codificar la información de sesiones contenidas en las cookies:<br /><pre><b>[root@testsrv config]# bundle exec rake generate_secret_token</b><br /></pre></li><li>Una vez concluido con el paso anterior nos posicionamos en el directorio <b>/opt/redmine</b> 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:<br /><pre><b>[root@testsrv config]# cd ..<br />[root@testsrv redmine]# RAILS_ENV=production bundle exec rake db:migrate<br />[root@testsrv redmine]# RAILS_ENV=production bundle exec rake redmine:load_default_data</b><br />(in /opt/redmine)<br /><br />Select language: bg, bs, ... en, en-GB, es, ... vi, zh, zh-TW [en] <span style="color: red;"><b>es</b></span><br />====================================<br />Default configuration data loaded.<br /></pre></li><li>Finalmente creamos un grupo y usuario de sistema, en ambos casos denominado <b>redmine</b>, y le hacemos dueño del directorio <b>/opt/redmine</b>:<br /><pre><b>[root@testsrv redmine]# groupadd -r redmine<br />[root@testsrv redmine]# useradd -r -g redmine redmine<br />[root@testsrv redmine]# chown -Rf redmine:redmine /opt/redmine</b><br /></pre></li><li>Ahora instalamos el módulo <b>Passenger</b> para permitir que <b>Apache2</b> pueda ejecutar aplicaciones <b>Ruby</b>:<br /><pre><b>[root@testsrv redmine]# gem install passenger<br />[root@testsrv redmine]# passenger-install-apache2-module<br />[root@testsrv redmine]# passenger-config validate-install<br />[root@testsrv redmine]# passenger-memory-stats</b><br /></pre>Ahora debemos crear en el directorio <b>/etc/httpd/conf.d</b> el archivo <b>passenger.conf</b> y luego editarlo,<br /><pre><b>[root@testsrv redmine]# touch /etc/httpd/conf.d/passenger.conf<br />[root@testsrv redmine]# vim /etc/httpd/conf.d/passenger.conf</b><br /></pre>Y copiar el siguiente contenido sugerido durante la instalación de la gema:<br /><pre><b>LoadModule passenger_module /usr/local/rvm/gems/ruby-2.4.6/gems/passenger-6.0.4/buildout/apache2/mod_passenger.so<br /><IfModule mod_passenger.c><br /> PassengerRoot /usr/local/rvm/gems/ruby-2.4.6/gems/passenger-6.0.4<br /> PassengerDefaultRuby /usr/local/rvm/gems/ruby-2.4.6/wrappers/ruby<br /></IfModule></b><br /></pre>Finalmente ejecutamos la directiva para validar la instalación del módulo <b>Passenger</b>:<br /><pre><b>[root@testsrv ~]# passenger-config validate-install</b><br />What would you like to validate?<br />Use <space> to select.<br />If the menu doesn't display correctly, press '!'<br /><br /> ⬢ Passenger itself<br /> ‣ ⬢ Apache<br /><br />-------------------------------------------------------------------------<br /><br />Checking whether there are multiple Apache installations...<br />Only a single installation detected. This is good.<br /><br />-------------------------------------------------------------------------<br /><br /> * Checking whether this Passenger install is in PATH... ✓<br /> * Checking whether there are no other Passenger installations... ✓<br /> * Checking whether Apache is installed... ✓<br /> * Checking whether the Passenger module is correctly configured in Apache... ✓<br /><br />Everything looks good. :-)<br /><b>[root@testsrv ~]#</b><br /></pre>Y comprobar el uso de memoria del mencionado módulo:<br /><pre><b>[root@testsrv ~]# passenger-memory-stats</b><br />Version: 6.0.4<br />Date : 2019-12-15 23:04:05 -0300<br /><br />---------- Apache processes ----------<br />PID PPID VMSize Private Name<br />--------------------------------------<br />11563 1 399.3 MB 0.4 MB /usr/sbin/httpd -DFOREGROUND<br />11609 11563 401.4 MB 0.3 MB /usr/sbin/httpd -DFOREGROUND<br />11610 11563 401.4 MB 0.3 MB /usr/sbin/httpd -DFOREGROUND<br />11611 11563 401.4 MB 0.4 MB /usr/sbin/httpd -DFOREGROUND<br />11612 11563 401.4 MB 0.3 MB /usr/sbin/httpd -DFOREGROUND<br />11613 11563 401.4 MB 0.3 MB /usr/sbin/httpd -DFOREGROUND<br />11661 11563 401.4 MB 0.3 MB /usr/sbin/httpd -DFOREGROUND<br />11700 11563 401.4 MB 0.2 MB /usr/sbin/httpd -DFOREGROUND<br />11701 11563 401.4 MB 0.2 MB /usr/sbin/httpd -DFOREGROUND<br />11702 11563 401.4 MB 0.2 MB /usr/sbin/httpd -DFOREGROUND<br />11703 11563 401.4 MB 0.2 MB /usr/sbin/httpd -DFOREGROUND<br />### Processes: 11<br />### Total private dirty RSS: 3.39 MB<br /><br /><br />-------- Nginx processes --------<br /><br />### Processes: 0<br />### Total private dirty RSS: 0.00 MB<br /><br /><br />------ Passenger processes ------<br />PID VMSize Private Name<br />---------------------------------<br />11589 357.7 MB 2.1 MB Passenger watchdog<br />11592 1119.2 MB 4.2 MB Passenger core<br />11674 469.4 MB 141.5 MB Passenger AppPreloader: /opt/redmine (forking...)<br />### Processes: 3<br />### Total private dirty RSS: 147.76 MB<br /><b>[root@testsrv ~]#</b><br /></pre></li><li><b>(OPCIÓN 1) ACCESO MEDIANTE VIRTUAL HOSTS</b>: Si deseamos que <b>Apache</b> sirva el sitio web de <b>Redmine</b> a través de un nombre de dominio totalmente cualificado (<i>FQDN: Fully Qualified Domain Name</i>) resuelto a través de servidores de nombres (<i>DNS</i>) internos o externos podemos configurar un host virtual para dicho fin. Para ello nos dirigimos al directorio <b>/etc/httpd/conf.d</b> y creamos un nuevo archivo llamado <b>vredmine.conf</b>:<br /><pre><b>[root@testsrv ~]# cd /etc/httpd/conf.d<br />[root@testsrv conf.d]# touch vredmine.conf</b></pre>Editamos el archivo con nuestro editor de texto preferido..<br /><pre><b>[root@testsrv conf.d]# vim vredmine.conf</b><br /></pre>Y luego agregamos las siguientes directivas:<br /><pre><i># -- ES NECESARIO DEFINIR LA DIRECTIVA NameVirtualHost CUANDO<br /># SE CONFIGURAN HOSTS VIRTUALES BASADOS EN NOMBRES.</i><br /><b>NameVirtualHost *:80</b><br /><b>NameVirtualHost *:443</b><br /><br /><i># -- CONFIGURACION DEL HOST VIRTUAL POR DEFECTO, QUE APUNTA<br /># A LA RUTA TRADICIONAL.</i><br /><b><VirtualHost *:80 *:443></b><br /><b> ServerName <span style="color: red;">testsrv</span></b><br /><b> ServerAlias <span style="color: red;">testsrv *.testsrv testsrv.gknet.local *testsrv.gknet.local</span></b><br /><b> DocumentRoot /srv/www/htdocs</b><br /><b></VirtualHost></b><br /><br /><i># -- CONFIGURACION DEL VIRTUAL HOST PARA REDMINE</i><br /><b><VirtualHost *:80 *:443></b><br /><b> Options +Indexes</b><br /><b> ServerAdmin <span style="color: red;">nombre_usuario@gmail.com</span></b><br /><b> ServerName <span style="color: red;">redminesrv</span></b><br /><b> ServerAlias <span style="color: red;">redminesrv.gknet.local *.redminesrv.gknet.local redminesrv *.redminesrv</span></b><br /><b> DocumentRoot <span style="color: red;">/opt/redmine/public</span></b><br /><b> RailsEnv production</b><br /><br /><b> PassengerUser apache</b><br /><b> PassengerGroup apache</b><br /><br /><b> <Directory "<span style="color: red;">/opt/redmine/public</span>"></b><br /><b> Options +Indexes -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch</b><br /><b> AllowOverride All</b><br /><i> # Configuracion Apache 2.2<br /> #Order allow,deny<br /> #Allow from all<br /><br /> # Configuracion Apache 2.4 --> https://httpd.apache.org/docs/2.4/upgrading.html</i><br /><b> Require all granted</b><br /><b> </Directory></b><br /><b></VirtualHost></b><br /></pre>Con esto ya tenemos el servidor web configurado con soporte virtual host.<br /><br /></li><li><b>(OPCIÓN 2) ACCESO MEDIANTE SUBDIRECTORIOS</b>: Una opción alternativa a la configuración de host virtual de <b>Apache</b> para desplegar <b>Redmine</b> 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.<br /><br />Como primer paso nos dirigimos al directorio <b>/etc/httpd/conf.d</b>, para luego crear y editar un nuevo archivo llamado <b>redmine.conf</b>:<br /><pre><b>[root@testsrv ~]# cd /etc/httpd/conf.d</b><br /><b>[root@testsrv conf.d]# touch redmine.conf<br />[root@testsrv conf.d]# vim redmine.conf</b><br /></pre>Al que le agregamos la siguiente configuración:<br /><pre><i># -- ALIAS DEL SUBDIRECTORIO APUNTANDO A LA RUTA REAL DE<br /># LA HERRAMIENTA REDMINE.</i><br /><b>Alias <span style="color: red;">/redmine /opt/redmine/public</span></b><br /><br /><i># -- DEFINICION DEL ENTORNO RAILS.</i><br /><b>RailsEnv production</b><br /><b>RailsBaseURI <span style="color: red;">/redmine</span></b><br /><br /><i># -- CONFIGURACION DE PASSENGER.</i><br /><b>PassengerUser apache<br />PassengerGroup apache</b><br /><br /><i># -- CONFIGURACIONES DEL DIRECTORIO DE TRABAJO.</i><br /><b><Directory "<span style="color: red;">/opt/redmine/public</span>"></b><br /><b> Options -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch</b><br /><b> AllowOverride All</b><br /><i> # Configuracion Apache 2.2<br /> #Order allow,deny<br /> #Allow from all<br /> <br /> # Configuracion Apache 2.4 --> https://httpd.apache.org/docs/2.4/upgrading.html</i><br /><b> Require all granted</b><br /><b></Directory></b><br /></pre>Si queremos<b> evitar que aparezca el sitio web de bienvenida de Apache</b> al acceder al <b>documento root</b> (http://ip_o_nombre_dominio_servidor), podemos hacer que automáticamente se redirija al sub-directorio <b>redmine</b> (http://ip_o_nombre_dominio_servidor/redmine) editando el archivo <b>welcome.conf</b> del directorio <b>/etc/httpd/conf.d</b>:<br /><pre><b>[root@testsrv conf.d]# vim /etc/httpd/conf.d/welcome.conf</b><br /></pre>Y luego agregarle antes de todo la directiva <b>RedirectMatch</b> de la siguiente manera:<br /><pre><i>#<br /># This configuration file enables the default "Welcome" page if there<br /># is no default index page present for the root URL. To disable the<br /># Welcome page, comment out all the lines below.<br />#<br /># NOTE: if this file is removed, it will be restored on upgrades.<br />#</i><br /><b>RedirectMatch ^/$ /redmine/</b><br /><br /><LocationMatch "^/+$"><br /> Options -Indexes<br /> ErrorDocument 403 /.noindex.html<br /></LocationMatch><br /><br /><Directory /usr/share/httpd/noindex><br /> AllowOverride None<br /> Require all granted<br /></Directory><br /><br />Alias /.noindex.html /usr/share/httpd/noindex/index.html<br />Alias /noindex/css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css<br />Alias /noindex/css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css<br />Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif<br />Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png<br /></pre></li><li>Asignamos el usuario <b>apache</b> y al grupo <b>apach</b> como dueños de ciertos directorios, y aplicamos algunos permisos de escritura y lectura:<br /><pre><b>[root@testsrv conf.d]# cd /opt/redmine<br />[root@testsrv conf.d]# chown -Rf apache:apache files log tmp vendor public/plugin_assets<br />[root@testsrv conf.d]# chmod -Rf 755 files log tmp vendor public/plugin_assets</b><br /></pre></li><li>Para que el módulo <b>Passenger</b> de Apache interprete correctamente el contenido del directorio <b>/opt/redmine/public</b>, tenemos que crear un enlace simbólico del mencionado directorio en el directorio <b>/var/www/html</b> de la siguiente manera:<br /><pre><b>[root@testsrv conf.d]# ln -s /opt/redmine/public /var/www/html/redmine</b><br /></pre></li><li>Finalmente reiniciamos el servicio <b>httpd</b>:<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre></li></ol><br /><br /><h2>Acceso a Redmine</h2><ol><li>Si para acceder a la herramienta <b>Redmine</b> hemos configurado el servicio <b>Apache</b> 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 <b>DNS</b> o mediante alguna entrada al archivo <b>/etc/hosts</b> en la máquina cliente que se trata de conectar a la herramienta. Como ejemplo podríamos tener la siguiente <b>URL</b>:<br /><pre><b>http://redmine.mi_dominio.local</b><br /></pre></li><li>Si en el caso contrario hemos configurado el acceso a la herramienta <b>Remine</b> mediante un subdirectorio en <b>Apache</b>, la <b>URL </b>deberá ser similar a la siguiente:<br /><pre><b>http://ip_o_nombre_dominio_servidor/redmine</b><br /></pre>Por defecto la herramienta se ve así:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1098" height="500" src="http://files.tormentadebits.com/images/00025-redmine-01.png" width="640" /></a></div><br /><blockquote class="green"><b>OBS:</b> El login del usuario administrador es <b>admin</b> y su contraseña por defecto también es <b>admin</b>, pero inmediatamente después la herramienta nos obligará a reemplazarla por una diferente.</blockquote><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1098" height="497" src="http://files.tormentadebits.com/images/00025-redmine-02.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-03.png" imageanchor="1"><img border="0" data-original-height="860" data-original-width="1098" height="499" src="http://files.tormentadebits.com/images/00025-redmine-03.png" width="640" /></a></div><br />En el apartado <b>Mi Cuenta</b> del usuario <b>admin</b>, accesible desde el enlace de la esquina superior derecha, se recomienda configurar las siguientes opciones:<br />- Correo electrónico<br />- Idioma<br />- Notificaciones por correo<br />- Zona horaria<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="859" data-original-width="1106" height="497" src="http://files.tormentadebits.com/images/00025-redmine-04.png" width="640" /></a></div></li></ol><br /><br /><h2>Instalación de Plugins</h2><ol><li>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 <a href="http://www.redmine.org/plugins?utf8=%E2%9C%93&page=1&sort=&v=3.4" target="_blank"><b>éste enlace</b></a>, de entre los cuales me gusta instalar los siguientes:<br /><br /><b>Plugins libres:</b><br />- <a href="http://www.redmine.org/plugins/redmine_theme_changer" target="_blank"><b>Theme Changer</b></a><br />- <a href="http://www.redmine.org/plugins/clipboard_image_paste" target="_blank"><b>Attach image from clipboard</b></a><br />- <a href="https://www.redmine.org/plugins/redmine_lightbox2" target="_blank"><b>Lightbox Plugin 2</b></a><br />- <a href="https://www.redmine.org/plugins/scrum-plugin" target="_blank"><b>Scrum Plugin</b></a><br />- <a href="https://www.redmine.org/plugins/redmine_periodic_task" target="_blank"><b>Periodic Task</b></a><br /><br /><b>Plugins de RedmineUP:</b><br />- <a href="http://www.redmine.org/plugins/redmine_people" target="_blank"><b>People</b></a><br />- <a href="http://www.redmine.org/plugins/redmine_checklists" target="_blank"><b>Checklists</b></a><br /><br /><blockquote class="red">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.</blockquote><br /></li><li>Para proceder con la instalación de un plugin, lo que tenemos que hacer es dirigimos al directorio de plugins de Redmine:<br /><pre><b>[root@testsrv ~]# cd /opt/redmine/plugins/</b><br /></pre>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 <b>wget</b> para descargar el paquete como se muestra a continuación:<br /><pre><b>[root@testsrv plugins]# wget https://github.com/haru/redmine_theme_changer/releases/download/0.3.1/redmine_theme_changer-0.3.1.zip<br />[root@testsrv plugins]# unzip redmine_theme_changer-0.3.1.zip<br />[root@testsrv plugins]# rm redmine_theme_changer-0.3.1.zip<br />[root@testsrv plugins]# chown -Rf redmine:redmine redmine_theme_changer/</b><br /></pre>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.<br /><pre><b>[root@testsrv plugins]# bundle exec rake redmine:plugins:migrate RAILS_ENV=production</b><br /></pre></li><li>Si el proyecto se encuentra disponible en algún repositorio <b>Git</b> en la web podemos descargar el complemento clonando en repositorio remoto y lo instalamos de la siguiente manera: <br /><pre><b>[root@testsrv plugins]# git clone https://github.com/peclik/clipboard_image_paste.git<br />[root@testsrv plugins]# chown -Rf redmine:redmine clipboard_image_paste/<br />[root@testsrv plugins]# bundle exec rake redmine:plugins:migrate RAILS_ENV=production</b><br /></pre></li><li>A continuación instalamos el plugin <b>redmine_lightbox2</b>:<br /><pre><b>[root@testsrv plugins]# wget https://github.com/paginagmbh/redmine_lightbox2/archive/v0.4.4.zip<br />[root@testsrv plugins]# unzip v0.4.4.zip<br />[root@testsrv plugins]# rm v0.4.4.zip<br />[root@testsrv plugins]# mv redmine_lightbox2-0.4.4 redmine_lightbox2<br />[root@testsrv plugins]# chown -Rf redmine:redmine redmine_lightbox2<br />[root@testsrv plugins]# bundle exec rake redmine:plugins NAME=redmine_lightbox2 RAILS_ENV=production</b><br /></pre>El plugin <b>scrum-plugin</b>:<br /><pre><b>[root@testsrv plugins]# wget https://redmine.ociotec.com/attachments/download/476/scrum-v0.18.0.tar.gz<br />[root@testsrv plugins]# tar -xzvf scrum-v0.18.0.tar.gz<br />[root@testsrv plugins]# rm scrum-v0.18.0.tar.gz<br />[root@testsrv plugins]# chown -Rf redmine:redmine scrum<br />[root@testsrv plugins]# bundle exec rake redmine:plugins NAME=scrum RAILS_ENV=production</b><br /></pre></li><li>Para instalar el plugin <b>Redmine-Periodic-Task</b> primero también debemos tener instalados algunos gemas adicionales:<br /><pre><b>[root@testsrv plugins]# gem install activesupport -v 5.2.4.1<br />[root@testsrv plugins]# gem install business_time<br />[root@testsrv plugins]# gem install protected_attributes_continued -v 1.4.0<br />[root@testsrv plugins]# gem install activemodel -v 4.2.11.1<br />[root@testsrv plugins]# wget https://www.redmine.org/attachments/download/22557/Redmine-Periodic-Task-4.1.0.zip<br />[root@testsrv plugins]# unzip Redmine-Periodic-Task-4.1.0.zip<br />[root@testsrv plugins]# rm Redmine-Periodic-Task-4.1.0.zip<br />[root@testsrv plugins]# mv Redmine-Periodic-Task-4.1.0 periodictask<br />[root@testsrv plugins]# chown -Rf redmine:redmine periodictask<br />[root@testsrv plugins]# bundle exec rake redmine:plugins NAME=periodictask RAILS_ENV=production</b><br /></pre>El plugin <b>Redmine-Periodic-Task</b> también necesita que se ejecute un <b>Crontab</b> que verifique periódicamente la generación de las tareas periódicas registradas, para lo cual editamos el archivo llamado <b>redmine</b> dentro del directorio <b>/etc/cron.d</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/cron.d/redmine</b><br /></pre>Archivo en el cual agregamos al final el siguiente contenido para que cada 10 minutos verifique la generación de una tarea preconfigurada:<br /><pre><i># Ejecucion periodica para la generacion automatica de tareas mediante el complemento periodictasks.</i><br /><b>*/10 * * * * root rake -f /opt/redmine/Rakefile redmine:check_periodictasks RAILS_ENV="production" LOCALE="de"</b><br /></pre>Finalmente reiniciamos el servicio <b>crond</b>:<br /><pre><b>[root@testsrv plugins]# systemctl restart crond</b><br /></pre>Para mas información consultar el apartado <b>CONFIGURATION</b> del archivo <a href="https://github.com/jperelli/Redmine-Periodic-Task/blob/master/README.md" target="_blank"><b>README.md</b></a> del repositorio GitHub del autor del plugin.<br /><br /></li><li>Para instalar los pluggins <a href="http://www.redmine.org/plugins/redmine_people" target="_blank"><b>People</b></a> y <a href="http://www.redmine.org/plugins/redmine_checklists" target="_blank"><b>Plugin Checklists</b></a> antes se tienen que instalar algunas dependencias de la siguiente forma:<br /><pre><b>[root@testsrv plugins]# gem install vcard<br />[root@testsrv plugins]# gem install redmine_crm</b><br /></pre>Ahora si ya podemos instalar el pluggin <a href="http://www.redmine.org/plugins/redmine_people" target="_blank"><b>People</b></a> en su versión ligera (Ligth) descargada desde <a href="www.redmineup.com" target="_blank">www.redmineup.com</a>:<br /><pre><b>[root@testsrv plugins]# unzip redmine_people-1_4_1-light.zip<br />[root@testsrv plugins]# chown -Rf redmine:redmine redmine_people<br />[root@testsrv plugins]# bundle exec rake redmine:plugins NAME=redmine_people RAILS_ENV=production</b><br /></pre>Así como el plugin <a href="http://www.redmine.org/plugins/redmine_checklists" target="_blank"><b>Plugin Checklists</b></a>:<br /><pre><b>[root@testsrv plugins]# unzip redmine_checklists-3_1_16-light.zip<br />[root@testsrv plugins]# chown -Rf redmine:redmine redmine_checklists<br />[root@testsrv plugins]# bundle exec rake redmine:plugins NAME=redmine_checklists RAILS_ENV=production</b><br /></pre></li><li>Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre></li></ol><br /><br /><h2>Actualización de temas (themes)</h2>Podemos agregar nuevos themes para personalizar el look & feel de la herramienta, los pasos para agregarlos van a continuación. <br /><ol><li>Lo primero es descargar el nuevo tema que deseamos instalar desde el sitio web que sigue a continuación:<br /><pre><b>URL: <a href="http://www.redmine.org/projects/redmine/wiki/Theme_List">http://www.redmine.org/projects/redmine/wiki/Theme_List</a></b><br /></pre>De mi parte les recomiendo probar los siguientes themes disponibles:<br />- <a href="https://www.redmineup.com/pages/themes/a1" target="_blank"><b>A1</b></a><br />- <a href="https://www.redmineup.com/pages/themes/circle" target="_blank"><b>Circle</b></a><br />- <a href="https://github.com/themondays/Dwarf" target="_blank"><b>Dwarf</b></a><br /><br /></li><li>Si el archivo está empaquetado bajo los formatos tar.gz, tgz, zip, etc, entonces tenemos que copiar el archivo en la carpeta <b>/opt/redmine/public/themes</b>, descomprimirlo y asignarle el nuevo dueño:<br /><pre><b>[root@testsrv ~]# cd /opt/redmine/public/themes<br />[root@testsrv themes]# unzip a1_theme-2_0_0.zip<br />[root@testsrv themes]# rm a1_theme-2_0_0.zip<br />[root@testsrv themes]# chown -Rf redmine:redmine a1</b><br /></pre>Si el <b>theme</b> se encuentra en un repositorio <b>git</b> lo podemos instalar siguiendo los siguientes pasos (El theme Dwarf se tiene que mover de una sub-carpeta a <b>/opt/redmine/public/themes</b>, en los demás themes esto no suele ser necesario):<br /><pre><b>[root@testsrv ~]# cd /opt/redmine/public/themes<br />[root@testsrv themes]# git clone https://github.com/themondays/Dwarf.git<br />[root@testsrv themes]# cd Dwarf/production/<br />[root@testsrv production]# mv dwarf/ ../../<br />[root@testsrv production]# cd ../../<br />[root@testsrv themes]# chown -Rf redmine:redmine dwarf<br />[root@testsrv themes]# rm -Rf Dwarf</b><br /></pre>También recomendamos instalar y probar el siguiente <b>theme</b>:<br /><pre><b><br />[root@testsrv themes]# git clone https://bitbucket.org/dkuk/redmine_alex_skin.git<br />[root@testsrv themes]# chown -Rf redmine:redmine redmine_alex_skin</b><br /></pre>Finalmente es necesario reiniciar el servicio <b>httpd</b> para que los nuevos <b>themes</b> sean tomados en cuenta:<br /><pre><b>root@testsrv themes]# systemctl restart httpd</b><br /></pre></li><li>Con eso ya está, ya podremos seleccionar los nuevos temas agregados en la pestaña <b>Mostrar</b> (Show) de la sección de <b>Administración</b> de la herramienta, y si tenemos instalado el plugin <b>Theme Changer</b> cada usuario podrá personalizar su theme directamente desde la página de su perfil.<br /></li></ol><br /><br /><h2>Configuración para envío de correos</h2>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: <br /><ol><li>Primeramente nos dirigimos al directorio <b>/opt/redmine/config</b> y creamos el archivo <b>configuration.yml</b> a partir del archivo plantilla del mismo directorio.<br /><pre><b>[root@testsrv ~]# cd /opt/redmine/config/<br />[root@testsrv config]# cp configuration.yml.example configuration.yml</b><br /></pre></li><li>Luego editamos el archivo <b>configuration.yml</b>,<br /><pre><b>[root@testsrv config]# vim configuration.yml</b><br /></pre>y lo configuramos similar a lo que sigue en el caso de que tengamos un servidor de correo local:<br /><pre><b>default:<br /> email_delivery:<br /> delivery_method: :smtp<br /> smtp_settings:<br /> address: ip_servidor_local<br /> port: 25<br /> domain: midominio.com<br /> authentication: :none<br /> openssl_verify_mode: none</b><br /></pre>Para una cuenta de <b>Gmail</b> la configuración podría ser similar a lo que sigue:<br /><pre><b>default:<br /> email_delivery:<br /> delivery_method: :smtp<br /> smtp_settings:<br /> enable_starttls_auto: true<br /> address: "smtp.gmail.com"<br /> port: 587<br /> domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps<br /> authentication: :plain<br /> user_name: "your_email@gmail.com"<br /> password: "your_password"</b><br /></pre><b>OBS:</b> Recuerda que si usas <b>Gmail</b> tendrás que habilitar en el correo los servicios de <b>IMAP</b> y activar el acceso a aplicaciones menos seguras. Referencias:<br />- <a href="https://support.google.com/mail/answer/7126229?hl=es" target="_blank">Leer mensajes de Gmail desde otros clientes de correo mediante IMAP</a><br />- <a href="https://support.google.com/accounts/answer/6010255?hl=es" target="_blank">Permitir que las aplicaciones menos seguras accedan a tu cuenta</a><br /><br /></li><li>Reiniciamos el servicio Apache para que la configuración anterior tome efecto:<br /><pre><b>[root@testsrv config]# systemctl restart httpd</b><br /></pre></li><li>Y finalmente realizamos las configuraciones faltantes en la interfaz Web. Primeramente realizamos algunos cambios en la sección de configuración <b>Administración-->Configuración-->General</b>, en la cual debemos configurar el <b>Nombre y la ruta del servidor</b> y el <b>Protocolo</b>, 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.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1102" height="499" src="http://files.tormentadebits.com/images/00025-redmine-05.png" width="640" /></a></div><br />Luego seguimos con cambios en la opción de configuración <b>Administración-->Configuración-->Notificaciones por correo</b> de la interfaz web de Redmine.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="859" data-original-width="1106" height="497" src="http://files.tormentadebits.com/images/00025-redmine-08.png" width="640" /></a></div><br />En este apartado se recomienda configurar las opciones:<br />- Correo desde el que enviar mensajes<br />- Opción de notificación por defecto<br />- Pie de mensajes<br /><br />Una vez concluida con las configuraciones guardamos los cambios con el botón <b>Guardar</b> y luego probamos el funcionamiento de envío de correos haciendo clic en el enlace <b>Enviar un correo de prueba</b>, que intentará enviar un correo de prueba a la cuenta definida en el apartado <b>Mi Cuenta</b> del usuario <b>admin</b>, que previamente había configurado como <b>contacto(ARROBA).tormentadebits.com</b>.<br /></li></ol><br /><br /><h2>Registro de tareas a partir de correos electrónicos</h2>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. <br /><ol><li>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. <br /><br /></li><li>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 <b>/opt/redmine</b>,<br /><pre><b>[root@testsrv ~]# cd /opt/redmine</b><br /></pre>y ejecutando el siguiente comando que lo tenemos que adecuar a nuestras necesidades:<br /><pre><b>[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'</b><br /></pre>En este caso se utiliza de ejemplo una cuenta de correo <b>Gmail</b> con acceso IMAP. Las directivas de configuración relacionadas al protocolo IMAP son las siguientes:<br /><ul><li><b>host=imap.gmail.com</b>: IMAP server host (default: 127.0.0.1)</li><li><b>port=993</b>: IMAP server port (default: 143)</li><li><b>ssl=1</b>: Usa SSL? El valor 1 indica que si se usa SSL (default: false)</li><li><b>username=USERNAME</b>: IMAP account</li><li><b>password=PASSWORD</b>: IMAP password</li><li><b>folder=INBOX</b>: Directorio IMAP a leer (default: INBOX)</li><li><b>move_on_success=INBOX</b>: 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.</li><li><b>move_on_failure=INBOX</b>: 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.</li><li><b>-r 'openssl' -E 'OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE</b>: En CentOS se agregan las directivas para forzar a que ignore la verificación del certificado <b>SSL</b> del protocolo <b>IMAP</b> en el <b>puerto 993</b>, ya que sin dicha directiva la ejecución del comando generaba la siguiente excepción:<br /><pre>rake aborted! OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed<br /></pre>Referencia: <a href="https://www.redmine.org/boards/1/topics/33669?page=2" target="_blank"><b>Receiving emails from imap ssl</b></a><br /><br /></li></ul>También podemos controlar la forma en que se agrega una nueva tarea en Redmine incluyendo los siguientes argumentos en el cuerpo del correo:<br /><ul><li><b>project=PROJECT</b>: Identifier of the target project</li><li><b>tracker=TRACKER</b>: Name of the target tracker</li><li><b>category=CATEGORY</b>: Name of the target category</li><li><b>priority=PRIORITY</b>: Name of the target priority</li><li><b>allow_override=ATTRS</b>: Allow email content to override attributes specified by previous options ATTRS is a comma separated list of attributes</li><li><b>unknown_user=ACTION</b></li><li><b>no_permission_check=[0|1]</b></li></ul>Según como se haya definido la directiva <b>unknown_user</b> 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 <b>unknown_user=accept</b>, que permite generar tareas a partir de correos cuyas cuentas de usuario no corresponden a un usuario de Redmine debidamente registrado.<br /><br />A continuación se muestran todas las opciones disponibles para la directiva <b>unknown_user</b>:<br /><pre><b>unknown_user=ACTION how to handle emails from an unknown user where ACTION can be one of the following<br />values:<br />- ignore: the email is ignored (default)<br />- accept: the sender is considered as an anonymous user and the email is accepted<br />- create: a user account is created for the sender (username/password are sent back to the user) and the email is accepted</b><br /></pre>Para que los usuarios no registrados puedan agregar tareas vía e-mail sin problemas no basta con solo agregar la directiva <b>unknown_user=accept</b>, también debemos agregar la directiva <b>no_permission_check=1</b> que evitará que <b>redmine:email:receive_imap</b> verifique los permisos relacionados al usuario <b>Anonymous</b>, que es el usuario de Redmine al cual serán asociadas las nuevas tareas generadas.<br /><br />Ahora bien, es importante aclarar que si queremos utilizar la directiva <b>unknown_user=accept</b> sin especificar la directiva <b>no_permission_check=1</b> será necesario configurar los permisos del <b>rol Anonymous</b>, 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.<br /><br />Por último y para no olvidar, como le hemos especificado el valor <b>Soporte</b> al argumento <b>tracker</b> del comando anterior, es importante agregar la opción <b>Soporte</b> a la lista de <b>Actividades</b>, que es configurable accediendo al menú <b>Administración-->Listas de valores</b> como se observa a continuación:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-06.png" width="640" /></a></div><br />El comando utiliza el argumento <b>tracker</b> 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:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="507" data-original-width="562" height="361" src="http://files.tormentadebits.com/images/00025-redmine-07.png" width="400" /></a></div><br /></li><li>El siguiente paso consiste en registrar una nueva tarea programada que se encargue de buscar los correos periódicamente. Para ello editamos el archivo <b>redmine</b> del directorio <b>/etc/cron.d</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/cron.d/redmine</b><br /></pre>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.<br /><pre><i># Generacion de tareas a partir de correos entrantes.</i><br /><b>* * * * * 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</b><br /></pre><b>OBS</b>: En CentOS se agrega al final las directivas <b>"-r 'openssl' -E 'OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE'"</b> para forzar a que ignore la verificación del certificado <b>SSL</b> del protocolo <b>IMAP</b> en el <b>puerto 993</b>, ya que sin dicha directiva la ejecución del comando generaba la siguiente excepción:<br /><pre>rake aborted! OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed<br /></pre>Referencia: <a href="https://www.redmine.org/boards/1/topics/33669?page=2" target="_blank"><b>Receiving emails from imap ssl</b></a><br /><br />Finalmente reiniciamos el servicio cron para activar la tarea.<br /><pre><b>[root@testsrv ~]# systemctl restart crond</b><br /></pre></li><li>Si hemos utilizado las directivas <b>unknown_user=accept</b> y <b>no_permission_check=1</b>, 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.<br /><br />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 <b>mail_handler.rb</b> ubicado en el directorio <b>/opt/redmine/app/models</b>, que se encarga de procesar los correos entrantes:<br /><pre><b>[root@testsrv ~]# vim /opt/redmine/app/models/mail_handler.rb</b><br /></pre>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.<br /><pre><i># Creates a new issue</i><br /> def receive_issue<br /> project = target_project<br /> # check permission<br /> unless handler_options[:no_permission_check]<br /> raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)<br /> end<br /><br /> issue = Issue.new(:author => user, :project => project)<br /> attributes = issue_attributes_from_keywords(issue)<br /> if handler_options[:no_permission_check]<br /> issue.tracker_id = attributes['tracker_id']<br /> if project<br /> issue.tracker_id ||= project.trackers.first.try(:id)<br /> end<br /> end<br /> issue.safe_attributes = issue_attributes_from_keywords(issue)<br /> issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}<br /> <i>#issue.subject = cleaned_up_subject</i><br /> <span style="background-color: #edff21;">issue.subject = cleaned_up_subject + " (#{email.from.to_a.first.to_s.strip.gsub(/@.*$/, '').strip})"</span><br /> if issue.subject.blank?<br /> issue.subject = '(no subject)'<br /> end<br /> <i>#issue.description = cleaned_up_text_body</i><br /> <span style="background-color: #edff21;">issue.description = "ENVIADO POR: #{email.from.to_a.first.to_s.strip}\r\n\r\n" + cleaned_up_text_body</span><br /> issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?<br /> issue.is_private = (handler_options[:issue][:is_private] == '1')<br /><br /> <i># add To and Cc as watchers before saving so the watchers can reply to Redmine</i><br /> add_watchers(issue)<br /> issue.save!<br /> add_attachments(issue)<br /> logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info<br /> issue<br />end<br /></pre></li><li>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 <a href="https://github.com/ageis/redmine_cc_addresses/tree/upgrade"><b>CC Address Plugin for Redmine</b></a>, un fork del proyecto original <a href="https://github.com/peelman/redmine_cc_addresses"><b>redmine_cc_addresses</b></a> 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.<br /><br />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:<br /><pre><b>[root@testsrv ~]# cd /opt/redmine/plugins/<br />[root@testsrv plugins]# git clone https://github.com/ageis/redmine_cc_addresses.git<br />[root@testsrv plugins]# chown -Rf redmine:redmine redmine_cc_addresses/<br />[root@testsrv plugins]# bundle exec rake redmine:plugins:migrate RAILS_ENV=production</b><br /></pre>Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre>Hay que tener en cuenta que en la sección de <b>Configuración -> Módulo</b> de cada proyecto hay que activar el módulo <b>CC addresses</b> para que la sección <b>CC Addresses</b> 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 <b>Administración -> Perfiles y permisos -> Perfil X</b>.<br /><br /></li><li>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 <b>redmine_cc_addresses</b> 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.<br /><br />Para implementar esta funcionalidad tenemos que volver a modificar el código del archivo <b>mail_handler.rb</b><br /><pre><b>[root@testsrv ~]# vim /opt/redmine/app/models/mail_handler.rb</b><br /></pre>Luego nos tenemos que posicionar entre los métodos <b>add_attachments</b> y <b>add_accept_attachment?</b> para agregar un nuevo método llamado <b>add_cc_addresses</b>, 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:<br /><pre>def add_attachments(obj)<br /> ...<br /> end<br /><br /><span style="background-color: #edff21;"><i> # Metodo que agrega a la lista de correo CC de la peticion las cuentas del emisor<br /> # y de los asociados como copia (CC).</i><br /> def add_cc_addresses(obj)<br /> addresses = [email.from, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}<br /> unless addresses.empty?<br /> addresses.each do |address|<br /> <i># Agrega a la tabla cc_addresses los correos.</i><br /> addr = CcAddress.create(:mail => address, :issue_id => obj.id)<br /> end<br /> end<br /> end</span><br /><br /> # Returns false if the +attachment+ of the incoming email should be ignored<br /> def accept_attachment?(attachment)<br /> .....<br /> end<br /></pre>A continuación buscamos el método <b>receive_issue</b> y agregamos el código necesario para que por cada nuevo correo entrante que se procese se ejecute el método <b>add_cc_addresses</b>:<br /><pre><i># Creates a new issue</i><br /> def receive_issue<br /> project = target_project<br /> <i># check permission</i><br /> unless handler_options[:no_permission_check]<br /> raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)<br /> end<br /><br /> issue = Issue.new(:author => user, :project => project)<br /> attributes = issue_attributes_from_keywords(issue)<br /> if handler_options[:no_permission_check]<br /> issue.tracker_id = attributes['tracker_id']<br /> if project<br /> issue.tracker_id ||= project.trackers.first.try(:id)<br /> end<br /> end<br /> issue.safe_attributes = attributes<br /> issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}<br /> <i>#issue.subject = cleaned_up_subject</i><br /> issue.subject = cleaned_up_subject + " (#{email.from.to_a.first.to_s.strip.gsub(/@.*$/, '').strip})"<br /> if issue.subject.blank?<br /> issue.subject = '(no subject)'<br /> end<br /> <i>#issue.description = cleaned_up_text_body</i><br /> issue.description = "ENVIADO POR: #{email.from.to_a.first.to_s.strip}\r\n\r\n" + cleaned_up_text_body<br /> issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?<br /> issue.is_private = (handler_options[:issue][:is_private] == '1')<br /><br /> <i># add To and Cc as watchers before saving so the watchers can reply to Redmine</i><br /> add_watchers(issue)<br /> issue.save!<br /> <span style="background-color: #edff21;">add_cc_addresses(issue)</span><br /> add_attachments(issue)<br /> logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger<br /> issue<br /> end<br /></pre>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 <b>mail_handler.rb</b>.<br /><br /><b>OBS:</b> Es importante tener en cuenta que no se van a enviar correos si probamos modificar una tarea con el usuario <b>Admin</b>, a menos que dicho usuario esté registrado como <b>miembro del proyecto</b>. 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.<br /></li></ol><br /><br /><h2>Configuración SCM (Subversion)</h2>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. <br /><ol><li>Lo primero que tenemos que hacer es crear un directorio dentro del directorio home de Redmine para almacenar los proyectos y repositorios de Subversion:<br /><pre><b>[root@testsrv ~]# mkdir /opt/redmine/svn<br />[root@testsrv ~]# chown -Rf apache:apache /opt/redmine/svn<br />[root@testsrv ~]# chmod -Rf 750 /opt/redmine/svn</b><br /></pre></li><li>Luego tenemos que instalar en openSUSE los paquetes relacionados a Subversion y otros requisitos más:<br /><pre><b>[root@testsrv ~]# yum install subversion curl mod_perl perl-DBI perl-DBD-Pg perl-Digest-SHA mod_dav_svn</b><br /></pre>También instalamos las gemas <b>activesupport</b>, <b>rails-observers</b> y <b>activeresource</b> en sus respectivas versiones compatibles con la versión <b>Ruby 2.4.6</b>:<br /><pre><b>[root@testsrv ~]# gem install activesupport -v 5.2.4.1<br />[root@testsrv ~]# gem install rails-observers -v 0.1.5<br />[root@testsrv ~]# gem install activeresource -v 5.1.0</b><br /></pre></li><li>Verificamos que en el directorio <b>/etc/httpd/conf.modules.d</b> se encuentren activos los módulos <b>dav</b>, <b>perl</b> y <b>subversion</b> para Subversion.<br /><pre><b>#[root@testsrv ~]# cat /etc/httpd/conf.modules.d/00-dav.conf</b><br />LoadModule dav_module modules/mod_dav.so<br />LoadModule dav_fs_module modules/mod_dav_fs.so<br />LoadModule dav_lock_module modules/mod_dav_lock.so<br /><b>[root@testsrv ~]# cat /etc/httpd/conf.modules.d/02-perl.conf</b><br />#<br /># Mod_perl incorporates a Perl interpreter into the Apache web server,<br /># so that the Apache web server can directly execute Perl code.<br /># Mod_perl links the Perl runtime library into the Apache web server<br /># and provides an object-oriented Perl interface for Apache's C<br /># language API. The end result is a quicker CGI script turnaround<br /># process, since no external Perl interpreter has to be started.<br />#<br /><br />LoadModule perl_module modules/mod_perl.so<br /><b>[root@testsrv ~]# cat /etc/httpd/conf.modules.d/10-subversion.conf</b><br />LoadModule dav_svn_module modules/mod_dav_svn.so<br />LoadModule authz_svn_module modules/mod_authz_svn.so<br />LoadModule dontdothat_module modules/mod_dontdothat.so<br /><b>#</b><br /></pre></li><li>Necesitamos crear un enlace simbólico en el directorio <b>/usr/lib64/perl5/vendor_perl/Apache2</b> a partir del archivo <b>Redmine.pm</b> que se encuentra ubicado en la ruta <b>/opt/redmine/extra/svn</b>:<br /><pre><b>[root@testsrv ~]# ln -s /opt/redmine/extra/svn/Redmine.pm /usr/lib64/perl5/vendor_perl/Apache2/</b><br /></pre></li><li>Tenemos que agregar la configuración requerida para Apache, para ello creamos y editamos posteriormente el archivo <b>redmine_svn.conf</b> dentro del directorio <b>/etc/httpd/conf.d</b>.<br /><pre><b>[root@testsrv ~]# touch /etc/httpd/conf.d/redmine_svn.conf<br />[root@testsrv ~]# vim /etc/httpd/conf.d/redmine_svn.conf</b><br /></pre>A dicho archivo le agregamos la siguiente configuración:<br /><pre>PerlLoadModule Apache2::Redmine<br /><location /svn><br /> DAV svn<br /> SVNParentPath "/opt/redmine/svn"<br /><br /> PerlAccessHandler Apache::Authn::Redmine::access_handler<br /> PerlAuthenHandler Apache::Authn::Redmine::authen_handler<br /> AuthType Basic<br /> AuthName "Redmine Subversion Repository"<br /> Require valid-user<br /><br /> <i>## For mysql<br /> # RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"<br /> ## For postgresql</i><br /> RedmineDSN "DBI:Pg:dbname=redmine;host=localhost"<br /> RedmineDbUser "redmine"<br /> RedmineDbPass "redmine"<br /><br /> <i>## Optional where clause (fulltext search would be slow and<br /> ## database dependant).<br /> # RedmineDbWhereClause "and members.role_id IN (1,2)"<br /> ## Optional credentials cache size<br /> # RedmineCacheCredsMax 50</i><br /></location><br /></pre>Finalmente reiniciamos el servicio Apache.<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre></li><li>El siguiente paso consiste en dirigirnos a la pestaña <b>Administration -> Configuración –> Repositorios</b> 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ó <b>X9YEsWGYUbevDmX4u5ep</b>. Es importante aclarar que la llave API generada anteriormente será utilizada desde la línea de comandos para crear los repositorios Subversion en Redmine.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1086" height="507" src="http://files.tormentadebits.com/images/00025-redmine-09.png" width="640" /></a></div><br />En este ventana también se recomienda configurar las siguientes opciones:<br />- Desmarcar todos los tipos de servicios SCM a excepción de los que deseamos utilizar.<br />- Marcar la opción <b>Habilitar registro de horas</b>.<br /><br />Una vez realizado lo anterior tenemos que guardar los cambios.<br /><br /></li><li>Para habilitar y crear el repositorio Subversion para un proyecto de Redmine primero debemos seleccionar nuestro proyecto, dirigirnos a la pestaña <b>Módulos</b> en la sección <b>Configuración</b> del proyecto y activar la opción <b>Repositorio</b>. 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:<br /><pre><b>[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</b><br /></pre>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:<br /><pre><b>404<br /><br />La entrada y/o la revisión no existe en el repositorio.</b><br /></pre>Pueden probar cambiar el dueño y grupo de usuario a <b>apache apache</b> del archivo <b>environment.rb</b> ubicado en la carpeta <b>config</b>,<br /><pre><b>[root@testsrv ~]# chown -Rf apache:apache /opt/redmine/config/environment.rb</b><br /></pre>reiniciando posteriormente el servicio Apache como se muestra a continuación:<br /><pre><b>[root@testsrv ~]# systemctl restart httpd</b><br /></pre></li><li>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 <b>/etc/cron.d/redmine</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/cron.d/redmine</b><br /></pre>Al final del cual agregamos una nueva tarea programada que se encargue de realizar cada minuto la comprobación correspondiente:<br /><pre><i># Generacion automatica de repositorios subversion.</i><br /><b>* * * * * 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</b><br /></pre>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.<br /><pre><i># Sincronizacion de comentarios de commits asociados a tareas.</i><br />* * * * * root curl "http://IP_SERVIDOR/redmine/sys/fetch_changesets?key=X9YEsWGYUbevDmX4u5ep" > /dev/null 2>&1<br /></pre>Finalmente reiniciamos el servicio cron.<br /><pre><b>[root@testsrv ~]# systemctl restart crond</b><br /></pre></li><li>Con los pasos anteriores ya podremos utilizar el repositorio, su integración en la herramienta quedaría como sigue:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-10.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-11.png" width="640" /></a></div></li></ol><h4>ACLARACIONES SOBRE EL MÓDULO REPOSITORIO DE REDMINE:</h4><ol><li>El proyecto tiene que tener activo el módulo <b>Repositorio</b> para que la aplicación <b>reposman.rb</b> pueda crear el repositorio svn físico en el directorio <b>/opt/redmine/svn</b>.<br /><br /></li><li>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.<br /><br /></li><li>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 <b>Jefe de proyecto</b> o <b>Desarrollador</b>, porque si tiene asignado el perfil <b>Informador</b> solo podrá descargar el repositorio pero no subir actualizaciones.<br /><br /></li><li>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 <b>Usuarios</b> de la pestaña <b>Configuración --> Repositorio</b> del proyecto en cuestión.<br /></li></ol><br /><br /><h2>Realización de copias de seguridad</h2>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. <br /><ol><li>En principio necesitamos definir un directorio en donde ubicar las copias de seguridad realizadas, en mi caso voy a crear una carpeta llamada <b>backups</b> en el directorio raíz.<br /><pre><b>[root@testsrv ~]# mkdir /backups</b><br /></pre></li><li>Luego pasamos a crear los directorios <b>backups</b> y <b>backups/svndumps</b> dentro de <b>/opt/redmine</b> para almacenar las copias de seguridad en bruto de la base de datos y de los repositorios subversion que tenemos agregados:<br /><pre><b>[root@testsrv ~]# mkdir -p /opt/redmine/backups/svndumps</b><br /></pre></li><li>A continuación accedemos al directorio <b>/opt/redmine/script</b> y creamos el archivo <b>backup</b> que contendrá el script que realizará la copia de seguridad, además se le asignará los permisos correspondientes:<br /><pre><b>[root@testsrv ~]# cd /opt/redmine/script/<br />[root@testsrv script]# touch backup<br />[root@testsrv script]# chmod 750 backup</b><br /></pre></li><li>Luego editamos el archivo <b>backup</b>,<br /><pre><b>[root@testsrv script]# vim backup</b><br /></pre>y le agregamos el siguiente script bash:<br /><pre><i>#!/bin/bash<br /># Realiza una copia de seguridad completa de la herramienta Redmine.</i><br />DIA=`date +"%Y%m%d"`<br />HORA=`date +"%H%M"`<br />BACKUP_PATH=/backups<br /> <br /><i># -- REDMINE</i><br />REDMINE_HOME=/opt/redmine<br />REDMINE_DB_TYPE=pg #[pg|mysql]<br />REDMINE_DB_NAME=redmine<br />REDMINE_DB_USER=redmine<br />REDMINE_DB_PASS=redmine<br />REDMINE_DB_BACKUP=$REDMINE_HOME/backups/redmine_db.sql<br />REDMINE_BACKUP_NAME="redmine_"$DIA"_"$HORA".tar.gz"<br />REDMINE_BACKUP_HISTO="histo_redmine_"$DIA"_"$HORA".tar.gz"<br />REDMINE_BACKUP_LIVE_TIME=30<br />REDMINE_BACKUP_HISTO_LIVE_TIME=365<br /> <br /><i># -- SVN</i><br />SVN_REPOS_PATH=$REDMINE_HOME/svn<br />SVN_BACKUP_PATH=$REDMINE_HOME/backups/svndumps<br /> <br /><i># -- PATRON LIMPIEZA</i><br />PATRON_BKP_DIARIO=redmine_*.tar.gz<br />PATRON_BKP_HISTO=histo_redmine_*.tar.gz<br /> <br /><i># -- FTP</i><br />FTP_COPIAR="N" #[S|N]<br />FTP_SERVER=ip_servidor_backup_ftp<br />FTP_USER=usuario_ftp<br />FTP_PASS=password_ftp<br />FTP_REMOTE_CD=remote_backups<br />FTP_LOCAL_CD=$BACKUP_PATH<br /> <br /><i># Backup de Proyectos SVN</i><br />echo<br />echo "-->BACKUP DE REPOSITORIOS SVN"<br />echo "===================================================================="<br />cd $SVN_REPOS_PATH<br />for SVN_REPO_NAME in *<br />do<br /> echo "---------- Iniciando exportacion del repositorio '$SVN_REPO_NAME' ----------"<br /> /usr/bin/svnadmin dump $SVN_REPOS_PATH/$SVN_REPO_NAME > $SVN_BACKUP_PATH/$SVN_REPO_NAME.dump<br /> echo "------------- Fin exportacion del repositorio '$SVN_REPO_NAME' -------------"<br /> echo<br />done<br /> <br /><i># Segun el motor de base de datos especificado se procede a exportar la base de datos de Redmine.</i><br />echo<br />echo "-->BACKUP DE LA BASE DE DATOS DE REDMINE"<br />echo "===================================================================="<br />if [ $REDMINE_DB_TYPE == "mysql" ]; then<br /> echo "Exportando la base de datos de Redmine a partir de MySQL. Aguarde un momento..."<br /> mysqldump -v -u $REDMINE_DB_USER -p$REDMINE_DB_PASS --database $REDMINE_DB_NAME > $REDMINE_DB_BACKUP<br /> echo "Fin del proceso de exportacion."<br /> echo<br />elif [ $REDMINE_DB_TYPE == "pg" ]; then<br /> echo "Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento..."<br /> export PGUSER=$REDMINE_DB_USER<br /> export PGPASSWORD=$REDMINE_DB_PASS<br /> pg_dump -b -F p --column-inserts $REDMINE_DB_NAME > $REDMINE_DB_BACKUP<br /> unset PGUSER<br /> unset PGPASSWORD<br /> echo "Fin del proceso de exportacion."<br />fi<br /> <br /><i># Se generan los archivos con todas las copias de seguridad para ser enviadas a una unidad de cinta.</i><br />echo<br />echo "-->CREANDO FULL BACKUP DE REDMINE"<br />echo "===================================================================="<br />tar -czf $BACKUP_PATH/$REDMINE_BACKUP_NAME $REDMINE_HOME<br /> <br /><i># Almacenando una copia de seguridad alternativa si la fecha corresponde a fin de mes.</i><br />TOMORROW=`date --date=tomorrow +%d`<br />if [ $TOMORROW -eq "1" ]; then<br /> echo<br /> echo "-->CREANDO BACKUP HISTORICO POR SER FIN DE MES"<br /> echo "===================================================================="<br /> cp $BACKUP_PATH/$REDMINE_BACKUP_NAME $BACKUP_PATH/$REDMINE_BACKUP_HISTO<br />fi<br /> <br /><i># Para no llenar el disco duro con backups, se eliminan todos los backups diarios pasados la cantidad<br /># de dias especificados en la variable REDMINE_BACKUP_LIVE_TIME, lo backups historicos se eliminan luego <br /># de la cantidad de dias expecificados en la variable REDMINE_BACKUP_HISTO_LIVE_TIME.</i><br />echo<br />echo "-->LIMPIEZA DE BACKUPS ANTIGUOS"<br />echo "===================================================================="<br />find $BACKUP_PATH/$PATRON_BKP_DIARIO -mtime +$REDMINE_BACKUP_LIVE_TIME -exec rm {} \;<br />find $BACKUP_PATH/$PATRON_BKP_HISTO -mtime +$REDMINE_BACKUP_HISTO_LIVE_TIME -exec rm {} \;<br /> <br /><i># Se copia el full backup a un servidor de respaldo.</i><br />if [ $FTP_COPIAR == "S" ]; then<br /> echo<br /> echo "-->COPIANDO EL FULL BACKUP DE REDMINE A UN SERVIDOR DE RESPALDO"<br /> echo "===================================================================="<br /> /usr/bin/ftp -n <<EOD<br /> open $FTP_SERVER<br /> quote USER $FTP_USER<br /> quote PASS $FTP_PASS<br /> bin<br /> cd $FTP_REMOTE_CD<br /> lcd $FTP_LOCAL_CD<br /> put $REDMINE_BACKUP_NAME<br /> bye<br />EOD<br />else<br /> echo<br /> echo "-->COPIA FTP INHABILITADA!"<br /> echo<br />fi<br /></pre>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 <b>tar.gz</b> de todo el directorio <b>/opt/redmine</b>, 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.<br /><br />En este punto ya podemos probar la ejecución del script de la siguiente manera<br /><pre><b>[root@testsrv ~]# /opt/redmine/script/backup</b><br /><br />-->BACKUP DE REPOSITORIOS SVN<br />====================================================================<br />---------- Iniciando exportacion del repositorio 'prueba' ----------<br />* Dumped revision 0.<br />* Dumped revision 1.<br />* Dumped revision 2.<br />* Dumped revision 3.<br />* Dumped revision 4.<br />* Dumped revision 5.<br />------------- Fin exportacion del repositorio 'prueba' -------------<br /><br />---------- Iniciando exportacion del repositorio 'test' ----------<br />* Dumped revision 0.<br />------------- Fin exportacion del repositorio 'test' -------------<br /><br /><br />-->BACKUP DE LA BASE DE DATOS DE REDMINE<br />====================================================================<br />Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento...<br />Fin del proceso de exportacion.<br /><br />-->CREANDO FULL BACKUP DE REDMINE<br />====================================================================<br />tar: Removing leading `/' from member names<br /><br />-->LIMPIEZA DE BACKUPS ANTIGUOS<br />====================================================================<br />find: ‘/backups/histo_redmine_*.tar.gz’: No such file or directory<br /><br />-->COPIA FTP INHABILITADA!<br /><br /><b>#</b><br /></pre></li><li>Para programar la ejecución periódica del script debemos agregar una tarea programada. Para ello editamos nuevamente el archivo <b>/etc/cron.d/redmine</b>:<br /><pre><b>[root@testsrv ~]# vim /etc/cron.d/redmine</b><br /></pre>Para luego agregarle al final del mismo el siguiente contenido:<br /><pre><i># Backup Redmine</i><br /><b>30 22 * * * root /opt/redmine/script/backup > /opt/redmine/log/backup.log 2>&1</b><br /></pre>Finalmente reiniciamos el servicio <b>cron</b> para que la tarea programada sea funcional.<br /><pre><b>[root@testsrv ~]# systemctl restart crond</b><br /></pre></li></ol><br /><br /><h2>Otras capturas de pantalla</h2><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-12.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-13.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-14.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-15.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-16.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-17.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-18.png" width="640" /></a></div><br /><br /><h2>Información técnica</h2><ul><li><b>CentOS 7 (release 1905)</b><br /></li><li><b>PostgreSQL 9.2.24</b><br /></li><li><b>Apache 2.4.6</b><br /></li><li><b>Ruby 2.4.6</b><br /></li><li><b>Redmine 3.4.13</b><br /></li><li><b>Perl 5.16.3</b><br /></li></ul><br /><br /><h2>Fuentes</h2><ul><li><a href="http://www.redmine.org/" target="_blank"><b>Redmine (Sitio Oficial)</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki" target="_blank"><b>Redmine Wiki</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineInstall" target="_blank"><b>Redmine Install</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Install_Redmine_346_on_Centos_75" target="_blank"><b>Install Redmine 3.4.6 on CentOS 7.5</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/HowTos" target="_blank"><b>Redmine HowTos</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineUpgrade" target="_blank"><b>Redmine Upgrade</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineReceivingEmails" target="_blank"><b>Redmine Receiving Emails</b></a><br /></li><li><a href="https://github.com/ageis/redmine_cc_addresses/tree/upgrade" target="_blank"><b>github.com/ageis/redmine_cc_addresses/tree/upgrade</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Plugins" target="_blank"><b>Redmine Plugins</b></a><br /></li><li><a href="http://www.redmine.org/plugins" target="_blank"><b>Lista de Plugins</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Themes" target="_blank"><b>Redmine Themes</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Theme_List" target="_blank"><b>Lista de Temas (Themes)</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/EmailConfiguration" target="_blank"><b>Redmine Email Configuration</b></a><br /></li><li><a href="https://www.redmine.org/boards/1/topics/33669?page=2" target="_blank"><b>Receiving emails from imap ssl</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineRepositories" target="_blank"><b>Redmine Repositories</b></a><br /></li><li><a href="https://www.phusionpassenger.com/library/config/apache/reference/" target="_blank"><b>Sobre el Módulo Passenger de Apache</b></a><br /></li><li><a href="https://tecadmin.net/install-ruby-latest-stable-centos/" target="_blank"><b>Instalación y configuración de RVM (Ruby Version Manager)</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-64780485597193057122019-09-19T00:35:00.004-04:002022-10-04T22:59:28.596-03:00Configuración de OpenVPN 2.4.3 en openSUSE Linux 15.1<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00024.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="615" height="156" src="http://files.tormentadebits.com/covers/portada-00024.png" width="320" /></a></div><b>OpenVPN</b> permite implementar túneles de comunicación encriptados y establecer VPN's a través de Internet, que dependiendo de la configuración puede ser entre una o varias redes empresariales u hogareñas, o bien también entre una red y hosts específicos.<br /><br />En esta guía se abarcará básicamente la configuración necesaria para que un equipo cliente o varios de ellos (Roadwarriors) pueden conectarse mediante Internet a los equipos de una red ubicada detrás del servidor OpenVPN que hace de pasarela.<br /><a name="more"></a><br /><br /><h3>Servidor OpenVPN para Roadwarriors</h3>La denominación <b>RoadWarrior</b> se refiere a aquellos equipos que siempre están en movimiento y se encuentran conectados al extremo de un túnel <b>VPN</b> normalmente desde una <span style="text-decoration: underline;"><b>IP dinámica</b></span><b> </b> (<b><a href="http://en.wikipedia.org/wiki/Road_warrior_%28computing%29" target="_blank" title="Road Warrior">véase en wikipedia</a></b>). Esta configuración no contempla una <b>VPN</b> bajo el esquema <b>red a red</b>, sino solamente <b>equipo/s a red</b> como se muestra a modo de ejemplo en el siguiente gráfico:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00013-openvpn-01-esquema-roadwarrior.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://files.tormentadebits.com/images/00013-openvpn-01-esquema-roadwarrior.jpg" width="580" /></a></div><br />Finalizando esta sección, quisiera comentarles que primero se abarcarán las configuraciones correspondientes al servidor OpenVPN y posteriormente los pasos para configurar los equipos clientes.<br /><br /><br /><h3>Paquetes requeridos</h3><ol><li>Debemos verificar que los paquetes requeridos para <b>OpenVPN</b> se encuentren instalados, lo podemos hacer mediante el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper search -i openvpn easy-rsa telnet</b><br /></pre></li><li>Si algunos paquetes no se encuentran instalados los instalamos de la siguiente manera:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper install openvpn easy-rsa telnet</b><br /></pre>Para <b>openSUSE 15.1</b> el paquete <b>openvpn</b> que viene en el repositorio es la <b>versión 2.4.3</b>. <br /></li></ol><br /><br /><h3>Generación de llaves y certificados para CA y servidor</h3><ol><li><b>Autoridad de Certificación</b>: En este punto vamos a comenzar a realizar algunos ajustes y configuraciones para preparar la base del servicio <b>OpenVPN</b>. En los siguientes pasos necesitamos generar una llave y un certificado para la <a href="http://es.wikipedia.org/wiki/Autoridad_de_certificaci%C3%B3n" target="_blank"><b>Autoridad de Certificación</b></a> (de ahora en más llamado CA) que en este caso será el mismo equipo en el que va a correr el servidor <b>OpenVPN</b>. Lo primero que debemos hacer es ubicarmos en el directorio <b>/etc/openvpn</b>, creamos el archivo <b>vars</b> a partir del archivo <b>vars.example</b> y lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cp /etc/easy-rsa/vars.example /etc/easy-rsa/vars<br /><span style="color: red;">testsrv:~ #</span> vi /etc/easy-rsa/vars</b><br /></pre>Una vez abierto el archivo <b>vars</b> podemos verificar y descomentar la directiva <b>EASYRSA_KEY_SIZE</b>, para configurar el <b>tamaño de la clave</b> que en esta versión ya se encuentra configurado por defecto en <b>2048</b>.<br /><pre><b>set_var EASYRSA_KEY_SIZE=2048</b><br /></pre>Sin embargo, lo más importante que tenemos que configurar es la información relacionada al <b>CA</b>, para ello configuramos las siguientes variables con nuestra información.<br /><pre><b>set_var EASYRSA_REQ_COUNTRY "PY"<br />set_var EASYRSA_REQ_PROVINCE "IT"<br />set_var EASYRSA_REQ_CITY "nombre_ciudad"<br />set_var EASYRSA_REQ_ORG "nombre_organizacion"<br />set_var EASYRSA_REQ_EMAIL "admin@dominio"<br />set_var EASYRSA_REQ_OU "unidad_de_la_empresa"</b><br />
</pre>Otras configuraciones importantes a revisar son las directivas <b>EASYRSA_CA_EXPIRE</b> y <b>EASYRSA_CERT_EXPIRE</b>, que permiten configurar la cantidad de días en que expiran automáticamente los certificados generados para la entidad certificadora (CA) y para los roadwarriors respectivamente. En este ejemplo se ha configurado en 100 años la expiración de la entidad certificadora y en 10 años para los roadwarriors, si algún certificado se llega a vencer.
<pre><i># In how many days should the root CA key expire?</i>
<b>set_var EASYRSA_CA_EXPIRE 36500</b>
<i># In how many days should certificates expire?</i>
<b>set_var EASYRSA_CERT_EXPIRE 3650</b>
</pre>Y finalmente verificamos que la configuración de la <b>variable EASYRSA_REQ_CN esté debidamente comentada</b>. Esta directiva se utiliza al crear una llave para un cliente, sin embargo, conviene que la misma sea configurada con el nombre del cliente para el cual se generar la llave y no con un nombre genérico, esto se verá más adelante donde mediante un script se seteará dicha directiva cada vez que generemos la llave para un cliente:<br /><pre><b># Default CN:<br /># This is best left alone. Interactively you will set this manually, and BATCH<br /># callers are expected to set this themselves.<br /><br />#set_var EASYRSA_REQ_CN "ChangeMe"</b><br /></pre>Salimos del archivo guardando los cambios.<br /><br /></li><li>A continuación nos trasladamos al directorio <b>/etc/openvpn</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/openvpn</b><br /></pre></li><li>Una vez ubicados en el directorio <b>/etc/openvpn</b> procedemos a ejecutar el comando <b>pkitool</b> para crear la llave y el certificado para la <b>CA</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> easyrsa init-pki</b><br /><br />Note: using Easy-RSA configuration from: /etc/easy-rsa/vars<br /><br />init-pki complete; you may now create a CA or requests.<br />Your newly created PKI dir is: /etc/openvpn/pki<br /><br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre></li><li>Generamos la configuración del certificado para la <b>CA</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> easyrsa build-ca nopass</b><br /><br />Note: using Easy-RSA configuration from: /etc/easy-rsa/vars<br /><br />Using SSL: openssl OpenSSL 1.1.0i-fips 14 Aug 2018<br /><br />Enter New CA Key Passphrase:<br />Re-Enter New CA Key Passphrase:<br />Generating RSA private key, 2048 bit long modulus<br />..+++++<br />.......................................+++++<br />e is 65537 (0x010001)<br />You are about to be asked to enter information that will be incorporated<br />into your certificate request.<br />What you are about to enter is what is called a Distinguished Name or a DN.<br />There are quite a few fields but you can leave some blank<br />For some fields there will be a default value,<br />If you enter '.', the field will be left blank.<br />-----<br />Common Name (eg: your user, host, or server name) [Easy-RSA CA]:<b><span style="color: red;">testsrv</span></b><br /><br />CA creation complete and you may now import and sign cert requests.<br />Your new CA certificate file for publishing is at:<br />/etc/openvpn/pki/ca.crt<br /><br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre></li><li>Ahora procedemos a generar los parámetros <a href="http://es.wikipedia.org/wiki/Diffie-Hellman" target="_blank"><b>Diffie Hellman</b></a>, para lo cual ejecutamos la siguiente directiva:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> easyrsa gen-dh</b><br /><br />Note: using Easy-RSA configuration from: /etc/easy-rsa/vars<br /><br />Using SSL: openssl OpenSSL 1.1.0i-fips 14 Aug 2018<br />Generating DH parameters, 2048 bit long safe prime, generator 2<br />This is going to take a long time<br />.............................................................................<br />................................................................+............<br />............................................+................................<br />................................................+............++*++*++*++*<br /><br />DH parameters of size 2048 created at /etc/openvpn/pki/dh.pem<br /><br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre></li><li><b>Generación de llave y certificado para el servidor</b>: En los siguientes pasos vamos a generar la llave y el certificado para el servidor que ejecutará el servicio <b>OpenVPN</b>, para ello ejecutamos nuevamente el comando <b>pkitool</b> pero con los siguientes argumentos:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> easyrsa gen-req servidor nopass</b><br /><br />Note: using Easy-RSA configuration from: /etc/easy-rsa/vars<br /><br />Using SSL: openssl OpenSSL 1.1.0i-fips 14 Aug 2018<br />Generating a 2048 bit RSA private key<br />...+++++<br />.........+++++<br />writing new private key to '/etc/openvpn/pki/private/servidor.key.fXdSTOSkoX'<br />-----<br />You are about to be asked to enter information that will be incorporated<br />into your certificate request.<br />What you are about to enter is what is called a Distinguished Name or a DN.<br />There are quite a few fields but you can leave some blank<br />For some fields there will be a default value,<br />If you enter '.', the field will be left blank.<br />-----<br />Common Name (eg: your user, host, or server name) [servidor]:<b><span style="color: red;">testsrv</span></b><br /><br />Keypair and certificate request completed. Your files are:<br />req: /etc/openvpn/pki/reqs/servidor.req<br />key: /etc/openvpn/pki/private/servidor.key<br /><br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre>Una observación, para el tercer parámetro se ha utilizado la palabra <b>servidor</b>, que es el nombre con el cual se genera la <b>petición de firma</b> y el <b>certificado</b>, los archivos resultantes serán <b>servidor.req</b> y <b>servidor.key</b> respectivamente, y que más adelante serán utilizados en la configuración del servicio <b>OpenVPN</b>.<br /><br /></li><li>A continuación, la llave <b>servidor.key</b> generada previamente tiene que ser firmada digitalmente por la entidad certificadora (CA):<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> easyrsa sign-req server servidor</b><br /><br />Note: using Easy-RSA configuration from: /etc/easy-rsa/vars<br /><br />Using SSL: openssl OpenSSL 1.1.0i-fips 14 Aug 2018<br /><br /><br />You are about to sign the following certificate.<br />Please check over the details shown below for accuracy. Note that this request<br />has not been cryptographically verified. Please be sure it came from a trusted<br />source or that you have verified the request checksum with the sender.<br /><br />Request subject, to be signed as a server certificate for 1080 days:<br /><br />subject=<br /> commonName = testsrv<br /><br /><br />Type the word 'yes' to continue, or any other input to abort.<br /> Confirm request details: <b><span style="color: red;">yes</span></b><br />Using configuration from /etc/easy-rsa/safessl-easyrsa.cnf<br />Can't open /etc/openvpn/pki/index.txt.attr for reading, No such file or directory<br />140072140343104:error:02001002:system library:fopen::crypto/bio/bss_file.c:74:fopen('/etc/openvpn/pki/index.txt.attr','r')<br />140072140343104:error:2006D080:BIO routines:BIO_new_file:no such file:crypto/bio/bss_file.c:81:<br />Check that the request matches the signature<br />Signature ok<br />The Subject's Distinguished Name is as follows<br />commonName :ASN.1 12:'testsrv'<br />Certificate is to be certified until Jun 11 17:09:29 2022 GMT (1080 days)<br /><br />Write out database with 1 new entries<br />Data Base Updated<br /><br />Certificate created at: /etc/openvpn/pki/issued/servidor.crt<br /><br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre></li><li><b>Generación de firma HMAC tls-auth</b>: Necesitamos generar una firma <b><a href="http://es.wikipedia.org/wiki/Message_authentication_code" target="_blank">HMAC</a> tls-auth</b> que aumenta los niveles de seguridad en varios aspectos. Para ello estando en el directorio <b>/etc/openvpn</b> ejecutamos el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> openvpn --genkey --secret ta.key</b><br /></pre>Y con este paso concluimos esta sección.<br /></li></ol><br /><br /><h3>Configuración del servidor</h3><ol><li>El archivo <b>server.conf</b> que será utilizado por el servicio <b>OpenVPN</b> lo creamos a partir del archivo de mismo nombre ubicado en el directorio <b>/usr/share/doc/packages/openvpn/sample-config-files</b> como se muestra a continuación:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> cp /usr/share/doc/packages/openvpn/sample-config-files/server.conf /etc/openvpn</b><br /></pre></li><li>Procedemos a editar el archivo <b>server.conf</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> vi /etc/openvpn/server.conf</b><br /></pre>Y configuramos las directivas correspondientes a la entidad <b>CA</b>, al <b>certificado y llave</b> para el servidor, el parámetro <b>DH</b>, la <b>autenticación TLS</b> y la configuración <b>cipher</b>. Es importante aclarar que debemos especificar la ruta completa a los archivos relacionados como se muestra a continuación:<br /><pre><b>ca /etc/openvpn/pki/ca.crt<br />cert /etc/openvpn/pki/issued/servidor.crt<br />key /etc/openvpn/pki/private/servidor.key<br />dh /etc/openvpn/pki/dh.pem<br />tls-auth /etc/openvpn/ta.key 0<br />cipher AES-256-GCM</b><br /></pre>Descomentamos la configuración <b>comp-lzo</b>:<br /><pre><b>comp-lzo</b><br /></pre>Luego descomentamos la directiva <b>client-config-dir ccd</b> que permite definir el directorio en donde se colocarán todas las políticas personalizadas de acceso para cada uno de los clientes que generaremos más adelante.<br /><pre><b>client-config-dir ccd</b><br /></pre>También debemos descomentar la directiva <b>log-append</b> y debería quedar configurado como sigue:<br /><pre><b>log-append /var/log/openvpn.log</b><br /></pre>Nos vamos al final del archivo y especificamos la directiva <b>crt-verify</b> y le especificamos el archivo que contendrá los certificados que fueron revocados por el administrador del servicio <b>OpenVPN</b> (los pasos para revocar certificados será abordados más adelante):<br /><pre><b># -- SE AGREGA LA DIRECTIVA QUE ESPECIFICA EL ARCHIVO EN DONDE<br /># SE ENCUENTRAN LOS CERTIFICADOS REVOCADOS.<br />crl-verify /etc/openvpn/pki/crl.pem</b><br /></pre>A continuación de la directiva anterior agregamos la directiva <b>management</b> para definir el host y el puerto desde los cuales se podrá acceder a la consola de administración de <b>OpenVPN</b>. Si bien se puede configurar la dirección IP de la interfaz de red activa para que la consola de administración se encuentre accesible remotamente, se recomienda que <b>solo se habilite en el localhost</b> ya que no solicita usuario ni contraseña al conectarnos a ella.<br /><pre><b># -- SE HABILITA LA CONSOLA DE ADMINISTRACION EN EL PUERTO 1195<br /># DE LA INTERFAZ LOCALHOST (Recomendado, ya que al acceder a la<br /># consola no pide usuario y contrasenia) DEL SERVIDOR<br />management 127.0.0.1 1195</b><br /></pre>También agregamos las siguientes configuraciones relacionadas con el MTU:<br /><pre><b># -- CONFIGURACION DEL MTU DE LA INTERFAZ TUN:<br />tun-mtu 1500</b><br /></pre>Con lo anterior hemos finalizado con la configuración de las directivas del archivo <b>server.conf</b>, guardamos los cambios realizados y salimos del archivo para continuar con el siguiente paso.<br /><br /></li><li>Luego creamos los directorios <b>keys</b> para almacenar las llaves de los clientes y <b>ccd</b> (definido en la directiva <b>client-config-dir</b> del paso anterior) para almacenar los archivos de políticas de acceso para los distintos <b>common name</b> de los clientes.<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> mkdir /etc/openvpn/keys<br /><span style="color: red;">testsrv:/etc/openvpn #</span> mkdir /etc/openvpn/ccd</b><br /></pre></li><li>Para evitar problemas durante el arranque necesitamos generar una lista para certificados revocados vacía denominada <b>crl.pem</b> en el directorio <b>/etc/openvpn/pki</b>, para lo cual primero procedemos a editar el archivo de configuración <b>openssl-easyrsa.cnf</b> del directorio <b>/etc/openvpn/pki</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> vim /etc/openvpn/pki/openssl-easyrsa.cnf</b><br /></pre>A fin de asignar el valor <b>3650</b> a las directivas <b>default_days</b> y <b>default_crl_days</b> para evitar expiraciones automáticas de llaves no deseadas como el <a href="https://forums.openvpn.net/viewtopic.php?t=23166" target="_blank"><b>caso comentado en éste foro</b></a>.<br /><pre><i>#default_days = $ENV::EASYRSA_CERT_EXPIRE # how long to certify for</i><br /><b>default_days = 3650</b> <i># how long to certify for</i><br /><i>#default_crl_days= $ENV::EASYRSA_CRL_DAYS # how long before next CRL</i><br /><b>default_crl_days= 3650</b> <i># how long before next CRL</i><br /></pre>Una vez finalizado con lo anterior ya podemos proceder a generar el archivo <b>crl.pem</b> con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> easyrsa gen-crl</b><br /><br />Note: using Easy-RSA configuration from: /etc/easy-rsa/vars<br /><br />Using SSL: openssl OpenSSL 1.1.0i-fips 14 Aug 2018<br />Using configuration from /etc/easy-rsa/safessl-easyrsa.cnf<br /><br />An updated CRL has been created.<br />CRL file: /etc/openvpn/pki/crl.pem<br /><br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre></li><li>Activamos el servicio <b>openvpn</b> para que se inicie durante el arranque del sistema operativo y finalmente lo arrancamos con los siguientes comandos:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> systemctl enable openvpn@server<br /><span style="color: red;">testsrv:/etc/openvpn #</span> systemctl start openvpn@server</b><br /></pre><b>OBS</b>: El <b>@server</b> hace referencia al archivo de configuración <b>server.conf</b>, ya que OpenVPN por defecto no viene con un script tradicional para gestionar el servicio.<br /></li></ol><br /><br /><h3>Configuración del Firewall</h3><ol><li><b><span style="text-decoration: underline;"> </span></b>Antes de configurar las directivas del <b>Firewall</b> de <b>OpenSUSE</b>, debemos tener en cuenta que con la ejecución del servicio <b>OpenVPN</b> se generará una nueva interfaz de red lógica para el <b>túnel ssh</b> llamado normalmente por defecto <b>tun0</b>. Recomiendo que la interfaz <b>tun0</b> se asigne a la <b>zona desmilitarizada</b> (DMZ) y la interfaz de red que utilizamos para nuestra <b>LAN</b> interna (eth0, eth1, etc. o el que hayan usado) a otra <b>zona</b> que utilizamos para ello <b>(externa</b> o <b>interna</b>), esto permite evitar que los servicios habilitados para la interfaz que se conecta a la <b>LAN</b> interna no se encuentren también publicados en la interfaz <b>tun0</b>. De esta forma los clientes (Roadwarriors) que se conecten al servicio <b>OpenVPN</b> (que lo pueden hacer únicamente a través de la interfaz <b>tun0</b>) solo podrán acceder a los servicios del servidor openvpn autorizados para esa zona.<br /><br /></li><li>Hecha la aclaración anterior comenzamos a configurar primero la zona pública editando el archivo <b>public.xml</b> del directorio <b>/etc/firewalld/zones</b>, que por defecto suele estar asociada a la interfaz <b>LAN</b> interna (eth0, eth1, etc).<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/firewalld/zones/public.xml</b><br /></pre>Una vez abierto lo dejamos como sigue:<br /><pre><?xml version="1.0" encoding="utf-8"?><br /><zone><br /> <short>Public</short><br /> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description><br /> <service name="ssh"/><br /> <service name="openvpn"/><br /> <masquerade/><br /></zone><br /></pre>En lo anterior resalta que la zona <b>Public</b> tiene habilitada los servicios <b>ssh</b> y <b>openvpn</b>, y tiene activada la función de enmascaramiento de los paquetes mediante la directiva <b>masquerade</b>.<br /><br /></li><li>A continuación creamos a partir del archivo <b>public.xml</b> el archivo <b>dmz.xml</b> para la zona <b>DMZ</b>, luego lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cp /etc/firewalld/zones/public.xml /etc/firewalld/zones/dmz.xml<br /><span style="color: red;">testsrv:~ #</span> vi /etc/firewalld/zones/dmz.xml</b><br /></pre>Y lo dejamos como sigue:<br /><pre><?xml version="1.0" encoding="utf-8"?><br /><zone><br /> <short>DMZ</short><br /> <description>For computers in your demilitarized zone that are publicly-accessible with limited access to your internal network. Only selected incoming connections are accepted.</description><br /> <interface name="tun0"/><br /></zone><br /></pre>Como se puede observar más arriba, en el archivo <b>dmz.xml</b> se le indica que la interfaz <b>tun0</b> se encuentra asociada a la zona <b>DMZ</b>, y como no se especifica ningún servicio (como por ejemplo ssh), <b>el cliente remoto no estará autorizado</b> para poder conectarse directamente al servidor OpenVPN a través de dicho protocolo, o lo que sería lo mismo, el firewall del servidor evita que los clientes Roadwarriors puedan conectarse al puerto <b>ssh 22 o a cualquier otro puerto</b> de algún servicio que pueda estar escuchando en la interfaz de red <b>tun0</b> del servidor (que por defecto suele tener la <b>IP 10.8.0.1/24</b>). También se incluye la directiva <b>masquerade</b> para permitir que el firewall permita enmascarar paquetes de la red corporativa que van al equipo RoadWarrior mediante la interfaz <b>tun0</b>.<br /><br /></li><li>El siguiente y último paso consiste en reiniciar el servicio del <b>Firewall</b> con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart firewalld</b><br /></pre></li></ol><br /><br /><br /><h3>IP Forwarding</h3>El siguiente paso que se debe realizar es activar el <b>IP forwarding</b>. Hay varias formas de hacerlo, pero en este caso la configuración se realiza mediante <b>sysctl</b> que no requiere el reinicio del sistema operativo. Los pasos son los siguientes:<br /><ol><li>Editamos el archivo <b>/etc/sysctl.conf</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysctl.conf</b><br /></pre></li><li>Asignamos el valor 1 a la siguiente directiva (o la agregamos en el caso de que no exista):<br /><pre><b>net.ipv4.ip_forward = 1</b><br /></pre>Luego guardamos los cambios y salimos del archivo <b>sysctl.conf</b>.<br /><br /></li><li>Para que los cambios tomen efecto en el sistema operativo sin reiniciarlo ejecutamos el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> sysctl -p</b><br /></pre></li></ol><br /><br /><h3>Generación de llaves y certificados para roadwarriors</h3>Para crear los certificados y las llaves que utilizarán los clientes vamos a crear un script que nos facilite la tarea de generación automatizando varios pasos que de otra forma deberían ser realizados manualmente. A este script solo será necesario pasarle el <b>Common Name</b> del cliente (el common name debe ser un nombre único para cada cliente) en forma de argumento para generar su correspondiente llave.<br /><ol><li>Lo primero que vamos a hacer es crear un archivo llamado <b>clientes_crear.sh</b> en el directorio <b>/etc/openvpn</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/openvpn<br /><span style="color: red;">testsrv:/etc/openvpn #</span> touch clientes_crear.sh</b><br /></pre></li><li>Luego editamos el archivo:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> vi clientes_crear.sh</b><br /></pre>Y le agregamos el siguiente <b>script bash</b>:<br /><pre><i>#!/bin/bash<br />#<br /># -- Definicion de variables globales</i><br />CLIENT=""<br />OPENVPN_DIR=/etc/openvpn<br />PKI_DIR=$OPENVPN_DIR/pki<br />KEY_DIR=$OPENVPN_DIR/keys<br /><br />CA_CRT=$PKI_DIR/ca.crt<br />TA_KEY=$OPENVPN_DIR/ta.key<br />DEFAULT_SERVER_IP="ip_o_dominio_del_servidor"<br />DEFAULT_SERVER_PORT="1194"<br />WIN_CFG_FILE=client.ovpn<br />LIN_CFG_FILE=client.conf<br /><br /><i># -- Se verifica que se haya pasado el parámetro<br /># correspondiente al cliente y que exista la<br /># carpeta en donde se van a colocar la llave y<br /># los certificados.</i><br />if [ -z "$1" ]; then<br /> echo "Debe Especificar el nombre del cliente!"<br /> exit<br />else<br /> CLIENT=$KEY_DIR/$1<br />fi<br />if ! [ -d "$CLIENT" ]; then<br /> mkdir -p $CLIENT<br />fi<br /><br /><i># -- Se procede a crear la llave y el certificado para<br /># el nuevo cliente, y luego firmarlo con la CA..</i><br />export EASYRSA_BATCH=1<br />export EASYRSA_REQ_CN=$1<br />easyrsa gen-req $1 nopass<br />easyrsa sign-req client $1<br />mv -v $PKI_DIR/private/$1.* $CLIENT<br />cp -v $PKI_DIR/issued/$1.* $CLIENT<br />cp -v $CA_CRT $CLIENT<br />cp -v $TA_KEY $CLIENT<br /><br /><i># -- Se crean los archivos de configuración para el nuevo<br /># cliente, tanto para Windows como para Linux.</i><br />echo "client" > $CLIENT/$WIN_CFG_FILE<br />echo "dev tun" >> $CLIENT/$WIN_CFG_FILE<br />echo "proto udp" >> $CLIENT/$WIN_CFG_FILE<br />echo "resolv-retry infinite" >> $CLIENT/$WIN_CFG_FILE<br />echo "nobind" >> $CLIENT/$WIN_CFG_FILE<br />echo "persist-key" >> $CLIENT/$WIN_CFG_FILE<br />echo "persist-tun" >> $CLIENT/$WIN_CFG_FILE<br />echo "ns-cert-type server" >> $CLIENT/$WIN_CFG_FILE<br />echo "comp-lzo" >> $CLIENT/$WIN_CFG_FILE<br />echo "verb 3" >> $CLIENT/$WIN_CFG_FILE<br />echo "ca ca.crt" >> $CLIENT/$WIN_CFG_FILE<br />echo "tls-auth ta.key 1" >> $CLIENT/$WIN_CFG_FILE<br />echo "tun-mtu 1500" >> $CLIENT/$WIN_CFG_FILE<br />echo "cipher AES-256-GCM" >> $CLIENT/$WIN_CFG_FILE<br />echo "cert $1.crt" >> $CLIENT/$WIN_CFG_FILE<br />echo "key $1.key" >> $CLIENT/$WIN_CFG_FILE<br /><br /><i># -- Se arma la directiva para especificar el servidor y<br /># el puerto del servidor openvpn para un cliente Windows.</i><br />if ! [ -z "$2" ]; then<br /> <i># -- Se verifica si el puerto se recibió como argumento.</i><br /> if ! [ -z "$3" ]; then<br /> echo "remote $2 $3" >> $CLIENT/$WIN_CFG_FILE<br /> else<br /> echo "remote $2 $DEFAULT_SERVER_PORT" >> $CLIENT/$WIN_CFG_FILE<br /> fi<br />else<br /> echo "remote $DEFAULT_SERVER_IP $DEFAULT_SERVER_PORT" >> $CLIENT/$WIN_CFG_FILE<br />fi<br /><br /><i># -- Se crea el archivo de configuración para Linux a partir del<br /># archivo de configuración de Windows generado anteriormente.</i><br />cp $CLIENT/$WIN_CFG_FILE $CLIENT/$LIN_CFG_FILE<br />echo "log-append /var/log/openvpn.log" >> $CLIENT/$LIN_CFG_FILE<br /></pre>Lo que hace el script es cargar las variables de entorno para la generación de llaves y certificados <b>OpenVPN</b>, se definen una seria de variables globales para ubicar los archivos <b>ca.crt</b> y <b>ta.key</b> que se necesitaran incluir en el paquete para el nuevo cliente, luego se verifica que se haya pasado como <b>primer argumento</b> ($1) del script el <b>Common Name</b> que se utiliza para nombrar a los archivos certificado (.crt) y llave (.key) del cliente. El siguiente paso automatizado consiste en definir la ruta en donde se colocarán los archivos a ser generados y se crea la carpeta en el caso de que no exista. Posteriormente se generan los archivos para el cliente y se los reubican en el directorio definido, copiándose en el mismo también los archivos <b>ca.crt</b> y <b>ta.key</b>. Por último se crea un archivo de configuración con las directivas necesarias para el cliente y que con la inclusión de los <b>argumentos dos y tres</b> ($2 y $3) en la ejecución del script <b>se puede configurar dinámicamente la dirección IP o nombre de dominio del servidor OpenVPN y el puerto UDP</b> en el cual se ejecuta el servicio respectivamente. El archivo resultante se coloca en el mismo directorio en donde fueron colocados la llave y el certificado del cliente.<br /><br />Guardamos los cambios y salimos del archivo.<br /><br /></li><li>El siguiente paso consiste en asignarle al archivo <b>clientes_crear.sh</b> los permisos de ejecución correspondientes:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> chmod 700 clientes_crear.sh</b><br /></pre></li><li>Ahora ya podemos ejecutar el script, como ejemplo básico podemos crear los archivos para un cliente llamado <b>empresaX</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> ./clientes_crear.sh empresaX</b><br />Generating a 2048 bit RSA private key<br />..........................+++++<br />...........................................................+++++<br />writing new private key to '/etc/openvpn/pki/private/empresaX.key.MnvO5YHgV8'<br />-----<br />Using configuration from /etc/easy-rsa/safessl-easyrsa.cnf<br />Check that the request matches the signature<br />Signature ok<br />The Subject's Distinguished Name is as follows<br />commonName :ASN.1 12:'empresaX'<br />Certificate is to be certified until Aug 27 02:41:17 2022 GMT (1080 days)<br /><br />Write out database with 1 new entries<br />Data Base Updated<br />renamed '/etc/openvpn/pki/private/empresaX.key' -> '/etc/openvpn/keys/empresaX/empresaX.key'<br />'/etc/openvpn/pki/issued/empresaX.crt' -> '/etc/openvpn/keys/empresaX/empresaX.crt'<br />'/etc/openvpn/pki/ca.crt' -> '/etc/openvpn/keys/empresaX/ca.crt'<br />'/etc/openvpn/ta.key' -> '/etc/openvpn/keys/empresaX/ta.key'<br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre>Otro ejemplo podría ser crear los archivos para un cliente llamado <b>empresaX</b> y que la configuración del servidor remoto tenga como IP y puerto lo siguiente:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> ./clientes_crear.sh empresaX 192.168.1.3 1194</b><br /></pre></li><li>Finalizado la ejecución del script se generará una carpeta con el common name <b>empresaX</b> (en base a los ejemplos del paso anterior) en el directorio <b>/etc/openvpn/keys con los archivos que deberán ser entregados al cliente</b>, la lista de archivos es la siguiente:<br /><ul><li><b>ca.crt</b><br /></li><li><b>ta.key</b><br /></li><li><b>empresaX.crt</b><br /></li><li><b>empresaX.key</b><br /></li><li><b>client.ovpn</b><br /></li><li><b>client.conf</b><br /></li></ul><br /></li><li>Aun nos faltan definir los <b>hosts</b> o nuestras <b>redes</b> corporativas a las cuales deseamos dar <b>acceso a nuestro cliente</b>, esto es algo que se puede definir fácilmente en nuestro servidor<b> OpenVPN</b>. Para lograr lo mencionado anteriormente debemos acceder al directorio <b>/etc/openvpn/ccd</b> y crear un archivo de configuración para el cliente con el <b>CommonName</b> utilizado para el mismo, en este caso utilizaremos como ejemplo nuevemente <b>empresaX</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/openvpn/ccd/<br /><span style="color: red;">testsrv:/etc/openvpn/ccd #</span> touch empresaX</b><br /></pre>Accedemos al archivo <b>empresaX</b>,<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn/ccd #</span> vi empresaX</b><br /></pre>y le asignamos las políticas que nos parezcan, por ejemplo, podemos autorizar al cliente <b>empresaX</b> para que pueda acceder a una <b>red interna</b> con el rango <b>192.168.1.0/24</b>, la directiva quedaría como sigue:<br /><pre><b>push "route 192.168.1.0 255.255.255.0"</b><br /></pre>También podríamos otorgar al cliente el acceso a una sola estación de trabajo que se encuentra dentro de la red interna <b>192.168.1.0/24 </b>mencionada anteriormente.<br /><pre><b>push "route 192.168.1.2 255.255.255.255"</b><br /></pre></li><li>Con el paso anterior culminamos con esta sección ya pudiendo generar los archivos necesarios para nuestros clientes.<br /></li></ol><br /><br /><h3>Revocar certificados</h3>Revocar un certificado consiste en invalidar uno que habíamos creado previamente y que por alguna razón necesitamos que deje de ser útil. Al revocar un certificado el cliente afectado ya no podrá conectarse al servicio <b>OpenVPN</b>, ya que este último rechazará todas aquellas conexiones que utilicen el certificado en cuestión.<br /><br />Podemos automatizar las cosas creando un <b>script</b> que simplifique la tarea de revocar los certificados de los clientes, los pasos a seguir se exponen a continuación.<br /><ol><li>Nos dirigimos al directorio <b>/etc/openvpn</b> y creamos un nuevo archivo de texto plano llamado <b>clientes_revocar.sh</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/openvpn<br /><span style="color: red;">testsrv:/etc/openvpn #</span> touch clientes_revocar.sh</b><br /></pre></li><li>Luego editamos el archivo <b>clientes_revocar.sh</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> vi clientes_revocar.sh</b><br /></pre>y le agregamos el siguiente contenido:<br /><pre><i>#!/bin/bash<br />#<br /># SCRIPT PARA REVOCAR LLAVES DE CLIENTES.<br />#<br /># -- Se verifica que se haya pasado el common name<br /># del cliente como argumento.</i><br />if [ -z "$1" ]; then<br /> echo "Debe Especificar el nombre del cliente!"<br /> exit<br />fi<br /><br /><i># -- Se procede a revocar la llave del cliente.</i><br />export EASYRSA_BATCH=1<br />export EASYRSA_REQ_CN=$1<br />easyrsa revoke $1<br />easyrsa gen-crl<br /></pre>Guardamos los cambios del archivo y salimos del mismo.<br /><br /></li><li>Le otorgamos los permisos de ejecución necesarios:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> chmod 700 clientes_revocar.sh</b><br /></pre></li><li>Y con eso ya está, ya podemos revocar los certificados ejecutando el script <b>clientes_revocar.sh</b> de la siguiente forma:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> ./clientes_revocar.sh empresaX</b><br />Using configuration from /etc/easy-rsa/safessl-easyrsa.cnf<br />Revoking Certificate 59C71CFB43E54378656640E37504EFDF.<br />Data Base Updated<br />Using configuration from /etc/easy-rsa/safessl-easyrsa.cnf<br /><b><span style="color: red;">testsrv:/etc/openvpn #</span></b><br /></pre>Según manual, si hemos revocado un cliente mientras este se encuentre conectado, su conexión seguirá funcionando hasta tanto intente renegociar su conexión que en <b>OpenVPN</b> se encuentra configurado por defecto en <b>una (1) hora</b>. Esta configuración se puede modificar declarando la directiva <b>reneg-sec n</b> en el archivo <b>/etc/openvpn/server.conf</b>, donde <b>n</b> es la cantidad de segundos que se desea esperar entre cada renegociación de conexión y que por defecto está configurado de forma implícita en <b>3600 segundos</b>, o lo que es lo mismo, la 1 hora que había mencionado al principio.<br /><br />Sin embargo, en el entorno de pruebas que configuré, la renegociación de la conexión de un cliente revocado no evitó que el tunel dejara de funcionar, tiraba un montón de errores de conexión en el log del servidor, pero el túnel seguía funcionando en ambas direcciones sin problemas. Para forzar que el servidor y el cliente se den cuenta de que el certificado se encuentra revocado, el único procedimiento que me funcionó fue <b>reiniciar el servicio openvpn</b>, con todo lo que ello implica para las demás conexiones activas y vigentes:<br /><pre><b><span style="color: red;">testsrv:/etc/openvpn #</span> systemctl restart openvpn@server</b><br /></pre></li></ol><br /><br /><h3>Consola de administración de OpenVPN</h3>Anteriormente, cuando configuramos el servicio <b>OpenVPN</b> mediante el archivo de configuración <b>server.conf</b> agregamos la directiva <b>management</b> cuya funcionalidad era la de activar la<b> consola de administración</b> del servicio, como en ese momento no se especificó la forma de acceder a dicha herramienta nos encargaremos de eso en esta sección.<br /><ol><li>Para acceder a la <b>consola de administración</b> del servico <b>OpenVPN</b> hacemos uso del protocolo <b>telnet</b> especificando el <b>host</b> y el <b>puerto</b> como se muestra con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> telnet 127.0.0.1 1195</b><br /></pre></li><li>El comando anterior desplegará una interfaz que nos permitirá introducir comandos para gestionar el servicio, a modo de ejemplo les dejo con la salida de la ejecución del comando <b>state</b>, pero si desean conocer la lista completa de opciones pueden ejecutar el comando <b>help</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> telnet 127.0.0.1 1195<br /></b>Trying 127.0.0.1...<br />Connected to 127.0.0.1.<br />Escape character is '^]'.<br />>INFO:OpenVPN Management Interface Version 1 -- type 'help' for more info<br /><span style="color: green;"><b>state<br /></b></span>1295529194,CONNECTED,SUCCESS,10.8.0.1,<br />END<br /><span style="color: green;"><b>exit<br /></b></span>Connection closed by foreign host.<br /><b><span style="color: red;">testsrv:~ #</span></b><br /></pre></li></ol><br /><br /><h3>Clientes OpenVPN en Windows</h3>A continuación se verán los pasos necesarios para configurar el cliente OpenVPN en Windows. Es importante tener en cuenta que en los equipos clientes la red de su interfaz debe ser distinta a las redes autorizadas en el servidor OpenVPN (en el archivo /etc/openvpn/ccd/empresaX), ya que en caso contrario se generará un conflicto en el ruteo de las redes. El equipo cliente no podrá identificar correctamente su propia red local con la red remota a la cual puede acceder a través del túnel de la VPN.<br /><ol><li>Si bien se recomienda descargar la última versión del programa <b>OpenVPN</b> para Windows desde su sitio oficial en Internet, para estas pruebas se usó la <b>versión 2.4.7</b> que ha funcionado correctamente con la <b>versión 2.4.3</b> del servidor Linux. <br /><pre><b>URL: <a href="https://openvpn.net/community-downloads/" target="_blank">https://openvpn.net/community-downloads/</a></b></pre></li><li>En el directorio <b>C:\Archivos de programa\OpenVPN\config</b> le copiamos los archivos generados en el servidor para nuestro cliente, en esta guía el cliente de ejemplo será <b>"empresaX</b>", los archivos que deben estar en ese directorio son los siguientes:<br /><ul><li><b>ca.crt</b><br /></li><li><b>ta.key</b><br /></li><li><b>empresaX.crt</b><br /></li><li><b>empresaX.key</b><br /></li><li><b>client.ovpn</b><br /></li><li><b>client.conf</b> (No requerido para Windows)<br /></li></ul><br /><b>OPCIONAL</b>: Si no disponemos de un archivo de configuración <b>.ovpn</b> generado por el script <b>clientes_crear.sh</b> mencionado en el apartado <b>Generación de llave y certificado para el cliente</b> de esta guía, podemos crear ese archivo de configuración a partir de un archivo de ejemplo que viene junto con la instalación, para ello creamos una copia del archivo <b>C:\Archivos de programa\OpenVPN\sample-config\client.ovpn</b> en el directorio <b>C:\Archivos de programa\OpenVPN\config</b>, luego editamos el archivo con nuestro editor preferido y le seteamos las siguientes directivas:<br /><pre><b>remote ip_o_dominio_de_servidor 1194<br />ca ca.crt<br />cert empresaX.crt<br />key empresaX.key<br />tls-auth ta.key 1</b><br /></pre>Guardamos los cambios del archivo.<br /><br /></li><li>Luego debemos configurar la ejecución del cliente <b>openvpn</b> como un servicio, para ello nos dirigimos a <b>Panel de Control -> Herramientas Administrativas -> Servicios</b>, en la ventana de la aplicación servicios buscamos la opción <b>openvpn</b> y la configuramos para que arranque de forma automática durante el inicio del sistema operativo. Esta opción funciona muy bien y es la recomendada, ya que mientras no haya conexión a Internet el servicio se mantendrá inactivo, cuando se restablece la conexión a Internet el <b>servicio openvpn</b> automáticamente también se iniciará estableciendo la conexión sin contratiempos y sin intervención del usuario.<br /><br />Si no queremos utilizar el servicio podemos ejecutar la aplicación <b>OpenVPN GUI</b> como <b>administrador</b>, cuyo icono se ubicará en el área de notificaciones y sobre el cual tenemos que hacer un clic con el botón derecho del mouse para seleccionar la opción <b>Connect</b>. Esta opción no es tan recomendada porque cuando no se ejecuta con permisos de administrador el programa puede no tener los permisos necesarios para establecer el túnel y crear las rutas, sin contemplar que el operador puede cerrar la aplicación o cambiar alguna configuración por error. <br /><br /></li><li>Para finalizar podemos controlar las <b>rutas</b> que fueron agregadas a la <b>tabla de ruteo</b> del sistema operativo luego de que el túnel se haya establecido de forma exitosa:<br /><pre><b>C:\>route print</b><br /></pre></li></ol><br /><h3>Vencimiento de Certificados</h3>Dejo una pequeña nota al final del artículo para recordar que si no hemos configurado apropiadamente las directivas <b>EASYRSA_CA_EXPIRE</b> y <b>EASYRSA_CERT_EXPIRE</b> en el archivo <b>/etc/easy-rsa/vars</b>, es posible que nuestros certificados expiren automáticamente en el momento menos previsto.<div><br /></div><div>Si les llega a expirar automáticamente un certificado de un roadwarrior, lo único que tenemos que hacer es volver a generar un nuevo certificado con el script <b>clientes_crear.sh</b>, usando el mismo nombre de cliente, y enviarle los nuevos archivos al equipo cliente para reemplazar los antiguos.</div><div><br /></div><div>Ahora bien, si el certificado de la Entidad Certificadora llega a expirar el problema será mucho mayor, ya que es posible que se tenga que volver a generar el certificado para la CA y luego volver a generar de nuevo todos los certificados para los equipos clientes, ya que al cambiar el certificado del CA todos los demás certificados ya quedarán obsoletos.</div><div><br /><h3>Fuentes</h3>Para la redacción de este artículo se han utilizado en gran parte las siguientes fuentes:<br /><ul><li><a href="https://www.blogger.com/2012/06/openvpn-roadwarrior-linux-opensuse-conf.html" target="_blank"><b>Tormenta de Bits - Instalación de OpenVPN en openSUSE 11.3 (2012)</b></a><br /></li><li><a href="https://juncotic.com/openvpn-easyrsa-3-montando-la-vpn/" target="_blank"><b>juncotic.com - OpenVPN + EasyRSA-3: Montando la VPN</b></a><br /></li><li><a href="https://www.howtoforge.com/tutorial/how-to-install-openvpn-server-and-client-with-easy-rsa-3-on-centos-7/" target="_blank"><b>howtoforge.com - Install OpenVPN Server and Client with EASY-RSA</b></a><br /></li><li><a href="https://doc.opensuse.org/documentation/leap/archive/15.0/security/html/book.security/cha.security.firewall.html" target="_blank"><b>doc.opensuse.org - Masquerading and Firewalls</b></a><br /></li><li><a href="https://forums.opensuse.org/showthread.php/513678" target="_blank"><b>forums.opensuse.org - VPN step-by-step</b></a><br /></li></ul></div>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com2tag:blogger.com,1999:blog-1035903216249592564.post-55454044361861862262019-09-09T22:50:00.005-04:002022-10-04T22:58:00.333-03:00Instalación de Cacti en openSUSE 15.1<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00020.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00020.png" width="320" /></a></div><b>Cacti</b> es una herramienta que ofrece una solución completa para el análisis de redes y equipos, su uso en tareas de monitoreo está ampliamente extendido y es capaz de generar potentes gráficos mediante la plataforma <b>RRDtools</b>.<br /><br />En este artículo se documentarán todos los pasos a seguir para instalar la versión <b>1.2.5</b> de <b>Cacti</b> en <b>openSUSE 15.1</b>, incluyendo también los pasos para instalar nuevos complementos que permiten agregar nuevas funcionalidades a la herramienta.<br /><a name='more'></a><br />Queda a cargo de los lectores investigar y aprender a usar la herramienta, y la manera de sacar el mayor provecho a la misma. Pueden visitar el artículo sobre <a href="http://es.wikipedia.org/wiki/Cacti" target="_blank"><b>Cacti en wikipedia</b></a> o su página oficial (cuyo enlace se encuentra al final de este artículo) para obtener mayor información acerca de la misma.<br /><br /><h3>Requisitos</h3><ol><li>Para comenzar primero tenemos que instalar y configurar el motor de base de datos <b>MariaDB</b>, para lo cual les recomiendo seguir la guía que escribí recientemente y que la pueden <a href="https://www.tormentadebits.com/2019/07/mariadb-y-phpmyadmin-en-opensuse-15-1.html" target="_blank"><b>consultar aquí</b></a>.<br /><br /></li><li>A continuación se necesitan tener instalados los siguientes paquetes:<br /><pre><b>apache2<br />apache2-mod_php7<br />rrdtool<br />php7<br />php7-mysql<br />php7-snmp<br />php7-gmp<br />php7-ldap<br />php7-openssl<br />php7-sockets<br />php7-posix<br />net-snmp</b><br /></pre>Para instalar los paquetes con zypper tenemos que ejecutar el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper in apache2 apache2-mod_php7 rrdtool php7 php7-mysql php7-snmp php7-gd php7-gettext php7-gmp php7-ldap php7-openssl php7-sockets php7-posix net-snmp</b><br /></pre></li></ol><br /><br /><h3>Instalación de la herramienta</h3>Los pasos que se siguieron para instalar esta herramienta de monitoreo son los siguientes:<br /><ol><li>Lo mejor es descargar la última versión desde el propio sitio web de <a href="https://www.cacti.net/downloads/cacti-latest.zip" target="_blank"><b>Cacti</b></a>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /srv/www<br /><span style="color: red;">testsrv:/srv/www/cacti #</span> wget https://www.cacti.net/downloads/cacti-1.2.5.zip<br /><span style="color: red;">testsrv:/srv/www/cacti #</span> unzip cacti-1.2.5.zip<br /><span style="color: red;">testsrv:/srv/www/cacti #</span> mv cacti-1.2.5/ cacti<br /><span style="color: red;">testsrv:/srv/www/cacti #</span> rm cacti-1.2.5.zip</b><br /></pre></li><li>El siguiente paso consiste en crear en el motor de base de datos <b>MariaDB</b> una nueva base de datos para la herramienta <b>Cacti</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> mysqladmin -u root -p create cacti</b><br /></pre></li><li>Nos conectamos a la base de datos MariaDB con el usuario <b>root</b> para cambiar el juego de caracteres a <b>UTF8</b>, crear un nuevo usuario denominado <b>cactiuser</b> y otorgarle los permisos necesarios para acceder y modificar el contenido de la base de datos <b>cacti</b> creada en el punto dos.<br /><pre><b><span style="color: red;">testsrv:~ #</span> mysql -u root -p mysql</b><br /></pre><pre>Reading table information for completion of table and column names<br />You can turn off this feature to get a quicker startup with -A<br /><br />Welcome to the MariaDB monitor. Commands end with ; or \g.<br />Your MariaDB connection id is 4601<br />Server version: 10.2.22-MariaDB openSUSE package<br /><br />Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.<br /><br /><b>MariaDB [mysql]> </b><span style="color: red; font-weight: bold;">ALTER DATABASE cacti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;</span><br />Query OK, 0 rows affected (0.00 sec)<br /><br /><b>MariaDB [mysql]> </b><span style="color: red; font-weight: bold;">GRANT ALL ON cacti.* TO cactiuser@localhost IDENTIFIED BY 'contraseña_para_cactiuser';</span><br />Query OK, 0 rows affected (0.00 sec)<br /><br /><b>MariaDB [mysql]> </b><span style="color: red; font-weight: bold;">GRANT SELECT ON mysql.time_zone_name TO cactiuser@localhost;</span><br />Query OK, 0 rows affected (0.00 sec)<br /><br /><b>MariaDB [mysql]> </b><span style="color: red; font-weight: bold;">flush privileges;</span><br />Query OK, 0 rows affected (0.00 sec)<br /><br /><b>MariaDB [mysql]> </b><span style="color: red; font-weight: bold;">exit</span><br />Bye<br /></pre></li><li>Luego cargamos registros relacionados con la configuración de <b>timezones</b> para <b>MariaDB</b> e importamos la base de datos inicial para la herramienta <b>Cacti</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mysql -u root -p mysql < /usr/share/mariadb/mysql_test_data_timezone.sql<br /><span style="color: red;">testsrv:~ #</span> mysql -u root -p cacti < /srv/www/cacti/cacti.sql</b><br /></pre></li><li>Editamos el archivo <b>config.php</b> ubicado en el directorio <b>/srv/www/cacti/include</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> vim /srv/www/cacti/include/config.php</b><br /></pre>y a continuación configuramos el tipo de base de datos (<b>$database_type</b>), la base de datos por defecto a ser utilizada por la herramienta (<b>$database_default</b>), el nombre del host en la cual se encuentra la base de datos (<b>$database_hostname</b>) y la definición del nombre del usuario y su respectiva contraseña con el cual Cacti se conectará a su base de datos (<b>$database_username</b> y <b>$database_password</b>). Por otro lado, en el caso de que hayamos modificado el número de puerto por defecto en el que el motor de base de datos MariaDB atiende las peticiones de conexión, tendremos que especificar ese mismo puerto en la directiva <b>$database_port</b>. El archivo <b>config.php</b> deberá quedar similar a lo que sigue:<br /><pre>$database_type = "mysql";<br />$database_default = "cacti";<br />$database_hostname = "localhost";<br />$database_username = "cactiuser";<br />$database_password = "contraseña_de_cactiuser";<br />$database_port = "3306";<br /></pre>Realizado lo anterior guardamos los cambios y cerramos el archivo <b>config.php</b> para pasar al siguiente punto de configuración.<br /><br /></li><li>En este paso tenemos que aplicar los permisos apropiados para varios directorios. Como la herramienta será ejecutada a través del servicio Apache, debemos asignar a los directorios el usuario/grupo <b>wwwrun/www</b> respectivamente de forma recursiva, para que el servicio pueda leer y escribir en dichos directorios.<br /><pre><b><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/rra<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/log<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/resource<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/scripts<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/cache/boost<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/cache/mibcache<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/cache/realtime<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /srv/www/cacti/cache/spikekill</b><br /></pre></li><li>A continuación creamos un archivo para la herramienta Cacti en el directorio <b>/etc/cron.d</b> y luego lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/cron.d/cacti<br /><span style="color: red;">testsrv:~ #</span> vi /etc/cron.d/cacti</b><br /></pre>Una vez abierto le agregamos el siguiente contenido:<br /><pre><i># Ejecución de la graficación de Cacti cada cinco minutos.</i><br />*/5 * * * * wwwrun php /srv/www/cacti/poller.php > /dev/null 2>&1<br /></pre>Finalmente guardamos los cambios y reiniciamos el servicio <b>cron</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart cron</b><br /></pre></li><li>También tenemos que configurar las directivas <b>memory_limit</b>, <b>max_execution_time</b> y <b>date.timezone</b> de PHP7 que afecta el despliegue de las fechas y horas en Cacti. Comenzamos por editar el archivo <b>php.ini</b> del directorio <b>/etc/php7/apache2</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/php7/apache2/php.ini</b><br /></pre>En el archivo buscamos las directivas <b>memory_limit</b> y <b>max_execution_time</b>, y las dejamos como sigue:<br /><pre><b>; Maximum amount of memory a script may consume (128MB)<br />; http://php.net/memory-limit<br />;memory_limit = 128M<br />memory_limit = 500M</b><br /></pre><pre><b>; Maximum execution time of each script, in seconds<br />; http://php.net/max-execution-time<br />; Note: This directive is hardcoded to 0 for the CLI SAPI<br />;max_execution_time = 30<br />max_execution_time = 60</b><br /></pre>Finalmente buscamos la directiva <b>date.timezone</b> de la sección <b>[Date]</b> que por defecto está configurada en UTC, la comentamos y justo abajo agregamos la misma directiva pero configurada con el timezone que corresponda para nuestro huso horario, en este ejemplo <b>America/Asuncion</b> (La lista de timezones de PHP se pueden ver en <a href="https://www.php.net/manual/es/timezones.php" target="_blank"><b>éste enlace</b></a>).<br /><pre><b>[Date]<br />; Defines the default timezone used by the date functions<br />; http://php.net/date.timezone<br />;date.timezone = 'UTC'<br />date.timezone = 'America/Asuncion'</b><br /></pre>Por otro lado, solo la directiva <b>date.timezone</b> configuramos en el archivo de mismo nombre <b>php.ini</b> pero del directorio <b>/etc/php7/cli</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/php7/cli/php.ini</b><br /></pre></li><li>Luego en el directorio <b>/etc/apache2/conf.d</b> creamos y editamos el archivo de configuración <b>cacti.conf</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/apache2/conf.d/cacti.conf<br /><span style="color: red;">testsrv:~ #</span> vim /etc/apache2/conf.d/cacti.conf</b><br /></pre>Y dejamos el contenido del archivo como se detalla a continuación:<br /><pre><i># Cacti - the complete rrdtool-based graphing solution<br /># <br /># Allows only localhost by default<br />#<br /># Allowing cacti to anyone other than localhost should be considered<br /># dangerous unless properly secured by SSL<br /><br /># Make sure, that httpd can read your cacti directories.<br /># At minimum, you need<br /># chmod ugo+r -R /your/cacti/dir<br /># Make sure to replace with your directories<br /><br /># When using SELinux, set the following:<br /># chcon -R -h -t httpd_sys_content_t /your/cacti/dir<br /># when using SELinux and you private homedir, enable<br /># setsebool -P httpd_enable_homedirs 1<br /># setsebool -P httpd_read_user_content 1</i><br />Alias /cacti /srv/www/cacti<br /><Directory /srv/www/cacti><br /> <i># AllowOverride None<br /> # Order Deny,Allow<br /> # Deny from all<br /> # Allow from 127.0.0.1<br /> # Allow from ::1</i><br /> Options Indexes Includes FollowSymLinks<br /> Require all granted<br /></Directory><br /><br /><i># These directories do not require access over HTTP <br />#</i><br /><Directory /srv/www/cacti/cli><br /> <i># Order Deny,Allow<br /> # Deny from All<br /> # Allow from None</i><br /> AllowOverride none<br /> Require all denied<br /></Directory><br /></pre></li><li>En cuanto a la configuración de Apache propiamente dicha, lo primero que debemos hacer es editar el archivo <b>apache2</b> del directorio <b>/etc/sysconfig</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/apache2</b><br /></pre>Una vez en el archivo nos dirigimos a la sección <b>APACHE_MODULES</b> para verificar que los módulos <b>ssl</b> y <b>php7</b> estén debidamente habilitados:<br /><pre><b>APACHE_MODULES</b>="actions alias auth_basic authn_core authn_file authz_host authz_groupfile authz_core authz_user autoindex cgi dir env expires include log_config mime negotiation setenvif <span style="color: red;"><b>ssl</b></span> socache_shmcb userdir reqtimeout <span style="color: red;"><b>php7</b></span>"<br /></pre>También, en el mismo archivo tenemos que asignar a la directiva <b>APACHE_SERVER_FLAGS</b> el valor <b>SSL</b> para habilitar la función en el Apache:<br /><pre><b>APACHE_SERVER_FLAGS</b>="<span style="color: red;"><b>SSL</b></span>"<br /></pre></li><li>El siguiente paso consiste en verificar que <b>Apache</b> esté correctamente configurado para que escuche en los puertos indicados tanto para el protocolo <b>http</b>, que por defecto usa el puerto <b>80</b>, como así también para las conexiones seguras bajo el protocolo <b>https</b> que normalmente usa el puerto <b>443</b>. Para ello abrimos el archivo llamado <b>listen.conf</b> ubicado en el directorio <b>/etc/apache2</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/apache2/listen.conf</b><br /></pre>que debería tener una configuración similar a lo que sigue:<br /><pre><b>Listen 80<br /><br /><IfDefine SSL><br /> <IfDefine !NOSSL><br /> <IfModule mod_ssl.c><br /><br /> Listen 443<br /><br /> </IfModule><br /> </IfDefine><br /></IfDefine></b><br /></pre></li><li>A continuación generamos un certificado personalizado mediante el comando <b>gensslcert</b> al que le pasamos varios argumentos para enriquecer el contenido del certificado como se muestra a continuación:<br /><pre><b><span style="color: red;">testsrv:~ #</span> gensslcert -N "Este es un Certificado de Ejemplo" -c PY -s It -l HO -o "Gabriel-Corp." -u "Informatica" -n "tdb.gknet.local" -e "contacto(ARROBA)tdb.com" -y 60</b><br /></pre>Al ejecutar el comando se crearán una serie de archivos inicialmente llamados con el nombre <b>tdb.gknet.local-</b> en los siguientes directorios:<br /><pre><b>/etc/apache2/ssl.crt/tdb.gknet.local-ca.crt<br />/etc/apache2/ssl.crt/tdb.gknet.local-server.crt<br />/etc/apache2/ssl.csr/tdb.gknet.local-server.csr<br />/etc/apache2/ssl.key/tdb.gknet.local-ca.key<br />/etc/apache2/ssl.key/tdb.gknet.local-server.key<br />/srv/www/htdocs/TDB.GKNET.LOCAL-CA.crt</b><br /></pre></li><li>A continuación nos dirigimos al directorio de configuración <b>/etc/apache2/vhosts.d</b> y creamos una copia a partir del archivo <b>vhost-ssl.template</b> con el nombre <b>vhost-ssl.conf</b>, que luego lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/apache2/vhosts.d<br /><span style="color: red;">testsrv:/etc/apache2/vhosts.d #</span> cp vhost-ssl.template vhost-ssl.conf<br /><span style="color: red;">testsrv:/etc/apache2/vhosts.d #</span> vim vhost-ssl.conf</b><br /></pre>En el archivo <b>vhost-ssl.conf</b> dejamos las directivas <b>SSLCertificateFile</b> y <b>SSLCertificateKeyFile</b> configuradas como sigue:<br /><pre><i># You can use per vhost certificates if SNI is supported.</i><br /><b>SSLCertificateFile /etc/apache2/ssl.crt/tdb.gknet.local-server.crt<br />SSLCertificateKeyFile /etc/apache2/ssl.key/tdb.gknet.local-server.key</b><br /></pre></li><li>Antes de iniciar el servicio Apache2 debemos verificar si el nombre del host se encuentra correctamente definido para nuestra dirección IP en el archivo <b>/etc/hosts</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cat /etc/hosts<br /><i>#<br /># hosts This file describes a number of hostname-to-address<br /># mappings for the TCP/IP subsystem. It is mostly<br /># used at boot time, when no name servers are running.<br /># On small systems, this file can be used instead of a<br /># "named" name server.<br /># Syntax:<br />#<br /># IP-Address Full-Qualified-Hostname Short-Hostname<br />#<br /></i><br />127.0.0.1 localhost<br /><br /><i># special IPv6 addresses</i><br />::1 localhost ipv6-localhost ipv6-loopback<br /><br />fe00::0 ipv6-localnet<br /><br />ff00::0 ipv6-mcastprefix<br />ff02::1 ipv6-allnodes<br />ff02::2 ipv6-allrouters<br />ff02::3 ipv6-allhosts<br /><b>192.168.1.100 tdb.gknet.local tdb</b><br /><span style="color: red;">testsrv:~ #</span></b><br /></pre>Sino está la línea accedemos al apartado de configuración de redes de <b>Yast</b> y configuramos el campo <b>Hostname</b> de la ventana que se muestra a continuación:<br /><pre>YaST2 - lan @ testsrv<br /><br /> Network Card Setup<br /> ┌General──Address──Hardware────────────────────────────────────────┐<br /> │ Device Type Configuration Name │<br /> │ Ethernet▒▒▒▒▒▒▒▒▒▒▒▒▒â eth0▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ │<br /> │( ) No Link and IP Setup (Bonding Slaves) [ ] Use iBFT Values │<br /> │( ) Dynamic Address DHCP▒▒▒▒▒▒▒▒▒▒â DHCP both version 4 and 6▒â │<br /> │(x) Statically Assigned IP Address │<br /> │IP Address Subnet Mask Hostname │<br /> │192.168.1.100▒▒▒▒▒▒ /24▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ <span style="color: red;"><b>tdb.gknet.local</b></span>▒▒ │<br /> │┌Additional Addresses────────────────────────────────────────────┐│<br /> ││ ┌─────────────────────────────────────────────────────────┐ ││<br /> ││ │IPv4 Address Label│IP Address│Netmask │ ││<br /> ││ │ │ ││<br /> ││ └─────────────────────────────────────────────────────────┘ ││<br /> ││ [Add][Edit][Delete] ││<br /> │└────────────────────────────────────────────────────────────────┘│<br /> └──────────────────────────────────────────────────────────────────┘<br />[Help] [Back] [Cancel] [Next]<br /><br />F1 Help F3 Add F9 Cancel F10 Next<br /></pre></li><li>A continuación verificamos que la configuración del servicio <b>apache2</b> esté correcta:<br /><pre><b><span style="color: red;">testsrv:~ #</span> apache2ctl configtest<br />Syntax OK<br /><span style="color: red;">testsrv:~ #</span></b><br /></pre>Y luego activamos y reiniciamos el servicio <b>apache2</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable apache2<br /><span style="color: red;">testsrv:~ #</span> systemctl restart apache2</b><br /></pre>Una vez iniciado el servicio <b>apache2</b> podemos verificar si funciona el servicio <b>https</b> de la siguiente manera.<br /><pre><b><span style="color: red;">testsrv:~ #</span> openssl s_client -connect tdb.gknet.local:443</b><br />CONNECTED(00000003)<br />depth=0 C = PY, ST = It, L = HO, O = Gabriel-Corp, OU = Informatica, CN = tdb.gknet.local, emailAddress = contacto(ARROBA)tdb.com<br />verify error:num=20:unable to get local issuer certificate<br />verify return:1<br /><br />depth=0 C = PY, ST = It, L = HO, O = Gabriel-Corp, OU = Informatica, CN = tdb.gknet.local, emailAddress = contacto(ARROBA)tdb.com<br />verify error:num=21:unable to verify the first certificate<br />verify return:1<br />---<br />Certificate chain<br /> 0 s:/C=PY/ST=It/L=HO/O=Gabriel-Corp/OU=Informatica/CN=tdb.gknet.local/emailAddress=contacto(ARROBA)tdb.com<br /> i:/C=PY/ST=It/L=HO/O=Gabriel-Corp/OU=CA/CN=tdb.gknet.local/emailAddress=contacto(ARROBA)tdb.com<br />---<br />Server certificate<br />-----BEGIN CERTIFICATE-----<br />MIIEQzCCAyugAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBqjELMAkGA1UEBhMCUFkx<br />..<br />..<br /></pre></li><li>Luego habilitamos el servicio Apache en el cortafuegos de openSUSE, para ello editamos el archivo <b>/etc/firewalld/zones/public.xml</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/firewalld/zones/public.xml</b><br /></pre>y el contenido debería quedar como se muestra a continuación:<br /><pre><zone><br /> <short>Public</short><br /> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description><br /> <service name="ssh"/><br /> <b><service name="http"/></b><br /> <b><service name="https"/></b><br /> <service name="dhcpv6-client"/><br /></zone></pre>Guardamos los cambios, salimos del editor y procedemos a reiniciar el cortafuegos con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart firewalld</b><br /></pre></li><li>En este punto ya podemos acceder a la interfaz web de la herramienta Cacti colocando en la barra de direcciones de nuestro navegador favorito la siguiente URL:<br /><pre><b>https://nombre_o_ip_servidor/cacti/</b><br /></pre>Sin embargo, aún nos falta trabajo por hacer que consiste en seguir las instrucciones que nos muestra la interfaz web para culminar la instalación y configuración de la herramienta. En la primera pantalla la herramienta nos solicitará actualizar la contraseña por defecto del usuario <b>admin</b>, que suele ser la palabra <b>admin</b> también:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-00.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="390" data-original-width="530" height="291" src="http://files.tormentadebits.com/images/00026-cacti-00.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-01.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="390" data-original-width="530" height="293" src="http://files.tormentadebits.com/images/00026-cacti-01.png" width="400" /></a></div></li><li>En el siguiente paso podemos definir el tema y el idioma predeterminado de la herramienta, además de tener que aceptar el acuerdo de la licencia, requisito obligatorio para avanzar al siguiente paso. Presionamos el botón <b>Comenzar</b> para avanzar.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-02.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="665" data-original-width="903" height="472" src="http://files.tormentadebits.com/images/00026-cacti-02.png" width="640" /></a></div></li><li>A continuación el asistente nos informará acerca de todas las dependencias que faltan instalar o configurar para que el entorno quede correctamente configurado para la herramienta Cacti. Uno de los casos que se requirió configurar fue el motor de base de datos <b>MariaDB</b>, que por defecto trae las configuraciones mínimas para funcionar pero que son insuficientes para un buen desempeño de la herramienta Cacti.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-03.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="803" data-original-width="906" height="567" src="http://files.tormentadebits.com/images/00026-cacti-03.png" width="640" /></a></div>En base a la información del asistente de instalación se procedió entonces a configurar el motor de base de datos con los parámetros recomendados. Se comenzó por editar el siguiente archivo de configuración:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/my.cnf</b><br /></pre>En el cual se configuraron las directivas con sus respectivos valores dentro de la sección <b>[mysqld]</b>, justo por encima de la sección <b>[mysqld_multi]</b>:<br /><pre><b># Parametros de configuracion para Cacti.<br />collation_server = utf8mb4_unicode_ci<br />max_heap_table_size = 300M<br />tmp_table_size = 100M<br />join_buffer_size = 200M<br />innodb_buffer_pool_size = 1500M<br />innodb_doublewrite = OFF<br />innodb_flush_log_at_timeout = 3<br />innodb_read_io_threads = 32<br />innodb_write_io_threads = 16<br />innodb_buffer_pool_instances = 17<br />innodb_io_capacity = 5000<br />innodb_io_capacity_max = 10000</b><br /></pre>Finalmente es importante recordar que si instalamos dependencias <b>php</b> y/o configuramos el motor de base de datos <b>MariaDB</b>, tendremos que reiniciar los servicios <b>apache2</b> y <b>mariadb</b> respectivamente para que los cambios tomen efecto:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart apache2<br /><span style="color: red;">testsrv:~ #</span> systemctl restart mariadb</b><br /></pre>Luego de reiniciar los servicios y de refrescar el asistente de instalación web se debería observar que todos los requisitos fueron cumplidos:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-04.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="668" data-original-width="904" height="473" src="http://files.tormentadebits.com/images/00026-cacti-04.png" width="640" /></a></div></li><li>En el paso que sigue el asistente nos solicitará seleccionar el tipo de instalación, dejamos la configuración por defecto <b>Nuevo servidor primario</b> y presionamos el botón <b>Siguiente</b> para continuar:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-05.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="664" data-original-width="904" height="470" src="http://files.tormentadebits.com/images/00026-cacti-05.png" width="640" /></a></div></li><li>En el siguiente paso el asistente verifica que los permisos de los directorios sean correctos:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-06.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="667" data-original-width="904" height="472" src="http://files.tormentadebits.com/images/00026-cacti-06.png" width="640" /></a></div></li><li>En este paso el asistente desplegará un formulario en el que muestra las rutas hacia los distintos directorios y librerías requeridos por la aplicación. Como se podrá ver más abajo en la imagen, el propio sistema informa si las rutas a los directorios son correctas, en el caso del ejemplo no fue necesario realizar ninguna modificación:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-07.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="664" data-original-width="903" height="471" src="http://files.tormentadebits.com/images/00026-cacti-07.png" width="640" /></a></div></li><li>El asistente nos permitirá configurar el intervalo de recopilación de información que recomiendo dejar por defecto, sin embargo, recomiendo desactivar la opción de escaneo automático de la red en búsqueda de dispositivos (encerrado en rojo).<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-08.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="667" data-original-width="903" height="473" src="http://files.tormentadebits.com/images/00026-cacti-08.png" width="640" /></a></div></li><li>En el siguiente paso el asistente nos dejará elegir que plantillas de dispositivos vamos a usar, recomiendo que todos queden marcados como se muestra en la captura que sigue:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-09.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="664" data-original-width="903" height="471" src="http://files.tormentadebits.com/images/00026-cacti-09.png" width="640" /></a></div></li><li>Si pasamos al siguiente paso el asistente verificará que la configuración del juego de caracteres sea adecuado en la base de datos y en la configuración de la herramienta Cacti:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-10.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="794" data-original-width="905" height="562" src="http://files.tormentadebits.com/images/00026-cacti-10.png" width="640" /></a></div></li><li>Finalmente llegamos al último paso, donde marcamos la opción <b>Confirmar instalación</b> y presionamos el botón <b>Instalar</b> para iniciar el proceso de instalación:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-11.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="663" data-original-width="902" height="470" src="http://files.tormentadebits.com/images/00026-cacti-11.png" width="640" /></a></div>El asistente de instalación nos mantendrá al tanto con el avance de la misma como se puede observar a continuación:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-12.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="663" data-original-width="900" height="471" src="http://files.tormentadebits.com/images/00026-cacti-12.png" width="640" /></a></div>Con la siguiente captura el asistente nos estará avisando que el proceso de instalación ha finalizado, podemos presionar el botón <b>Comenzar</b> que nos llevará directamente a la consola principal de la herramienta:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-13.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="846" data-original-width="905" height="598" src="http://files.tormentadebits.com/images/00026-cacti-13.png" width="640" /></a></div></li></ol><h3>Instalación de plugins</h3>Cacti cuenta con <a href="http://docs.cacti.net/plugins">varios plugins</a> que permiten ampliar su funcionalidad y el procedimiento de instalación es muy sencillo. <br /><ol><li>Antes que nada debemos dirigirnos a la carpeta <b>plugins</b> de Cacti ubicada en el directorio <b>/srv/www/cacti</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /srv/www/cacti/plugins</b><br /></pre></li><li>En la página de <a href="http://docs.cacti.net/plugins"><b>plugins de cacti</b></a> podemos buscar la URL del complemento que nos interesa instalar, de entre los cuales recomiendo los siguientes:<br /><ul><li><a href="http://docs.cacti.net/plugin:cycle"><b>Cycle</b></a><br /></li><li><a href="https://docs.cacti.net/plugin:thold"><b>Thold</b></a><br /></li></ul></li><li>En el siguiente paso procedemos a descargar ambos complementos con el programa <b>wget</b> para posteriormente descomprimirlos:<br /><pre><b><span style="color: red;">testsrv:/srv/www/cacti/plugins #</span> wget https://github.com/Cacti/plugin_cycle/archive/develop.zip -O cycle.zip<br /><span style="color: red;">testsrv:/srv/www/cacti/plugins #</span> unzip cycle.zip<br /><span style="color: red;">testsrv:/srv/www/cacti/plugins #</span> mv plugin_cycle-develop cycle</b><br /></pre><pre><b><span style="color: red;">testsrv:/srv/www/cacti/plugins #</span> wget https://github.com/Cacti/plugin_thold/archive/develop.zip -O thold.zip<br /><span style="color: red;">testsrv:/srv/www/cacti/plugins #</span> unzip thold.zip<br /><span style="color: red;">testsrv:/srv/www/cacti/plugins #</span> mv plugin_thold-develop/ thold</b><br /></pre></li><li>Para activar los nuevos complementos nos dirigimos a la consola de administración web de Cacti y seleccionamos la opción <b>Plugins</b> de la barra lateral izquierda. En esta interfaz solo resta instalar y habilitar los plugins presionando los botones <b>Instalar Plugin</b> y <b>Habilitar Plugin</b> respectivamente de la columna <b>Acciones</b> como se muestra en las siguientes capturas:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-14.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="260" data-original-width="430" src="http://files.tormentadebits.com/images/00026-cacti-14.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-15.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="260" data-original-width="430" src="http://files.tormentadebits.com/images/00026-cacti-15.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-16.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="742" data-original-width="1223" height="388" src="http://files.tormentadebits.com/images/00026-cacti-16.png" width="640" /></a></div></li></ol><h3>Observaciones sobre Threshold</h3><ul><li>Si bien esta guía no tiene el propósito de documentar los procedimientos para agregar dispositivos, gráficos y configurar la herramienta Cacti para un entorno de producción, si quisiera hacer una pequeña observación sobre la funcionalidad <b>Threshold</b> proveída por el plugin <b>Thold</b>, y es que he tenido problemas a la hora de configurar la generación de alertas cuando el tráfico de red de un gráfico alcanzaba el valor cero o no disponible (N/D), debido a que la interfaz de red del equipo remoto que se monitoreaba no generaba información por el corte en la red de datos. Luego de investigar bastante en el foro de Cacti, pude idear un workaround que básicamente consiste en lo siguiente:<br /><br />Para que las alertas de tipo <b>Warning</b> o <b>Alert</b> se disparen lo que se tiene que hacer es asignarles en principio un valor mínimo en el campo <b>Low Threshold</b> que sea superior a cero; en el ejemplo se usó el valor <b>1.1</b>, o lo que es lo mismo, 8.8 bits de velocidad. Luego, en el apartado de manipulación de datos se tiene que seleccionar de la lista <b>Data Type</b> el valor <b>RPN Expression</b>, y justo debajo introducir la expresión "<b>|ds:traffic_in|,1,+</b>", donde <b>al tráfico del gráfico asociado</b> (|ds:traffic_in|)<b> se le suma el valor 1 que corresponde a 1 byte</b> (8 bits), así cuando el valor del gráfico sea cero o N/D, la expresión le sumará 1 byte que justo quedará por debajo del umbral mínimo definido en 1.1 bytes, lo que finalmente disparará la alerta.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00026-cacti-17.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="742" data-original-width="1214" height="391" src="http://files.tormentadebits.com/images/00026-cacti-17.png" width="640" /></a></div></li></ul><h3>Observaciones sobre envío de correos con PHP Mailer:</h3><ul>Uno de los problemas que he tenido es la imposibilidad de enviar mails de alertas mediante ciertos servidores de correos que exigían que la conexión si o si se tenía que realizar a través del puerto 465 (<b>Puerto SMTP = 465</b>) y con seguridad SSL (<b>Seguridad SMTP = SSL</b>). Luego de investigar bastante finalmente pude identificar la causa del problema, que se debía a que el servidor de correos tenía un certificado auto firmado (self-signed), y la funcionalidad <b>PHP Mailer</b> que utiliza <b>Cacti</b> para enviar los correos no permitía por defecto aceptar automáticamente los certificados auto firmados del servidor de correo, motivo por el cual se tuvo que realizar lo siguiente para resolver el problema:</ul><ul> <br /> <li>Como la interfaz web de Cacti no permite configurar la aceptación de certificados auto firmados, la única opción es la de <b>modificar el código fuente PHP de Cacti</b> que se encarga de enviar los correos. Para ello tenemos que editar el archivo <b>functions.php</b> del directorio <b>/srv/www/cacti/lib</b>: <pre><b><span style="color: red;">testsrv:~ #</span> vim /srv/www/cacti/lib/functions.php</b><br /></pre> </li> <li>Una vez dentro del archivo <b>functions.php</b> buscamos la siguiente sección: <pre><b> </b><i>// Create the PHPMailer instance</i><b><br /> $mail = new PHPMailer\PHPMailer\PHPMailer;</b><br /></pre>Y justo abajo le agregamos el código referente a la configuración <b>SMTPOptions</b>: <pre><b> </b><i>// Create the PHPMailer instance</i><b><br /> $mail = new PHPMailer\PHPMailer\PHPMailer;<br /> $mail->SMTPOptions = array(<br /> 'ssl' => array(<br /> 'verify_peer' => false,<br /> 'verify_peer_name' => false,<br /> 'allow_self_signed' => true<br /> )<br /> );</b><br /></pre>Una vez realizada la modificación guardamos los cambios y salimos del archivo.</li></ul><ul><li>Finalmente, para que los cambios tomen efecto reiniciamos el servicio del <b>Apache</b>: <pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart apache2</b><br /></pre></li> <li>Si volvemos a probar el envío de un correo de prueba desde la interfaz web de Cacti ya debería funcionar.</li></ul> <h3>Fuentes</h3><ul><li><a href="https://docs.cacti.net/manual:100" target="_blank"><b>Manual de instalación de <b>Cacti v1.0.0</b> y superiores</b></a><br /></li><li><a href="http://www.cacti.net/" target="_blank"><b>Sitio oficial de Cacti</b></a><br /></li><li><a href="http://oss.oetiker.ch/rrdtool/" target="_blank"><b>Sitio oficial de RRDtool</b></a><br /></li><li><a href="http://docs.cacti.net/plugins" target="_blank"><b>Lista de plugins para Cacti</b></a><br /></li><li><a href="https://my-techie-guy.blogspot.com/2017/09/error-your-cacti-database-login-account.html" target="_blank"><b>ERROR: Your Cacti database login account does not have access to the MySQL TimeZone database.</b></a><br /></li><li><a href="https://www.seanmancini.com/2019/02/fixing-cacti-timezone-installation-error/" target="_blank"><b>Configuración de Timezone en PHP</b></a><br /></li><li><a href="https://www.php.net/manual/es/timezones.php" target="_blank"><b>Husos horarios (timezones) de PHP</b></a><br /></li><li><a href="https://forums.cacti.net/viewtopic.php?f=17&t=40296" target="_blank"><b>Cacti Forum - Zero Traffic Threshold Trigger</b></a><br /></li><li><a href="https://forums.cacti.net/viewtopic.php?f=17&t=29050&start=15" target="_blank"><b>Cacti Forum - Threshold for Bandwidth %</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-19488925326467479762019-07-26T13:25:00.004-04:002022-10-04T22:56:29.327-03:00MariaDB y phpMyAdmin en openSUSE 15.1<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00059.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://files.tormentadebits.com/covers/portada-00059.png" width="320" height="156" data-original-width="1230" data-original-height="600" /></a></div>Como ya lo dice el título, este artículo va a tratar acerca de la instalación y configuración básica para poner en marcha el motor de base de datos <b>MariaDB</b> (Fork de MySQL) y la herramienta web <b>phpMyAdmin</b> en <b>openSUSE 15.1</b>.<br /><br />Esta pequeña guía es una adaptación y actualización del tutorial que escribí hace años sobre el proceso de instalación y configuración básico de MySQL.<br /><a name='more'></a><br /><br /><h3>Motor de base de datos MariaDB</h3>Los pasos de configuración que van a continuación son los más básicos para poner en marcha el motor de base de datos MariaDB.<br /><ol><li>Instalamos los paquetes necesarios a partir de los repositorios en linea o del propio DVD de instalación mediante el comando <b>zypper</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper install mariadb</b><br /></pre></li><li>Luego activamos el inicio automático para el servicio <b>mariadb</b> durante el arranque del sistema operativo:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable mariadb</b><br /></pre></li><li>El siguiente paso consiste en iniciar la base de datos <b>MariaDB</b> en modo seguro (safe mode) para poder asignarle una contraseña al usuario <b>root</b>, ya que su contraseña por defecto se desconoce. Para ello ejecutamos la siguiente directiva:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mysqld_safe --skip-grant-tables &</b><br /></pre></li><li>Mientras la base de datos se encuentra iniciada en modo seguro procedemos a cambiar la contraseña del usuario <b>root</b> y realizar otras configuraciones adicionales mediante la ejecución del asistente de configuración <b>mysql_secure_instalation</b>, lo ejecutamos de la siguiente forma:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mysql_secure_installation</b><br /><br />NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB<br /> SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!<br /><br />In order to log into MariaDB to secure it, we'll need the current<br />password for the root user. If you've just installed MariaDB, and<br />you haven't set the root password yet, the password will be blank,<br />so you should just press enter here.<br /><br />Enter current password for root (enter for none): <br />OK, successfully used password, moving on...<br /><br />Setting the root password ensures that nobody can log into the MariaDB<br />root user without the proper authorisation.<br /><br /><b><span style="color: red;">Set root password? [Y/n] Y<br />New password: <br />Re-enter new password: </span></b><br />Password updated successfully!<br />Reloading privilege tables..<br /> ... Success!<br /><br /><br />By default, a MariaDB installation has an anonymous user, allowing anyone<br />to log into MariaDB without having to have a user account created for<br />them. This is intended only for testing, and to make the installation<br />go a bit smoother. You should remove them before moving into a<br />production environment.<br /><br /><b><span style="color: red;">Remove anonymous users? [Y/n] Y</span></b><br /> ... Success!<br /><br />Normally, root should only be allowed to connect from 'localhost'. This<br />ensures that someone cannot guess at the root password from the network.<br /><br /><b><span style="color: red;">Disallow root login remotely? [Y/n] Y</span></b><br /> ... Success!<br /><br />By default, MariaDB comes with a database named 'test' that anyone can<br />access. This is also intended only for testing, and should be removed<br />before moving into a production environment.<br /><br /><b><span style="color: red;">Remove test database and access to it? [Y/n] Y</span></b><br /> - Dropping test database...<br /> ... Success!<br /> - Removing privileges on test database...<br /> ... Success!<br /><br />Reloading the privilege tables will ensure that all changes made so far<br />will take effect immediately.<br /><br /><b><span style="color: red;">Reload privilege tables now? [Y/n] Y</span></b><br /> ... Success!<br /><br />Cleaning up...<br /><br />All done! If you've completed all of the above steps, your MariaDB<br />installation should now be secure.<br /><br />Thanks for using MariaDB!<br /></pre></li><li>Realizados todos los ajustes procedemos a <b>parar la base de datos</b> para salir del modo seguro. Al ejecutar el siguiente comando deberemos introducir la nueva contraseña especificada en el paso anterior:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mysqladmin -u root -p shutdown</b><br />Enter password: <br />[1]+ Hecho mysqld_safe --skip-grant-tables<br /><b><span style="color: red;">testsrv:~ #</span></b><br /></pre></li><li>Finalmente iniciamos el servicio <b>mariadb</b> de la forma normal:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl start mariadb</b><br /></pre></li></ol>Con los pasos anteriores ya tenemos el motor de base de datos MariaDB corriendo y listo para ser utilizado.<br /><br /><br /><h3>Herramienta phpMyAdmin</h3><ol><li>Primero instalamos algunos paquetes necesarios:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper install apache2 apache2-mod_php7 php7 php7-mysql php7-mbstring php7-pear-MDB2_Driver_mysqli</b><br /></pre></li><li>Una de las formas para obtener esta herramienta es descargándola desde su <a href="http://www.phpmyadmin.net/home_page/downloads.php" target="_blank"><b>sitio web</b></a>, para luego descomprimirla en el directorio <b>/srv/www/htdocs</b> y asignarle los permisos correspondientes como se aprecia en la siguiente secuencia de comandos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /srv/www/htdocs/<br /><span style="color: red;">testsrv:/srv/www/htdocs #</span> wget https://files.phpmyadmin.net/phpMyAdmin/4.9.0.1/phpMyAdmin-4.9.0.1-all-languages.tar.gz<br /><span style="color: red;">testsrv:/srv/www/htdocs #</span> tar -xzf phpMyAdmin-4.9.0.1-all-languages.tar.gz<br /><span style="color: red;">testsrv:/srv/www/htdocs #</span> mv phpMyAdmin-4.9.0.1-all-languages phpMyAdmin<br /><span style="color: red;">testsrv:/srv/www/htdocs #</span> rm phpMyAdmin-4.9.0.1-all-languages.tar.gz<br /><span style="color: red;">testsrv:/srv/www/htdocs #</span> chmod -Rf 755 phpMyAdmin<br /><span style="color: red;">testsrv:/srv/www/htdocs #</span> chown -Rf wwwrun:www phpMyAdmin</b><br /></pre></li><li>El siguiente paso consiste en crear una copia llamada <b>config.inc.php</b> a partir del archivo <b>/srv/www/htdocs/phpMyAdmin/config.sample.inc.php</b><br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /srv/www/htdocs/phpMyAdmin<br /><span style="color: red;">testsrv:/srv/www/htdocs/phpMyAdmin #</span> cp config.sample.inc.php config.inc.php</b><br /></pre></li><li>Editamos el nuevo archivo <b>config.inc.php</b>,<br /><pre><b><span style="color: red;">testsrv:/srv/www/htdocs/phpMyAdmin #</span> vi config.inc.php</b><br /></pre>y verificamos la configuración de las directivas <b>auth_type</b> y <b>host</b>. El contenido debería ser similar a lo sigue:<br /><pre>$cfg['Servers'][$i]['auth_type'] = 'cookie';<br />$cfg['Servers'][$i]['host'] = 'localhost'; <i>#(OBS: probar 127.0.0.1 si no funciona)</i><br /></pre></li><li>Guardamos los cambios y verificamos que el servidor <b>Apache</b> tenga activado el soporte <b>php</b> en la directiva <b>APACHE_MODULES</b> del archivo <b>/etc/sysconfig/apache2</b>, y si no lo está lo incluimos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/apache2</b><br /></pre><pre><b>APACHE_MODULES</b>="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 <span style="color: red;">php7</span>"<br /></pre></li><li>Luego especificamos los niveles de ejecución del servicio Apache y lo iniciamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable apache2<br /><span style="color: red;">testsrv:~ #</span> systemctl start apache2</b><br /></pre></li><li>Con estos pasos concluimos con la puesta en marcha de Apache, lo que nos permitirá acceder localmente a phpMyAdmin mediante la siguiente <b>URL</b>:<br /><pre><b>http://localhost/phpMyAdmin</b><br /></pre></li></ol><br /><br /><h3>Habilitación de puertos en el cortafuegos</h3>Si necesitamos acceder a los servicios de MariaDB y Apache (para acceder a phpMyAdmin) remotamente y no solo trabajar en forma local, necesitamos habilitar los puerto correspondiente en el firewall de openSUSE que se puede hacer fácilmente a través de YAST, o mejor aún a través de la línea de comandos como se explicará a continuación.<br /><ol><li>Editamos el archivo <b>/etc/firewalld/zones/public.xml</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/sysconfig #</span> vi /etc/firewalld/zones/public.xml</b><br /></pre></li><li>Configuración a la que le agregamos la línea referente al protocolo <b>http</b>, debiendo quedar similar a lo que sigue:<br /><pre><?xml version="1.0" encoding="utf-8"?><br /><zone><br /> <short>Public</short><br /> <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description><br /> <service name="ssh"/><br /> <b><service name="http"/></b><br /> <b><service name="mysql"/></b><br /> <service name="dhcpv6-client"/><br /></zone><br /></pre><blockquote>OBS: La directiva anterior habilitará en el cortafuego los puertos de los servicios Apache, MariaDB y SSH.</blockquote></li><li>Guardamos los cambios y salimos del editor, en mi caso con los comandos <b>:wq</b> para <b>Vim</b>, y luego procedemos a reiniciar el servicio del <b>firewall</b> de openSUSE con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:/etc/sysconfig #</span> systemctl restart firewalld</b><br /></pre></li><li>Con los pasos anteriores hemos habilitado los puertos deseados en el cortafuego, con lo cual hemos culminado.<br /></li></ol><br /><br /><h3>Observaciones finales</h3><ul><li>openSUSE 15.1 x86_64</li><li>MariaDB v10.2.22</li><li>Apache 2 v2.4.33</li><li>php 7</li><li>phpMyAdmin v4.9.0.1</li></ul><br />Estos fueron todos los pasos para poner en marcha el servicio <b>MariaDB</b> y la herramienta web <b>phpMyAdmin</b> que permite administrar dicho motor de base de datos.GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-69646911227934678002019-02-03T23:09:00.004-03:002022-10-04T22:55:08.328-03:00Script Batch de Windows con directivas FTP embebidas<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00003.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://files.tormentadebits.com/covers/portada-00003.png" width="320" height="156" data-original-width="615" data-original-height="300" /></a></div>En <a href="/2012/03/script-ftp-cliente-windows-linux-unix.html" target="_blank"><b>éste artículo</b></a> ya había presentado un ejemplo sobre como crear un <b>script DOS batch</b> en <b>Windows</b> que ejecute directivas <b>ftp</b>.<br /><br />Sin embargo dicho ejemplo tenía un problema, y era que requería de dos archivos, un archivo <b>.txt</b> con las directivas <b>ftp</b> y otro archivo <b>.bat</b> aparte que llamaba al comando ftp con la cadena de conexión y le pasaba el archivo <b>.txt</b> mencionado previamente. En definitiva, en éste artículo veremos que <b>si es posible meter todo</b> en un solo script batch de Windows.<br /><br />Antes de comenzar tengo que decir que la solución es un tanto rebuscada la verdad, así que la explicación será más extensa de lo pensado.<br /><a name='more'></a><br /><h3>Creación del script batch:</h3>Para comenzar abrimos nuestro editor de texto plano favorito de Windows, <b>Notepad</b>, y a continuación le agregamos el siguiente contenido similar al que sigue:<br /><pre><b>;@echo off<br />;set LOCAL_PATH=C:\<br />;(for /f "usebackq delims=" %%A in ("%~f0") do call echo.%%A)>"%~n0.ftp"<br />;PAUSE > nul<br />;ftp -i -s:"%~n0.ftp"<br />;PAUSE > nul<br />;del "%~n0.ftp"<br />;GOTO:EOF<br /><br />!:--- Datos de conexion a continuacion ---<br /><br />open ip_servidor_ftp<br />usuario_ftp<br />contraseña_del_usuario<br /><br />!:--- Directivas FTP a continuacion ---<br /><br />binary<br /><br />cd /archivos<br /><br />lcd %LOCAL_PATH%\libros<br />mget libros/*<br />lcd %LOCAL_PATH%\revistas<br />mget revistas/*<br /><br />bye</b><br /></pre><br />Como se puede observar más arriba el contenido es bastante extraño, y lo podemos subdividir en las siguientes secciones:<br /><ul><li>En la <b>primera parte</b> tenemos una serie de <b>comandos batch</b> que están iniciados con el signo de puntuación <b>punto y coma (;)</b>.</li><li>La siguiente sección <b>contiene los datos de conexión al servidor FTP</b>, donde debemos especificar la dirección IP del servidor, el usuario con el cual nos vamos a conectar y su respectiva contraseña.<br /></li><li>Y por último van las <b>directivas ftp</b> de cambios de directorio y copiado o manipulación de archivos que necesitamos realizar.<br /></li></ul>Para finalizar tenemos que guardar los cambios del archivo y cambiar la extensión del mismo a <b>.bat</b>. Con ello solo resta hacer doble clic en el archivo para ejecutar las directivas ftp que deseamos desde un solo archivo.<br /><br /><h3>Explicación del funcionamiento:</h3>Básicamente lo que hace este script al ejecutar el archivo <b>.bat</b> es que el intérprete de Windows ejecuta los primeros <b>comandos batch</b> que inician con los signos de puntuación <b>punto y coma (;)</b>, que finalizan en la directiva <b>GOTO:EOF</b> que lleva al fin del archivo y termina con la ejecución de los comandos batch hasta ese punto.<br /><br />En la <b>segunda línea</b> se define la variable de entorno <b>LOCAL_PATH</b>, y la misma debe ser modificado a la conveniencia de cada uno, ya que de ella depende la construcción de las directivas <b>ftp</b> que están al final del archivo (líneas 21 y 23).<br /><br />En la <b>tercera línea del script</b> se ejecuta el comando batch <b>for</b>, que recorre el contenido del propio archivo <b>.bat</b> que se está ejecutando <b>a fin de crear un archivo temporal</b> que <b>solo contenga las directivas ftp</b>. Esto lo logra debido a que para el comando <b>for</b> el <b>punto y coma (;) es considerado como fin de línea</b>, motivo por el cual todas las directivas batch inicializadas con dicho carácter (;) son consideradas como líneas inválidas, y por ende no son copiadas al archivo temporal.<br /><br />En la <b>quinta línea</b> básicamente se ejecuta el programa <b>ftp</b> y se le pasa como argumento el archivo temporal que en el paso anterior fue creado solo con las directivas ftp.<br /><br />Finalmente en la <b>séptima línea</b> se elimina el archivo temporal y en la línea siguiente se termina la ejecución del script.<br /><br /><b>OBS:</b> Quisiera aclarar que las directivas batch <b>"PAUSE > nul"</b> de las líneas 4 y 6 están para parar la ejecución del script, y facilitar el análisis de la ejecución de cada comando. En un <b>entorno de producción</b> dichas directivas deben ser borradas para evitar que el script quede esperando a que un operador presione alguna tecla para continuar o finalizar la ejecución del mismo.<br /><br /><h3>Fuentes:</h3><ul><li><a href="https://www.dostips.com/?t=Batch.FtpBatchUsingVariables" target="_blank">https://www.dostips.com/?t=Batch.FtpBatchUsingVariables</a></li><li><a href="https://www.dostips.com/DtTipsFtpBatchScript.php" target="_blank">https://www.dostips.com/DtTipsFtpBatchScript.php</a></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com2tag:blogger.com,1999:blog-1035903216249592564.post-80592297815098758832017-10-10T23:07:00.004-03:002022-10-04T22:53:56.504-03:00Upgrade de Proyectos Redmine 1.3 a Redmine 3.4<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00058.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1230" height="156" src="http://files.tormentadebits.com/covers/portada-00058.png" width="320" /></a></div>Es muy importante mantener los servicios actualizados con las últimas versiones disponibles, especialmente para hacer frente a problemas de seguridad, aunque en la práctica esto no siempre resulta ser tan sencillo como debería.<br /><br />Uno de los mayores temores con las actualizaciones es que deje de funcionar aquel servicio que tanto se necesita en el momento menos oportuno, sin embargo, migrar los proyectos <b>Redmine 1.3</b> a <b>Redmine 3.4</b> ha resultado ser bastante más sencillo de lo esperado como se verá a continuación... <br /><a name='more'></a><br />Los pasos que siguen contemplan la instalación de la nueva versión de Redmine, la importación y migración de la base de datos, copiado de archivos y repositorios Subversion, así que comencemos:<br /><ol><li>Como el salto entre las versiones 1.3 y 3.4 es bastante grande, mi decisión fue realizar una instalación totalmente nueva de <b>Redmine 3.4</b>, para lo cual pueden seguir <a href="http://www.tormentadebits.com/2017/09/instalacion-de-redmine-3.4-en-linux-opensuse.html" target="_blank"><b>éste artículo</b></a> que escribí hace unos días.<br /><br /></li><li>Con una instalación totalmente nueva, tenemos que proceder a importar y migrar nuestra base de datos 1.3 para que sea compatible con la requerida por Redmine 3.4. Para ello comenzamos por descomprimir nuestra copia de seguridad anterior:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mkdir /restore<br /><span style="color: red;">testsrv:~ #</span> cp /backup/redmine_20170913_2230.tar.gz /restore<br /><span style="color: red;">testsrv:~ #</span> cd /restore<br /><span style="color: red;">testsrv:/restore #</span> tar -xzvf migracion.tgz --strip-components=1</b><br /></pre>A continuación creamos una nueva base de datos vacía en la cual vamos a restablecer nuestra copia de seguridad de la versión 1.3 de Redmine.<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /restore/redmine/backups<br /><span style="color: red;">testsrv:~ #</span> su postgres -c psql postgres<br />postgres=# CREATE DATABASE redmine_up WITH ENCODING='UTF8' OWNER=redmine;<br />postgres-# \q</b><br /></pre>Luego procedemos a restaurar nuestra copia de seguridad de la base de datos Redmine 1.3:<br /><pre><b><span style="color: red;">testsrv:~ #</span> psql -U postgres -L salida.txt -d redmine_up -f redmine_db.sql</b><br /></pre>Nos dirigimos al directorio de configuración de la base de datos para Redmine y editamos el archivo <b>database.yml</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/config/<br /><span style="color: red;">testsrv:/opt/redmine/config #</span> vi database.yml</b><br /></pre>Y le renombramos el atributo <b>database</b> de la sección <b>production</b> a la base de datos recientemente restaurada:<br /><pre>production:<br /> adapter: postgresql<br /> database: <b>redmine_up</b><br /> host: localhost<br /> username: redmine<br /> password: redmine<br /> encoding: utf8<br /></pre></li><li>A continuación actualizamos la llave que utiliza Rails para codificar la información de sesiones contenidas en las cookies por una nueva:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> bundle.ruby2.4 exec rake generate_secret_token</b><br /></pre></li><li>Una vez concluido con el paso anterior nos posicionamos en el directorio <b>/opt/redmine</b> y procedemos a actualizar y migrar el esquema de base de datos de <b>Redmine 1.3</b> en PostgrSQL para que sea compatible con la versión 3.4 instalada:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> cd ..<br /><span style="color: red;">testsrv:/opt/redmine #</span> bundle.ruby2.4 exec rake db:migrate RAILS_ENV=production</b><br /></pre>También aprovechamos la ocasión para migrar la configuración de los plugins en la base de datos:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> bundle.ruby2.4 exec rake redmine:plugins:migrate RAILS_ENV=production</b><br /></pre></li><li>A continuación realizamos algunas limpiezas:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> bundle.ruby2.4 exec rake tmp:cache:clear RAILS_ENV=production<br /><span style="color: red;">testsrv:/opt/redmine #</span> bundle.ruby2.4 exec rake tmp:sessions:clear RAILS_ENV=production</b><br /></pre></li><li>No nos tenemos que olvidar de copiar los archivos de Redmine 1.3 al directorio <b>files</b> de la nueva instalación de Redmine 3.4:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> mv files files_orig<br /><span style="color: red;">testsrv:/opt/redmine #</span> cp -Rf /restore/redmine/files /opt/redmine<br /><span style="color: red;">testsrv:/opt/redmine #</span> chown -Rf wwwrun:www /opt/redmine/files</b><br /></pre></li><li>Para migrar un repositorio <b>Subversion</b> ya existente a un nuevo repositorio de Redmine procedemos a renombrar el directorio original <b>/opt/redmine/svn</b> y si hicimos una copia full del directorio del proyecto Redmine entonces lo podremos copiar directamente:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mv /opt/redmine/svn /opt/redmine/svn_orig<br /><span style="color: red;">testsrv:~ #</span> cp -Rf /restore/redmine/svn /opt/redmine<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /opt/redmine/svn</b><br /></pre>Si en el caso contrario solo disponemos de las copias de seguridad de los repositorios (archivos dump), entonces utilizando el comando <b>svnadmin</b> debemos crear un nuevo repositorio Subversion vacío para nuestro proyecto de Redmine y luego proceder a importar las revisiones a partir del archivo <b>dump</b>. Por último asignamos el dueño correspondiente a los repositorios de destino.<br /><pre><b><span style="color: red;">testsrv:~ #</span> mkdir /opt/redmine/svn<br /><span style="color: red;">testsrv:~ #</span> svnadmin create /opt/redmine/svn/prueba<br /><span style="color: red;">testsrv:~ #</span> svnadmin load /opt/redmine/svn/prueba < /restore/redmine/backups/svndumps/prueba.dump<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /opt/redmine/svn</b><br /></pre>El siguiente paso consiste en dirigirnos a la pestaña <b>Administration –> Settings –> Repositories</b> en la herramienta Redmine donde volvemos a re-generar la <b>API key</b> y <b>guardar los cambios</b>.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1086" height="507" src="http://files.tormentadebits.com/images/00025-redmine-09.png" width="640" /></a></div><br />Con el nuevo código del <b>API Key</b> editamos el archivo <b>redmine</b> del directorio <b>/etc/cron.d</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/cron.d/redmine</b><br /></pre>y procedemos a reemplazar el código anterior con el nuevo en todas las directivas programadas:<br /><pre><i># Generacion de tareas a partir de correos entrantes.</i><br />* * * * * 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<br /><br /><i># Generacion automatica de repositorios subversion.</i><br />* * * * * 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=<b><span style="color: red;">9U9RLWv097mKlRqpHIPG</span></b> >> /dev/null<br /><br /><i># Sincronización de comentarios de commits asociados a tareas.</i><br />* * * * * root curl "http://IP_SERVIDOR/redmine/sys/fetch_changesets?key=<b><span style="color: red;">9U9RLWv097mKlRqpHIPG</span></b>" > /dev/null 2>&1<br /><br /><i># Backup Redmine</i><br />30 22 * * * root /opt/redmine/script/backup >> /dev/null<br /></pre>Y para culminar este apartado debemos reiniciar el servicio <b>cron</b>:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> systemctl restart cron</b><br /></pre></li><li>Finalmente reiniciamos el servicio Apache:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> systemctl restart apache2</b><br /></pre></li></ol>Y eso es todo, con estos cambios el proceso de migración de proyectos Redmine de la versión 1.3 a la 3.4 debería haber resultado de forma exitosa, aunque como siempre en estas cosas nada está garantizado.<br /><br /><h3>Fuentes:</h3><ul><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineUpgrade" target="_blank"><b>http://www.redmine.org/projects/redmine/wiki/RedmineUpgrade</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Guide" target="_blank"><b>http://www.redmine.org/projects/redmine/wiki/Guide</b></a><br /></li><li><a href="http://www.admonsistemas.es/migrar-entre-versiones-de-redmine/" target="_blank"><b>http://www.admonsistemas.es/migrar-entre-versiones-de-redmine/</b></a><br /></li><li><a href="http://blog.elcacharreo.com/2013/09/18/actualizando-redmine-sin-perder-nuestros-datos/" target="_blank"><b>http://blog.elcacharreo.com/2013/09/18/actualizando-redmine-sin-perder-nuestros-datos/</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-686845258487828152017-09-14T22:19:00.004-04:002022-10-04T22:52:42.965-03:00Instalación de Redmine 3.4 en Linux openSUSE Leap 42.3<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00057.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://files.tormentadebits.com/covers/portada-00057.png" width="320" height="156" data-original-width="1230" data-original-height="600" /></a></div>La idea de este artículo es documentar todo el proceso de instalación de <b>Redmine 3.4</b> en <b>openSUSE Leap 42.3</b>, basándome en <a href="http://www.tormentadebits.com/2012/07/redmine-instalacion-en-linux-opensuse.html" target="_blank"><b>éste artículo</b></a> del 2012.<br /><br />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.<br /><a name='more'></a><br /><h3>Instalación y configuración básica</h3><ol><li>Para comenzar debemos instalar y configurar de forma básica el motor de base de datos <b>PostgreSQL</b>, que ya ha sido tratado en este blog y que lo pueden encontrar <b><a href="http://www.tormentadebits.com/2012/06/postgresql-linux-opensuse-install.html" target="_blank">aquí</a></b>.<br /><br /></li><li>Mediante el comando <b>zypper</b> instalamos algunas de las dependencias que necesita la herramienta.<br /><pre><b><span style="color: red;">testsrv:~ #</span> 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</b><br /></pre></li><li>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<br /><pre><b><span style="color: red;">testsrv:~ #</span> su postgres -c psql postgres<br />postgres=# CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'redmine' NOINHERIT VALID UNTIL 'infinity';<br />postgres=# CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;<br />postgres-# \q</b><br /></pre></li><li>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 <b>/opt</b> para luego descomprimirla en el mismo directorio:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/<br /><span style="color: red;">testsrv:/opt #</span> wget http://www.redmine.org/releases/redmine-3.4.2.tar.gz<br /><span style="color: red;">testsrv:/opt #</span> tar -xzf redmine-3.4.2.tar.gz<br /><span style="color: red;">testsrv:/opt #</span> rm redmine-3.4.2.tar.gz<br /><span style="color: red;">testsrv:/opt #</span> mv redmine-3.4.2 redmine<br /><span style="color: red;">testsrv:/opt #</span> cd redmine/<br /><span style="color: red;">testsrv:/opt/redmine #</span></b><br /></pre></li><li>Una vez dentro del directorio raíz de la herramienta nos dirigimos a la carpeta <b>config</b> para crear y editar el archivo de configuración <b>database.yml</b>.<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> cd config/<br /><span style="color: red;">testsrv:/opt/redmine/config #</span> cp database.yml.example database.yml<br /><span style="color: red;">testsrv:/opt/redmine/config #</span> vi database.yml</b><br /></pre>Al cual le agregamos la configuración adecuada del motor de base de datos que utilizará Redmine<br /><pre><b>production:<br /> adapter: postgresql<br /> database: redmine<br /> host: localhost<br /> username: redmine<br /> password: redmine<br /> encoding: utf8</b><br /></pre></li><li>Luego, con el gestor de paquetes <b>gem</b> de Ruby 2.4 instalamos el paquete <b>bundler</b>, y ejecutamos en el directorio <b>/opt/redmine/config</b> 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.<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> gem.ruby2.4 install bundler rdoc<br /><span style="color: red;">testsrv:/opt/redmine/config #</span> bundle.ruby2.4 install --without development test</b><br /></pre>El comando bundle se encargará de instalar todas las dependencias requeridas:<br /><pre>Fetching gem metadata from https://rubygems.org/..........<br />Fetching version metadata from https://rubygems.org/..<br />Fetching dependency metadata from https://rubygems.org/.<br />Resolving dependencies...<br />Fetching rake 12.0.0<br />Installing rake 12.0.0<br />..<br />..<br /></pre><b>OBS:</b> 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 <b>rmagick</b>, <b>pg</b> y <b>mysql2</b>. 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.<br /><br /></li><li>A continuación generamos una nueva llave que utiliza Rails para codificar la información de sesiones contenidas en las cookies:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> bundle.ruby2.4 exec rake generate_secret_token</b><br /></pre></li><li>Una vez concluido con el paso anterior nos posicionamos en el directorio <b>/opt/redmine</b> 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:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> cd ..<br /><span style="color: red;">testsrv:/opt/redmine #</span> RAILS_ENV=production bundle.ruby2.4 exec rake db:migrate<br /><span style="color: red;">testsrv:/opt/redmine #</span> RAILS_ENV=production bundle.ruby2.4 exec rake redmine:load_default_data</b><br />(in /opt/redmine)<br /><br />Select language: bg, bs, ... en, en-GB, es, ... vi, zh, zh-TW [en] <span style="color: red;"><b>es</b></span><br />====================================<br />Default configuration data loaded.<br /></pre></li><li>Finalmente creamos un grupo y usuario de sistema, en ambos casos denominado <b>redmine</b>, y le hacemos dueño del directorio <b>/opt/redmine</b>:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> groupadd -r redmine<br /><span style="color: red;">testsrv:/opt/redmine #</span> useradd -r -g redmine redmine<br /><span style="color: red;">testsrv:/opt/redmine #</span> chown -Rf redmine:redmine /opt/redmine</b><br /></pre></li></ol><br /><br /><h3>Configuración de Apache</h3><ol><li>En cuanto a la configuración de Apache, lo primero que debemos hacer es dirigirnos al directorio <b>/etc/sysconfig</b> y editar el archivo <b>apache2</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/apache2</b><br /></pre>Una vez en el archivo nos dirigimos a la sección <b>APACHE_MODULES</b> para verificar que el módulo <b>ssl</b> esté debidamente definido (para las conexiones https):<br /><pre><b>APACHE_MODULES</b>="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 <span style="color: red;"><b>ssl</b></span> userdir php5 perl"<br /></pre>También, en el mismo archivo tenemos que asignar a la directiva <b>APACHE_SERVER_FLAGS</b> el valor <b>SSL</b>, quedando como se muestra a continuación:<br /><pre><b>APACHE_SERVER_FLAGS</b>="<span style="color: red;"><b>SSL</b></span>"<br /></pre></li><li>El siguiente paso consiste en verificar que <b>Apache</b> esté correctamente configurado para que escuche en los puertos indicados, tanto en el puerto por defecto que es el <b>80</b> como así también para las conexiones seguras que normalmente es el <b>443</b>, para ello nos vamos al directorio <b>/etc/apache2/</b> y ahí abrimos el archivo llamado <b>listen.conf</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/apache2/listen.conf</b><br /></pre>debiendo tener la siguiente sección similar a lo que sigue:<br /><pre><b>Listen 80<br /><br /><IfDefine SSL><br /> <IfDefine !NOSSL><br /> <IfModule mod_ssl.c><br /><br /> Listen 443<br /><br /> </IfModule><br /> </IfDefine><br /></IfDefine></b><br /></pre></li><li><b>Generación de certificado no personalizado:</b> 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:<br /><pre><b><span style="color: red;">testsrv:~ #</span> gensslcert</b><br /></pre>Este comando sobre-escribirá los siguientes archivos:<br /><pre><b>/etc/apache2/ssl.crt/ca.crt<br />/etc/apache2/ssl.key/server.key<br />/etc/apache2/ssl.crt/server.crt<br />/etc/apache2/ssl.csr/server.csr</b><br /></pre>También creará un nuevo archivo <b>CA.crt</b> en el directorio <b>/srv/www/htdocs/</b> para ser descargado por los clientes que se conectan bajo el protocolo https.<br /><br /><b>Generación de certificado personalizado:</b> Si queremos generar un certificado con información personalizada de nuestra organización podemos indicarle al comando <b>gensslcert</b> varios argumentos para enriquecer el contenido del certificado como se muestra a continuación:<br /><pre><b><span style="color: red;">testsrv:~ #</span> 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</b><br /></pre>Al ejecutar el comando se crearán una serie de archivos inicialmente llamados con el nombre <b>tormentadebits-</b> en los siguientes directorios:<br /><pre><b>/etc/apache2/ssl.crt/tormentadebits-ca.crt<br />/etc/apache2/ssl.crt/tormentadebits-server.crt<br />/etc/apache2/ssl.csr/tormentadebits-server.csr<br />/etc/apache2/ssl.key/tormentadebits-ca.key<br />/etc/apache2/ssl.key/tormentadebits-server.key<br />/srv/www/htdocs/TORMENTADEBITS-CA.crt</b><br /></pre></li><li>Luego hay que crear una copiar del archivo <b>/etc/apache2/vhosts.d/vhost-ssl.template</b> y renombrarlo a <b>vhost-ssl.conf</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/apache2/vhosts.d<br /><span style="color: red;">testsrv:/etc/apache2/vhosts.d #</span> cp vhost-ssl.template vhost-ssl.conf</b><br /></pre>Si hemos creado un certificado personalizado y queremos que sea éste el certificado utilizado para la autenticación tendremos que editar el archivo <b>vhost-ssl.conf</b> en el directorio <b>/etc/apache2/vhosts.d/</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/apache2/vhosts.d/vhost-ssl.conf</b><br /></pre>y modificar las directivas que se citan a continuación con los nombres de los archivos (certificados) generados anteriormente:<br /><pre><b>SSLCertificateFile /etc/apache2/ssl.crt/tormentadebits-server.crt<br />SSLCertificateKeyFile /etc/apache2/ssl.key/tormentadebits-server.key</b><br /></pre>Con esto hemos creado un host virtual exclusivo para las conexiones seguras.<br /><br /></li><li>Ahora continuemos con la configuración para Redmine, debemos instalar el módulo <b>passenger</b> para Apache con el gestor de paquetes <b>gem.ruby2.4</b> 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 <b>passenger-install-apache2-module.ruby2.4</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> gem.ruby2.4 install passenger<br /><span style="color: red;">testsrv:~ #</span> exec passenger-install-apache2-module.ruby2.4</b><br />This installer will guide you through the entire installation process. It<br />shouldn't take more than 3 minutes in total.<br /><br />Here's what you can expect from the installation process:<br /><br /> 1. The Apache 2 module will be installed for you.<br /> 2. You'll learn how to configure Apache.<br /> 3. You'll learn how to deploy a Ruby on Rails application.<br /><br />Don't worry if anything goes wrong. This installer will advise you on how to<br />solve any problems.<br /><br />Press Enter to continue, or Ctrl-C to abort.<br /><br /><br />--------------------------------------------<br /><br />Which languages are you interested in?<br /><br />Use <space> to select.<br />If the menu doesn't display correctly, press '!'<br /><br />>⬢ Ruby<br /> ⬡ Python<br /> ⬡ Node.js<br /> ⬡ Meteor<br />...<br />...<br />cd 'buildout/ruby/ruby-2.4.1-x86_64-linux/' && make<br />compiling /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8/src/ruby_native_extension/passenger_native_support.c<br />linking shared-object passenger_native_support.so<br /><br />--------------------------------------------<br />Almost there!<br /><br />Please edit your Apache configuration file, and add these lines:<br /><br /> LoadModule passenger_module /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8/buildout/apache2/mod_passenger.so<br /> <ifmodule mod_passenger.c=""><br /> PassengerRoot /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8<br /> PassengerDefaultRuby /usr/bin/ruby.ruby2.4<br /> </ifmodule><br /><br />After you restart Apache, you are ready to deploy any number of web<br />applications on Apache, with a minimum amount of configuration!<br /><br />Press ENTER when you are done editing.<br /><br />--------------------------------------------<br /><br />Validating installation...<br />...<br />...<br />Detected 0 error(s), 2 warning(s).<br />Press ENTER to continue.<br /></pre></li><li>Ahora debemos dirigirnos al directorio <b>/etc/apache2/conf.d</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/apache2/conf.d</b><br /></pre>Agregar y editar un nuevo archivo llamado <b>passenger.conf</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/apache2/conf.d #</span> touch passenger.conf<br /><span style="color: red;">testsrv:/etc/apache2/conf.d #</span> vi passenger.conf</b><br /></pre>Y agregarle un contenido similar a lo que sigue para que Apache levante el módulo correspondiente:<br /><pre><i># Carga del modulo passenger en Apache.</i><br /><b>LoadModule passenger_module /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8/buildout/apache2/mod_passenger.so<br />PassengerRoot /usr/lib64/ruby/gems/2.4.0/gems/passenger-5.1.8<br />PassengerDefaultRuby /usr/bin/ruby.ruby2.4</b><br /></pre></li><li><b>(OPCIÓN 1) ACCESO MEDIANTE VIRTUAL HOSTS</b>: Si deseamos que <b>Apache</b> sirva el sitio web de <b>Redmine</b> a través de un nombre de dominio totalmente cualificado (<i>FQDN: Fully Qualified Domain Name</i>) resuelto a través de servidores de nombres (<i>DNS</i>) internos o externos podemos configurar un host virtual para dicho fin. Para ello nos dirigimos al directorio <b>/etc/apache2/vhosts.d</b> y creamos un nuevo archivo llamado <b>vhost.conf</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/apache2/vhosts.d<br /><span style="color: red;">testsrv:/etc/apache2/vhosts.d #</span> touch vhost.conf</b></pre>Editamos el archivo con nuestro editor de texto preferido..<br /><pre><b><span style="color: red;">testsrv:/etc/apache2/vhosts.d #</span> vi vhost.conf</b><br /></pre>Y luego agregamos las siguientes directivas:<br /><pre><i># -- ES NECESARIO DEFINIR LA DIRECTIVA NameVirtualHost CUANDO<br /># SE CONFIGURAN HOSTS VIRTUALES BASADOS EN NOMBRES.</i><br /><b>NameVirtualHost *:80</b><br /><b>NameVirtualHost *:443</b><br /><br /><i># -- CONFIGURACION DEL HOST VIRTUAL POR DEFECTO, QUE APUNTA<br /># A LA RUTA TRADICIONAL.</i><br /><b><VirtualHost *:80 *:443></b><br /><b> ServerName <span style="color: red;">testsrv</span></b><br /><b> ServerAlias <span style="color: red;">testsrv *.testsrv testsrv.gknet.local *testsrv.gknet.local</span></b><br /><b> DocumentRoot /srv/www/htdocs</b><br /><b></VirtualHost></b><br /><br /><i># -- CONFIGURACION DEL VIRTUAL HOST PARA REDMINE</i><br /><b><VirtualHost *:80 *:443></b><br /><b> Options +Indexes</b><br /><b> ServerAdmin <span style="color: red;">nombre_usuario@gmail.com</span></b><br /><b> ServerName <span style="color: red;">redminesrv</span></b><br /><b> ServerAlias <span style="color: red;">redminesrv.gknet.local *.redminesrv.gknet.local redminesrv *.redminesrv</span></b><br /><b> DocumentRoot <span style="color: red;">/opt/redmine/public</span></b><br /><b> RailsEnv production</b><br /><br /><b> PassengerUser wwwrun</b><br /><b> PassengerGroup www</b><br /><br /><b> <Directory "<span style="color: red;">/opt/redmine/public</span>"></b><br /><b> Options +Indexes -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch</b><br /><b> AllowOverride All</b><br /><i> # Configuracion Apache 2.2<br /> #Order allow,deny<br /> #Allow from all<br /><br /> # Configuracion Apache 2.4 --> https://httpd.apache.org/docs/2.4/upgrading.html</i><br /><b> Require all granted</b><br /><b> </Directory></b><br /><b></VirtualHost></b><br /></pre>Con esto ya tenemos el servidor web configurado con soporte virtual host.<br /><br /></li><li><b>(OPCIÓN 2) ACCESO MEDIANTE SUBDIRECTORIOS</b>: Una opción alternativa a la configuración de host virtual de <b>Apache</b> para desplegar <b>Redmine</b> 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.<br /><br />Como primer paso nos dirigimos al directorio <b>/etc/apache2/conf.d</b>, para luego crear y editar un nuevo archivo llamado <b>redmine.conf</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /etc/apache2/conf.d</b><br /><b><span style="color: red;">testsrv:/etc/apache2/conf.d #</span> touch redmine.conf<br /><span style="color: red;">testsrv:/etc/apache2/conf.d #</span> vi redmine.conf</b><br /></pre>Al que le agregamos la siguiente configuración:<br /><pre><i># -- ALIAS DEL SUBDIRECTORIO APUNTANDO A LA RUTA REAL DE<br /># LA HERRAMIENTA REDMINE.</i><br /><b>Alias <span style="color: red;">/redmine /opt/redmine/public</span></b><br /><br /><i># -- DEFINICION DEL ENTORNO RAILS.</i><br /><b>RailsEnv production</b><br /><b>RailsBaseURI <span style="color: red;">/redmine</span></b><br /><br /><i># -- CONFIGURACION DE PASSENGER.</i><br /><b>PassengerUser wwwrun<br />PassengerGroup www</b><br /><br /><i># -- CONFIGURACIONES DEL DIRECTORIO DE TRABAJO.</i><br /><b><Directory "<span style="color: red;">/opt/redmine/public</span>"></b><br /><b> Options -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch</b><br /><b> AllowOverride All</b><br /><i> # Configuracion Apache 2.2<br /> #Order allow,deny<br /> #Allow from all<br /> <br /> # Configuracion Apache 2.4 --> https://httpd.apache.org/docs/2.4/upgrading.html</i><br /><b> Require all granted</b><br /><b></Directory></b><br /></pre><b>OBS:</b> Una vez afuera del archivo anterior creamos un enlace simbólico del directorio <b>/opt/redmine/public</b> al directorio <b>/srv/www/htdocs</b>:<br /><pre><b><span style="color: red;">testsrv:/etc/apache2/conf.d #</span> ln -s /opt/redmine/public/ /srv/www/htdocs/redmine</b><br /></pre></li><li>Asignamos el usuario <b>wwwrun</b> y al grupo <b>www</b> como dueños de ciertos directorios, y aplicamos algunos permisos de escritura y lectura:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> chown -Rf wwwrun:www /opt/redmine/files /opt/redmine/log /opt/redmine/tmp /opt/redmine/public/plugin_assets<br /><span style="color: red;">testsrv:/opt/redmine #</span> chmod -Rf 755 /opt/redmine/files /opt/redmine/log /opt/redmine/tmp /opt/redmine/public/plugin_assets</b><br /></pre></li><li>Finalmente activamos los niveles de ejecución y luego iniciamos (o reiniciamos si ya se estaba ejecutando) el servicio <b>apache2</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable apache2.service<br /><span style="color: red;">testsrv:~ #</span> </b><b>systemctl restart apache2.service</b><br /></pre></li></ol><br /><br /><h3>Configuración del cortafuegos</h3><ol><li>Para que podamos acceder a la herramienta desde otro equipo remoto necesitamos abrir los puertos <b>HTTP (80)</b> y <b>HTTPS (443)</b> en el firewall del servidor<b>, </b>para ello editamos el archivo <b>SuSEfirewall2</b> del directorio <b>/etc/sysconfig</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/SuSEfirewall2</b></pre>y le asignamos los servicios <b>apache2</b> y <b>apache2-ssl</b> a la directiva <b>FW_CONFIGURATIONS_EXT</b> como se muestra a continuación:<br /><pre><b>FW_CONFIGURATIONS_EXT="sshd <span style="color: red;">apache2 apache2-ssl</span>"</b></pre></li><li>Luego reiniciamos el cortafuegos para que la nueva configuración tome efecto, lo realizamos con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> rcSuSEfirewall2 restart</b></pre></li></ol><br /><br /><h3>Acceso a Redmine</h3><ol><li>Si para acceder a la herramienta <b>Redmine</b> hemos configurado el servicio <b>Apache</b> 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 <b>DNS</b> o mediante alguna entrada al archivo <b>/etc/hosts</b> en la máquina cliente que se trata de conectar a la herramienta. Como ejemplo podríamos tener la siguiente <b>URL</b>:<br /><pre><b>http://redmine.mi_dominio.local</b><br /></pre></li><li>Si en el caso contrario hemos configurado el acceso a la herramienta <b>Remine</b> mediante un subdirectorio en <b>Apache</b>, la <b>URL </b>deberá ser similar a la siguiente:<br /><pre><b>http://ip_o_nombre_dominio_servidor/redmine</b><br /></pre>Por defecto la herramienta se ve así:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1098" height="500" src="http://files.tormentadebits.com/images/00025-redmine-01.png" width="640" /></a></div><br /><blockquote class="green"><b>OBS:</b> El login del usuario administrador es <b>admin</b> y su contraseña por defecto también es <b>admin</b>, pero inmediatamente después la herramienta nos obligará a reemplazarla por una diferente.</blockquote><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1098" height="497" src="http://files.tormentadebits.com/images/00025-redmine-02.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-03.png" imageanchor="1"><img border="0" data-original-height="860" data-original-width="1098" height="499" src="http://files.tormentadebits.com/images/00025-redmine-03.png" width="640" /></a></div><br />En el apartado <b>Mi Cuenta</b> del usuario <b>admin</b>, accesible desde el enlace de la esquina superior derecha, se recomienda configurar las siguientes opciones:<br />- Correo electrónico<br />- Idioma<br />- Notificaciones por correo<br />- Zona horaria<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="859" data-original-width="1106" height="497" src="http://files.tormentadebits.com/images/00025-redmine-04.png" width="640" /></a></div></li></ol><br /><br /><h3>Instalación de Plugins</h3><ol><li>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 <a href="http://www.redmine.org/plugins?utf8=%E2%9C%93&page=1&sort=&v=3.4" target="_blank"><b>éste enlace</b></a>, de entre los cuales me gusta instalar los siguientes:<br /><br />- <a href="https://github.com/ncoders/redmine_local_avatars" target="_blank"><b>Local Avatars</b></a><br />- <a href="http://www.redmine.org/plugins/redmine_theme_changer" target="_blank"><b>Theme Changer</b></a><br />- <a href="http://www.redmine.org/plugins/clipboard_image_paste" target="_blank"><b>Attach image from clipboard</b></a><br />- <a href="http://www.redmine.org/plugins/redmine_checklists" target="_blank"><b>Checklists</b></a><br /><br /><blockquote class="red">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.</blockquote><br /></li><li>Para proceder con la instalación de un plugin, lo que tenemos que hacer es dirigimos al directorio de plugins de Redmine:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/plugins/</b><br /></pre>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 <b>wget</b> para descargar el paquete como se muestra a continuación:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/plugins #</span> wget https://github.com/haru/redmine_theme_changer/releases/download/0.3.0/redmine_theme_changer-0.3.0.zip<br /><span style="color: red;">testsrv:/opt/redmine/plugins #</span> unzip redmine_theme_changer-0.3.0.zip<br /><span style="color: red;">testsrv:/opt/redmine/plugins #</span> rm redmine_theme_changer-0.3.0.zip<br /><span style="color: red;">testsrv:/opt/redmine/plugins #</span> chown -Rf redmine:redmine redmine_theme_changer/</b><br /></pre>Si el proyecto se encuentra disponible en algún repositorio <b>Git</b> en la web podemos descargar el complemento clonando en repositorio remoto de la siguiente manera: <br /><pre><b><span style="color: red;">testsrv:/opt/redmine/plugins #</span> git clone https://github.com/peclik/clipboard_image_paste.git<br /><span style="color: red;">testsrv:/opt/redmine/plugins #</span> chown -Rf redmine:redmine clipboard_image_paste/</b><br /></pre></li><li>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.<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/plugins #</span> cd /opt/redmine<br /><span style="color: red;">testsrv:/opt/redmine #</span> bundle.ruby2.4 exec rake redmine:plugins:migrate RAILS_ENV=production</b><br /></pre></li><li>Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart apache2</b><br /></pre></li></ol><br /><br /><h3>Actualización de temas (themes)</h3>Podemos agregar nuevos themes para personalizar el look & feel de la herramienta, los pasos para agregarlos van a continuación. <br /><ol><li>Lo primero es descargar el nuevo tema que deseamos instalar desde el sitio web que sigue a continuación:<br /><pre><b>URL: <a href="http://www.redmine.org/projects/redmine/wiki/Theme_List">http://www.redmine.org/projects/redmine/wiki/Theme_List</a></b><br /></pre>De mi parte les recomiendo probar los siguientes themes disponibles:<br />- <a href="https://www.redmineup.com/pages/themes/a1" target="_blank"><b>A1</b></a><br />- <a href="https://www.redmineup.com/pages/themes/circle" target="_blank"><b>Circle</b></a><br />- <a href="https://github.com/themondays/Dwarf" target="_blank"><b>Dwarf</b></a><br /><br /></li><li>Si el archivo está empaquetado bajo los formatos tar.gz, tgz, zip, etc, entonces tenemos que copiar el archivo en la carpeta <b>/opt/redmine/public/themes</b>, descomprimirlo y asignarle el nuevo dueño:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/public/themes<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> unzip a1_theme-2_0_0.zip<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> rm a1_theme-2_0_0.zip<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> chown -Rf redmine:redmine a1</b><br /></pre>Si el theme se encuentra en un repositorio <b>git</b> 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):<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/public/themes<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> git clone https://github.com/themondays/Dwarf.git<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> cd Dwarf/production/<br /><span style="color: red;">testsrv:/opt/redmine/public/themes/Dwarf/production #</span> mv dwarf/ ../../<br /><span style="color: red;">testsrv:/opt/redmine/public/themes/Dwarf/production #</span> cd ../../<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> chown -Rf redmine:redmine dwarf<br /><span style="color: red;">testsrv:/opt/redmine/public/themes #</span> rm -Rf Dwarf</b><br /></pre></li><li>Con eso ya está, ya podremos seleccionar los nuevos temas agregados en la pestaña <b>Mostrar</b> (Show) de la sección de <b>Administración</b> de la herramienta, y si tenemos instalado el plugin <b>Theme Changer</b> cada usuario podrá personalizar su theme directamente desde la página de su perfil.<br /></li></ol><br /><br /><h3>Configuración para envío de correos</h3>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: <br /><ol><li>Primeramente nos dirigimos al directorio <b>/opt/redmine/config</b> y creamos el archivo <b>configuration.yml</b> a partir del archivo plantilla del mismo directorio.<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/config/<br /><span style="color: red;">testsrv:/opt/redmine/config #</span> cp configuration.yml.example configuration.yml</b><br /></pre></li><li>Luego editamos el archivo <b>configuration.yml</b>,<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> vi configuration.yml</b><br /></pre>y lo configuramos similar a lo que sigue en el caso de que tengamos un servidor de correo local:<br /><pre><b>default:<br /> email_delivery:<br /> delivery_method: :smtp<br /> smtp_settings:<br /> address: ip_servidor_local<br /> port: 25<br /> domain: midominio.com<br /> authentication: :none</b><br /></pre>Para una cuenta de <b>Gmail</b> la configuración podría ser similar a lo que sigue:<br /><pre><b>default:<br /> email_delivery:<br /> delivery_method: :smtp<br /> smtp_settings:<br /> enable_starttls_auto: true<br /> address: "smtp.gmail.com"<br /> port: 587<br /> domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps<br /> authentication: :plain<br /> user_name: "your_email@gmail.com"<br /> password: "your_password"</b><br /></pre><b>OBS:</b> Recuerda que si usas <b>Gmail</b> tendrás que habilitar en el correo los servicios de <b>IMAP</b> y activar el acceso a aplicaciones menos seguras. Referencias:<br />- <a href="https://support.google.com/mail/answer/7126229?hl=es" target="_blank">Leer mensajes de Gmail desde otros clientes de correo mediante IMAP</a><br />- <a href="https://support.google.com/accounts/answer/6010255?hl=es" target="_blank">Permitir que las aplicaciones menos seguras accedan a tu cuenta</a><br /><br /></li><li>Reiniciamos el servicio Apache para que la configuración anterior tome efecto:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/config #</span> systemctl restart apache2.service</b><br /></pre></li><li>Y finalmente realizamos las configuraciones faltantes en la interfaz Web. Primeramente realizamos algunos cambios en la sección de configuración <b>Administración-->Configuración-->General</b>, en la cual debemos configurar el <b>Nombre y la ruta del servidor</b> y el <b>Protocolo</b>, 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.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1102" height="499" src="http://files.tormentadebits.com/images/00025-redmine-05.png" width="640" /></a></div><br />Luego seguimos con cambios en la opción de configuración <b>Administración-->Configuración-->Notificaciones por correo</b> de la interfaz web de Redmine.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="859" data-original-width="1106" height="497" src="http://files.tormentadebits.com/images/00025-redmine-08.png" width="640" /></a></div><br />En este apartado se recomienda configurar las opciones:<br />- Correo desde el que enviar mensajes<br />- Opción de notificación por defecto<br />- Pie de mensajes<br /><br />Una vez concluida con las configuraciones guardamos los cambios con el botón <b>Guardar</b> y luego probamos el funcionamiento de envío de correos haciendo clic en el enlace <b>Enviar un correo de prueba</b>, que intentará enviar un correo de prueba a la cuenta definida en el apartado <b>Mi Cuenta</b> del usuario <b>admin</b>, que previamente había configurado como <b>contacto(ARROBA).tormentadebits.com</b>.<br /></li></ol><br /><br /><h3>Registro de tareas a partir de correos electrónicos</h3>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. <br /><ol><li>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. <br /><br /></li><li>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 <b>/opt/redmine</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine</b><br /></pre>y ejecutando el siguiente comando que lo tenemos que adecuar a nuestras necesidades:<br /><pre><b><span style="color: red;">testsrv:/opt/redmine #</span> 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</b><br /></pre>En este caso se utiliza de ejemplo una cuenta de correo <b>Gmail</b> con acceso IMAP. Las directivas de configuración relacionadas al protocolo IMAP son las siguientes:<br /><ul><li><b>host=imap.gmail.com</b>: IMAP server host (default: 127.0.0.1)</li><li><b>port=993</b>: IMAP server port (default: 143)</li><li><b>ssl=SSL</b>: Usa SSL? (default: false)</li><li><b>username=USERNAME</b>: IMAP account</li><li><b>password=PASSWORD</b>: IMAP password</li><li><b>folder=INBOX</b>: Directorio IMAP a leer (default: INBOX)</li><li><b>move_on_success=INBOX</b>: 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.</li><li><b>move_on_failure=INBOX</b>: 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.</li></ul>También podemos controlar la forma en que se agrega una nueva tarea en Redmine incluyendo los siguientes argumentos en el cuerpo del correo:<br /><ul><li><b>project=PROJECT</b>: Identifier of the target project</li><li><b>tracker=TRACKER</b>: Name of the target tracker</li><li><b>category=CATEGORY</b>: Name of the target category</li><li><b>priority=PRIORITY</b>: Name of the target priority</li><li><b>allow_override=ATTRS</b>: Allow email content to override attributes specified by previous options ATTRS is a comma separated list of attributes</li><li><b>unknown_user=ACTION</b></li><li><b>no_permission_check=[0|1]</b></li></ul>Según como se haya definido la directiva <b>unknown_user</b> 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 <b>unknown_user=accept</b>, que permite generar tareas a partir de correos cuyas cuentas de usuario no corresponden a un usuario de Redmine debidamente registrado.<br /><br />A continuación se muestran todas las opciones disponibles para la directiva <b>unknown_user</b>:<br /><pre><b>unknown_user=ACTION how to handle emails from an unknown user where ACTION can be one of the following<br />values:<br />- ignore: the email is ignored (default)<br />- accept: the sender is considered as an anonymous user and the email is accepted<br />- create: a user account is created for the sender (username/password are sent back to the user) and the email is accepted</b><br /></pre>Para que los usuarios no registrados puedan agregar tareas vía e-mail sin problemas no basta con solo agregar la directiva <b>unknown_user=accept</b>, también debemos agregar la directiva <b>no_permission_check=1</b> que evitará que <b>redmine:email:receive_imap</b> verifique los permisos relacionados al usuario <b>Anonymous</b>, que es el usuario de Redmine al cual serán asociadas las nuevas tareas generadas.<br /><br />Ahora bien, es importante aclarar que si queremos utilizar la directiva <b>unknown_user=accept</b> sin especificar la directiva <b>no_permission_check=1</b> será necesario configurar los permisos del <b>rol Anonymous</b>, 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.<br /><br />Por último y para no olvidar, como le hemos especificado el valor <b>Soporte</b> al argumento <b>tracker</b> del comando anterior, es importante agregar la opción <b>Soporte</b> a la lista de <b>Actividades</b>, que es configurable accediendo al menú <b>Administración-->Listas de valores</b> como se observa a continuación:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-06.png" width="640" /></a></div><br />El comando utiliza el argumento <b>tracker</b> 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:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="507" data-original-width="562" height="361" src="http://files.tormentadebits.com/images/00025-redmine-07.png" width="400" /></a></div><br /></li><li>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 <b>redmine</b> dentro del directorio <b>/etc/cron.d</b> y luego lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/cron.d/redmine<br /><span style="color: red;">testsrv:~ #</span> vi /etc/cron.d/redmine</b><br /></pre>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.<br /><pre><i># Generacion de tareas a partir de correos entrantes.</i><br />* * * * * 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<br /></pre>Finalmente reiniciamos el servicio cron para activar la tarea.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart cron.service</b><br /></pre></li><li>Si hemos utilizado las directivas <b>unknown_user=accept</b> y <b>no_permission_check=1</b>, 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.<br /><br />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 <b>mail_handler.rb</b> ubicado en el directorio <b>/opt/redmine/app/models</b>, que se encarga de procesar los correos entrantes:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /opt/redmine/app/models/mail_handler.rb</b><br /></pre>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.<br /><pre><i># Creates a new issue</i><br /> def receive_issue<br /> project = target_project<br /> # check permission<br /> unless handler_options[:no_permission_check]<br /> raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)<br /> end<br /><br /> issue = Issue.new(:author => user, :project => project)<br /> attributes = issue_attributes_from_keywords(issue)<br /> if handler_options[:no_permission_check]<br /> issue.tracker_id = attributes['tracker_id']<br /> if project<br /> issue.tracker_id ||= project.trackers.first.try(:id)<br /> end<br /> end<br /> issue.safe_attributes = issue_attributes_from_keywords(issue)<br /> issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}<br /> <i>#issue.subject = cleaned_up_subject</i><br /> <span style="background-color: #edff21;">issue.subject = cleaned_up_subject + " (#{email.from.to_a.first.to_s.strip.gsub(/@.*$/, '').strip})"</span><br /> if issue.subject.blank?<br /> issue.subject = '(no subject)'<br /> end<br /> <i>#issue.description = cleaned_up_text_body</i><br /> <span style="background-color: #edff21;">issue.description = "ENVIADO POR: #{email.from.to_a.first.to_s.strip}\r\n\r\n" + cleaned_up_text_body</span><br /> issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?<br /> issue.is_private = (handler_options[:issue][:is_private] == '1')<br /><br /> <i># add To and Cc as watchers before saving so the watchers can reply to Redmine</i><br /> add_watchers(issue)<br /> issue.save!<br /> add_attachments(issue)<br /> logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info<br /> issue<br />end<br /></pre></li><li>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 <a href="https://github.com/ageis/redmine_cc_addresses/tree/upgrade"><b>CC Address Plugin for Redmine</b></a>, un fork del proyecto original <a href="https://github.com/peelman/redmine_cc_addresses"><b>redmine_cc_addresses</b></a> 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.<br /><br />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:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/plugins/<br /><span style="color: red;">testsrv:/opt/redmine/plugins #</span> git clone https://github.com/ageis/redmine_cc_addresses.git<br /><span style="color: red;">testsrv:/opt/redmine/plugins #</span> chown -Rf redmine:redmine redmine_cc_addresses/</b><br /></pre>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.<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/plugins #</span> cd /opt/redmine<br /><span style="color: red;">testsrv:/opt/redmine #</span> bundle.ruby2.4 exec rake redmine:plugins:migrate RAILS_ENV=production</b><br /></pre>Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart apache2.service</b><br /></pre>Hay que tener en cuenta que en la sección de <b>Configuración -> Módulo</b> de cada proyecto hay que activar el módulo <b>CC addresses</b> para que la sección <b>CC Addresses</b> 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 <b>Administración -> Perfiles y permisos -> Perfil X</b>.<br /><br /></li><li>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 <b>redmine_cc_addresses</b> 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.<br /><br />Para implementar esta funcionalidad tenemos que volver a modificar el código del archivo <b>mail_handler.rb</b><br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /opt/redmine/app/models/mail_handler.rb</b><br /></pre>Luego nos tenemos que posicionar entre los métodos <b>add_attachments</b> y <b>add_accept_attachment?</b> para agregar un nuevo método llamado <b>add_cc_addresses</b>, 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:<br /><pre>def add_attachments(obj)<br /> ...<br /> end<br /><br /><span style="background-color: #edff21;"><i> # Metodo que agrega a la lista de correo CC de la peticion las cuentas del emisor<br /> # y de los asociados como copia (CC).</i><br /> def add_cc_addresses(obj)<br /> addresses = [email.from, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}<br /> unless addresses.empty?<br /> addresses.each do |address|<br /> <i># Agrega a la tabla cc_addresses los correos.</i><br /> addr = CcAddress.create(:mail => address, :issue_id => obj.id)<br /> end<br /> end<br /> end</span><br /><br /> # Returns false if the +attachment+ of the incoming email should be ignored<br /> def accept_attachment?(attachment)<br /> .....<br /> end<br /></pre>A continuación buscamos el método <b>receive_issue</b> y agregamos el código necesario para que por cada nuevo correo entrante que se procese se ejecute el método <b>add_cc_addresses</b>:<br /><pre><i># Creates a new issue</i><br /> def receive_issue<br /> project = target_project<br /> <i># check permission</i><br /> unless handler_options[:no_permission_check]<br /> raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)<br /> end<br /><br /> issue = Issue.new(:author => user, :project => project)<br /> attributes = issue_attributes_from_keywords(issue)<br /> if handler_options[:no_permission_check]<br /> issue.tracker_id = attributes['tracker_id']<br /> if project<br /> issue.tracker_id ||= project.trackers.first.try(:id)<br /> end<br /> end<br /> issue.safe_attributes = attributes<br /> issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}<br /> <i>#issue.subject = cleaned_up_subject</i><br /> issue.subject = cleaned_up_subject + " (#{email.from.to_a.first.to_s.strip.gsub(/@.*$/, '').strip})"<br /> if issue.subject.blank?<br /> issue.subject = '(no subject)'<br /> end<br /> <i>#issue.description = cleaned_up_text_body</i><br /> issue.description = "ENVIADO POR: #{email.from.to_a.first.to_s.strip}\r\n\r\n" + cleaned_up_text_body<br /> issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?<br /> issue.is_private = (handler_options[:issue][:is_private] == '1')<br /><br /> <i># add To and Cc as watchers before saving so the watchers can reply to Redmine</i><br /> add_watchers(issue)<br /> issue.save!<br /> <span style="background-color: #edff21;">add_cc_addresses(issue)</span><br /> add_attachments(issue)<br /> logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger<br /> issue<br /> end<br /></pre>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 <b>mail_handler.rb</b>.<br /><br /><b>OBS:</b> Es importante tener en cuenta que no se van a enviar correos si probamos modificar una tarea con el usuario <b>Admin</b>, a menos que dicho usuario esté registrado como <b>miembro del proyecto</b>. 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.<br /></li></ol><br /><br /><h3>Configuración SCM (Subversion)</h3>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. <br /><ol><li>Lo primero que tenemos que hacer es crear un directorio dentro del directorio home de Redmine para almacenar los proyectos y repositorios de Subversion:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mkdir /opt/redmine/svn<br /><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /opt/redmine/svn<br /><span style="color: red;">testsrv:~ #</span> chmod -Rf 750 /opt/redmine/svn</b><br /></pre></li><li>Luego tenemos que instalar en openSUSE los paquetes relacionados a Subversion y otros requisitos más:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper in subversion-server curl apache2-mod_perl perl-Apache-DBI perl-DBD-Pg</b></pre>También instalamos las gemas <b>activesupport</b> y <b>activeresource</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> gem.ruby2.4 install activesupport activeresource</b><br /></pre></li><li>Verificamos que en el archivo <b>/etc/sysconfig/apache2</b> se encuentren activos los módulos <b>perl</b>, <b>dav</b> y <b>dav_svn</b> para Subversion.<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/apache2</b><br /></pre><pre><b>APACHE_MODULES="actions alias ... passenger <span style="color: red;">perl dav dav_svn</span>"</b><br /></pre></li><li>Necesitamos crear un enlace simbólico en el directorio <b>/usr/lib/perl5/vendor_perl/5.18.2/Apache</b> a partir del archivo <b>Redmine.pm</b> que se encuentra ubicado en la ruta <b>/opt/redmine/extra/svn</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> ln -s /opt/redmine/extra/svn/Redmine.pm /usr/lib/perl5/vendor_perl/5.18.2/Apache/</b><br /></pre></li><li>Tenemos que agregar la configuración requerida para Apache, para ello creamos y editamos posteriormente el archivo <b>redmine_svn.conf</b> dentro del directorio <b>/etc/apache2/conf.d</b>.<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/apache2/conf.d/redmine_svn.conf<br /><span style="color: red;">testsrv:~ #</span> vi /etc/apache2/conf.d/redmine_svn.conf</b><br /></pre>A dicho archivo le agregamos la siguiente configuración:<br /><pre>PerlLoadModule Apache::Redmine<br /><location /svn><br /> DAV svn<br /> SVNParentPath "/opt/redmine/svn"<br /><br /> PerlAccessHandler Apache::Authn::Redmine::access_handler<br /> PerlAuthenHandler Apache::Authn::Redmine::authen_handler<br /> AuthType Basic<br /> AuthName "Redmine Subversion Repository"<br /> Require valid-user<br /><br /> <i>## For mysql<br /> # RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"<br /> ## For postgresql</i><br /> RedmineDSN "DBI:Pg:dbname=redmine;host=localhost"<br /> RedmineDbUser "redmine"<br /> RedmineDbPass "redmine"<br /><br /> <i>## Optional where clause (fulltext search would be slow and<br /> ## database dependant).<br /> # RedmineDbWhereClause "and members.role_id IN (1,2)"<br /> ## Optional credentials cache size<br /> # RedmineCacheCredsMax 50</i><br /></location><br /></pre>Finalmente reiniciamos el servicio Apache.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart apache2.service</b><br /></pre></li><li>El siguiente paso consiste en dirigirnos a la pestaña <b>Administration – Settings – Repositories</b> 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ó <b>X9YEsWGYUbevDmX4u5ep</b>. Es importante aclarar que la llave API generada anteriormente será utilizada desde la línea de comandos para crear los repositorios Subversion en Redmine.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1086" height="507" src="http://files.tormentadebits.com/images/00025-redmine-09.png" width="640" /></a></div><br />En este ventana también se recomienda configurar las siguientes opciones:<br />- Desmarcar todos los tipos de servicios SCM a excepción de los que deseamos utilizar.<br />- Marcar la opción <b>Habilitar registro de horas</b>.<br /><br />Una vez realizado lo anterior tenemos que guardar los cambios.<br /><br /></li><li>Para habilitar y crear el repositorio Subversion para un proyecto de Redmine primero debemos seleccionar nuestro proyecto, dirigirnos a la pestaña <b>Módulos</b> en la sección <b>Configuración</b> del proyecto y activar la opción <b>Repositorio</b>. 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:<br /><pre><b><span style="color: red;">testsrv:~ #</span> 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</b><br /></pre>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:<br /><pre><b>404<br /><br />La entrada y/o la revisión no existe en el repositorio.</b><br /></pre>Pueden probar cambiar el dueño y grupo de usuario a <b>wwwrun www</b> del archivo <b>environment.rb</b> ubicado en la carpeta <b>config</b>,<br /><pre><b><span style="color: red;">testsrv:~ #</span> chown -Rf wwwrun:www /opt/redmine/config/environment.rb</b><br /></pre>reiniciando posteriormente el servicio Apache como se muestra a continuación:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart apache2.service</b><br /></pre></li><li>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 <b>/etc/cron.d/redmine</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/cron.d/redmine</b><br /></pre>Al final del cual agregamos una nueva tarea programada que se encargue de realizar cada minuto la comprobación correspondiente:<br /><pre><i># Generacion automatica de repositorios subversion.</i><br />* * * * * 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<br /></pre>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.<br /><pre><i># Sincronización de comentarios de commits asociados a tareas.</i><br />* * * * * root curl "http://IP_SERVIDOR/redmine/sys/fetch_changesets?key=X9YEsWGYUbevDmX4u5ep" > /dev/null 2>&1<br /></pre>Finalmente reiniciamos el servicio cron.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart cron</b><br /></pre></li><li>Con los pasos anteriores ya podremos utilizar el repositorio, su integración en la herramienta quedaría como sigue:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-10.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-11.png" width="640" /></a></div></li></ol><br /><h4>ACLARACIONES SOBRE EL MÓDULO REPOSITORIO DE REDMINE:</h4><ol><li>El proyecto tiene que tener activo el módulo <b>Repositorio</b> para que la aplicación <b>reposman.rb</b> pueda crear el repositorio svn físico en el directorio <b>/opt/redmine/svn</b>.<br /><br /></li><li>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.<br /><br /></li><li>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 <b>Jefe de proyecto</b> o <b>Desarrollador</b>, porque si tiene asignado el perfil <b>Informador</b> solo podrá descargar el repositorio pero no subir actualizaciones.<br /><br /></li><li>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 <b>Usuarios</b> de la pestaña <b>Configuración --> Repositorio</b> del proyecto en cuestión.<br /></li></ol><br /><br /><h3>Realización de copias de seguridad</h3>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. <br /><ol><li>En principio necesitamos definir un directorio en donde ubicar las copias de seguridad realizadas, en mi caso voy a crear una carpeta llamada <b>backups</b> en el directorio raíz.<br /><pre><b><span style="color: red;">testsrv:~ #</span> mkdir /backups</b><br /></pre></li><li>Luego pasamos a crear los directorios <b>backups</b> y <b>backups/svndumps</b> dentro de <b>/opt/redmine</b> para almacenar las copias de seguridad en bruto de la base de datos y de los repositorios subversion que tenemos agregados:<br /><pre><b><span style="color: red;">testsrv:~ #</span> mkdir -p /opt/redmine/backups/svndumps</b><br /></pre></li><li>A continuación accedemos al directorio <b>/opt/redmine/script</b> y creamos el archivo <b>backup</b> que contendrá el script que realizará la copia de seguridad, además se le asignará los permisos correspondientes:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /opt/redmine/script/<br /><span style="color: red;">testsrv:/opt/redmine/script #</span> touch backup<br /><span style="color: red;">testsrv:/opt/redmine/script #</span> chmod 750 backup</b><br /></pre></li><li>Luego editamos el archivo <b>backup</b>,<br /><pre><b><span style="color: red;">testsrv:/opt/redmine/script #</span> vi backup</b><br /></pre>y le agregamos el siguiente script bash:<br /><pre><i>#!/bin/bash<br /># Realiza una copia de seguridad completa de la herramienta Redmine.</i><br />DIA=`date +"%Y%m%d"`<br />HORA=`date +"%H%M"`<br />BACKUP_PATH=/backups<br /> <br /><i># -- REDMINE</i><br />REDMINE_HOME=/opt/redmine<br />REDMINE_DB_TYPE=pg #[pg|mysql]<br />REDMINE_DB_NAME=redmine<br />REDMINE_DB_USER=redmine<br />REDMINE_DB_PASS=redmine<br />REDMINE_DB_BACKUP=$REDMINE_HOME/backups/redmine_db.sql<br />REDMINE_BACKUP_NAME="redmine_"$DIA"_"$HORA".tar.gz"<br />REDMINE_BACKUP_HISTO="histo_redmine_"$DIA"_"$HORA".tar.gz"<br />REDMINE_BACKUP_LIVE_TIME=30<br />REDMINE_BACKUP_HISTO_LIVE_TIME=365<br /> <br /><i># -- SVN</i><br />SVN_REPOS_PATH=$REDMINE_HOME/svn<br />SVN_BACKUP_PATH=$REDMINE_HOME/backups/svndumps<br /> <br /><i># -- PATRON LIMPIEZA</i><br />PATRON_BKP_DIARIO=redmine_*.tar.gz<br />PATRON_BKP_HISTO=histo_redmine_*.tar.gz<br /> <br /><i># -- FTP</i><br />FTP_COPIAR="N" #[S|N]<br />FTP_SERVER=ip_servidor_backup_ftp<br />FTP_USER=usuario_ftp<br />FTP_PASS=password_ftp<br />FTP_REMOTE_CD=remote_backups<br />FTP_LOCAL_CD=$BACKUP_PATH<br /> <br /><i># Backup de Proyectos SVN</i><br />echo<br />echo "-->BACKUP DE REPOSITORIOS SVN"<br />echo "===================================================================="<br />cd $SVN_REPOS_PATH<br />for SVN_REPO_NAME in *<br />do<br /> echo "---------- Iniciando exportacion del repositorio '$SVN_REPO_NAME' ----------"<br /> /usr/bin/svnadmin dump $SVN_REPOS_PATH/$SVN_REPO_NAME > $SVN_BACKUP_PATH/$SVN_REPO_NAME.dump<br /> echo "------------- Fin exportacion del repositorio '$SVN_REPO_NAME' -------------"<br /> echo<br />done<br /> <br /><i># Segun el motor de base de datos especificado se procede a exportar la base de datos de Redmine.</i><br />echo<br />echo "-->BACKUP DE LA BASE DE DATOS DE REDMINE"<br />echo "===================================================================="<br />if [ $REDMINE_DB_TYPE == "mysql" ]; then<br /> echo "Exportando la base de datos de Redmine a partir de MySQL. Aguarde un momento..."<br /> mysqldump -v -u $REDMINE_DB_USER -p$REDMINE_DB_PASS --database $REDMINE_DB_NAME > $REDMINE_DB_BACKUP<br /> echo "Fin del proceso de exportacion."<br /> echo<br />elif [ $REDMINE_DB_TYPE == "pg" ]; then<br /> echo "Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento..."<br /> export PGUSER=$REDMINE_DB_USER<br /> export PGPASSWORD=$REDMINE_DB_PASS<br /> pg_dump -b -F p --column-inserts $REDMINE_DB_NAME > $REDMINE_DB_BACKUP<br /> unset PGUSER<br /> unset PGPASSWORD<br /> echo "Fin del proceso de exportacion."<br />fi<br /> <br /><i># Se generan los archivos con todas las copias de seguridad para ser enviadas a una unidad de cinta.</i><br />echo<br />echo "-->CREANDO FULL BACKUP DE REDMINE"<br />echo "===================================================================="<br />tar -czf $BACKUP_PATH/$REDMINE_BACKUP_NAME $REDMINE_HOME<br /> <br /><i># Almacenando una copia de seguridad alternativa si la fecha corresponde a fin de mes.</i><br />TOMORROW=`date --date=tomorrow +%d`<br />if [ $TOMORROW -eq "1" ]; then<br /> echo<br /> echo "-->CREANDO BACKUP HISTORICO POR SER FIN DE MES"<br /> echo "===================================================================="<br /> cp $BACKUP_PATH/$REDMINE_BACKUP_NAME $BACKUP_PATH/$REDMINE_BACKUP_HISTO<br />fi<br /> <br /><i># Para no llenar el disco duro con backups, se eliminan todos los backups diarios pasados la cantidad<br /># de dias especificados en la variable REDMINE_BACKUP_LIVE_TIME, lo backups historicos se eliminan luego <br /># de la cantidad de dias expecificados en la variable REDMINE_BACKUP_HISTO_LIVE_TIME.</i><br />echo<br />echo "-->LIMPIEZA DE BACKUPS ANTIGUOS"<br />echo "===================================================================="<br />find $BACKUP_PATH/$PATRON_BKP_DIARIO -mtime +$REDMINE_BACKUP_LIVE_TIME -exec rm {} \;<br />find $BACKUP_PATH/$PATRON_BKP_HISTO -mtime +$REDMINE_BACKUP_HISTO_LIVE_TIME -exec rm {} \;<br /> <br /><i># Se copia el full backup a un servidor de respaldo.</i><br />if [ $FTP_COPIAR == "S" ]; then<br /> echo<br /> echo "-->COPIANDO EL FULL BACKUP DE REDMINE A UN SERVIDOR DE RESPALDO"<br /> echo "===================================================================="<br /> /usr/bin/ftp -n <<EOD<br /> open $FTP_SERVER<br /> quote USER $FTP_USER<br /> quote PASS $FTP_PASS<br /> bin<br /> cd $FTP_REMOTE_CD<br /> lcd $FTP_LOCAL_CD<br /> put $REDMINE_BACKUP_NAME<br /> bye<br />EOD<br />else<br /> echo<br /> echo "-->COPIA FTP INHABILITADA!"<br /> echo<br />fi<br /></pre>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 <b>tar.gz</b> de todo el directorio <b>/opt/redmine</b>, 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.<br /><br />En este punto ya podemos probar la ejecución del script de la siguiente manera<br /><pre><b><span style="color: red;">testsrv:~ #</span> /opt/redmine/script/backup</b><br /><br />-->BACKUP DE REPOSITORIOS SVN<br />====================================================================<br />---------- Iniciando exportacion del repositorio 'prueba' ----------<br />* Dumped revision 0.<br />* Dumped revision 1.<br />* Dumped revision 2.<br />* Dumped revision 3.<br />* Dumped revision 4.<br />* Dumped revision 5.<br />------------- Fin exportacion del repositorio 'prueba' -------------<br /><br />---------- Iniciando exportacion del repositorio 'test' ----------<br />* Dumped revision 0.<br />------------- Fin exportacion del repositorio 'test' -------------<br /><br /><br />-->BACKUP DE LA BASE DE DATOS DE REDMINE<br />====================================================================<br />Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento...<br />Fin del proceso de exportacion.<br /><br />-->CREANDO FULL BACKUP DE REDMINE<br />====================================================================<br />tar: Removing leading `/' from member names<br /><br />-->LIMPIEZA DE BACKUPS ANTIGUOS<br />====================================================================<br />find: ‘/backups/histo_redmine_*.tar.gz’: No such file or directory<br /><br />-->COPIA FTP INHABILITADA!<br /><br /><b><span style="color: red;">testsrv:~ #</span></b><br /></pre></li><li>Para programar la ejecución periódica del script debemos agregar una tarea programada. Para ello editamos nuevamente el archivo <b>/etc/cron.d/redmine</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/cron.d/redmine</b><br /></pre>Para luego agregarle al final del mismo el siguiente contenido:<br /><pre><i># Backup Redmine</i><br />30 22 * * * root /opt/redmine/script/backup >> /dev/null<br /></pre>Finalmente reiniciamos el servicio <b>cron</b> para que la tarea programada sea funcional.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart cron</b><br /></pre></li></ol><br /><br /><h3>Otras capturas de pantalla</h3><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-12.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-13.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-14.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-15.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-16.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-17.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00025-redmine-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="860" data-original-width="1103" height="499" src="http://files.tormentadebits.com/images/00025-redmine-18.png" width="640" /></a></div><br /><br /><h3>Información técnica</h3><ul><li><b>openSUSE Leap 42.3 x64</b><br /></li><li><b>Apache 2.4</b><br /></li><li><b>Ruby 2.4.1</b><br /></li><li><b>Redmine 3.4.2</b><br /></li><li><b>Perl 5.18.2</b><br /></li></ul><br /><br /><h3>Fuentes</h3><ul><li><a href="http://www.redmine.org/" target="_blank"><b>Redmine (Sitio Oficial)</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki" target="_blank"><b>Redmine Wiki</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineInstall" target="_blank"><b>Redmine Install</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/HowTos" target="_blank"><b>Redmine HowTos</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineUpgrade" target="_blank"><b>Redmine Upgrade</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineReceivingEmails" target="_blank"><b>Redmine Receiving Emails</b></a><br /></li><li><a href="https://github.com/ageis/redmine_cc_addresses/tree/upgrade" target="_blank"><b>github.com/ageis/redmine_cc_addresses/tree/upgrade</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Plugins" target="_blank"><b>Redmine Plugins</b></a><br /></li><li><a href="http://www.redmine.org/plugins" target="_blank"><b>Lista de Plugins</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Themes" target="_blank"><b>Redmine Themes</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/Theme_List" target="_blank"><b>Lista de Temas (Themes)</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/EmailConfiguration" target="_blank"><b>Redmine Email Configuration</b></a><br /></li><li><a href="http://www.redmine.org/projects/redmine/wiki/RedmineRepositories" target="_blank"><b>Redmine Repositories</b></a><br /></li><li><a href="https://www.phusionpassenger.com/library/config/apache/reference/" target="_blank"><b>Sobre el Módulo Passenger de Apache</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-79098121190857810912017-07-10T18:34:00.004-04:002022-10-04T22:51:28.435-03:00Configuración y lectura de puerto serial en sistemas operativos UNIX Like<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00035.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="615" height="156" src="http://files.tormentadebits.com/covers/portada-00035.png" width="320" /></a></div>Esta entrada es una de aquellas que se encontraba dormida hace años entre los borradores del blog.<br /><br />Trata acerca de la configuración de puertos seriales de sistemas operativos Unix like y el comando que permita la lectura de la información que se recibe a través del mismo. <br /><a name='more'></a><br />Si bien tengo entendido que la información corresponde a la configuración utilizada en un Unix, las directivas de los comandos podrían variar mínimamente entre sistemas operativos Unix y distribuciones Linux. Por otro lado, tampoco tengo forma de probarla ya que no dispongo de un entorno de pruebas adecuado para validar la información, de todas formas lo hago público por si le llega a ser de utilidad a alguien, mejor así que perdido entre los borradores.<br /><br />Para leer información de un puerto serial lo que deberíamos hacer son dos cosas:<br /><ol><li>Primero deberíamos configurar la velocidad del puerto, los bits de paridad, etc., y esto lo logramos mediante el comando <b>stty</b> de la siguiente manera:<br /><pre><b># stty 9600 cs7 istrip parenb -parodd min 1 time 0 ignpar -echo ignbrk -icanon < /dev/tty1a</b><br /></pre>Es importante aclarar que el puerto serial al cual se hace referencia en el comando anterior (/dev/tty1a) corresponde a un sistema operativo basado Unix, en las distribuciones Linux los puertos seriales se encuentran en el mismo directorio <b>/dev</b> pero enumerados de forma diferente como por ejemplo <b>ttyS0</b>, <b>ttyS1</b>, <b>ttyS2</b>, etc.<br /><br />Para conocer más acerca del comando <b>stty</b> y de todos sus argumentos pueden consultar el <a href="http://es.tldp.org/Paginas-manual/man-pages-es-extra-0.8a/man1/stty.1.html" target="_blank"><b>man page aquí</b></a>.<br /><pre><b># man stty</b><br /><br />stty(C)<br /> ____________________________________________________________<br /><br /> stty -- set the options for a terminal<br /><br />Synopsis<br /><br /> stty [-a] [-g] [options]<br /><br />Description<br /><br /> stty sets certain terminal I/O options for the device that is the<br /> current standard input; without arguments, it reports the<br /> settings of certain options.<br /><br /> In the input and output of stty, if a character is preceded by a<br /> caret (^), then the value of that option is the corresponding<br /> control character (for example, ``^h'' is <ctrl>H; in this case,<br /> recall that <ctrl>H is the same as the ``backspace'' key.) The<br /> sequence ``^''' means that an option has a null value.<br /><br /> The -- argument is used to indicate the end of options. Any<br /> arguments following the -- are treated as operands, even if they<br /> begin with a -. The -- should not be used as an option nor as an<br /> operand.<br /> -a<br /> Report all option settings.<br /> -g<br /> Report current settings in a form that can be used as an<br /> argument to another stty command.<br /><br /> For detailed information about the modes listed in sections<br /> ``Control modes'' through ``Local modes''. See termio(M). For<br /> detailed information about the modes listed in sections<br /> ``Hardware flow control modes'' and ``Clock modes''. See<br /> termiox(M). Options described in the ``Combination Modes''<br /> section are implemented using options in the earlier sections.<br /> Note that many combinations of options make no sense, but no<br /> sanity checking is performed. Hardware flow control and clock<br /> modes options may not be supported by all hardware interfaces.<br /></ctrl></ctrl></pre></li><li>El siguiente paso consiste en leer la información recibida a través del puerto serial, para ello se puede utilizar el comando <b>line</b>:<br /><pre><b># line < /dev/tty1a > /tmp/captura_puerto_serial.txt</b><br /></pre>Para conocer más acerca del comando <b>line</b> pueden consultar su <b>man page</b>:<br /><pre><b># man line</b><br /><br />line(C)<br /> ____________________________________________________________<br /><br /> line -- read one line<br /><br />Syntax<br /><br /> line<br /><br />Description<br /><br /> line copies one line (up to a new line) from the standard input<br /> and writes it on the standard output.<br /><br /> line is often used within shell scripts to read from the user's<br /> terminal.<br /><br /> line always prints at least a new line.<br /><br />Exit values<br /><br /> line returns 0 on successful completion; 1 on end-of-file<br /> detected on input.<br /></pre></li></ol><br /><h3>Fuentes relacionadas:<br /></h3><ul><li><a href="http://es.tldp.org/Paginas-manual/man-pages-es-extra-0.8a/man1/stty.1.html" target="_blank"><b>Man Page del comando stty</b></a><br /></li><li><a href="http://www.cyberciti.biz/faq/unix-linux-apple-osx-bsd-screen-set-baud-rate/" target="_blank"><b>Set Baud Rate vía Cyberciti</b></a><br /></li><li><a href="http://stackoverflow.com/questions/3918032/bash-serial-i-o-and-arduino" target="_blank"><b>Bash, serial I/O and Arduino vía Stackoverflow</b></a><br /></li><li><a href="http://www.ubuntu-es.org/node/128304#.URVSTKWsh8E" target="_blank"><b>Como configuro el com1 vía ubuntu-es.org</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-67416958454399604562017-07-07T11:53:00.004-04:002022-10-04T22:50:18.730-03:00Konsole: Configuración de perfil para acceso a Unix SCO<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00055.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://files.tormentadebits.com/covers/portada-00055.png" width="320" height="156" data-original-width="1230" data-original-height="600" /></a></div>Si bien hoy en día estamos acostumbrados a que los intérpretes de comandos de las distribuciones Linux, como bash, no nos presenten inconvenientes al momento de escribir nuestros comandos, o ejecutar algunas aplicaciones remotas, la verdad es que existen varios otros intérpretes y entornos que si nos pueden dar dolores de cabeza.<br /><br />Esa fue mi experiencia con los intérpretes <b>KSH</b> y <b>SH</b> del sistema operativo <b>SCO OpenServer</b>, cuyas configuraciones no son las más compatibles con las aplicaciones de consola actuales.<br /><a name='more'></a><br />Los intérpretes de comandos que utiliza el sistema operativo <b>SCO OpenServe</b>r, que se encuentra basado en Unix, suelen ser como ya mencioné <b>SH</b> o <b>KSH</b> por defecto, también cuenta con <b>bash</b>, pero aún eligiendo el intérprete de comandos bash la experiencia no es la misma que la que nos ofrecen las distribuciones Linux.<br /><br />Básicamente, la diferencia se encuentra en las configuraciones del entorno del intérprete de comandos que utiliza el sistema operativo, en este caso <b>Unix SCO OpenServer</b>, y como el OS interpreta cada una de las teclas presionadas en el equipo cliente, que suelen ser enviadas remotamente desde aplicaciones cliente de consolas (PuTTY, Konsole, etc.).<br /><br />Es así, que para el caso de la aplicación de consola cliente de <b>KDE</b>, o sea, <b>Konsole</b>, debemos crear un <b>profile</b> de conexión que cuente con la configuración compatible con la configuración del sistema operativo <b>SCO OpenServer</b>, para lo cual debemos seguir los siguientes pasos verificados para un sistema operativo <b>openSUSE Leap 42.2</b> con <b>KDE 5</b>:<br /><ol><li>Comenzamos por dirigirnos al directorio <b>home</b> de nuestro usuario operador que intenta conectarse mediante <b>Konsole</b> a un equipo remoto que usa el sistema operativo SCO, y creamos un archivo denominado <b>sco.profile</b> en el directorio que corresponde:<br /><pre><b>gabriel@testpc:~></b> cd /home/gabriel/<br /><b>gabriel@testpc:~></b> touch .local/share/konsole/sco.profile<br /><b>gabriel@testpc:~></b> chown gabriel:users .local/share/konsole/sco.profile<br /><b>gabriel@testpc:~></b> chmod 600 .local/share/konsole/sco.profile<br /><b>gabriel@testpc:~></b> vi .local/share/konsole/sco.profile<br /></pre><b>OBS:</b> Para la versión 4 de KDE, el directorio para crear los archivos es <b>.kde4/share/apps/konsole/</b>.<br /><br />A dicho archivo le agregamos el siguiente contenido:<br /><pre>[Appearance]<br />ColorScheme=WhiteOnBlack<br />Font=Monospace,14,-1,2,50,0,0,0,0,0<br /><br />[Encoding Options]<br />DefaultEncoding=IBM850<br /><br />[General]<br />Command=/bin/bash<br />Environment=TERM=vt100,LANG=en_US.IBM850,LC_COLLATE=en_US.IBM850,LC_CTYPE=en_US,LC_MESSAGES=C,LC_MONETARY=en_US.IBM850,LC_NUMERIC=en_US.IBM850,LC_TIME=en_US.IBM850<br />Name=SCO<br />Parent=FALLBACK/<br />TabBarMode=0<br /><br />[Keyboard]<br />KeyBindings=sco<br /><br />[Scrolling]<br />HistoryMode=0<br /></pre>En la configuración anterior quisiera resaltar dos de ellas que son las más importantes, aparte de la configuración del tamaño de texto, colores, etc. Las configuraciones de interés son <b>TERM=vt100</b> en la propiedad <b>Environment</b> y la configuración <b>KeyBindings=sco</b>. En la primera le informamos al cliente de consola <b>Konsole</b> que utilice el estándar de terminal <b>vt100</b> para comunicarse con el servidor SCO ya que es compatible, y en la segunda le informamos que utilice un archivo de configuración denominado <b>sco.keytab</b>, que si no vamos a necesitar modificar las funciones de ciertas teclas del teclado, la opción <b>KeyBindings</b> debería ser omitida.<br /><br /></li><li>La aplicación cliente <b>Konsole</b> permite reemplazar el valor original generado al presionar ciertas teclas del teclado del equipo cliente, y enviar al equipo remoto un valor diferente. En este ejemplo, la asociación de la teclas que se desean reemplazar por valores diferentes se agregan al archivo denominado <b>sco.keytab</b>, que lo podemos crear con las siguientes directivas:<br /><pre><b>gabriel@testpc:~></b> cd<br /><b>gabriel@testpc:~></b> touch .local/share/konsole/sco.keytab<br /><b>gabriel@testpc:~></b> chown gabriel:users .local/share/konsole/sco.keytab<br /><b>gabriel@testpc:~></b> chmod 600 .local/share/konsole/sco.keytab<br /><b>gabriel@testpc:~></b> vi .local/share/konsole/sco.keytab<br /></pre>Se le puede agregar la siguiente configuración de ejemplo que es muy rebuscada, ya que cambia los valores de las teclas F1 al F7 por códigos <span style="font-family: "times new roman" , serif; font-size: 13.5pt; line-height: 115%;">ASCII </span>del 1 al 7, lo mismo con las teclas de cursores que devuelven números. Ya queda a criterio de cada uno hacer las adaptaciones que crean convenientes.<br /><pre>keyboard "SCO"<br />key Esc : "\E"<br />key Tab : "\t"<br />key Backspace : "\b"<br />key Return+Alt : "\E\r"<br />key Return-Alt : "\r"<br />key Enter : "\r"<br />key Ins-Shift : "\E[2~"<br />key Del : "\E[3~"<br />key F1 : "\x01"<br />key F2 : "\x02"<br />key F3 : "\x03"<br />key F4 : "\x04"<br />key F5 : "\x05"<br />key Home : "\E[1~"<br />key F6 : "\x06"<br />key End : "\E[4~"<br />key F7 : "\x07"<br />key F8 : "\E[19~"<br />key Left-Shift : "4"<br />key Up+Shift : ScrollLineUp<br />key Up-Shift : "8"<br />key F9 : "\E[20~"<br />key F10 : "\E[21~"<br />key Right-Shift : "6"<br />key Down+Shift : ScrollLineDown<br />key Down-Shift : "2"<br />key F11 : "\E[23~"<br />key PgUp-Shift : "\E[5~"<br />key PgUp+Shift : ScrollPageUp<br />key F12 : "\E[24~"<br />key Space+Ctrl : ""<br />key PgDown-Shift : "\E[6~"<br />key PgDown+Shift : ScrollPageDown<br /></pre>Esta opción que nos ofrece Konsole es muy importante ya que los valores que se generan al presionar una tecla del teclado pueden variar en función a la configuración del entorno de ejecución del intérprete de comandos que usamos, y al sistema operativo desde donde se ejecute la aplicación cliente de tipo consola, que no siempre son exactamente compatibles con la configuración del sistema operativo remoto.<br /><br /></li><li>Una vez creados los archivos anteriores ya podemos utilizar el nuevo perfil ejecutando la aplicación <b>Konsole</b> y accediendo al menú <b>Preferencias --> Cambiar perfil --> SCO</b>.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00024-konsole-profiles-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="513" data-original-width="771" height="265" src="http://files.tormentadebits.com/images/00024-konsole-profiles-1.png" width="400" /></a></div>Sin embargo, podemos facilitar el acceso a dicha configuración creando un acceso directo que ejecute la aplicación <b>Konsole</b>, cargue el perfil <b>sco.profile</b> y se conecte automáticamente al equipo con el sistema operativo<b> SCO OpenServer</b>. Comenzamos por crear el archivo de acceso directo <b>sco.desktop</b>:<br /><pre><b>gabriel@testpc:~></b> cd<br /><b>gabriel@testpc:~></b> touch Escritorio/sco.desktop<br /><b>gabriel@testpc:~></b> chown gabriel:users Escritorio/sco.desktop<br /><b>gabriel@testpc:~></b> chmod 755 Escritorio/sco.desktop<br /><b>gabriel@testpc:~></b> vi Escritorio/sco.desktop<br /></pre>Al cual le agregamos el siguiente contenido:<br /><pre>#!/usr/bin/env xdg-open<br />[Desktop Entry]<br />Comment[es]=<br />Comment=<br />Exec=konsole --profile sco.profile -e ssh ip_o_nombre_equipo_sco<br />GenericName[es]=<br />GenericName=<br />Icon=package_internet_terminal<br />MimeType=<br />Name[es]=Acceso a OS SCO<br />Name=Acceso a OS SCO<br />Path=<br />StartupNotify=true<br />Terminal=false<br />TerminalOptions=<br />Type=Application<br />X-DBUS-ServiceName=<br />X-DBUS-StartupType=<br />X-KDE-SubstituteUID=false<br />X-KDE-Username=<br /></pre></li><li>Para finalizar es importante mencionar que desde el menú <b>Preferencias --> Gestionar Perfiles...</b> podemos elegir el perfil <b>SCO</b> creado previamente por comandos y editar sus propiedades a través de la interfaz gráfica de configuraciones provista por <b>Konsole</b>, lo que nos facilitará configurar propiedades como el tamaño de texto, colores de la consola, etc.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00024-konsole-profiles-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="511" data-original-width="769" height="266" src="http://files.tormentadebits.com/images/00024-konsole-profiles-2.png" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/images/00024-konsole-profiles-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="471" data-original-width="708" height="133" src="http://files.tormentadebits.com/images/00024-konsole-profiles-3.png" width="200" /></a> <a href="http://files.tormentadebits.com/images/00024-konsole-profiles-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="633" data-original-width="741" height="170" src="http://files.tormentadebits.com/images/00024-konsole-profiles-4.png" width="200" /></a></div></li></ol>Y eso es todo por el momento, creo.<br /><br /><h3>Fuentes:</h3><ul><li><a href="https://en.wikipedia.org/wiki/OpenServer" target="_blank">https://en.wikipedia.org/wiki/OpenServer</a><br /></li><li><a href="http://www.sco.com/products/openserver6/" target="_blank">http://www.sco.com/products/openserver6/</a><br /></li><li><a href="https://es.wikipedia.org/wiki/VT100" target="_blank">https://es.wikipedia.org/wiki/VT100</a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com2tag:blogger.com,1999:blog-1035903216249592564.post-44485192616239215892017-06-04T23:53:00.004-04:002022-10-04T22:49:00.235-03:00Apertura de gavetas de dinero desde un sistema POS remoto<a href="http://files.tormentadebits.com/covers/portada-00028.png" imageanchor="1" style="clear: left; display: inline; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00028.png" width="320" /></a>En este artículo quiero escribir sobre una de esas tantas soluciones rebuscadas que he tenido que encontrar, para resolver uno de esos problemas curiosos que se presentan muy a menudo en esta profesión.<br /><br />El artículo trata acerca de la implementación de la apertura de gavetas de dinero en puntos de ventas de un local comercial, pero como verán los lectores más adelante, el escenario dista mucho de ser el "tradicional" punto de ventas de un supermercado.<br /><a name='more'></a><br />Normalmente, las gavetas de dinero utilizadas en los puntos de ventas (POS, Point of sale) de los supermercados suelen estar conectadas a impresoras de tickets matriciales. Cuando las impresoras reciben un comando ESC/POS enviadas desde el sistema, la misma envía un pulso eléctrico de 24v a través de su interfaz RJ12 a la gaveta, y la misma procede a su apertura.<br /><br />En este caso el objetivo era que al finalizar la transacción comercial en el punto de venta, el sistema se encargara de imprimir el comprobante legal y de abrir automáticamente la gaveta de dinero al cajero así como en un supermercado, pero en un entorno de trabajo con las siguientes características:<br /><ol><li>Las impresoras de comprobantes eran las tradicionales Epson LX-300 o bien impresoras Láser para imprimir facturas de gran tamaño, tipos de impresoras que no llevan el puerto RJ12 presente en cualquier impresora de tickets de los supermercados.<br /></li><li>Los puntos de ventas eran computadores normales con un sistema operativo openSUSE Linux.<br /></li><li>El sistema de punto de venta no era una aplicación gráfica instalada en el sistema operativo, sino un sistema de tipo terminal que se ejecutaba en un servidor remoto al cual se accedía a través de conexiones SSH.<br /></li></ol><br />Bajo las condiciones antes mencionadas se decidió proceder con las siguientes soluciones, algunas de ellas "algo rebuscadas":<br /><ol><li><b>Impresoras EPSON LX-300 y/o impresoras Láser:</b><br />Era un requerimiento utilizar este tipo de impresoras debido a que en los mencionados puntos de ventas se deseaban imprimir las facturas de gran tamaño. Como las mencionadas impresoras no llevan el <b>Drawer Port RJ12</b>, se optó por comprar unas gavetas de dinero con puertos seriales <b>RS232</b> que iban conectadas directamente el ordenador.<br /><br />Si bien las gavetas funcionan bien, tienen la particularidad de que necesitan un pequeño integrado que entienda el comando que se le está enviando y algunos modelos incluso un transformador adicional que alimente al interruptor de apertura de la gaveta con la energía necesaria, ya que el puerto serial no tiene el voltaje suficiente para el accionamiento directo del interruptor.<br /><br />Hasta aquí la solución fue optar por un hardware diferente, ahora pasemos al siguiente.<br /><br /></li><li><b>Puntos de ventas con sistemas operativos Linux</b>:<br />Los entornos tradicionales utilizarían un ordenador con un sistema operativo Windows, desde el cual podemos abrir las gavetas de dinero con puertos seriales RS232 ejecutando los siguientes comandos desde el intérprete de comandos CMD de Windows:<br /><pre><b>CMD></b> mode com1 9600,N,8,1<br /><b>CMD></b> echo "^G" > com1<br /></pre>Básicamente lo que se realiza primero es configurar la velocidad del puerto serial que recomienda el proveedor de la gaveta de dinero y luego enviarle el comando <b>Ctrl+G</b>(^G) al puerto serial <b>com1</b>.<br /><br />Desde una distribución Linux el comando tampoco es que varíe demasiado, no necesitamos configurar la velocidad del puerto serial, sino simplemente enviar el siguiente comando desde el usuario root:<br /><pre><b>cajero@testsrv:~></b> su -<br /><b><span style="color: red;">testsrv:~ #</span> echo -en "\07" > /dev/ttyS0</b><br /></pre>El comando anterior redirecciona la salida del comando <b>echo</b> al puerto serial <b>/dev/ttyS0</b> (lo que en windows sería el com1). Es necesario que el comando <b>echo</b> se ejecute con los argumentos <a href="http://linuxcommand.org/lc3_man_pages/echoh.html" target="_blank"><b>-en</b></a>, para que pueda enviar de forma directa al puerto serial el valor hexadecimal <b>07</b>, o lo que es lo mismo, el valor <b>Ctrl+G</b> (BELL) como podemos apreciar en la tabla ASCII de <a href="https://es.wikipedia.org/wiki/ASCII" target="_blank"><b>ésta entrada en Wikipedia</b></a>.<br /><br />Ahora bien, en openSUSE Linux solo el usuario <b>root</b> está autorizado por defecto a acceder de forma directa a los puertos seriales, y como el usuario del sistema operativo encargado de ejecutar el sistema de puntos de ventas era un usuario normal denominado <b>cajero</b> sin los mencionados privilegios (nadie en su sano juicio debería utilizar el usuario root para esto), se le tuvo que agregar al grupo de usuarios del sistema operativo <b>dialout</b> de la siguiente manera:<br /><pre><b>cajero@testsrv:~></b> su -<br /><b><span style="color: red;">testsrv:~ #</span> usermod -G dialout cajero</b><br /></pre>Para verificar a que grupos se encuentre asociado un usuario de Linux siempre podemos ejecutar el siguiente comando:<br /><pre><b>cajero@testsrv:~></b> su -<br /><b><span style="color: red;">testsrv:~ #</span> groups cajero</b><br />cajero: users dialout<br /><b><span style="color: red;">testsrv:~ #</span></b><br /></pre>Bien, hasta aquí logramos estar en condiciones de poder abrir nuestras gavetas desde un usuario normal de un sistema operativo Linux, sigamos adelante.<br /><br /></li><li><b>Monitoreo de flujos de texto para identificación de código patrón de apertura de gaveta</b>:<br />Uno de los principales problemas era que los usuarios del punto de venta se conectaban desde la terminal Linux Konsole a un servidor remoto mediante el protocolo SSH para ejecutar el sistema, lo que evidentemente implica que el programa no se ejecutaba en la máquina cliente, sino solamente en el servidor, permitiendo solamente el acceso a las unidades y dispositivos del servidor.<br /><br />Para resolver ese "pequeño" inconveniente lo único que se me ocurrió fue desarrollar un servicio en el equipo cliente que sea capaz de procesar el flujo de texto constante generado por la aplicación remota y poder identificar entre dicho caudal de información algún código o patrón previamente convenido que permita saber en que momento se debía abrir la gaveta de dinero.<br /><br />Pero un momento, es posible redirigir todo el texto que genera una aplicación remota a un servicio que filtre dicho contenido y lo siga mostrando en la pantalla del equipo cliente? Si, se puede, y la herramienta clave se llama <b>tee</b>. El comando <b>tee</b> permite recibir la salida estándar de un programa, que en este caso sería la conexión remota, y generar dos salidas idénticas, una a la pantalla del usuario (salida estándar) y la otra hacia un archivo, o bien a una tubería.<br /><br />Pero antes pasemos primero por el desarrollo del servicio denominado <b>tubgaveta</b>, el mismo se creó de la siguiente manera:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /usr/bin/tubgaveta<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /usr/bin/tubgaveta<br /><span style="color: red;">testsrv:~ #</span> chown root:root /usr/bin/tubgaveta<br /><span style="color: red;">testsrv:~ #</span> vi /usr/bin/tubgaveta</b><br /></pre>El script <b>tubgaveta</b> estaba conformado por el siguiente código, cuya funcionalidad se detalla más abajo.<br /><pre><span style="color: #6aa84f;">#!/bin/bash<br />#############################################################<br /># SCRIT GENERADOR DE PULSO PARA APERTURA DE GAVETA DE DINERO<br /># ----------------------------------------------------------<br /># GABRIEL KFR - DIC 2009<br />#############################################################<br /># Definicion de variables para el script.</span><br />TUBERIA=/dev/puerto_gaveta<br />PUERTO_SERIAL=/dev/ttyS0<br />PATRON="&&ABRIRGAVETA&&"<br /><br /><span style="color: #6aa84f;"># Renueva la tuberia</span><br />rm -f $TUBERIA<br />mkfifo $TUBERIA<br />chmod 666 $TUBERIA<br /><br /><span style="color: #6aa84f;"># Queda en un loop eterno a menos que se pare<br /># el servicio.</span><br />while [ 0 ]; do<br /><span style="color: #274e13;"> </span><span style="color: #6aa84f;"> # A continuacion se realizan las siguientes tareas:<br /> # + cat $TUBERIA: Constantemente se va mostrando lo que viene por la tuberia.<br /> #<br /> # + grep -o --line-buffered $PATRON: filtra y muestra el patron de caracteres solo si recibe<br /> # una cadena cuyo contenido lo tenga. El argumento -o indica que solo saque al output la<br /> # porcion correspondiente al patron y no toda la linea, ya que es posible que el patron<br /> # venga entre medio de una cadena de caracteres mas extensa. El argumento --line-buffered<br /> # le indica a grep que recien cuando reciba una linea completa de la tuberia proceda a <br /> # aplicar el filtro para buscar coincidencias.<br /> #<br /> # + sed -u 's/'$PATRON'/\x07/g': La cadena resultante del grep que debe ser igual al patron se<br /> # reemplaza en su totalidad por el caracter CTRL+G para la apertura de gaveta.</span><br /> cat $TUBERIA | grep -o --line-buffered $PATRON | sed -u 's/'$PATRON'/\x07/g' >> $PUERTO_SERIAL <br />done<br /></pre>En resumen, cuando se ejecuta la aplicación anterior básicamente se crea una tubería con el comando <b>mkfifo</b>, se le asigna los permisos correspondientes y luego la aplicación entra en un loop infinito a la espera de recibir algo desde la misma. Si durante el monitoreo de la tubería (<i>cat $TUBERIA</i>) se recibe un flujo de texto, dicho flujo será derivado al siguiente filtro (<i>grep -o --line-buffered $PATRON</i>) que solo deja pasar el texto detallado en la variable <i>PATRON</i> al siguiente comando (<i>sed 's/'$PATRON'/\x07/g'</i>), que reemplazará el texto del patrón por el comando ascii correspondiente a <b>Ctrl+G</b> (BELL).<br /><br />El script <b>tubgaveta</b> se debía iniciar durante el arranque del sistema operativo, para lo cual en aquella ocasión se creó un script de arranque denominado <b>tgaveta</b>, que a día de hoy sigue funcionando de mala gana. Los pasos para su creación fueron los siguientes:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/init.d/tgaveta<br /><span style="color: red;">testsrv:~ #</span> chown root:root /etc/init.d/tgaveta<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /etc/init.d/tgaveta<br /><span style="color: red;">testsrv:~ #</span> vi /etc/init.d/tgaveta</b><br /></pre>Archivo al cual se le agregó el siguiente código:<br /><pre><span style="color: #6aa84f;">#!/bin/sh<br /># Author: Gabriel K<br />#<br /># /etc/init.d/tgaveta<br />#<br />### BEGIN INIT INFO<br /># Provides: tubgaveta<br /># Required-Start: <br /># Required-Stop: <br /># Default-Start: 3 5<br /># Default-Stop: 0 1 2 6<br /># Short-Description: Analizador Tuberia<br /># Description: Analizador de Tuberia para generación de pulso para apertura de gaveta.<br />### END INIT INFO</span><br />PROGRAM=/usr/bin/tubgaveta<br /><br />. /etc/rc.status<br /><br /><span style="color: #6aa84f;"># The echo return value for success (defined in /etc/rc.config).</span><br />return=$rc_done<br />case "$1" in<br /> start)<br /> echo -n "Starting service Analizador Tuberia para Apertura de Gaveta "<br /><span style="color: #6aa84f;"> ##<br /> ## Start daemon with startproc(8). If this fails<br /> ## the echo return value is set appropriate.</span><br /> startproc -q -s $PROGRAM<br /> rc_status -v<br /> ;;<br /><br /> stop)<br /> echo -n "Shutting down service Analizador Tuberia para Apertura de Gaveta "<br /><span style="color: #6aa84f;"> ## Stop daemon with killproc(8) and if this fails<br /> ## set echo the echo return value.</span><br /> killproc -g $PROGRAM<br /> rc_status -v<br /> ;;<br /><br /> try-restart)<br /> $0 status<br /> if test $? = 0; then<br /> $0 restart<br /> else<br /> rc_reset<br /> fi<br /> rc_status<br /> ;;<br /><br /> restart)<br /> $0 stop<br /> $0 start<br /> rc_status<br /> ;;<br /><br /> status)<br /> echo -n "Checking for service Analizador Tuberia: "<br /><span style="color: #6aa84f;"> ## Check status with checkproc(8), if process is running<br /> ## checkproc will return with exit status 0.</span><br /> checkproc $PROGRAM<br /> rc_status -v<br /> ;;<br /><br /> *)<br /> echo "Usage: $0 {start|stop|restart|status|try-restart}"<br /> exit 1<br /> ;;<br />esac<br />rc_exit<br /></pre>La activación, iniciado y verificación del estado del servicio es posible mediante los siguientes comandos que se quejan un poco de la vejez del script anterior:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable tgaveta.service</b><br />tgaveta.service is not a native service, redirecting to systemd-sysv-install<br />Executing /usr/lib/systemd/systemd-sysv-install enable tgaveta<br /><b><span style="color: red;">testsrv:~ #</span> systemctl start tgaveta.service<br /><span style="color: red;">testsrv:~ #</span> systemctl status tgaveta.service</b><br /><span style="color: #6aa84f;">●</span> tgaveta.service - LSB: Analizador Tuberia<br /> Loaded: loaded (/etc/init.d/tgaveta; bad; vendor preset: disabled)<br /> Active: <b><span style="color: #6aa84f;">active (running)</span></b> since Thu 2017-04-27 21:33:59 PYT; 1s ago<br /> Docs: man:systemd-sysv-generator(8)<br /> Process: 2320 ExecStart=/etc/init.d/tgaveta start (code=exited, status=0/SUCCESS)<br /> Tasks: 4 (limit: 512)<br /> CGroup: /system.slice/tgaveta.service<br /> ├─2329 /bin/bash /usr/bin/tubgaveta<br /> ├─2333 cat /dev/puerto_gaveta<br /> ├─2334 grep -o --line-buffered &&ABRIRGAVETA&&<br /> └─2335 sed -u s/&&ABRIRGAVETA&&/\x07/g<br /><br />Apr 27 21:33:59 testsrv systemd[1]: Starting LSB: Analizador Tuberia...<br />Apr 27 21:33:59 testsrv tgaveta[2320]: Starting service Analizador Tuberia para Apertura de Gaveta ..done<br />Apr 27 21:33:59 testsrv systemd[1]: Started LSB: Analizador Tuberia.<br /><b><span style="color: red;">testsrv:~ #</span></b><br /></pre>¿Y eso debería ser todo no? pues no, falta lo más importante: ¿Como alimentamos al servicio <b>tubgaveta</b> desde el otro lado de la tubería?<br /><br /></li><li><b>Redirección del flujo de texto de la aplicación remota a la tuberia</b>:<br />Redirigir todo el flujo de texto de nuestro sistema de punto de venta al servicio <b>tubgaveta</b> era el siguiente paso. En este punto el comando <b>tee</b> del cual ya hablamos mas arriba viene a ser el pilar fundamental de la solución, instalable fácilmente de la siguiente manera:<br /><pre><b>cajero@testsrv:~></b> su -<br /><b><span style="color: red;">testsrv:~ #</span> zypper in tee</b><br /></pre>Teniendo el programa <b>tee</b> instalado, solo era necesario crear un acceso directo personalizado para el despliegue de la aplicación <b>Konsole</b>:<br /><pre><b>cajero@testsrv:~></b> touch /home/cajero/Escritorio/posgaveta.desktop<br /><b>cajero@testsrv:~></b> chown cajero:users /home/cajero/Escritorio/posgaveta.desktop<br /><b>cajero@testsrv:~></b> chmod 755 /home/cajero/Escritorio/posgaveta.desktop<br /><b>cajero@testsrv:~></b> vi /home/cajero/Escritorio/posgaveta.desktop<br /></pre>Que como se puede observar en el siguiente código, se le indique en la propiedad <b>Exec</b> que ejecute la aplicación <b>Konsole</b>, pero que a su vez ejecutará un comando <b>sh</b> especificado en comillas simples:<br /><pre><span style="color: #6aa84f;">#!/usr/bin/env xdg-open</span><br />[Desktop Entry]<br />Comment[es]=<br />Comment=<br />Exec=konsole -e sh -c 'ssh mi_servidor | tee -a /dev/puerto_gaveta'<br />GenericName[es]=<br />GenericName=<br />Icon=<br />MimeType=<br />Name[es]=Sistema POS con Apertura Gaveta<br />Name=POS con Apertura Gaveta<br />Path=<br />StartupNotify=true<br />Terminal=false<br />TerminalOptions=<br />Type=Application<br />X-DBUS-ServiceName=<br />X-DBUS-StartupType=<br />X-KDE-SubstituteUID=false<br />X-KDE-Username=<br />X-SuSE-translate=true<br /></pre>El comando <b>'ssh mi_servidor | tee -a /dev/puerto_gaveta'</b> se encarga de establecer una conexión <b>ssh</b> al servidor remoto (mi_servidor), y la salida estándar de dicha conexión que normalmente se mostraría directamente en la pantalla del usuario se vuelve a redirigir al comando <b>tee</b>. <b>Tee</b> muestra el flujo de texto de la conexión <b>ssh</b> en la pantalla del usuario, pero a su vez genera una copia exacta de dicho flujo que lo redirige a la tubería <b>/dev/puerto_gaveta</b>, donde del otro lado estará el servicio <b>tubgaveta</b> escuchando y filtrando todo el texto recibido en búsqueda del patrón que dispare la apertura de la gaveta.<br /><br /></li><li><b>Adaptación del sistema de Punto de Venta (POS) remoto</b>:<br />La aplicación del sistema de punto de ventas fue la que menos cambios requirió, solo el despliegue ofuscado y veloz del patrón de texto que permita al equipo cliente realizar la apertura de gaveta.<br /><br /></li><li><b>Prueba de funcionamiento</b>:<br />Para comprobar el funcionamiento de toda esta solución rebuscada se creó un script en el servidor remoto que desplegaba de forma imperceptible el código patrón, para obligar a la máquina cliente el disparo del comando de apertura de la gaveta. Para crear el script se siguió el siguiente procedimiento:<br /><pre><b>cajero@testsrv:~></b> touch genera_patron_apertura.sh<br /><b>cajero@testsrv:~></b> chmod 755 genera_patron_apertura.sh<br /><b>cajero@testsrv:~></b> vi genera_patron_apertura.sh<br /></pre>Script al que se le agregó el siguiente contenido:<br /><pre><span style="color: #6aa84f;">#!/bin/bash</span><br />echo "Para la ejecucion"<br />read<br />echo "&&ABRIRGAVETA&&"<br />clear<br />echo "Se mostro el patron sin que el operador lo haya visto, se limpio la pantalla y se desplego este mensaje!"<br /></pre>Para comprobar el funcionamiento, desde la máquina cliente se ejecutó el acceso directo <b>posgaveta.desktop</b> previamente configurado para que se conecte automáticamente al servidor remoto. Luego del logueo del usuario solo se tuvo que ejecutar el comando <b>./genera_patron_apertura.sh</b>, lo que mostró el mensaje y disparó el comando de apertura de gaveta como se esperaba, sin que el operador viera en ningún momento el patrón de apertura, que en este ejemplo se definió como <b>&&ABRIRGAVETA&&</b>.<br /><br />Otra forma de probar fue abriendo la terminal <b>Konsole</b> y ejecutando de forma manual los mismos comandos que se pasan como argumentos en el acceso directo:<br /><pre><b>cajero@testsrv:~></b> sh -c 'ssh gabriel@miservidor | tee -a /dev/puerto_gaveta'<br />Password:<br />Last login: Thu Apr 27 23:39:35 2017 from 192.168.1.50<br />Have a lot of fun...<br /><b><span style="color: red;">gabriel@miservidor:~></span> ./genera_patron_apertura.sh</b><br />Para la ejecucion<br />....<br />Se mostro el patron sin que el operador lo haya visto, se limpio la pantalla y se desplego este mensaje!<br /><br /><b><span style="color: red;">gabriel@miservidor:~></span></b><br /></pre>Tengo que confesar que el desempeño de toda esta solución me ha sorprendido gratamente, ha funcionado por buen tiempo hasta que finalmente se desechó luego de la implementación de un nuevo sistema gráfico de punto de ventas. Solamente tuvimos problemas con su funcionamiento cuando se paraba por error el servicio <b>tubgaveta</b> mientras la conexión remota estuviese establecida, o cuando la aplicación remota generaba una cantidad exagerada de flujo de texto que el servicio o el comando <b>tee</b> eran incapaces de procesar.<br /></li></ol>Para finalizar, si ha llegado hasta este punto querido lector y ha comprendido esta historia, o al menos la ha leído, le agradecería que deje un comentario especificando cual fue el motivo que le hizo llegar hasta aquí, si fue alguna necesidad específica tratada en el artículo o simplemente curiosidad (cosa que dudo). Estaré atento!!GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com5tag:blogger.com,1999:blog-1035903216249592564.post-54220188413196497162017-04-11T22:44:00.005-04:002022-10-04T22:47:38.684-03:00Bower, instalación y configuración en Linux<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00054.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://files.tormentadebits.com/covers/portada-00054.png" width="320" height="156" data-original-width="1230" data-original-height="600" /></a></div>Ya hace unos meses que fue la última vez que estuve experimentando con un proyecto web y que en su momento me obligó a tomar algunas notas, en este caso sobre <a href="https://bower.io/" target="_blank"><b>Bower</b></a>.<br /><br /><b>Bower</b> es un manejador de paquetes que permite gestionar toda esta maraña de librerías, frameworks, utilidades, componentes, etc. y sus respectivas versiones (que evolucionan rápida e incompatiblemente a cada segundo) de forma organizada y estructura en nuestros proyectos.<br /><a name='more'></a><br />Básicamente nos permite instalar y gestionar paquetes requeridos por nuestros proyectos web desde su repositorio online, y por supuesto mantener la consistencia de las versiones de los mencionados paquetes en todas nuestras instalaciones que tengamos del mismo proyecto. Si quieren saber más sobre <b>Bower</b>, y su uso en comparación al otro gran gestor de paquetes <b>npm</b>, les recomiendo leer los enlaces que están al final.<br /><br />A continuación pasaremos directamente a la instalación de la herramienta en openSUSE Linux y su configuración inicial para un proyecto.<br /><ol><li>Comenzamos por instalar <b>git</b> y <b>npm</b>, siendo este último uno de los manejadores de paquetes más importantes hoy en día, que se hizo popular con la llegada de <a href="https://es.wikipedia.org/wiki/Node.js" target="_blank"><b>Node.js</b></a>.<br /><pre><b>gabriel@testsrv:~></b> sudo zypper in git npm<br /></pre></li><li>Con <a href="https://es.wikipedia.org/wiki/Npm" target="_blank"><b>npm</b></a> instalado, pasamos a instalar <b>bower</b> con la siguiente directiva:<br /><pre><b>gabriel@testsrv:~></b> sudo npm install bower -g<br /></pre>El parámetro <b>-g</b> permite que el paquete se instale a nivel general del sistema operativo y por ende con alcance para todos sus usuarios. Si no se incluye dicho parámetro, la herramienta solo quedará accesible para el usuario que la instale.<br /><br />Si queremos actualizar nuestra versión de <b>Bower</b> instalada podemos ejecutar la siguiente directiva, nuevamente utilizando el parámetro <b>-g</b>.<br /><pre><b>gabriel@testsrv:~></b> sudo npm update bower -g<br /></pre></li><li>Para comenzar a instalar paquetes mediante <b>Bower</b>, lo primero que debemos realizar es generar el archivo <b>bower.json</b>, que permite detallar información acerca de nuestro proyecto y más adelante gestionar las dependencias de los paquetes que vayamos instalando. En este ejemplo el archivo se va a crear en el directorio de objetos estáticos del proyecto (static/), ejecutando las siguientes directivas y respondiendo a sus consultas:<br /><pre><b>gabriel@testsrv:~></b> cd static/<br /><b>gabriel@testsrv:~../static></b> bower init<br />? name <span style="color: green;"><b>mynewproject</b></span><br />? description <span style="color: green;"><b>Bower repo for MyNewProject.</b></span><br />? main file <span style="color: green;"><b>index.html</b></span><br />? keywords <br />? authors <span style="color: green;"><b>gabrielkfr</b></span><br />? license <span style="color: green;"><b>MIT</b></span><br />? homepage <br />? set currently installed components as dependencies? <span style="color: green;"><b>Yes</b></span><br />? add commonly ignored files to ignore list? <span style="color: green;"><b>Yes</b></span><br />? would you like to mark this package as private which prevents it from being accidentally published to the registry? <span style="color: green;"><b>Yes</b></span><br /><br />{<br /> name: 'mynewproject',<br /> authors: [<br /> 'gabrielkfr'<br /> ],<br /> description: 'Bower repo for MyNewProject.',<br /> main: 'index.html',<br /> license: 'MIT',<br /> homepage: '',<br /> private: true,<br /> ignore: [<br /> '**/.*',<br /> 'node_modules',<br /> 'bower_components',<br /> 'test',<br /> 'tests'<br /> ]<br />}<br /><br />? Looks good? <span style="color: green;"><b>Yes</b></span><br /><b>gabriel@testsrv:~../static></b><br /></pre>Una vez finalizado con el interrogatorio y generado el archivo de configuración <b>bower.json</b>, lo abrimos y verificamos que la configuración sea similar a la sugerida inicialmente:<br /><pre>{<br /> "name": "mynewproject",<br /> "authors": [<br /> "gabrielkfr"<br /> ],<br /> "description": "Bower repo for MyNewProject.",<br /> "main": "index.html",<br /> "license": "MIT",<br /> "homepage": "",<br /> "private": true,<br /> "ignore": [<br /> "**/.*",<br /> "node_modules",<br /> "bower_components",<br /> "test",<br /> "tests"<br /> ]<br />}<br /></pre></li><li>A continuación ya podemos proceder a instalar un paquete como se muestra con el siguiente ejemplo:<br /><pre><b>gabriel@testsrv:~../static></b> bower install clipboard --save<br /></pre>Al no especificar el argumento <b>-g</b> en la directiva anterior, la instalación del paquete <b>clipboard</b> se realiza de forma local, o sea, con alcance limitado al entorno del usuario del sistema operativo que lo instaló.<br /><br />Por su parte el argumento <b>--save</b> lo que hace es agregar o registrar la dependencia (nombre y versión) en el archivo de configuración del proyecto <b>bower.json</b>, que si lo volvemos a revisar podremos observar que al final se agregó el atributo <b>dependencies</b> con el nuevo paquete:<br /><pre>"dependencies": {<br /> "clipboard": "^1.5.16"<br /> }<br /></pre>Donde el carácter <b>^</b> indica que se puede instalar cualquier versión igual o superior (preferentemente superior) a la versión 1.5.16. Si deseamos que una versión específica sea la que se instale en otros servidores de desarrollo o producción y no una mayor disponible, por ejemplo la versión "1.5.16", simplemente tenemos que quitarle el carácter <b>^</b> dejando la entrada de la siguiente manera:<br /><pre>"dependencies": {<br /> "clipboard": "1.5.16"<br /> }<br /></pre>Es importante también mencionar que todos los componentes que vayamos instando con la herramienta, como es el caso del paquete <b>clipboard</b>, serán ubicados dentro de la nueva carpeta contenedora denominada <b>bower_components</b>.<br /></li><li>Para desinstalar un paquete previamente instalado podemos ejecutar el siguiente comando:<br /><pre><b>gabriel@testsrv:~../static></b> bower uninstall clipboard<br />bower uninstall clipboard<br /><b>gabriel@testsrv:~../static></b> <br /></pre></li><li>La lista de paquetes disponibles para su instalación mediante <b>Bower</b> es bastante extensa (jQuery, bootstrap, angular, normalizer-css, etc). Podemos buscar nuestros paquetes de preferencia en el buscador de su sitio web <b><a href="https://bower.io/search/" target="_blank">aquí</a></b>, o bien ejecutando la siguiente directiva en la línea de comandos:<br /><pre><b>gabriel@testsrv:~../static></b> bower search jquery<br />Search results:<br /><br /> jQuery https://github.com/jquery/jquery.git<br /> jquery https://github.com/jquery/jquery-dist.git<br /> jquery.x https://github.com/jljLabs/jquery.x.git<br /> ...<br /> ...<br /> jquery.bem https://github.com/zenwalker/jquery-bem.git<br /><b>gabriel@testsrv:~../static></b> <br /></pre></li><li>Por otro lado, podemos listar todos los paquetes que actualmente tenemos instalado ejecutando en el directorio donde se encuentra el archivo <b>bower.json</b> la siguiente directiva:<br /><pre><b>gabriel@testsrv:~../static></b> bower list<br />bower check-new Checking for new versions of the project dependencies...<br />mynewproject /home/gabriel/mynewproject/static<br />└── clipboard#1.6.1<br /><b>gabriel@testsrv:~../static></b> <br /></pre></li><li>Si deseamos instalar nuestro proyecto en otro servidor simplemente necesitamos tener instalado <b>Bower</b> y el archivo de configuración <b>bower.json</b>, donde a partir de este último podremos instalar las dependencias de nuestro proyecto con sus correspondientes versiones de la siguiente manera:<br /><pre><b>gabriel@testsrv:~../static></b> bower install<br />bower clipboard#^1.5.16 cached https://github.com/zenorocha/clipboard.js.git#1.6.1<br />bower clipboard#^1.5.16 validate 1.6.1 against https://github.com/zenorocha/clipboard.js.git#^1.5.16<br />bower clipboard#^1.5.16 install clipboard#1.6.1<br /><br /><b>gabriel@testsrv:~../static></b> <br /></pre></li></ol>Y hasta aquí llegó mi tiempo, será hasta la próxima entrada, dentro de.. ¿un año?<br /><br /><h3>Fuentes:</h3><ul><li><a href="https://bower.io/" target="_blank"><b>bower.io</b></a><br /></li><li><a href="https://webdesign.tutsplus.com/es/tutorials/the-command-line-for-web-design-taming-3rd-party-packages--cms-23451" target="_blank"><b>webdesign.tutsplus.com/es/tutorials/the-command-line-for-web-design-taming-3rd-party-packages--cms-23451</b></a><br /></li><li><a href="https://zellwk.com/blog/bower/" target="_blank"><b>zellwk.com/blog/bower/</b></a><br /></li><li><a href="https://bower.io/" target="_blank"><b>bower.io</b></a><br /></li><li><a href="http://blog.teamtreehouse.com/getting-started-bower" target="_blank"><b>blog.teamtreehouse.com/getting-started-bower</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-23421832756213630662016-05-31T13:11:00.004-04:002022-10-04T22:46:25.243-03:00Configuración de entornos virtuales en Python 3<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00056.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1230" height="156" src="http://files.tormentadebits.com/covers/portada-00056.png" width="320" /></a></div>Durante mis primeras pruebas con Python en Windows nunca he tenido problemas con la ejecución de proyectos creados con el framework Django.<br /><br />Sin embargo, cuando comencé a realizar pruebas en mi distro openSUSE Linux con el mismo framework he tenido algunos problemas relacionados con las versiones de Python, y que como veremos más adelante se soluciona configurando <b>entornos virtuales de desarrollo</b>.<br /><a name='more'></a><br />El error que me llevó a todo esto se presentó durante la ejecución del siguiente comando:<br /><pre><b>gabriel@testsrv:~/Desarrollo/miproyecto> python manage.py runserver</b><br />Traceback (most recent call last):<br /> File "manage.py", line 8, in <module><br /> from django.core.management import execute_from_command_line<br />ImportError: No module named django.core.management<br /><b>gabriel@testsrv:~/Desarrollo/ciproyecto></b><br /></module></pre>Esto se debió a que en mi distro Linux tenía instalado dos versiones distintas de Python, la versión 2 y la 3. Para saber que versión de Python se ejecuta por defecto podemos ejecutar el siguiente comando:<br /><pre><b>gabriel@testsrv:~> python -V</b><br />Python 2.7.9<br /><b>gabriel@testsrv:~></b><br /></pre>Como vemos la versión que se ejecuta por defecto es la 2.7.9. También podemos verificar si tenemos instalada la versión 3 de Python de la siguiente forma:<br /><pre><b>gabriel@testsrv:~> python3 -V</b><br />Python 3.4.1<br /><b>gabriel@testsrv:~></b><br /></pre>Podríamos pensar que para preparar nuestro entorno de desarrollo deberíamos desinstalar una de las versiones de Python y dejar solo la que nos interesa, pero tenemos que recordar que en nuestra distribución Linux existen otras aplicaciones que dependen de una versión o de la otra para funcionar, así que hacer eso no sería una buena elección.<br /><br />Para solventar este dilema se pueden crear entornos virtuales de programación para Python, los mismos le permiten al desarrollador disponer de un entorno limpio de programación sin que podamos dañar las dependencias de nuestro sistema operativo local. Para aclarar un poco más como viene la mano vamos a crear un entorno virtual para Python 3:<br /><ol><li>Como me gusta tener todo ordenado en el home de mi usuario voy a crear una carpeta llamada <b>.virtualenvs</b> para agrupar en la misma todas las configuraciones de entornos virtuales que deseo emplear para mis proyectos.<br /><pre><b>gabriel@testsrv:~> mkdir .virtualenvs</b><br /></pre></li><li>Luego procedemos a crear un entorno virtual para Python 3 mediante el uso del módulo <b>venv</b> que ya viene preinstalado. En este ejemplo el nombre del entorno virtual es <b>miproyecto</b>:<br /><pre><b>gabriel@testsrv:~> python3 -m venv .virtualenvs/miproyecto</b><br /></pre></li><li>Para activar el entorno virtual podemos utilizar la siguiente directiva:<br /><pre><b>gabriel@testsrv:~> source ~/.virtualenvs/miproyecto/bin/activate<br />(miproyecto) gabriel@testsrv:~></b><br /></pre>O bien la siguiente:<br /><pre><b>gabriel@testsrv:~> . ~/.virtualenvs/miproyecto/bin/activate<br />(miproyecto) gabriel@testsrv:~></b><br /></pre>Para desactivarlo ejecutamos simplemente el comando <b>deactivate</b>:<br /><pre><b>(miproyecto) gabriel@testsrv:~> deactivate<br />gabriel@testsrv:~></b><br /></pre></li><li>Para evitar tener que andar introduciendo toda la ruta cada vez que deseamos activar el entorno podemos crear un alias para simplificar la activación. Para ello necesitamos editar el archivo <b>.bashrc</b> del home:<br /><pre><b>gabriel@testsrv:~> vi .bashrc</b><br /></pre>y al final del script agregar el siguiente <b>alias</b>.<br /><pre><b>alias activatemiproyecto="source ~/.virtualenvs/miproyecto/bin/activate"</b><br /></pre>Para probar el nuevo alias tenemos que reiniciar nuestra consola (cerrar y volver abrir Konsole, Terminal, etc.) o cargar las últimas configuraciones del script <b>.bashrc</b>.<br /><pre><b>gabriel@testsrv:~> source ~/.bashrc</b><br /></pre>Y listo, ya podremos activar el entorno ejecutando el alias creado reciéntemente:<br /><pre><b>gabriel@testsrv:~> activatemiproyecto <br />(miproyecto) gabriel@testsrv:~></b><br /></pre></li><li>Si deseamos que al ejecutar el comando <b>activatemiproyecto</b> ya se ubique en el directorio del proyecto podemos en primer lugar editar el script <b>activate</b> de la configuración del nuevo entorno virtual:<br /><pre><b>gabriel@testsrv:~> vi ~/.virtualenvs/miproyecto/bin/activate</b><br /></pre>Una vez abierto el script nos dirigimos al final y le agregamos una directiva similar a la siguiente que nos ubique en el directorio que deseamos:<br /><pre><b>cd ~/Desarrollo/miproyecto</b><br /></pre>Al volver a probar activar nuestro entorno virtual automáticamente ya se debería ubicar en el directorio que le indicamos:<br /><pre><b>gabriel@testsrv:~> activatemiproyecto<br />(miproyecto) gabriel@testsrv:~/Desarrollo/miproyecto></b><br /></pre></li><li>Si antes de activar el entorno virtual verificamos los paquetes instalados mediante <b>pip list</b>, podremos ver que ya existen unos cuantos instalados en nuestro equipo:<br /><pre><b>gabriel@testsrv:~> pip list</b><br />apparmor (2.10.1)<br />bottle (0.12.8)<br />coverage (3.7.1)<br />cupshelpers (1.0)<br />Django (1.9.6)<br />LibAppArmor (2.10.1)<br />nose (1.3.7)<br />pip (8.1.2)<br />py (1.4.30)<br />pycups (1.9.72)<br />pycurl (7.19.5.1)<br />pygobject (3.16.2)<br />pysmbc (1.0.15.4)<br />requests (2.7.0)<br />setuptools (18.3.2)<br />simplejson (3.8.0)<br /><b>gabriel@testsrv:~></b><br /></pre>Una vez activado el entorno virtual podremos verificar con el mismo comando que la instalación está totalmente limpia, y solo existen los dos paquetes básicos necesarios para comenzar:<br /><pre><b>(miproyecto) gabriel@testsrv:~> pip list</b><br />pip (1.5.6)<br />setuptools (2.1)<br /><b>(miproyecto) gabriel@testsrv:~></b><br /></pre>Ahora solo nos resta instalar los paquetes adicionales que necesitamos para comenzar a trabajar:<br /><pre><b>(miproyecto) gabriel@testsrv:~> pip install django</b><br />Downloading/unpacking django<br /> Downloading Django-1.9.6-py2.py3-none-any.whl (6.6MB): 6.6MB downloaded<br />Installing collected packages: django<br />Successfully installed django<br />Cleaning up...<br /><b>(miproyecto) gabriel@testsrv:~> pip list</b><br />Django (1.9.6)<br />pip (1.5.6)<br />setuptools (2.1)<br /><b>(miproyecto) gabriel@testsrv:~></b><br /></pre></li></ol><br /><h3>Fuentes</h3><ul><li><a href="http://python-para-impacientes.blogspot.com/2015/02/entornos-virtuales-con-python.html" target="_blank"><b>http://python-para-impacientes.blogspot.com/2015/02/entornos-virtuales-con-python.html</b></a><br /></li><li><a href="http://docs.python-guide.org/en/latest/dev/virtualenvs" target="_blank"><b>http://docs.python-guide.org/en/latest/dev/virtualenvs</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com4tag:blogger.com,1999:blog-1035903216249592564.post-45672077420771006952016-05-26T22:16:00.004-04:002022-10-04T22:45:06.148-03:00Paquetes esenciales para desarrollo full stack con Sublime Text 3<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00052.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00052.png" width="320" /></a></div>Configurar el entorno de trabajo del editor de código <b>Sublime Text</b> a nuestras necesidades es fundamental para poder trabajar de forma adecuada y ágil.<br /><br />Es por ello que decidí tomar nota de todas las mejoras que le he realizado al editor hasta el momento para adaptar el entorno lo mejor posible para desarrollar en Python y demás tecnologías web, mejoras que en el futuro probablemente se amplíen según los nuevos requerimientos que se vayan presentando.<br /><a name="more"></a><br /><h3>Instalación del Gestor de Paquetes</h3>Antes que nada tenemos que instalar el gestor de paquetes para Sublime Text 3 (que es la versión de Sublime de mi interés) para poder agregar más adelante los paquetes que me permitan mejorar las funcionalidades de la herramienta.<br /><ol><li>Comenzamos por ejecutar la aplicación Sublime Text 3 y desplegar la <b>Consola</b> que viene integrada en la herramienta mediante el menú <b>View > Show</b> Console.<br /></li><li>Luego copiamos <a href="https://packagecontrol.io/installation#st3" target="_blank"><b>éste código Python</b></a> en la consola y lo ejecutamos. Esto procederá con la instalación del manejador de paquetes de Sublime.<br /></li><li>Y eso es todo, para proceder con la instalación de los paquetes podemos ir al menú <b>Preferences > Package Control</b> o presionar la combinación de teclas <b>Ctrl+Shift+P</b> y elegir la opción <b>Package Control: Install Package</b> que desplegará una lista donde podemos introducir el nombre del paquete que deseamos instalar.<br /></li></ol><br /><h3>Paquetes Recomendados</h3><ul><li><a href="https://packagecontrol.io/packages/AdvancedNewFile" target="_blank"><b>AdvancedNewFile</b></a>: Agrega un método alternativo que nos permite crear archivos de forma más rápida especificando el nombre, su extensión y la ruta en donde debe ir ubicado. Sin embargo es necesario reemplazar el shortcut de teclado Ctrl+N (crear nuevo archivo) para que llame a este complemento, esto lo logramos agregando el siguiente código en el menú <b>Preferences > Key Bindings – User</b> o desde <b>Preferences > Package Settings > AdvancedNewFile > Key Bindings – User</b>:<br /><pre>[<br /> { "keys": ["cmd+n"], "command": "advanced_new_file_new"}<br />]<br /></pre></li><li><a href="https://packagecontrol.io/packages/Anaconda" target="_blank"><b>Anaconda</b></a>: Agrega funcionalidades varias a ST3 para desarrollo de código Python como ser autocompletado, comprobación de código, etc.<br /></li><li><a href="https://packagecontrol.io/packages/Djaneiro" target="_blank"><b>Djaneiro</b></a>: Soporta plantillas de Django y provee code snippets que facilitan el autocompletado de código en Sublime Text.<br /></li><li><a href="https://packagecontrol.io/packages/Emmet" target="_blank"><b>Emmet</b></a>: Permite generar HTML o CSS code snippets mediante métodos abreviados.<br /></li><li><a href="https://packagecontrol.io/packages/GitGutter" target="_blank"><b>GitGutter</b></a>: Pluggin que resalta los cambios realizados al código fuente cuando usamos Git.<br /></li><li><a href="https://packagecontrol.io/packages/Markdown%20Preview" target="_blank"><b>Markdown Preview</b></a>: Permite generar archivos XHTML.<br /></li><li><a href="https://packagecontrol.io/packages/requirementstxt" target="_blank"><b>requirementstxt</b></a>: Provee autocompletado y corrección de sintaxis durante la gestión de los archivos requirements.txt.<br /></li><li><a href="https://packagecontrol.io/packages/SideBarEnhancements" target="_blank"><b>SideBarEnhancements</b></a>: Agrega más opciones al menú de opciones desplegables de la barra lateral izquierda de Carpetas y Archivos.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter" target="_blank"><b>SublimeLinter</b></a>: Es un framework para implementar analizadores interactivos de sintaxis en Sublime Text 3. Los analizadores de sintaxis se instalan por separado según el lenguaje de código que se requiera.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-csslint" target="_blank"><b>SublimeLinter-csslint</b></a>: Analizador sintáctico para código css.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-html-tidy" target="_blank"><b>SublimeLinter-html-tidy</b></a>: Analizador sintáctico para código html.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-jshint" target="_blank"><b>SublimeLinter-jshint</b></a>: Analizador sintáctico para código JavaScript.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-json" target="_blank"><b>SublimeLinter-json</b></a>: Analizador sintáctico para lenguaje Json.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-pep8" target="_blank"><b>SublimeLinter-pep8</b></a>: Analizador sintáctico para código Python basado en las guías de estilo de programación PEP 8.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-pyflakes" target="_blank"><b>SublimeLinter-pyflakes</b></a>: Analizador sintáctico para código Python.<br /></li><li><a href="https://packagecontrol.io/packages/SublimeLinter-pyyaml" target="_blank"><b>SublimeLinter-pyyaml</b></a>: Analizador sintáctico para lenguaje Yaml.<br /></li><li>Theme - Flatland: <br /></li></ul><br /><b>Observaciones:</b><br /><ul><li>Para usar las funcionalidades del paquete <b>Markdown</b> tenemos que presionar Ctrl+Shift+P y escribir Markdown Preview.<br /></li><li>En un archivo .html podemos generar la estructura básica de un archivo html con el pluggin <b>Emmet</b> colocando el carácter "<b>!</b>" y luego presionando la tecla Tab.<br /></li><li>Se recomienda desactivar la caraterística <b>anaconda_linting</b> en <b>Preferences > Settings - User</b> para que no se solape con SublimeLinter:<br /><pre>{<br /> "anaconda_linting": false,<br /> "auto_complete": false,<br /> "color_scheme": "Packages/User/SublimeLinter/Flatland Dark (SL).tmTheme",<br /> "font_size": 12,<br /> "ignored_packages":<br /> [<br /> "Vintage"<br /> ],<br /> "tab_size": 4,<br /> "translate_tabs_to_spaces": true,<br /> "theme": "Flatland Dark.sublime-theme",<br /> "word_wrap": true<br />}<br /></pre></li></ul><br /><br /><h3>Fuentes y Enlaces Útiles:</h3><ul><li><a href="https://realpython.com/blog/python/setting-up-sublime-text-3-for-full-stack-python-development/" target="_blank"><b>Sublime Text 3 for full stack Python development - RealPython</b></a><br /></li><li><a href="http://www.emezeta.com/articulos/guia-sublime-text" target="_blank"><b>Características interesantes de Sublime Text</b></a><br /></li><li><a href="http://sublime-text-unofficial-documentation.readthedocs.io/en/latest/reference/keyboard_shortcuts_win.html" target="_blank"><b>Sublime Text Keyboard Shortcuts for Windows/Linux</b></a><br /></li><li><a href="http://sublime-text-unofficial-documentation.readthedocs.io/en/latest/reference/keyboard_shortcuts_win.html" target="_blank"><b>KSublime Text packagues list</b></a><br /></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-27674484353258224462016-05-25T09:47:00.003-04:002022-10-04T22:43:59.489-03:00Instalación y configuración de MiniDLNA en openSUSE Linux<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00053.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00053.png" width="320" /></a></div>Este manual básico busca documentar brevemente los mínimos pasos necesarios para configurar un servidor de medios en una distro Linux que permita ofrecer nuestros contenidos multimedia a todos los dispositivos "smart" de nuestra red hogareña.<br /><br />En este caso ese servidor de medios elegido es <b>MiniDLNA</b> que permite compartir contenido con dispositivos certificados con los estándares DLNA (Digital Living Network Alliance) mediante el protocolo UPnP (Universal Plug and Play).<br /><a name="more"></a><br />He de reconocer que lo probé solo un poquito para compartir fotografías y videos, y funcionó, así que vamos a comenzar a continuación:<br /><br /><ol><li>Tenemos que instalar el paquete, pero antes tenemos que verificar que tengamos añadido el repositorio packman de la siguiente manera:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper repos</b><br /></pre>Si no aparece en la lista lo tenemos que agregar con un comando similar al que sigue donde repetamos la versión de nuestro sistema operativo, en este caso 13.2:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper ar -f http://ftp.gwdg.de/pub/linux/misc/packman/suse/openSUSE_13.2 packman</b><br /></pre>Y finalmente actualizamos la lista de paquetes de todos los repositorios online de la siguiente manera:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper refresh</b><br /></pre></li><li>Ahora si procedemos con la instalación del paquete minidlna:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper in minidlna</b><br /></pre></li><li>Luego editamos su archivo de configuración:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/minidlna</b><br /></pre>Y verificamos que las siguientes directivas sean similares a las siguientes:<br /><pre><i># Puerto en el que el servicio va a estar disponible, <br /># se recomienda mantener el puerto por defecto 8200.</i><br />port="8200"<br /><br /><i># La directiva network_interface permite especificar en que interfaz de<br /># red estará escuchando el servicio, en este ejemplo solo tengo una (usar<br /># el comando ifconfig para ver las interfaces de red del equipo, pero se<br /># pueden especificar varias mediante su separación por comas (wlp2s0,eth0,eth1)</i><br />network_interface="enp2s0"<br /><br /><i># Se especifica bajo el poder de que usuario correrá el servicio, por defecto<br /># está definido el usuario root y así lo voy a dejar también.</i><br />user="root"<br /><br /><i># Con la directiva media_dir especificamos que directorios del equipo van a<br /># proveer los contenidos multimedias que deseamos servir. Podemos especificar<br /># varios directorios separados por Pipes, y el tipo de contenido de dichos<br /># directorios que se desean compartir como lo indican los siguientes ejemplos.<br /># + "A" for audio (eg. A,/home/jmaggard/Music)<br /># + "V" for video (eg. V,/home/jmaggard/Videos)<br /># + "P" for images (eg. P,/home/jmaggard/Pictures)<br /># + "PV" for pictures and video (eg. AV,/home/jmaggard/digital_camera)<br /># media_dir="A,/home/jmaggard/Music | V,/home/jmaggard/Videos | P,/home/jmaggard/Pictures"</i><br />media_dir="PV,/home/gabriel/Media"<br /><br /><i># Le damos un nombre amigable a nuestro servidor de medios:</i><br />friendly_name="My MiniDLNA Server"<br /><br /><i># Con la directiva album_art_names podemos especificar todos los nombres de<br /># archivos que el servidor de medios puede tomar en cuenta para sacar información<br /># acerca de los artistas, películas, etc:</i><br />album_art_names="Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg"<br /><br /><i># La siguiente directiva permite configurar el intérvalo de tiempo en que el<br /># servidor de medios informa a los clientes de la red sobre su estado. La <br /># configuración que sugiero es la de 300 segundos, o sea, 5 minutos.</i><br />notify_interval="300"<br /><br /><i># Le asignamos el valor yes a la directiva rescan para que durante el inicio<br /># del servicio actualice su base de datos de contenidos.</i><br />rescan="yes"<br /></pre>Y eso fue todo lo que necesitamos verificar en el archivo de configuración, guardamos los cambios y salimos para continuar.<br /><br /></li><li>A continuación habilitamos el puerto del servicio MiniDLNA en el Firewall de openSUSE, para ello editamos el archivo de configuración:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/SuSEfirewall2</b><br /></pre>Y buscamos la siguiente directiva a la que le agregamos el puerto 8200, si se encuentra otro puerto añadido previamente podemos agregar el nuevo puerto al final dejando un espacio entre uno y otro.<br /><pre>FW_SERVICES_EXT_TCP="3128 <b>8200</b>"<br /></pre>Luego salimos del archivo y reiniciamos el Firewall de openSUSE de la siguiente manera:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart SuSEfirewall2.service</b><br /></pre></li><li>Finalmente procedemos a habilitar el servicio para que inicie durante el arranque del sistema operativo, ponerlo en ejecución y verificar que esté corriendo:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable minidlna.service<br /><span style="color: red;">testsrv:~ #</span> systemctl start minidlna.service<br /><span style="color: red;">testsrv:~ #</span> systemctl status minidlna.service</b><br /></pre></li><li>Podemos verificar el archivo log del servicio MiniDLNA con el siguiente comando:<br /><pre><b><span style="color: red;">testsrv:~ #</span> tail -f /var/log/minidlna/minidlna.log</b><br /></pre>También podemos comprobar el estado del servicio desde un navegador web introduciendo una URL similar a la siguiente:<br /><pre><a href="http://ip_del_servidor:8200" target="_blank"><b>http://ip_del_servidor:8200</b></a><br /></pre></li><li>Si agregamos nuevo contenido multimedia a nuestro directorio (en mi caso /home/gabriel/Media) tendremos que reiniciar el servicio de MiniDLNA para que haga un scan del directorio y actualice su base de datos.<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl restart minidlna.service</b><br /></pre>También podemos comprobar el estado del servicio desde un navegador web introduciendo una URL similar a la siguiente:<br /><pre><a href="http://ip_del_servidor:8200" target="_blank"><b>http://ip_del_servidor:8200</b></a><br /></pre></li></ol>Y eso es todo, solo resta disfrutar de nuestros contenidos favoritos.GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com2tag:blogger.com,1999:blog-1035903216249592564.post-9381192786663386672016-05-16T22:11:00.004-04:002022-10-04T22:42:38.473-03:00Instalación de Sublime Text 3 en openSUSE Linux<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00052.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00052.png" width="320" /></a></div>La idea de este artículo es simplemente documentar la instalación de uno de los mejores editores de código existes que agradada por su simplicidad y ligereza: Sublime Text.<br /><br />En este caso la versión que se va a instalar en esta guía es la 3, y como no existe un paquete .rpm oficial por ahí vamos a tener que improvisar un poquito. Como ya es costumbre del blog los pasos siguen a continuación:<br /><a name="more"></a><br /><ol><li>Primero nos dirigimos al sitio web de Sublime Text con nuestro navegador preferido y descargamos la última versión, pero tenemos que elegir la opción <b>tarball</b> ya que como dije no existe la versión empaquetada en .rpm.<br /><pre><a href="https://www.sublimetext.com/3" target="_blank"><b>https://www.sublimetext.com/3</b></a><br /></pre></li><li>En el directorio Descargas de nuestro home descomprimimos el paquete directamente al directorio <b>/opt</b> con el usuario <b>root</b> de la siguiente manera.<br /><pre><b>gabriel@testsrv:~> sudo tar -xvjf Descargas/sublime_text_3_build_3114_x64.tar.bz2 -C /opt</b><br /></pre></li><li>Luego creamos un enlace simbólico al directorio <b>/usr/bin/subl</b> para que lo podamos llamar desde la consola directamente.<br /><pre><b>gabriel@testsrv:~> sudo ln -s /opt/sublime_text_3/sublime_text /usr/bin/subl</b><br /></pre></li><li>Editamos el archivo <b>sublime_text.desktop</b>:<br /><pre><b>gabriel@testsrv:~> sudo vi /opt/sublime_text_3/sublime_text.desktop</b><br /></pre>Y le modificamos las directivas <b>Name</b> y <b>Exec</b> dejándolo como sigue:<br /><pre><b>[Desktop Entry]<br />Version=1.0<br />Type=Application<br /><span style="background-color: #fff2cc;">Name=Sublime Text 3</span><br />GenericName=Text Editor<br />Comment=Sophisticated text editor for code, markup and prose<br /><span style="background-color: #fff2cc;">Exec=sublime_text %F</span><br />Terminal=false<br />MimeType=text/plain;<br />Icon=sublime-text<br />Categories=TextEditor;Development;<br />StartupNotify=true<br />Actions=Window;Document;<br /><br />[Desktop Action Window]<br />Name=New Window<br /><span style="background-color: #fff2cc;">Exec=sublime_text -n</span><br />OnlyShowIn=Unity;<br /><br />[Desktop Action Document]<br />Name=New File<br /><span style="background-color: #fff2cc;">Exec=sublime_text --command new_file</span><br />OnlyShowIn=Unity;</b><br /></pre>Al quitarle la ruta de la aplicación en la directiva <b>Exec</b> vamos a obligar al icono de escritorio a usar el acceso mediante el enlace simbólico creado en la carpeta <b>/usr/bin</b>, que ya tiene todos los permisos de ejecución para cualquier usuario del sistema operativo.<br /><br /></li><li>Y por último copiamos el archivo <b>sublime_text.desktop</b> al directorio <b>/usr/share/applications</b>.<br /><pre><b>gabriel@testsrv:~> sudo cp /opt/sublime_text_3/sublime_text.desktop /usr/share/applications/</b><br /></pre></li></ol><div>Y eso es todo, hasta para instalar uno de los editores de desarrollo más populares hay que dar mil vueltas en algunas distribuciones.</div><br /><pre></pre>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-49822294004781659592016-03-11T01:05:00.004-03:002022-10-04T22:41:29.112-03:00Control de ancho de banda con Linux Traffic Control (tc)<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00051.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00051.png" width="320" /></a></div>Este artículo tratará acerca de <b>Linux Traffic Control</b>, la herramienta que nos ofrece el kernel de Linux para controlar el uso del ancho de banda cuando usamos este sistema operativo como puerta de enlace para la navegación a Internet, como equipo de ruteo entre diferentes redes corporativas, etc.<br /><br />Sea como sea, en mi caso lo llegué a utilizar en conjunto con el servicio Squid (sobre el que escribí hace poco <a href="2016/03/configuracion-basica-squid-opensuse-linux.html" target="_blank"><b>aquí</b></a>), donde aparte de dar servicio de caché de navegación el servidor se encargaba de controlar el ancho de banda de los usuarios. Su implementación como siempre es muy sencilla como lo veremos a continuación.<br /><a name="more"></a><br />Las directivas de la herramienta <b>Linux Traffic Control</b> se realizan mediante el comando <b>tc</b>, que se encuentra disponible en el paquete <b>iproute2</b>, en openSUSE específicamente se llama <b>xiproute2</b> (xLinux network configuration utilities) y se instala por defecto durante la instalación del sistema operativo, solo resta utilizarlo según los siguientes pasos.<br /><ol><li>Comenzamos por crear un script bash que se encargará de implementar las directivas de control de ancho de banda en el kernel de Linux. Con los siguientes comandos que deben ser ejecutados con el usuario root creamos el archivo <b>tclimitar</b>, le asignamos permisos de ejecución y lo editamos...<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /bin/tclimitar<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /bin/tclimitar<br /><span style="color: red;">testsrv:~ #</span> vi /bin/tclimitar</b><br /></pre></li><li>Si queremos controlar solamente la velocidad de bajada podemos utilizar una configuración similar a la que sigue:<br /><pre><i>#!/bin/bash<br /><br /># Sección 1: Seccion para definicion de variables y limites de ancho de banda<br /># mediante comando tc:<br /><br /># Definicion de variables:</i><br />INTERFACE="enp2s0"<br />IN="tc filter add dev $INTERFACE parent 1:0 protocol ip prio 1 u32 match ip dst "<br />PUERTO="match ip sport "<br />REGLA="0xffff flowid"<br /><br /><i># Definicion de limites de ancho de banda:</i><br />tc qdisc del dev $INTERFACE root<br />tc qdisc add dev $INTERFACE root handle 1: htb default 10<br />tc class add dev $INTERFACE parent 1: classid 1:1 htb rate 1024kbit<br />tc class add dev $INTERFACE parent 1:1 classid 1:10 htb rate 1024kbit<br />tc class add dev $INTERFACE parent 1:1 classid 1:20 htb rate 2048kbit<br />tc class add dev $INTERFACE parent 1:1 classid 1:30 htb rate 3072kbit<br />tc class add dev $INTERFACE parent 1:1 classid 1:40 htb rate 4096kbit<br />tc qdisc add dev $INTERFACE parent 1:10 handle 10: sfq perturb 10<br />tc qdisc add dev $INTERFACE parent 1:20 handle 20: sfq perturb 10<br />tc qdisc add dev $INTERFACE parent 1:30 handle 30: sfq perturb 10<br />tc qdisc add dev $INTERFACE parent 1:40 handle 40: sfq perturb 10<br /><br /><i># Sección 2: Sección de habilitación de dispositivos o redes (respetar orden):<br /># Limite individual por equipo (mayor prioridad):</i><br />$IN 192.168.1.20/32 $PUERTO 3128 $REGLA 1:30<br />$IN 192.168.1.50/32 $PUERTO 3128 $REGLA 1:40<br /><br /><i># Limite por defecto para todos los equipos de la red (menor prioridad):</i><br />$IN 192.168.1.0/24 $PUERTO 3128 $REGLA 1:20<br /><br /><i># Mensaje de finalizacion en la aplicacion de reglas:</i><br />echo<br />echo "Se han aplicado exitosamente las reglas de control de ancho de banda!"<br />echo<br /></pre>A continuación van algunas observaciones que considero de importancia aclarar con respecto al script anterior:<br /><ul><li>El contenido anterior se separa en dos secciones, la primera donde se encuentran predefinidas las variables y las reglas de control de ancho de banda que se suelen editar en pocas ocasiones; y la segunda sección (la que más se va a modificar) donde se aplican las reglas de control de ancho de banda definidas en la primera sección a los equipos o redes que deseamos controlar.<br /></li><li>El fragmento "<b>default 10</b>" de la directiva "<b>tc qdisc add dev $INTERFACE root handle 1: htb default 10</b>" indica que por defecto todo el tráfico de bajado y subida estará limitado a la regla 1:10, o lo que es lo mismo, a un límite de 1024 kbit/s.<br /></li><li>Esta versión del script no controla el tráfico entrante, la velocidad de subida máxima estará limitada por el límite de descarga asignado por defecto, al equipo o a la red, es decir si se aplica la regla 1:10 a 1024 kbit, si es 1:20 a 2048.<br /></li><li>Para limitar todo tipo de tráfico que se dirige al equipo con IP 192.168.1.50 a 2048 kbps (regla 1:20) tenemos que especificar la directiva de la siguiente forma:<br /><pre><b>$IN 192.168.1.50/32 flowid 1:20</b><br /></pre>Si queremos limitar el tráfico correspondiente al puerto 3128 del servicio <b>Squid</b> la directiva debería ser la siguiente:<br /><pre><b>$IN 192.168.1.50/32 $PUERTO 3128 $REGLA 1:20</b><br /></pre>También podemos aplicar reglas similares a las anteriores pero a redes de la siguiente forma:<br /><pre><b>$IN 192.168.1.0/24 $PUERTO 3128 $REGLA 1:20</b><br /></pre></li><li>Al establecer los límites siempre tenemos que colocar en orden primero las de carácter más específicas y luego las menos específicas. En el script primero se definen reglas para una dirección IP (específico) y luego para la red (general) a la cual corresponde esa misma dirección IP.<br /></li><li>Hay que reemplazar el valor de la variable <b>INTERFACE</b> por la unidad de red que corresponda, en mi openSUSE 13.2 de prueba el nombre de la interfaz era <b>enp2s0</b>.<br /><br /></li></ul>Sin embargo, si deseamos poder especificar un <b>límite de subida</b> inferior a un <b>límite de descarga</b> para una misma dirección IP o red ya no basta con el ejemplo anterior, la configuración que permite realizar eso es la siguiente:<br /><pre><i>#!/bin/bash<br /><br /># ======================================================================================<br /># Sección 1: Seccion para definicion de variables y limites de ancho de banda<br /># mediante comando tc:<br /># ======================================================================================<br /># Definicion de variables:</i><br />INTERFACE_IN="enp2s0"<br />INTERFACE_OUT="ifb0"<br />IN="tc filter add dev $INTERFACE_IN parent 1:0 protocol ip prio 1 u32 match ip dst "<br />OUT="tc filter add dev $INTERFACE_OUT parent 1:0 protocol ip prio 1 u32 match ip src "<br />PUERTO="match ip sport "<br />REGLA="0xffff flowid"<br /><br /><i># Cargar y habilitar interfaces virtuales para ccontrol de uploads. Luego redirigir<br /># el trafico entrante de la intefaz fisica a la interfaz virtual.</i><br />modprobe ifb numifbs=1<br />ip link set dev $INTERFACE_OUT up<br />tc qdisc del dev $INTERFACE_IN root 2>/dev/null<br />tc qdisc del dev $INTERFACE_IN ingress 2>/dev/null<br />tc qdisc del dev $INTERFACE_OUT root 2>/dev/null<br />tc qdisc add dev $INTERFACE_IN handle ffff: ingress<br />tc filter add dev $INTERFACE_IN parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $INTERFACE_OUT<br /><br /><i># Definicion de limites de ancho de banda para download:</i><br />tc qdisc add dev $INTERFACE_IN root handle 1: htb<br />tc class add dev $INTERFACE_IN parent 1: classid 1:1 htb rate 1mbit<br />tc class add dev $INTERFACE_IN parent 1:1 classid 1:10 htb rate 1mbit<br />tc class add dev $INTERFACE_IN parent 1:1 classid 1:20 htb rate 2mbit<br />tc class add dev $INTERFACE_IN parent 1:1 classid 1:30 htb rate 3mbit<br />tc class add dev $INTERFACE_IN parent 1:1 classid 1:40 htb rate 4mbit<br />tc qdisc add dev $INTERFACE_IN parent 1:10 handle 10: sfq perturb 10<br />tc qdisc add dev $INTERFACE_IN parent 1:20 handle 20: sfq perturb 10<br />tc qdisc add dev $INTERFACE_IN parent 1:30 handle 30: sfq perturb 10<br />tc qdisc add dev $INTERFACE_IN parent 1:40 handle 40: sfq perturb 10<br /><br /><i># Definicion de limites de ancho de banda para upload:</i><br />tc qdisc add dev $INTERFACE_OUT root handle 1: htb<br />tc class add dev $INTERFACE_OUT parent 1: classid 1:1 htb rate 1024kbit<br />tc class add dev $INTERFACE_OUT parent 1:1 classid 1:10 htb rate 1024kbit<br />tc class add dev $INTERFACE_OUT parent 1:1 classid 1:20 htb rate 2048kbit<br />tc class add dev $INTERFACE_OUT parent 1:1 classid 1:30 htb rate 3072kbit<br />tc class add dev $INTERFACE_OUT parent 1:1 classid 1:40 htb rate 4096kbit<br />tc qdisc add dev $INTERFACE_OUT parent 1:10 handle 10: sfq perturb 10<br />tc qdisc add dev $INTERFACE_OUT parent 1:20 handle 20: sfq perturb 10<br />tc qdisc add dev $INTERFACE_OUT parent 1:30 handle 30: sfq perturb 10<br />tc qdisc add dev $INTERFACE_OUT parent 1:40 handle 40: sfq perturb 10<br /><br /><i># ======================================================================================<br /># Sección 2: Sección de habilitación de dispositivos o redes (respetar orden):<br /># ======================================================================================<br /># Limite individual por equipo (mayor prioridad):</i><br />$IN 192.168.1.90/32 $PUERTO 3128 $REGLA 1:40<br />$OUT 192.168.1.90/32 flowid 1:40<br /><br /><i># Limite por defecto para todos los equipos de la red (menor prioridad):</i><br />$IN 192.168.1.0/24 $PUERTO 3128 $REGLA 1:20<br />$OUT 192.168.1.0/24 flowid 1:10<br /><br /><i># Mensaje de finalizacion en la aplicacion de reglas:</i><br />echo<br />echo "Se han aplicado exitosamente las reglas de control de ancho de banda!"<br />echo<br /></pre>Como se puede observar este script tiene varias diferencias en comparación al anterior, las mismas se detallan a continuación:<br /><ul><li>En este script se opta por utilizar una interfaz virtual <b>ifb0</b> a la cual se le redirige el tráfico entrante de la interfaz física, a fin de que se puedan aplicar los mismos tipos de filtros al tráfico entrante como al saliente.<br /></li><li>Al redirigir el tráfico entrante de la interfaz física a la interfaz virtual ifb0 estamos logrando que las direcciones IP o redes que son filtradas como destino (dst) para el tráfico entrante puedan ser identificadas como origen (src) cuando el tráfico es saliente.<br /></li><li>Se definen filtros y límites por separados para la interfaz física y la virtual ifb0.<br /></li><li>El límite <b>1mbit</b> equivale a <b>1024kbit</b>.<br /></li><li>Para limitar la velocidad de descarga se tiene que anteponer la variables <b>$IN</b> y <b>$OUT</b> para limitar la velocidad de subida.<br /></li><li>Al limitar la velocidad de subida especificando la variable <b>$OUT</b> solo se puede utilizar la regla <b>flowid</b>, ya que la máquina de origen dueña de los paquetes actuará como cliente y utilizará puertos tcp/ip altos (Puertos dinámicos o privados) de forma dinámica para la conexión.<br /></li><li>No se especifica el fragmento "<b>default 10</b>" en las directivas "<b>tc qdisc add dev $INTERFACE_IN root handle 1: htb</b>" y "<b>tc qdisc add dev $INTERFACE_OUT root handle 1: htb</b>" para evitar problemas con la especificación de límites por defecto. Sin embargo esto nos obliga a especificar un límite por defecto a las redes que estarán utilizando del servicio, de lo contrario tendrán navegación con velocidad ilimitada.<br /><br /></li></ul></li><li>Continuemos. Para liberar los controles de ancho de banda tenemos que crear un script que se encargue de dicha tarea:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /bin/tcliberar<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /bin/tcliberar<br /><span style="color: red;">testsrv:~ #</span> vi /bin/tcliberar</b><br /></pre>Editado el archivo le agregamos el siguiente contenido:<br /><pre><i>#!/bin/bash<br /><br /># Definicion de variables:</i><br />INTERFACE_IN="enp2s0"<br />INTERFACE_OUT="ifb0"<br /><br /><i># Liberacion de filtros:</i><br />tc qdisc del dev $INTERFACE_IN root 2>/dev/null<br />tc qdisc del dev $INTERFACE_IN ingress 2>/dev/null<br />tc qdisc del dev $INTERFACE_OUT root 2>/dev/null<br /><br /><i># Mensaje de culminacion:</i><br />echo<br />echo Navegacion liberada.<br />echo<br /></pre></li><li>Por otro lado, para facilitar la modificación de reglas y el registro de nuevas directivas de limitación a equipos/redes, y posterior implementación automática de las reglas podemos crear otro script que se encargue de ello como se muestra a continuación:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /bin/tcmodificar<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /bin/tcmodificar<br /><span style="color: red;">testsrv:~ #</span> vi /bin/tcmodificar</b><br /></pre>Al archivo se le agrega el siguiente contenido que simplemente edita el archivo con Vim y luego lo ejecuta para aplicar los cambios realizados previamente.<br /><pre><i>#!/bin/bash</i><br />vim /bin/tclimitar<br />/bin/tclimitar</pre></li><li>Finalmente ejecutamos el siguiente comando para que durante el arranque del sistema operativo automáticamente se carguen las directivas de control de ancho de banda:<br /><pre><b><span style="color: red;">testsrv:~ #</span> echo "/bin/tclimitar" >> /etc/init.d/boot.local</b><br /></pre>Y eso es todo, fácil, apenas me llevó más de tres noches (madrugadas incluidas) hacer las pruebas para verificar que me funcione más o menos bien, sin entrar en detalle en nada..<br /></li></ol><br /><h3>Fuentes</h3><ul><li><a href="ttp://tldp.org/HOWTO/Traffic-Control-HOWTO/intro.html" target="_blank">ttp://tldp.org/HOWTO/Traffic-Control-HOWTO/intro.html</a></li><li><a href="https://en.wikipedia.org/wiki/Tc_(Linux)" target="_blank">https://en.wikipedia.org/wiki/Tc_(Linux)</a></li><li><a href="http://serverfault.com/questions/350023/tc-ingress-policing-and-ifb-mirroring" target="_blank">http://serverfault.com/questions/350023/tc-ingress-policing-and-ifb-mirroring</a></li><li><a href="https://wiki.gentoo.org/wiki/Traffic_shaping" target="_blank">https://wiki.gentoo.org/wiki/Traffic_shaping</a></li><li><a href="http://superuser.com/questions/583484/traffic-shaping-linux-upload-issue" target="_blank">http://superuser.com/questions/583484/traffic-shaping-linux-upload-issue</a></li></ul>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com5tag:blogger.com,1999:blog-1035903216249592564.post-12729669772695417982016-03-04T23:06:00.005-03:002022-10-04T22:40:13.387-03:00Configuración básica de Squid en openSUSE Linux<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00049.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00049.png" width="320" /></a></div>Hace tiempo que tengo guardado los pasos para configurar un servidor de proxy Squid, de forma básica, muy básica y poco segura pero que cumple con su función, y que estos días decidí probarlo nuevamente en un equipo con openSUSE 13.2 para ver si sigue funcionando en las nuevas versiones de Squid.<br /><br />Configurar correctamente un servidor proxy lleva tiempo y dedicación, por mi parte no recomiendo esta configuración para un entorno de producción, pero si alguien está interesado en probar o experimentar con dicho servicio pueden seguir leyendo este artículo que lo terminé de escribír para evitar la pérdida del poco <b>know how</b> que tengo acerca del tema.<br /><a name="more"></a><br /><h3>Pasos de instalación y configuración</h3><ol><li>Primero comenzamos por instalar el paquete <b>squid</b>, eso lo hacemos ejecutando el siguiente comando con el usuario <b>root</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> zypper in squid</b><br /></pre></li><li>Luego editamos el archivo de configuración con nuestro editor favorito, en mi caso el <b>Vim</b> como siempre..<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/squid/squid.conf</b><br /></pre></li><li>En mi caso se configuraron en el archivo las siguientes directivas:<br /><pre><i>###<br />### -->Configuracion de Importancia</i><br />auth_param basic children 5<br />auth_param basic realm Squid proxy-caching web server<br />auth_param basic credentialsttl 2 hours<br /><br /><i>### -->Configuracion de Importancia</i><br />acl to_localhost dst 127.0.0.0/8<br />acl words url_regex "/etc/squid/palabras_denegadas"<br />acl hosts src "/etc/squid/hosts_habilitados"<br /><br /><i>###acl localnet src 10.0.0.0/8 # RFC1918 possible internal network<br />###acl localnet src 172.16.0.0/12 # RFC1918 possible internal network<br />###acl localnet src 192.168.0.0/16 # RFC1918 possible internal network<br />###acl localnet src fc00::/7 # RFC 4193 local private network range<br />###acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines<br />###acl networks src 192.168.10.0/24 192.168.100.0/24</i><br /><br />acl SSL_ports port 443<br />acl Safe_ports port 80 # http<br />acl Safe_ports port 21 # ftp<br />acl Safe_ports port 443 # https<br />acl Safe_ports port 70 # gopher<br />acl Safe_ports port 210 # wais<br />acl Safe_ports port 1025-65535 # unregistered ports<br />acl Safe_ports port 280 # http-mgmt<br />acl Safe_ports port 488 # gss-http<br />acl Safe_ports port 591 # filemaker<br />acl Safe_ports port 777 # multiling http<br />acl CONNECT method CONNECT<br /><br /><i>#<br /># INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS<br />#<br /><br />### -->Configuracion de Importancia</i><br />http_access deny words<br />http_access allow hosts<br /><i>###http_access allow networks</i><br /><br /><i># And finally deny all other access to this proxy</i><br />http_access deny all<br /><br /><i># TAG: http_reply_access<br /># Allow replies to client requests. This is complementary to http_access.<br />#<br /># http_reply_access allow|deny [!] aclname ...<br />#<br /># NOTE: if there are no access lines present, the default is to allow<br /># all replies<br />#<br /># If none of the access lines cause a match the opposite of the<br /># last line will apply. Thus it is good practice to end the rules<br /># with an "allow all" or "deny all" entry.<br />#<br />#Default:<br /># none<br /><br /><i>###<br />### -->Directorio de Cache</i><br />cache_dir ufs /var/cache/squid 2048 16 256<br /><br />###<br />### -->Configuracion de Importancia</i><br />http_reply_access allow all<br /><br /><i>###<br />### -->Configuracion de Importancia</i><br />icp_access allow all<br /><br /><i>###<br />### -->Configuracion de Importancia</i><br />cache_mem 2048 MB<br /><br /><i>###<br />### -->Tamanio maximo de objetos</i><br />maximum_object_size 25600 KB<br /><br /><i>###<br />### --> Configuracion adicional</i><br />emulate_httpd_log off<br /></pre>Si bien podemos definir de forma explícita en el archivo de configuración squid.conf los equipos y las redes autorizadas a utilizar el servicio, en este caso se opta por registrarlos en un archivo externo así como también las palabras excluidas con las directivas <b>acl hosts src</b> y <b>acl words url_regex</b> respectivamente.<br /><br /></li><li>Ahora pasamos a crear el archivo en el cual especificaremos las direcciones IP de los equipos o de las redes autorizadas a utilizar el proxy. Creamos el archivo en el directorio correspondiente y lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/squid/hosts_habilitados<br /><span style="color: red;">testsrv:~ #</span> vi /etc/squid/hosts_habilitados</b><br /></pre>Y le agregamos contenido similar al que sigue para otorgar las autorizaciones:<br /><pre><i>#!/bin/bash<br /># Terminales y redes habilitadas para la navegacion en el sistema<br /># ===============================================================</i><br />192.168.1.10/255.255.255.255<br />192.168.2.0/255.255.255.0<br /></pre></li><li>Para facilitar la tarea de mantenimiento de los equipos y las redes autorizadas se crea a continuación un script bash que edita el archivo y posteriormente reinicia el servicio para que tome en cuenta las nuevas configuraciones:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /bin/squidhosts<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /bin/squidhosts<br /><span style="color: red;">testsrv:~ #</span> vi /bin/squidhosts</b><br /></pre>El archivo debe contener el siguiente código:<br /><pre><i>#!/bin/bash</i><br />vim /etc/squid/hosts_habilitados<br />clear<br />/usr/bin/systemctl restart squid.service<br />echo<br />echo Configuracion aplicada y servicio reiniciado exitosamente!<br />echo<br /></pre></li><li>Pasamos a crear el archivo en el cual vamos a especificar las palabras que queremos denegar a partir de las url's a las que tratan de acceder los usuarios. Como siempre editamos el archivo y luego lo editamos:<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /etc/squid/palabras_denegadas<br /><span style="color: red;">testsrv:~ #</span> vi /etc/squid/palabras_denegadas</b><br /></pre>Y le especificamos nuestra lista de palabras denegadas.<br /><pre><i>#!/bin/bash</i><br />xxx<br />blabla<br />bleble<br /></pre></li><li>Al igual como hicimos para modificar los equipos y las redes autorizadas, también creamos un script para facilitar la edición de la lista de palabras denegadas..<br /><pre><b><span style="color: red;">testsrv:~ #</span> touch /bin/squidwords<br /><span style="color: red;">testsrv:~ #</span> chmod 755 /bin/squidwords<br /><span style="color: red;">testsrv:~ #</span> vi /bin/squidwords</b><br /></pre>Al archivo <b>squidwords</b> le agregamos el siguiente código:<br /><pre><i>#!/bin/bash</i><br />vim /etc/squid/palabras_denegadas<br />clear<br />/usr/bin/systemctl restart squid.service<br /><br />echo<br />echo Configuracion aplicada y servicio reiniciado exitosamente!<br />echo<br /></pre></li><li>Nos falta habilitar el servicio en el firewall de openSUSE. Para ello editamos el archivo <b>SuSEfirewall2</b> ubicado en el directorio <b>/etc/sysconfig</b> con el usuario root:<br /><pre><b><span style="color: red;">testsrv:~ #</span> vi /etc/sysconfig/SuSEfirewall2</b><br /></pre>Buscamos la directiva <b>FW_SERVICES_EXT_TCP</b> que es normalmente la zona de firewall a la cual se encuentra asociada por defecto la interfaz de red y le agregamos el puerto <b>3128</b> correspondiente al servicio <b>squid</b>:<br /><pre><b>FW_SERVICES_EXT_TCP="<span style="color: red;">3128</span>"</b><br /></pre>Guardamos los cambios del archivo y reiniciamos el firewall:<br /><pre><b><span style="color: red;">testsrv:~ #</span> rcSuSEfirewall2 restart</b><br /></pre></li><li>Por último habilitamos el servicio squid y lo arrancamos por primera vez de la siguiente manera:<br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl enable squid.service<br /><span style="color: red;">testsrv:~ #</span> systemctl start squid.service</b><br /></pre>Por supuesto, podemos verificar que el servicio esté corriendo correctamente <br /><pre><b><span style="color: red;">testsrv:~ #</span> systemctl status squid.service</b><br /></pre></li><li>Para acceder al servicio desde otro equipo dentro de nuestra red tenemos que configurar el apartado Proxy del navegador especificando la dirección IP de nuestro servidor Proxy y el puerto del servicio 3128.<br /><br />Si necesitamos autorizar a un nuevo equipo o red para que puedan utilizar el proxy podemos ejecutar el script <b>squidhosts</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> squidhosts</b><br /></pre>O el script <b>squidwords</b> para agregar nuevas palabras a la lista de palabras denegadas de squid:<br /><pre><b><span style="color: red;">testsrv:~ #</span> squidwords</b><br /></pre>Tampoco tenemos que olvidar de revisar uno de los archivos logs más importantes de squid: access.log.<br /><pre><b><span style="color: red;">testsrv:~ #</span> tail -f /var/log/squid/access.log</b><br /></pre></li></ol><br /><h3>Fuentes:</h3><ol><li><a href="http://wiki.squid-cache.org/SquidFaq/ConfiguringSquid" target="_blank">http://wiki.squid-cache.org/SquidFaq/ConfiguringSquid</a></li><li><a href="http://www.squid-cache.org/" target="_blank">http://www.squid-cache.org/</a></li></ol>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-87268633643717597532016-02-03T23:05:00.004-03:002022-10-04T22:37:06.218-03:00Generar sentencias SQL con Oracle sqlplus desde un script bash<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00050.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00050.png" width="320" /></a></div>Que mejor que volver al blog con una entrada livianita, luego de tanto tiempo sin escribir no hay nada mejor que comenzar por algo poco exigente, así no salgo huyendo de aquí para volver a aparecer luego de seis meses.<br /><br />El artículo de hoy trata acerca de como hacer un script bash que se conecte a nuestra base de datos Oracle, ejecute unas sentencias SQL cuya salida sean sentencias SQL en si mismas, y que dichas salidas se escriban directamente en un archivo de texto plano.<br /><a name="more"></a><br /><ol><li>Básicamente lo que tenemos que hacer es crear un archivo de texto plano, asignarle permisos de ejecución y luego editarlo:<br /><pre><b><span style="color: red;">usuario@testsrv:~></span> touch generar_sentencias_sql.sh<br /><span style="color: red;">usuario@testsrv:~></span> chmod 755 generar_sentencias_sql.sh<br /><span style="color: red;">usuario@testsrv:~></span> vi generar_sentencias_sql.sh</b><br /></pre></li><li>Una vez abierto agregarle un contenido similar al que sigue:<br /><pre><i>#!/bin/bash<br /><br /># Script para generacion de sentencias SQL de creacion automatica de <br /># usuarios del motor de base de datos a partir del contenido de una tabla.</i><br />USERS_FILE=/tmp/usuarios.sql<br /><br /><i># Se exportan variables de entorno para Oracle 11G.</i><br />export ORACLE_SID=orcl<br />export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1<br /><br /><i># Se llama a la herramienta sqlplus y se ejecuta la sentencia SQL especificada.</i><br />$ORACLE_HOME/bin/sqlplus -S "mi_usuario/mi_contrasenia@orcl" << EOF > $USERS_FILE<br />set linesize 500<br />set pages 0<br />set heading off<br />set feed off<br />SELECT ('INSERT INTO USUARIOS (LOGIN_USUARIO, NOMBRE_USUARIO) VALUES ('||U.LOGIN_USUARIO||', '''||U.NOMBRE_USUARIO||''');') AS INSERCION_USUARIOS<br />FROM USUARIOS U<br />WHERE U.LOGIN_USUARIO <> 'X';<br />EOF<br /></pre>En el ejemplo anterior el script genera las sentencias de inserción de los propios registros leídos de la tabla <b>USUARIOS</b>. Las rutas especificadas para las variables <b>USERS_FILE</b> y <b>ORACLE_HOME</b> son solamente de referencia, así como la propia sentencia SQL.<br /><br /></li><li>Ahora ya solo nos resta ejecutar el script desde el intérprete de comandos o desde el programador de tareas automáticas crontab y debería funcionar:<br /><pre><b><span style="color: red;">usuario@testsrv:~></span> ./generar_sentencias_sql.sh</b><br /></pre>Por último verificamos que el archivo <b>usuarios.sql</b> contenga las sentencias SQL esperadas.<br /><pre><b><span style="color: red;">usuario@testsrv:~></span> vi /tmp/usuarios.sql</b><br /></pre></li></ol>Y eso nomas por el momento, que ya fue suficiente para dar el punta pié inicial al 2016.GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com1tag:blogger.com,1999:blog-1035903216249592564.post-17106666482246459982015-07-16T13:31:00.004-04:002022-10-04T22:35:49.445-03:00Ejecutar aplicaciones como administrador y cambiar permisos desde el CMD de Windows<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00035.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00035.png" width="320" /></a></div>Este artículo trata acerca de lanzar una aplicación gráfica con permisos de administrador desde el intérprete de comandos CMD de Windows con el comando <b>runas</b>, y sobre cómo cambiar los permisos de acceso y de ejecución de un archivo y/o aplicación desde el CMD utilizando el comando <b>cacls</b>.<br /><br />Si bien no es muy común utilizar estas opciones, las documento justamente porque alguna vez me sirvieron.<br /><a name="more"></a><br />Pero vayamos al caso en donde me fue útil esta funcionalidad, se presentó una situación en la que tenía que cambiar los permisos de ejecución de una aplicación instalada en un equipo con el sistema operativo Windows 7, y como solo tenía acceso al escritorio de un usuario de sistema operativo limitado (sin permisos de administrador) tuve que ver la forma de solucionarlo. En aquel entonces lo solucioné desde el CMD (seguro que había una forma más simple y sencilla de hacerlo) y estos fueron los pasos que seguí:<br /><ol><li>Lo primero que realicé fue ejecutar el <b>cmd</b> desde el menú inicio del usuario con accesos limitados, y utilizando el comando <b>runas</b> le indiqué que quería ejecutar nuevamente la aplicación <b>cmd</b> pero con el usuario administrador del sistema operativo:<br /><pre><b>C:\Archivos de programa></b>runas /user:administrador cmd<br />Escriba la contraseña para administrador: <i>-aquí especificamos la contraseña-</i><br />Intentando iniciar cmd como usuario "MIEQUIPO\administrador" ...<br /></pre>La ejecución de anterior desplegará otra ventana CMD totalmente nueva e independiente, pero ya con todos los permisos propios del administrador del sistema.<br /><br /></li><li>Teniendo una ventana <b>cmd</b> con permisos de administrador procedí a modificar el nivel de acceso sobre el directorio de instalación de una aplicación a la que todos los usuarios limitados del sistema operativo debían tener <b>control total</b>. Para realizar esta tarea utilicé el comando <b>cacls</b> que hoy en día está obsoleto pero que de igual manera sigue funcionando:<br /><pre><b>C:\WINDOWS\system32></b>cacls "c:\Archivos de programa\Carpeta_Aplicacion" /T /E /P Todos:F<br /></pre>Para comprender que funciones cumplen cada uno de los argumentos que se le pasan al comando <b>cacls</b> pueden consultar su ayuda, de la cual va un fragmento a continuación:<br /><pre><b>C:\></b>cacls /?<br /><br /> NOTA: el comando Cacls está obsoleto, use Icacls.<br /><br /> Muestra o modifica listas de control de acceso (ACL) de archivos<br /><br /> CACLS archivo [/T] [/M] [/L] [/S[:SDDL]] [/E] [/C] [/G usuario:perm]<br /> [/R usuario [...]] [/P usuario:perm [...]] [/D usuario [...]]<br /><br /> archivo Muestra las ACL.<br /> <span style="background-color: #fff2cc;">/T Cambia las ACL de archivos especificados en</span><br /> <span style="background-color: #fff2cc;"> el directorio actual y todos los subdirectorios.</span><br /> /L Trabaja en el propio vínculo simbólico en lugar del destino.<br /> /M Cambia las ACL de los volúmenes montados en un directorio.<br /> /S Muestra la cadena SDDL para la DACL.<br /> /S:SDDL Reemplaza las ACL por las especificadas en la cadena SDDL<br /> (no válido con /E, /G, /R, /P ni /D).<br /> <span style="background-color: #fff2cc;">/E Edita la ACL en vez de remplazarla.</span><br /> /C Continúa, omitiendo los errores de acceso denegado.<br /> /G usuario:perm Concede derechos de acceso del usuario.<br /> Perm puede ser: R Leer<br /> W Escribir<br /> C Cambiar (escribir)<br /> F Control total<br /> /R usuario Revoca derechos del usuario (sólo válida con /E).<br /> <span style="background-color: #fff2cc;">/P usuario:perm Reemplaza derechos de acceso del usuario.</span><br /> Perm puede ser: N Ninguno<br /> R Leer<br /> W Escribir<br /> C Cambiar (escribir)<br /> <span style="background-color: #fff2cc;">F Control total</span><br /> /D usuario Deniega acceso al usuario especificado.<br /></pre></li><li>Sin embargo, ahora que lo pienso bien podría haber realizado algo más sencillo que usar el comando <b>cacls</b> para cambiar los permisos de la aplicación (o Icacls como me recomienda Windows), simplemente podría haber ejecutado el siguiente comando:<br /><pre><b>C:\Archivos de programa></b>runas /user:administrador explorer<br />Escriba la contraseña para administrador: <br />Intentando iniciar explorer como usuario "MIEQUIPO\administrador" ...<br /></pre>Con el cual me hubiese desplegado el explorador de Windows con permisos de administrador, mediante el cual el cambio de permiso hubiese sido totalmente gráfico. Esto me hubiese ahorrado todo el trabajo de investigación sobre el uso del comando <b>cacls</b>, pero bueno, la lamparita no siempre se prende en el momento indicado, y a veces por buenas razones, al menos aprendí a usar un comando obsoleto.<br /></li></ol>GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0tag:blogger.com,1999:blog-1035903216249592564.post-6949200476083533042015-07-13T13:41:00.004-04:002022-10-04T22:34:30.870-03:00Desplegar aplicaciones gráficas sin escritorio en openSUSE Linux<div class="separator" style="clear: both; text-align: center;"><a href="http://files.tormentadebits.com/covers/portada-00048.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="156" src="http://files.tormentadebits.com/covers/portada-00048.png" width="320" /></a></div>En ciertas ocasiones necesitamos lanzar una aplicación que sea la única que se encuentre disponible en el escritorio de nuestro operador y que éste no tenga acceso a nada más, ya sea porque solo debe usar la aplicación designada o bien porque el equipo está destinado para una tarea específica. <br /><br />Y es que lograr ejecutar una aplicación de forma solitaria en la pantalla de un operador no es tan complicado en las distribuciones Línux como uno se podría imaginar, solo hay que seguir leyendo.<br /><a name="more"></a><br />El principio es muy simple en Linux, consiste en crear un usuario y reconfigurar las rutinas de arranque del escritorio de su perfil que por defecto suelen ser iguales para todos los usuarios del sistema operativo. A continuación va un ejemplo muy sencillo probado en la distribución <b>openSUSE</b>, donde se consigue desplegar de forma independiente y exclusiva la aplicación <b>Firefox</b>.<br /><ol><li>Lo primero consiste en conectarnos con el usuario <b>root</b> y crear el usuario de sistema operativo que deseamos que solo pueda ejecutar la aplicación específica. En este caso es el usuario en cuestión es <b>test</b><br /><pre><b><span style="color: red;">testsrv:~ #</span> su -<br /><span style="color: red;">testsrv:~ #</span> useradd -r -g users puntoventa</b><br /></pre></li><li>Luego nos dirigimos al <b>home</b> del usuario <b>test</b> donde creamos el archivo <b>.xinitrc</b> a partir del archivo <b>.xinitrc.template</b>:<br /><pre><b><span style="color: red;">testsrv:~ #</span> cd /home/test<br /><span style="color: red;">testsrv:/home/test #</span> cp .xinitrc.template .xinitrc<br /><span style="color: red;">testsrv:/home/test #</span> vi .xinitrc</b><br /></pre></li><li>Una vez editado el archivo <b>.xinitrc</b> borramos todo su contenido y agregamos las aplicaciones que deseamos que se inicien. En el ejemplo que sigue a continuación se despliega el gestor de ventanas <b>kwin</b> en segundo plano (<i>por el ampersand</i>) y finalmente la aplicación específica a la que tendrá acceso nuestro operador: <b>Firefox</b>. La ejecución de <b>kwin</b> en segundo plano mejora el manejo y la decoración de la ventana en la cual se ejecuta Firefox.<br /><pre><b><i>#!/bin/bash</i><br />kwin &<br />firefox</b><br /></pre>Otro ejemplo de ejecución de aplicaciones es el siguiente, en donde se ejecuta el <b>kwin</b> y el <b>x11vnc</b> en segundo plano para el manejo de ventanas y habilitar el acceso remoto respectivamente, y finalmente la aplicación <b>konsole</b> que como se ve a continuación ejecuta un script basado con el intérprete <b>expect</b>, que como ya saben de <a href="http://www.tormentadebits.com/2013/03/expect-automatizar-ejecucion-de-comandos-interactivos.html" target="_blank"><b>éste artículo</b></a> permite automatizar la interactividad en tareas de consolas.<br /><pre><b><i>#!/bin/bash</i><br />kwin &<br />x11vnc &<br />konsole --nofork --profile miperfil.profile -e $HOME/script_except.sh</b><br /></pre></li></ol>Como se puede ver la forma de hacerlo es muy sencilla, queda en manos de cada uno ser creativos y experimentar con esta funcionalidad para quizás poder sacarle algún provecho, como me ha sucedido a mí.GabrielKfrhttp://www.blogger.com/profile/13974751487532249166noreply@blogger.com0