Realizar un deploy automático desde un repositorio GIT a un servidor remoto

Durante años mi forma de poner un sistema web en producción consistía en abrir filezilla y copiar los archivos sobre la carpeta www, pero esa forma de trabajar crea muchos inconvenientes. Puede que solo pierdas tiempo, pero posiblemente en alguna ocasión te paso que se te olvidó subir un archivo que no recordabas que habías modificado, o sobreescribiste un archivo y no supiste cual fue, o alguien mas sobreescribio un cambio que tu realizaste, etc. Si usas repositorios para trabajar en tu código seguro que no tendrás mayores problemas, y si ya usamos repositorios para el desarrollo ¿por que no usar repositorios para realizar el deploy de nuestra aplicación y evitarnos estos inconvenientes?

El proceso descrito abajo esta basado en un servidor ubuntu hosteado en DigitalOcean, pero estos conceptos se aplican a cualquier servidor linux realizando los respectivos ajustes.

 

Preparar el servidor

Lo primero que debemos hacer es instalar GIT en nuestro servidor, en mi caso ejecuto el siguiente comando:

sudo apt-get install git

Una vez instalado git creamos un usuario que será con el que nos conectaremos para realizar el push, en mi caso lo llame “git”. Para que este usuario pueda funcionar como conexión con nuestro repositorio se debe configurar que los comandos que reciba se ejecuten a traves de git, para eso usamos la opción -s /usr/bin/git. El comando debería lucir así:

sudo useradd -m -s /usr/bin/git-shell git

Si tenemos alguna clave pública de conexión la podemos agregar a nuestro usuario git para que pueda autenticarse en el momento de la conexión. Lo que vamos a hacer es cambiar de usuario a git, ingresar a la carpeta home de git, crear una carpeta .ssh y copiar la clave pública en un archivo llamado authorized_keys:

sudo -u git bash
cd ~
## cd /home/git
mkdir -p .ssh
vim .ssh/authorized_keys

este comando debe abrir el editor de texto vim en nuestra consola, ahí debemos copiar nuestra clave pública y grabar. Si tienes una conexión FTP y acceso al directorio /home/git, entonces tambien lo puedes hacer copiando el archivo desde tu maquina al servidor. Si lo haces de la segunda forma, asegurate que el usuario git sea el propietario del archivo y tenga los permisos adecuados. Recuerda que la clave pública debe empezar por ssh-rsa seguido de un espacio y la cadena de datos cifrados, todo en una sola linea.

 

Configurar el repositorio remoto

Con git instalado y nuestro usuario de conexión listo, vamos a crear nuestro repositorio remoto. nos ubicamos en la carpeta donde estará el repositorio, puede ser dentro de la carpeta home del usuario git o en cualquier otra parte del sistema. Cuando estemos situados en la ruta que hayamos definido, crearemos la carpeta que contendrá nuestro repositorio e ingresamos a ella. En mi caso voy a ubicar el repositorio en /home/git/proyecto-remoto, los comandos que he usado son:

cd ~
## cd /home/git
mkdir proyecto-remoto
cd proyecto-remoto

Ahora iniciamos un repositorio minimo mediante el siguiente comando:

git init --bare

Git trabaja mediante archivos comprimidos que contienen todos los cambios que se realizaron en el commit. Es por esto que cuando realicemos el push al servidor, no veremos nuestros archivos en la carpeta proyecto-remoto. Para obtener los archivos de la misma forma que en nuestra maquina local, haremos uso de los hooks que tiene git. En especifico, haremos uso del hook post-receive que se ejecuta automáticamente despues de que se ha realizado un push al servidor. Para esto creamos el archivo post-receive dentro de la carpeta hooks de nuestro repositorio:

cd ~/proyecto-remoto/hooks
## cd /home/git/proyecto-remoto/hooks
vim post-receive

Se nos abrirá el editor de texto y dentro copiamos lo siguiente:

#!/bin/bash
git --work-tree=/var/www/html/deploy-folder --git-dir=/home/git/proyecto-remoto checkout -f

Este script se ejecuta automáticamente despues de que el push se haya completado y lo que hace es expandir los archivos que recibe el repositorio. La carpeta deploy-folder será el lugar donde se copiaran nuestros archivos descomprimidos para que entren a producción. Guardamos los cambios, y dado que es un script, lo hacemos ejecutable para el usuario git:

chown git /home/git/proyecto-remoto/hooks/post-receive
chmod +x /home/git/proyecto-remoto/hooks/post-receive

Tambien debemos dar los permisos necesarios para poder copiar los archivos a la carpeta deploy-folder:

chown git /var/www/html/deploy-folder
chmod 775 /var/www/html/deploy-folder

Lo que hemos hecho hasta ahora ha sido configurar nuestro servidor para podernos conectarnos mediante git, crear nuestro repositorio y decirle que cada vez que hagamos un push, expanda los archivos a la carpeta de produccion. Ahora configuraremos nuestro repositorio local para poder enviar los cambios al servidor.

Configurar el repositorio local

En esta parte vamos a asummir que ya tenemos configurado git en nuestra maquina local, hemos clonado un repositorio y estamos listo para enviar a producción. Lo primero que debemos hacer es agregar nuestro servidor en el listado de repositorios remotos, para esto usamos los siguientes comandos:

git remote add production git@miproyecto.com:/home/git/proyecto-remoto

Algunos detalles de este comando son:

  • production es el nombre con el que identificaremos a nuestro servidor dentro del git local
  • git@miproyecto.com corresponde al usuario que creamos al inicio “git” y miproyecto.com es el dominio de nuestro servidor, tambien puede reemplazarse esto por la ip pública del servidor si es que no tiene dominio.
  • /home/git/proyecto-remoto es la carpeta dentro de nuestro servidor donde está alojado nuestro repositorio

Cuando se haya añadido el repositorio remoto, probaremos que todo funcione. Primero crearemos un archivo index.html con el texto “Deploy desde GIT”:

echo "<h2>Deploy desde GIT</h2>" >> index.html

Tambien lo podemos hacer desde un editor de texto y guardar el archivo en la carpeta de nuestro repositorio. Ahora realizaremos el push sobre nuestro servidor

git add .
git commit -m "Probando el deploy con git"
git push production master

Si todo estuvo correcto, podremos ver los cambios reflejados en nuestro servidor. Entramos desde nuestro navegador a https://miproyecto.com/deploy-folder y debería aparecernos el mensaje “Deploy desde GIT”.

Errores que encontre

El primer error que encontre fue al configurar la dirección del repositorio remoto en mi maquina local, inicialmente le ponia el prefijo http:// pero si se hace eso git lo asume como un repositorio de solo lectura y no envia la información. En tal caso quitandole el prefijo del protocolo funciona.

El segundo error que me daba era que al hacer push el script post-receive no se ejecutaba. Eso era por que no tenia permisos de ejecución y tampoco era propiedad del usuario git, por lo que no podía realizar la acción.

El tercer problema que me dió fue por los permisos de la carpeta deploy-folder, el usuario git no tenía permisos de escritura sobre ella y por consiguiente no podía copiar los archivos ahí. Haciendo chown git y chmod 775 se soluciona, sin embargo, puede que al cambiar de usuario la carpeta no pueda ser vista por el webserver. En el caso de docker no hay ese problema, pero si se usa apache o nginx es posible que sea necesario agregar el usuario www-data como copropietario de la carpeta.

Conclusiones

Mediante este proceso tendremos un método de deploy mucho más seguro y fácil de manejar. Al tener todas las ventajas de un repositorio podemos permitir que varias personas realicen actualizaciones, hacer rollbacks en caso de error y reducir tiempo y errores al copiar archivos. Una forma de mejorar la configuración actual sería reducir el push a una sola rama, por ejemplo, solo permitir hacer push de la rama master. También podriamos hacer push de una rama de desarrollo y enviarla a un subdominio para poder hacer pruebas de la aplicación sin necesidad de enviarlas al servidor de producción. Incluso podríamos configurar que el post receive nos envíe alertas, para saber cada vez que alguien hace un deploy.

Espero que este tutorial les ayude a implementar este proceso de deploy en sus servidores y de esta forma mejorar sus procesos de puesta en producción. Exitos a todos y nos vemos en la próxima!

 

Fuentes:

 

 

 

 

Anuncios

Levantar un servidor de Nginx en docker

Una de las mejores caracterizticas de Docker es la facilidad para crear un nuevo contenedor a partir de un solo archivo de configuracion (un concepto similar al de un archivo package.json de node). Siguiendo este tutorial: http://www.penta-code.com/creating-a-lemp-stack-with-docker-compose/ he podido levantar un contenedor de nginx mediante docker-compose. El contenedor que levanté con las instrucciones del tutorial ejecuta Nginx, PHP, MariaDB (fork de MySQL) y PHPMyAdmin. A continuación revisaré brevemente los pasos que seguí para poner el contenedor en marcha, si tienen alguna duda del tema pueden revisar el tutorial donde se dan mas detalles sobre cada paso.

Prepara los archivos

Primero revisemos la estructura de las carpetas que vamos a usar. En la ruta /var/www de tu servidor deberían ir estos archivos:

directorios

El archivo docker-compose.yml contiene la configuración para levantar el contenedor se instalaran. El contenido del archivo es el que se muestra a continuación, no olvides cambiar la clave de la MYSQL_ROOT_PASSWORD: admin

nginx:
    image: nginx
    ports:
        - "80:80"
    links:
        - phpfpm
    volumes:
        - ./config/nginx/default:/etc/nginx/conf.d/default.conf
        - ./config/nginx/logs/nginx-error.log:/var/log/nginx/error.log
        - ./config/nginx/logs/nginx-access.log:/var/log/nginx/access.log
        - ./html:/var/www/html
    container_name: nginx
    restart: always

phpfpm:
    image: php:fpm
    links:
        - mysql
    ports:
        - "9000:9000"
    volumes:
        - ./html:/var/www/html
        - ./config/php/php.ini:/usr/local/etc/php-fpm.d/php.ini
    container_name: phpfpm

mysql:
    image: mariadb
    volumes:
      - "./config/database:/var/lib/mysql"
    environment:
        MYSQL_ROOT_PASSWORD: admin
    container_name: mysql

phpmyadmin:
    image: phpmyadmin/phpmyadmin
    links:
        - mysql
    ports:
        - 8183:80
    environment:
        MYSQL_USERNAME: admin
        MYSQL_ROOT_PASSWORD: admin
        PMA_ARBITRARY: 1
    container_name: phpmyadmin
    restart: always

Dentro de la carpeta html/ se deben copiar los archivos de la página web. En la carpeta nginx/ están los archivos de configuración y la carpeta de logs:

directorio_nginx

El archivo default contiene la configuración del servidor nginx. El siguiente es un ejemplo de como luce un archivo con la configuración básica para ejecutar PHP. Ten en cuenta que “tudominio.com” se debe reemplazar con el nombre de tu dominio.

server {
 listen 80;
 listen [::]:80;


 # this path MUST be exactly as docker-compose.fpm.volumes,
 # even if it doesn't exists in this dock.
 root /usr/share/nginx/html/;
 index index.php index.html index.html;

 server_name tudominio.com www.tudominio.com;

 location / {
 try_files $uri $uri/ /index.php?q=$uri&$args;
 }
 
 error_page 404 /404.html;
 error_page 500 502 503 504 /50x.html;

 location ~ \.php$ {
 try_files $uri =404;
 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 fastcgi_pass phpfpm:9000; 
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 include fastcgi_params;
 }
}

Levantar el contenedor

Una vez que todos los archivos y carpetas están listos, levantaremos el contenedor usando estos comandos:

  1. Nos ubicamos en la carpeta donde estan nuestros archivos:
    cd /var/www
  2. Ejecutamos docker-compose para levantar el contenedor, le añadimos el parametro -d para que se ejecute en segundo plano:
    docker-compose up -d
  3. Ingresamos a la imagen de PHP:
    docker exec -it www_phpfpm_1 bash
  4. Instalamos en la imagen de PHP el soporte para MySQL:
    docker-php-ext-install mysqli pdo pdo_mysql
  5. Reiniciamos el servidor para que se reflejen los cambios:
    docker-compose restart

 

Ultimos ajustes

Como mencione antes, el contenedor ejecuta Nginx en conjunto con PHP, MariaDB y phpMyAdmin. Lo utilizo principalmente para paginas webs hechas en wordpress. por lo que esa configuración funciona perfectamente. Siempre es posible editar el archivo docker-compose.yml para ajustar el contenedor a las necesidades de cada persona.

Si se desea acceder a MySQL desde la consola del servidor, se lo puede hacer usando el comando:

docker-compose exec mysql sh

y luego se ejecuta:

mysql -u root -p

La clave del root se setea en el archivo docker-compose.yml, en el ejemplo usado es “admin”. No olvides cambiar esta clave por algo más seguro

Espero esto te haya sido de ayuda para levantar rapidamente un servidor Nginx y contribuya a tu interes por aprender más acerca de esta tecnología. ¡Hasta la próxima!

 

Como cambiar la url de un archivo de respaldo de wordpress

Hace mucho no me había tocado migrar un sitio web hecho en wordpress, y por lo general esto no es muy difícil; por lo general saco un respaldo de la base de datos usando mysqldump, lo abro en algún editor de texto y reemplazo la url anterior por la nueva, antes de subir el respaldo a la nueva base de datos. Pero esta vez el archivo era tan grande que no lo podía abrir en un editor de texto. Una opción era sacar respaldo solo de la tabla de configuración de wordpress, editarla y volverla a subir, pero llegue a una mejor solución:

 UPDATE wp_options SET option_value = replace(option_value, 'http://url-vieja', 'http://url-nueva');

Con esta sentencia SQL cambiamos todas las referencias de la url anterior a la nueva sin necesidad de editar el archivo .sql, de esta misma forma pueden reemplazar cualquier llamada que se encuentre en otras tablas como posts o sliders. Espero esto les ayude aunque sea a ahorrar un par de minutos :).

Como configurar Flash Develop en windows y compilar proyectos AIR 15.0 para android

Este es un tutorial para instalar todos los componentes necesarios y configurar FlashDevelop para compilar proyectos AIR 15.0 para ios y android. Lo primero es descargar todos los archivos necesarios (las versiones que se mencionan son las más recientes a la fecha de la publicación de este artículo):

Cuando tengas todos los archivos, empezaremos la instalación.

Adobe Flex SDK

  1. Descomprime el archivo flex_sdk_4.6.zip en una ruta de tu preferencia. Por cuestiones de la explicación, yo usaré la ruta: “C:\path\to\flex-sdk_15\“, tu debes cambiar esto por la ruta real de tu carpeta.
  2. Originalmente la versión 4.6 de Flex SDK viene con AIR SDK 3.1, asi que vamos a actualizarlo a la versión 15.0 que nos hemos descargado. Para esto copiamos los archivos dentro de AIRSDK_Compiler.zip en la raiz de “C:\path\to\flex-sdk_15\” y le decimos que reemplaze cualquier archivo duplicado que encuentre.
  3. Ahora solo falta agregar el Flash Player, y lo haremos en dos pasos. Primero mueve el archivo playerglobal15_0.swc a la carpeta “C:\path\to\flex-sdk_15\frameworks\libs\player\11.2\“, si la carpeta no existe la creas. Renombra el archivo a playerglobal.swc y listo.
  4. Copiamos el archivo flashplayer_15_sa_debug en la carpeta “C:\path\to\flex-sdk_15\runtimes\player\11.2\win\“, si la carpeta no existe la creas.

Con estos pasos, ya tenemos configurado Flex SDK 4.6 con Adobe Air 15.0 listo para compilar nuestras aplicaciones. Lo siguiente será configurar Flash Develop para que trabaje con este SDK.

FlashDevelop

  1.  Inicia FlashDevelop y ve al menu Tools>Program Settings…, se abrira un dialogo con todas las configuraciones de los plugins de  FlashDevelop.
  2. Selecciona el plugin AS3Context y busca la variable Installed Flex SDKs, agrega una nueva entrada en la variable y en la parte que pide el path (en la seccion location) busca la carpeta “C:\path\to\flex-sdk_15\“. El resto de valores se configuraran solos.
  3. Selecciona el plugin FlashViewer y en la variable External Player Path busca el archivo: “C:\path\to\flex-sdk_15\runtimes\player\11.2\win\FlashPlayerDebugger.exe“. Cerramos la ventana de settings.
  4. Vamos a el menu Tools>Flash Tools>Documentation Generator.. en la parte de Settings buscamos la opcion ASDoc location, y buscamos la carpeta “C:\path\to\flex-sdk_15\bin“. Guardamos los cambios y cerramos.

Ahora Flash Develop va a poder compilar con Adobe AIR 15.0, pero aún falta decirle a nuestros proyectos que usen el nuevo SDK que hemos configurado.

PROYECTO

  1. Inicia un nuevo proyecto en FlashDevelop. Project>New Project y selecciona la opcion AIR Mobile AS3 App. llena los datos y crea el proyecto.
  2. Ve al menú Project>Properties y en la pestaña SDK selecciona el SDK que diga: Flex 4.6.0, AIR 15.0.
  3. Dentro del proyecto, busca el archivo “bat\SetupSDK.bat” y edita las variables FLEX_SDK y ANDROID_SDK, en mi caso quedaron así:
    :: Path to Flex SDK
    set FLEX_SDK=C:\path\to\flex-sdk_15
    set AUTO_INSTALL_IOS=yes
    
    :: Path to Android SDK
    set ANDROID_SDK=C:\Program Files (x86)\Android\android-sdk
  4. Prueba tu proyecto, y si todo ha ido bien, te mostrar la pantalla de AIR en tamaño smartphone.

 

Referencias:

http://www.flashdevelop.org/wikidocs/index.php?title=Configuration

http://www.toxicfork.com/42/configuring-flashdevelop-for-flash-version-11-2

Configurar laravel dentro de un wordpress en go daddy

Me ha pasado que instalé un sitio hecho en laravel dentro de una carpeta en el root de un sitio hecho con wordpress, y bueno, laravel no funcionaba. El problema se ocasiona por las reglas .htaccess de wordpres, estas reglas están tratan de parsear las rutas de laravel con el index.php de wordpress. Me ha tomado un tiempo poner a funcionar el laravel con las soluciones que encontré en internet, así que dejo anotado el procedimiento que seguí por si a alguien le ayuda en el futuro.

Editar el .htaccess de laravel

En internet todos hablan de editar el .htaccess de laravel, pero yo no sabia exactamente como. Lo que deben hacer es abrir el .htaccess que se encuentra en la carpeta public de laravel (si por alguna razón no lo tienen, pueden descargarlo desde aquí: https://github.com/laravel/laravel/blob/master/public/.htaccess) y en la linea que dice:

RewriteRule ^ index.php [L]

Añades la ruta completa a tu carpeta public. te debe quedar algo como:

RewriteRule ^ /ruta/hasta/laravel/public/index.php [L]

El archivo .htaccess puede variar un poco dependiendo de la versión de laravel que estes usando, pero lo importante es llegar a la linea que contiene la referencia a index.php y cambiar eso por /ruta/hasta/laravel/public/index.php para que sobreescriba las reglas de wordpress. a la final el archivo .htaccess debería lucir mas o menos como esto:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes...
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ /ruta/hasta/laravel/public/index.php [L]
</IfModule>

Actualizamos el .htaccess en el hosting de goDaddy y ya podemos entrar a http://tudominio.com/ruta/hasta/laravel/public/ para usar la aplicación. Si queremos evitar el uso de “public/” en la URL de nuestro sitio, para pasar de  “http://tudominio.com/ruta/hasta/laravel/public/ ”  a  algo como “http://tudominio.com/ruta/hasta/laravel/&#8221; tendremos que hacer un paso adicional. Vamos a crear un .htaccess adicional en la carpeta de laravel ( al mismo nivel que la carpeta app/ y public/ )  y en ese archivo pondremos las siguientes reglas:

<IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_URI} ^/trabajos/mansion
    RewriteRule ^ /trabajos/mansion/public/index.php [L]
</IfModule>

Lo grabamos y lo subimos en la carpeta de laravel, y ahora podemos acceder a nuestra aplicación sin necesidad de escribir “public” en el url.

Estas reglas deberían funcionar en otro tipo de situaciones y no solo para poder instalar un proyecto de laravel dentro de una instalación de wordpress. Sobre todo el ultimo que es más general y sirve para evitar el uso de “public” en las URLs de laravel. Espero esto les sirva y si tienen una mejor solución dejame saber en los comentarios.

Problemas al instalar paquetes npm de forma global en linux (ubuntu)

Hoy he estado configurando node en una instalacion nueva de linux y al instalar grunt-cli me ha dado un error parecido a este:

error_npm_permisos

En el mensaje de error nos sugiere ejecutar el comando como root, y aunque esto soluciona el problema, no es lo mas recomendado. Una forma de solucionar el problema, sin comprometer la seguridad del equipo, es con los siguientes comandos:

npm config set prefix "/usr/local"
sudo chown -R $USER /usr/local

el primer comando le dice a npm que no utilize "/usr/lib/node_modules/" sino que redireccione las instalaciones a la carpeta "/usr/local". El segundo comando añade al usuario actual como dueño de la carpeta "usr/local" para que asi tengas control total sobre los archivos. Con eso hemos solucionado el problema de las instalaciones globales de npm, existen otras formas de solucionarlo como por ejemplo ejecutar la instalacion como root o añadir el parametro --no-bin-links al comando npm, pero no confio en la seguridad de esos metodos.

fuentes:
http://stackoverflow.com/questions/13527889/global-installation-of-grunt-js-fails
http://howtonode.org/introduction-to-npm

Como instalar tus templates de joomla 1.5 en joomla 1.6

Comparto un pequeño tip que descubrí hoy, en joomla 1.5 cuando creabas un template bastaba con colocarlo en la carpeta de templates y automáticamente el administrador lo reconocía y lo podías usar. Sin embargo en joomla 1.6 eso no ocurre… la solución es sencilla:

  1. copias la carpeta del template en /templates/ (dentro de la carpeta donde instalaste joomla, lo que se hace normalmente)
  2. vas al administrador del sitio
  3. vas a: Extensions > Extensions Manager
  4. seleccionas la opcion discover
  5. y en la barra de herramientas hay una opcion llamada Discover, le das click
  6. ahora debe aparacerte todos los templates, modulos, plugins o componentes que no estan formalmente instalados, seleccionas el template que deseas instalar y le das clik al boton  install de la barra de herramientas.
  7. Listo! ya tienes tu template instalado y listo para usar