Composer y la version de PHP correcta en systemas Linux.

Cuando hay muchas version de php tenemos que hacer malabares para fijar la que nos hace falta, con programas como Laravel debemos que funcionen también para los usuarios por comandos cuando hay que hacer los deploy.

El problema

Tenemos instalada la ultima versión de php pero composer se queja de que no está detectando la última version de PHP.

No podemos installar paquetes porque nos dice que el php no es compatible con lo que nuestro nuevo paquete necesita como requerimiento mínimo.

Soluciones

Las soluciones son varias, pero lo mejor es no tocar demasiado en las librerías instaladas, y mucho menos en un servidor dedicado con clientes con webs de mas de 10 años, donde actualizar php no es una opción viable.

Creo que una de las soluciones mas sencillas es crear unos alias en el perfil del usuario que tiene los problemas, ya sea en el .profile, .bashrc, .bash_profile. Dependerá de tu distribución y forma de lograrte en tu servidor.

Alias

Tendrás que editar el fichero que carga tu usuario al hacer login, añade las 2 primeras líneas, si quieres puedes añadir las demás también, no van a hacer ningún daño.


alias php="/usr/bin/php71" alias composer="php /bin/composer" // ya es estamos, vamos a darle mas comandos. alias ka="php artisan" alias kdump="composer dump autoload"

Espero os ayude, siempre es bueno tener esto a mano para no andar buscando lejos.

Saludos.

Laravel Envoy for Virtualmin servers

Os dejo un enlace al gist donde mantengo una version de las funciones mas utilizadas al preparar un nuevo servidor que va a correr Laravel.

Para que funcione hay que tener instalado Laravel Envoy, y crear un archivo en la raiz del projecto, desde donde se lanzan los camandos.

ej: envoy run deploy conectar al servidor, descarga el commit mas reciente del repositorio que hayamos preconfigurado en nuestro projecto, en nuestro repositorio publico privado y va a instalar los paquetes de del composer que encuentre nuevo.

Podeis ver el archivo completo aquí:

https://gist.github.com/kikoseijo/205c49fbc66aba03bbb6d3ff456124ef

@servers(['remote' => 'xx.xx.com', 'local' => '127.0.0.1'])

@include('vendor/autoload.php')

@setup

    (new Dotenv\Dotenv(__DIR__, '.env'))->load();

    $now = date('Ymd-His');
    $branch = "origin/master";
    $username = "hes";
    $key_email = "no-reply@sunnyface.com";
    $repo_domain = "xx.xx.com";
    $repo_group = "xxx";
    $repo_name = "xx";
    $project_root = "/home/$username/$repo_name";
    $domain = $username.'.xxxxxxx.com';
    $slack = env('SLACK_ENDPOINT');
    $crons = [
        'Laravel Schedule' => [
            '* * * * *',
            "/usr/bin/php71 $project_root/artisan schedule:run >> /dev/null 2>&1"
        ]
    ];
    $alias = [
        'alias php="/usr/bin/php71"',
        'alias composer="php /bin/composer"',
        'alias ka="php artisan"',
        'alias kdump="composer dump autoload"',
    ];
    $envs = [
        'SLACK_ENDPOINT="https://hooks.slack.com/services/xxxxx/xxxxxx/xxxxxxxx"',
    ];
@endsetup


@task('php', ['on' => 'remote'])
    su -l  {{ $username }}
    php -v
@endtask

@task('deploy', ['on' => 'remote'])
    su -l  {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan down --message="Upgrading system.." --retry=60
    git fetch --all
    git reset --hard {{ $branch }}
    git pull origin master
    composer update --no-dev --prefer-dist
    php artisan up
@endtask

@task('composer', ['on' => 'remote'])
    su -l  {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan down --message="Upgrading system.." --retry=60
    composer install --no-dev --prefer-dist
    php artisan up
@endtask

@task('ssh', ['on' => 'remote', 'confirm' => true])
    su -l {{ $username }}
    [ -d ~/.ssh ] || echo "~/.ssh directory does not exist, lets create"
    [ -d ~/.ssh ] || mkdir ~/.ssh
    echo "Adding {{ $repo_domain }} domain to known_hosts"
    ssh-keyscan {{ $repo_domain }} >> ~/.ssh/known_hosts
    cd ~/.ssh
    echo "Deleting ssh keys..."
    rm -rf id_rsa id_rsa.pub
    ssh-keygen -t rsa -C "{{ $repo_domain }}" -b 4096  -N "" -f id_rsa
    cat  ~/.ssh/id_rsa.pub
@endtask

@story('setup')
    download
    install
@endstory

@task('download', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~
    echo "Cloning {{ "git@" . $repo_domain .":". $repo_group ."/" . $repo_name . ".git" }}"
    git clone {{ "git@" . $repo_domain .":". $repo_group ."/" . $repo_name . ".git" }}
    cd ~/{{ $repo_name }}
    echo "Done download"
@endtask

@task('install', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    composer install --no-dev
    [ -e .env ] || echo ".env does not exist, using default .env.example"
    [ -e .env ] || cp .env.example .env
    [ -e .env ] || echo "Generating new KEY for .env"
    [ -e .env ] || php artisan key:generate
    echo "Linking storage folder"
    php artisan storage:link
@endtask

@task('alias', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~
    @foreach ($alias as $alia)
        LINE='{{$alia}}'
        FILE=.profile
        grep -qF "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
    @endforeach
    alias
    echo "Done."
@endtask

@task('add_env', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    @foreach ($envs as $env)
        LINE='{{$env}}'
        FILE=.env
        grep -qF "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
    @endforeach
    cat .env
    echo "Done."
@endtask

@task('publish', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~
    rm -rf public_html
    ln -s ~/{{ $repo_name }}/public ~/public_html
    echo "App should be now live."
@endtask

@task('cron_add', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    echo "# write out current crontab"
    @foreach ($crons as $cron_name => $cron_job)
        echo "{{$cron_job[1]}}"
        croncmd="{{$cron_job[1]}}"
        cronjob="{{$cron_job[0]}} $croncmd"
        ( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -
    @endforeach
    echo "# Done addCrons"
@endtask

@task('cron_remove', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    echo "# remove crontabs"
    @foreach ($crons as $cron_name => $cron_job)
        croncmd="{{$cron_job[1]}}"
        ( crontab -l | grep -v -F "$cron_name" ) | crontab -
        ( crontab -l | grep -v -F "$croncmd" ) | crontab -
    @endforeach
    echo "# Done rmCrons"
@endtask

@task('apachelogswatch', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    tail -f /var/log/virtualmin/{{$domain}}_error_log
@endtask

@task('laralogswatch', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    tail -f storage/logs/laravel.log
@endtask

@task('catenv', ['on' => 'local'])
    cat .env
@endtask

@task('klean', ['on' => 'local'])
    php artisan clear-compiled
    php artisan migrate:refresh
    php artisan db:seed
@endtask

@task('dump', ['on' => 'local'])
    composer dump-autoload
    php artisan config:clear
    php artisan view:clear
    php artisan cache:clear
    php artisan clear-compiled
@endtask

@task('up', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan up
@endtask

@task('down', ['on' => ['remote']])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan down
@endtask

@story('fm', ['on' => ['remote']])

    migrate_fresh
    migrate_seed
    passport
@endstory
@task('migrate_fresh', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan migrate:refresh --force
@endtask
@task('migrate_seed', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    composer update
    php artisan db:seed --force
@endtask
@task('passport', ['on' => 'remote'])
    su -l  {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan passport:keys --force
    php artisan passport:install
    # php artisan vendor:publish --tag=passport-components
@endtask

@story('migrate')
    warning
    run_migration_seed
@endstory

@task('warning', ['on' => ['local']])
    echo "---------------------------------------------"
    echo "---------------------------------------------"
    echo "--------------- "ATTENTION" -----------------"
    echo "---------------------------------------------"
    echo "---------------------------------------------"
    echo "-------------  Are you sure?  ---------------"
    echo "---------------------------------------------"
    echo "---------------------------------------------"
@endtask

@task('run_migration_seed', ['on' => 'remote', 'confirm' => true])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan migrate --force
    @if ($seed)
        php artisan db:seed --force
    @endif
@endtask

@task('m:r', ['on' => 'remote'])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan migrate:rollback --force
@endtask

@task('rights', ['on' => 'remote', 'confirm' => true])
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    chmod -R 0777 public/upload app/storage
    find . -type d -exec chmod 775 {} \;
    find . -type f -exec chmod 664 {} \;
@endtask

@task('reload_php_server', ['on' => 'remote'])
    /etc/rc.d/init.d/php-fcgi-{{str_replace('.', '-', $domain)}} restart
@endtask

@task('reload_nginx', ['on' => 'remote'])
    systemctl restart nginx
@endtask

@task('optimizeInstallation', ['on' => 'remote'])
    echo 'start optimizeInstallation'
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan clear-compiled
    php artisan optimize
@endtask

@task('backupDatabase', ['on' => 'remote'])
    echo 'start backupDatabase'
    su -l {{ $username }}
    cd ~/{{ $repo_name }}
    php artisan backup:run
@endtask

Espero os ayude.

Actualizar MariaDB5 a MariaDB10 en Centos7

Lo primero, saber si necesitamos actualizar, vamos a asegurarnos que tienes un Centos7 y que tienes MariaDB5, para ello vamos a correr los siguientes comandos y ver si nuestro sistema es parecido al mío.

https://downloads.mariadb.org/mariadb/repositories/

# cat /etc/redhat-release 
CentOS Linux release 7.1.1503 (Core) 
# mysql -v
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 5.5.44-MariaDB MariaDB Server

Vale, ahora directamente vamos a eliminar mariaDB del sistema, no os preocupéis, esto no va a borrar ninguna base de datos, de todas formas, si te parece haz una copia de seguridad por si las moscas.

yum remove mariadb mariadb-server

Creamos el archivo donde vamos a añadir el repositorio de MariaDB

vi /etc/yum.repos.d/MariaDB.rep

copia y guarda el contenido de más abajo en este nuevo archivo.

# MariaDB 10.1 RedHat repository list - created 2016-02-06 03:30 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/rhel7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

Ahora le vamos a decir que nos vuelva a instalar mariaDB, nos preguntará si nos fiamos de las firmas del repositorio, tenemos que decir que si, de lo contrario no podremos instalar.

yum install mariadb mariadb-server

Por ultimo, arrancamos nuestra recien instalada version de mariaDB10 y nos aseguramos que se arranca sola durante los reinicios.

systemctl start mariadb
systemctl enable mariadb.service

IMPORTANTE: Ahora puedes hacer un mysql_upgrade para actualizar MariaDB a una version más moderna.<

mysql_upgrade -u root -p

Esto es todo amigos.

Actualizar Centos7 php5 a php7

En esta entrada os indico como actualizar la versión de PHP en un servidor Centos7. Sabemos que PHP7 cuatriplica la velocidad de procesamiento y reduce en un 30% la memoria que necesita, asi que después de valorarlo en algunos entornos en producción nos vemos obligados a instalarlos en todos los servidores nuevos que vamos creando.
Los comandos son sencillos, asumimos que los hacemos con root o si necesitas un sudoer puedes añadirle los comandos necesarios.

Antes de nada, para poder ejecutar el comando yum-config-manager necesitamos tener instalados la herramienta yum-utils, este grupo de herramientas del gestor de paquetes YUM de Centos que van a hacer la vida más fácil. Vamos a ello:

yum install yum-utils

Vamos a importar los repositorios de REMI y habilitarlos, simplemente tenemos que ejecutar un yum update y nuestros sistema estará de forma muy sencilla corriendo de forma nativa la version 7 de PHP.

wget -q http://rpms.remirepo.net/enterprise/remi-release-7.rpm
wget -q https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh remi-release-7.rpm epel-release-latest-7.noarch.rpm
# PARA PHP 7.0 EJECUTAR:
yum-config-manager --enable remi-php70
# PARA PHP 7.1 EJECUTAR:
yum-config-manager --enable remi-php71
yum update

Voilà, ahora si, lo verificamos y comprobamos que estamos corriendo la version de php elegida, ahora nuestro web server va a servir los WordPress’s 4 veces mas rápido y nuestro servidor puede dar servicio a muchos más clientes usando los mismos recursos.

[root@XXXX ~]# php -v
PHP 7.0.17 (cli) (built: Mar 14 2017 15:14:30) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies

Os lo recomiendo si no lo habeis hecho todavía por miedo a los famoso upgrade.

Esto es todo amigos, 😜

Tunear PHP.ini para Centos7 y Nginx

Cada vez que creamos un nuevo Servidor Virtual nuestro sistema de creación replica el archivo que encuentra en /etc/php.ini, por eso lo que hacemos es editarla al crear el servidor y asi usaremos los mismos parámetros bases para todos los servidores virtuales que vamos añadiendo a cada Servidor Dedicado.

La seguridad es lo primero

Esconder la version de PHP en las cabeceras de las páginas servidas a nuestros usuarios maliciosos:

expose_php = Off

Output buffering – Error 502 Nginx

Deshabilitar output buffering, con esto deshabitamos el ob_flush(), esto evita errores tipo 502 en los servidores Nginx, sinceramente, es cuestión de gustos, si no hay buffer la experiencia del usuario se ve truncada a que termine de ejecutar un script hasta que muestra el resultado en pantalla, el caso más claro es cuando WordPress instala/actualiza los plugins y vamos viendo como se instala uno detrás de otro, con el buffering a Off solo veríamos el resultado final, el servidor retiene todo el contenido hasta que ha terminado todos los proceso que le require la carga de está página de WordPress, lo ideal es subir el limite por defecto que nos pone por defecto de 4096 bytes, pero si necesitamos recursos extras lo podemos subir a 16384 bytes.

output_buffering = Off
– or –
output_buffering = 16384

Tiempo de ejecución de los Script

En nuestro caso, corremos bases de datos bastante grandes, hacemos backups y sincronización de datos, a veces los 30 segundos que nos da PHP por defecto nos viene corta, por eso la subimos a 120 segundos el tiempo de espera a que se ejecute un script en una página php.

max_execution_time = 120

Otros valores

Queremos errores, nada más.

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_WARNING & ~E_NOTICE

Mejor un error que una página en blanco que no dice nada.

display_errors = On

Estos valores dependen de vuestros usuarios, que tipo de aplicaciones utilizan.


post_max_size = 20M
upload_max_filesize = 19M

Substituir Apache por nginx en Centos7 + Virtualmin

Somos fanáticos de NGINX, no podemos ocultarlo, es más complicado tunearlo pero los rendimientos son sorprendentes, entre los beneficios que nos da nginx es que no estamos limitados a correr servicios para PHP sino que tambien podemos usar Ruby o cualquier tipo de SOCKET.

Los pasos a seguir son los siguientes:

[bash]
service httpd stop ; chkconfig httpd off
yum install nginx
systemctl start nginx
yum install wbm-virtualmin-nginx wbm-virtualmin-nginx-ssl
[/bash]

 
Login to Virtualmin as root, and go to Webmin -> Servers -> Nginx Webserver and make sure that Nginx and its configuration files are found.
If not, click on the Module Config link and set the config and command paths correctly.

Return to Virtualmin, and go to System Settings -> Features and Plugins.

Un-check the “Apache website” , “SSL website” and “DAV Login”, “Mailman”, “Protected web directories”, “AWstats reporting” and “Subversion repositories” features.

Check the “Nginx website” and “Nginx SSL website” features, then click “Save”.

If Virtualmin reports that any other features cannot be used without Apache, go back and de-select them too.

Go to the System Information page and click Refresh system information in the top right.

Verify that Nginx is shown as running in the “Status” section.

Esto es todo amigos,..

FUENTE: https://www.virtualmin.com/documentation/web/nginx

Instalar un servidor web para alojar páginas webs desde cero

Hola amigos,

Hoy vamos a instalar un servidor web para dar servicio de páginas web y correo electrónico a nuestros clientes.
Lo primero que tenemos que hacer es conseguir un servidor, el mercado tiene un amplio abanico de posibilidades, si quereis algo para hacer unas pruebas, que no sea caro y podáis probar diferentes distribuciones os recomiendo echarle un vistazo a Digital Ocean, son una empresa con años de experiencia, pioneros en la tecnología que implementan y con una infraestructura verdaderamente robusta. Muy pronto van a contar con un Data Center en Gibraltar y la latencia para España va a ser extraordinaria.

La instalación es muy sencilla, los comando son muy pocos los que se necesitan para echar a andar el servidor web, al final de este POST teneis unas notas sobre que hacer después y por donde seguir.
Este post está dedicado a como hacerlo funcionar en un Centos, al día de hoy estamos usando la version 7 a 64bits, pero se puede hacer con Ubuntu el sistema recomendado por este panel de control es la de RedHat o en nuestro caso Centos7.
NOTA: Podeis seguir el ejemplo usando una máquina virtual con programas tales VirtualBox podeis bajaros la distro desde aqui: Centos Mirrors arrancar desde el CD e instalar la version mínima, son solo 600Mb.
Yo en mi caso dispongo de una distribución virtualizada para los desarrollos, luego solo tengo que exportar e importar el servidor virtual en el servidor de producción.

El único requerimiento previo antes de poder instalar el sistema es aseguraros de tener un nombre de HOST válido. Para ello debemos correr el siguiente comando hostname -f y os debe mostrar un nombre de internet válido tipo servidor.dominio.com. Este ha de tener una reversa o de lo contrario los clientes no podrán acceder a tu servidor. Este paso es el más importante. Piensa antes de decir que YES.

Una vez tengamos nuestro Centos7 64bits recien instalado, y hemos comprobado que el Hostname es válido, vamos a poceder a instalar todo nuestros paquetes para convertir este equipo en un autentico servidor web, para ello nos vamos a entrar por ssh al servidor, entra como root en nuestra nueva máquina y vamos a correr los siguientes comandos:

[code]
yum update
# si no teneis wget instalado porque no viene con la instalación mínima de Centos:::
yum install wget
# nos descargamos el instalador de nuestro servidor web
wget http://software.virtualmin.com/gpl/scripts/install.sh
/bin/sh install.sh
[/code]

Esto es todo, pasado unos minutos podemos acceder a nuestro recien creado webserver a través de la dirección https://servidor.dominio.com:10000, solo tendrás que substituir servidor.dominio.com por el hostname que hayas elegido.

Siguientes recomendaciones a seguir:

Cambiar la version de PHP5 a PHP7, podeis seguir este tutorial.
Cambiar la version de MariaDb5 a MariaDb10, tambien tenemos un tutorial a medida.
Cambiar Apache por Nginx, aqui teneis el tutorial (Este paso es para usuario avanzados).
Activar / Instalar FirewallD, la seguridad es muy importante, no menosprecies una buena configuración del firewall.
Instalar Fail2Ban, nos protege de ataques por fuerza bruta.