Laravel lumen GraphQL Server for React Relay Moder

DEPRECATED

This project it’s no longer maintained in favor of v2 of nuwave/lighthouse.
You can find an example implementation for lumen on: https://github.com/kikoseijo/lumen-lighthouse-graphql

A GraphQL Server in PHP, its core its a fast micro-framework implementation (Lumen), and capable of delivering GraphQL (Relay) API responses.

React-Relay Modern, aka GraphQL v1.*

Visit repository

Introduction

On this Lumen version of a GraphQL server implementation you will be able to start coding right away a fully qualified GraphQL server with support for react-relay (Modern version).

With a Laravel heart, on his delighting micro-framework version (Lumen) and a help of a couple of other packages/plugins, we provide you with the basic server setup.

Why Lumen? and why PHP?

Why not my little Artisan? PHP limitations today for a GraphQL server are asynchronous calls, but this are problems PHP programmers been dealing with since the old days, the missing part are the GraphQL subscriptions, this can be resolved using lots of tools, like Redis or NodeJS.

PHP never been so optimized like it is today, its stable, fast and efficient. And Lumen?, because its a masterpiece, a lightweight version of Laravel, sharing same core and data structure. Perfect for building APIs.

For little Artisan like myself this is the perfect atmosphere to understand how things are achieved.

Who is this for?

People wanting to get hands dirty with GraphQL, to serve as a boilerplate to kick-off API projects, a knowledge of Laravel its recommended, at a installation level, not covered here.

Included features
  • Full CRUD example.
  • GraphQL Playground.
  • Database migrations.
  • GraphQl database schema generator and endpoint.
  • User authentication using Passport.
  • Ready to start after setup!
Client Web App

If you work with React we have published for you an application, there you can test all demo features, its a React + Relay based Web App. This is probably best way to have a full picture of what Relay its capable off, in my opinion, one of the best facebook´s open sourced contribution and React´s best friend. 💑

Visit the React Relay – WebApp client.

Laravel & Lumen Polymorphic Relations seeder

Se pueden crear tablas con relaciones polimorficas con Laravel de una form muy sencilla, un ejemplo de implementacion de las mismas.

<?php

use Ramsey\Uuid\Uuid;

$factory->define(App\Models\Post::class, function ($faker) {
    $taggable = [
        App\Models\PostVideo::class,
        App\Models\PostAudio::class,
        App\Models\PostText::class,
        App\Models\PostImage::class,
        App\Models\PostYoutube::class,
        App\Models\PostSoundCloud::class,
    ];
    return [
        'title' => $faker->catchPhrase,
        'body' => $faker->text,
        'uuid' => Uuid::uuid4(),
        'hub_id' => rand(1,50),
        'owner_id' => rand(1,50),
        'votes' => rand(0,200),
        'plays' => rand(0,200),
        'featured' => $faker->boolean,
        'active' => $faker->boolean,
        'public' => $faker->boolean,
        'upload_ip' => $faker->ipv4,
        'post_id'   => 1,
        'post_type' => $faker->randomElement($taggable),
    ];
});


$factory->defineAs(App\Models\Post::class, 'audio', function (Faker\Generator $faker) use ($factory) {
    $follow = $factory->raw(App\Models\Post::class);
    $extras = [
        'post_id'   => $faker->randomElement(App\Models\PostAudio::pluck('id')->toArray()),
        'post_type' => App\Models\PostAudio::class,
    ];

    return array_merge($follow, $extras);
});

$factory->defineAs(App\Models\Post::class, 'image', function (Faker\Generator $faker) use ($factory) {
    $follow = $factory->raw(App\Models\Post::class);
    $extras = [
        'img_thumb' => $faker->imageUrl(300, 300),
        'img_cover' => $faker->imageUrl(1900, 450),
        'post_id'   => $faker->randomElement(App\Models\PostImage::pluck('id')->toArray()),
        'post_type' => App\Models\PostImage::class,
    ];

    return array_merge($follow, $extras);
});

$factory->defineAs(App\Models\Post::class, 'soundcloud', function (Faker\Generator $faker) use ($factory) {
    $cloudFiles = [
        'https://soundcloud.com/mr-mark-scott/long-live-the-chief-freestyle-mark-scott',
        'https://soundcloud.com/gusgus/biggi-veira-dj-set-queretaro-part2',
        'https://soundcloud.com/gusgus/sets/deep-inside-demos',
        'https://soundcloud.com/henry-saiz/sets/henry-saiz-for-days-and-nights',
        'https://soundcloud.com/futureclassic/flume-chet-faker-drop-the-3',
        'https://soundcloud.com/wknd/chet-faker-x-wknd-lover',
        'https://soundcloud.com/nickraymondg/flume-chet-faker-drop-the-game-the-golden-pony-remix-free-download',

    ];
    $follow = $factory->raw(App\Models\Post::class);
    $extras = [
        'url' => $faker->randomElement($cloudFiles),
        'post_id'   => $faker->randomElement(App\Models\PostSoundCloud::pluck('id')->toArray()),
        'post_type' => App\Models\PostSoundCloud::class,
    ];

    return array_merge($follow, $extras);
});

$factory->defineAs(App\Models\Post::class, 'text', function (Faker\Generator $faker) use ($factory) {
    $follow = $factory->raw(App\Models\Post::class);
    $extras = [
        'post_id'   => $faker->randomElement(App\Models\PostText::pluck('id')->toArray()),
        'post_type' => App\Models\PostText::class,
    ];

    return array_merge($follow, $extras);
});

$factory->defineAs(App\Models\Post::class, 'video', function (Faker\Generator $faker) use ($factory) {
    $follow = $factory->raw(App\Models\Post::class);
    $extras = [
        'post_id'   => $faker->randomElement(App\Models\PostVideo::pluck('id')->toArray()),
        'post_type' => App\Models\PostVideo::class,
    ];

    return array_merge($follow, $extras);
});

$factory->defineAs(App\Models\Post::class, 'youtube', function (Faker\Generator $faker) use ($factory) {
    $youFiles = [
        'https://www.youtube.com/watch?v=9tBOtSPrNik',
        'https://www.youtube.com/watch?v=UDVtMYqUAyw',
        'https://www.youtube.com/watch?v=rE7GU7SLguo',
        'https://www.youtube.com/watch?v=XINlEYXA3k0',
        'https://www.youtube.com/watch?v=5ANlWQy7-I0',
    ];
    $follow = $factory->raw(App\Models\Post::class);
    $extras = [
        'url' => $faker->randomElement($youFiles),
        'post_id'   => $faker->randomElement(App\Models\PostYoutube::pluck('id')->toArray()),
        'post_type' => App\Models\PostYoutube::class,
    ];

    return array_merge($follow, $extras);
});

PHP Lumen desarrollo rápido

The main purpose of this package its to generate on the fly several classes inside your projects,
on a clean an easy way will provide by default with full CRUD with Swagger generation on a clever and simple
way.

This are the main functionalities you can find on this package-library.

Example:

We are going to create a full CRUD for the models Role inside a Subfolder
called Admin and route prefix v1 crud using the console

$ php artisan make:krud Roles --folder=Admin --prefix=v1

We could do it even more dynamic adding this to your route file and visiting /krud, because will generate it from an array at once.

// routes/web.php
use Illuminate\Support\Facades\Artisan;

$prefix = 'v1';
$theKruds = [
  'ChatMessages' => 'User',
  'ChatUsers' => 'User',
  'Chats' => 'User',
  'Settings' => 'User',
  'Users' => 'User',
  'PrivateMessages' => 'User',
  'Roles' => 'Admin',
];

Route::get('krud', function () use ($theKruds){
  foreach ($theKruds as $kKey => $kVal){
    echo "doing KRUD for $kKey<br>\n";
    Artisan::call('ksoft:krud', [
      'model' => $kKey, '--folder' => $kVal, '--prefix' => $prefix
    ]);
  }
  echo 'All jobs done done.';
});

What will KRUD produce

Will give you following structure from each given model: replacing ‘Example’ with your model name.

Functionality FilePath
Model Controller /Controllers/Subfolder/ExampleController.php
Controller Contract /Contracts/Subfolder/ExampleRepository.php
Model repository /Repositories/Subfolder/ExampleRepository.php
Update Interaction Contract /Contracts/Subfolder/ExampleUpdate.php
Create Interaction Contract /Contracts/Subfolder/ExampleCreate.php
Update Interaction /Interactions/Subfolder/ExampleUpdate.php
Create Interaction /Interactions/Subfolder/ExampleCreate.php

This package will add a single line for building a full crud api route, and will save it to routes\api.php with the following:

/**
 * Chats Krud Resource Route
 */
lumen_resource($router, '/v1/chats', 'v1.chats', 'User\ChatsController');

Full procedure

The full scope of this start making the models by generating the migrations, spend time on this, so, start by:

  • Creating your Migrations.
  • Make Seeders, its not strictly necesary, but you should…
  • Make your model (Working on automate this, follow this guide: Ethereal)
  • Generate CRUD: php artisan ksoft:krud Model
  • Generate Swagger: php artisan ksoft:swagger

Thats all, you got full working API, with its Swagger v2 Specks,

So, basicaly, instead of creating each of this configuration, this package does it for you, isnt it handy? will create the files for each model, this command will produce this files, extending all its base functionality from other packages thats provides an extra layer of functionality.

and now What?

Well, if yo got reading this far all this above might make sense to you, am i right?

You should concentrate in validation, make custom validations if you need them, if you havent done so when creating the models, othewise just concentrate on giving your app the customized functionality, you can overwrite all functionality thanks to the class this files extends from. Just follow the thanks section to have a deeper understanting of what all this is about, or checkout dependancies on composer.json-

Notes

Generating model directly from the table database its one of the next features, right now you could have it done with couple packages, them both not enabled right now.

\\ Ksoft\Klaravel\Console\Commands\MakeKrud
protected function setupModelName()
{
    $model           = $this->appNamespace.$this->argument('model');
    $this->model     = str_replace('/', '\\', $model);
    $modelParts      = explode('\\', $this->model);
    $this->modelName = array_pop($modelParts);
    if ($this->force || !class_exists($this->model)) {
        // $this->call('code:models', ['--table' => snake_case($this->modelName)]);
        // $this->call('infyom:model', ['model' => str_singular($this->modelName), '--fromTable' => 'yes']);
    }
}

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.

Atom plugin para desarrolladores, larvel, bootstrap, babel, react, bulma

Como programador avanzado una de las cosas que solemos tener son Snippets, los snippets sin trocitos de código fuente que solemos usar con frecuencia y por comodidad gracias a los atajos y editores de texto como Atom podemos tener nuestra librería de estos trocitos de código.
Sinceramente, cuando los usas ya no puedes vivir sin ellos, son de mucha utilidad cuando se hacen tareas repetitivas.

Los mio los comparto con el mundo entero a través de este plugin que he creado para Atom y recoge algunos de los lenguajes de programación que se trabajan en Atom. Entre ellos hay librerías de css, javascript o html, va creciendo a medida que se va haciendo necesario implementar nuevos.

Atom

Os dejo un plugin con muchos snippets para Atom.

https://atom.io/packages/bootstrap-3-snippets-for-atom

También podeis acceder al repositorio y ver como se ha hecho para tomar ideas, o utilizar lo que necesites, sin restricciones. es OS”

Github

https://github.com/kikoseijo/atom-sf-bootstrap-snippets

larvel, bootstrap, babel, react, bulma,…

Un saludo.

Reglas para fail2ban 2017

# /maillog
# /secure

# DOVECOT

(?: pop3-login|imap-login): .*(?:Disconnected|Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed).*rip=(?P<host>\S*),.*
pam.*dovecot.*(?:authentication failure).*rhost=(?:::f{4,6}:)?(?P<host>\S*)

# DOVECOT-(ignoreregex)

imap-login: Disconnected.*\(no auth attempts\).*



# POSTFIX

NOQUEUE: reject: RCPT from \S+\[<HOST>\]: 554 5\.7\.1\s*$
NOQUEUE: reject: RCPT from \S+\[<HOST>\]: 450 4\.7\.1 : Helo command rejected: Host not found; from=<> to=<> proto=ESMTP helo=\s*$
NOQUEUE: reject: VRFY from \S+\[<HOST>\]: 550 5\.1\.1\s*$
improper command pipelining after \S+ from [^[]*\[<HOST>\]:\s*$
NOQUEUE: reject: RCPT from (.*)\[<HOST>\]: 454 4\.7\.1\.*
warning: \S+\[<HOST>\]: SASL ((?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed
RCPT from \S+\[<HOST>\]: 454 4.7.1

# POSTFIX-(ignoreregex)

authentication failed: Connection lost to authentication server$

# SPAM
RCPT from \S+\[<HOST>\]: 550 5.7.1
RCPT from \S+\[<HOST>\]: 450 4.7.1
RCPT from \S+\[<HOST>\]: 554 5.7.1
RCPT from \S+\[<HOST>\]: 535.5.7.0
RCPT from \S+\[<HOST>\]: 535 5.7.0

# MAIL-QUOTA
NOQUEUE: milter-reject: RCPT from \S+\[<HOST>\]: 551 5.7.1

(3 email por minuto)

Las 10 mejores parejas de fuentes en 2016

1. Lato and Merriweather

Lato & Merriweather

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Lato:700|Merriweather:300,300italic,700');

h1,h2,h3,h4,h5,h6 {
  font-family: "Lato", sans-serif;
  font-weight: 700;
}
p,a,li,blockquote {
  font-family: "Merriweather", serif;
  font-weight: 300;
}

2. Playfair Display and Source Sans Pro

Playfair Display & Source Sans Pro

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Playfair+Display:900|Source+Sans+Pro:300,300italic,700');

h1,h2,h3,h4,h5,h6 {
  font-family: "Playfair Display", serif;
  font-weight: 400;
}
p,a,li,blockquote {
  font-family: "Source Sans Pro", sans-serif;
  font-weight: 300;
}

3. Montserrat and Roboto

Montserrat & Roboto

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Montserrat:700|Roboto:400,400italic,700');

h1,h2,h3,h4,h5,h6 {
  font-family: "Montserrat", sans-serif;
  font-weight: 700;
}
p,a,li,blockquote {
  font-family: "Roboto", sans-serif;
  font-weight: 400;
}

4. Alegreya and Open Sans

Alegreya & Open Sans

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Alegreya|Open+Sans:300,300italic,700');

h1,h2,h3,h4,h5,h6 {
  font-family: "Alegreya", serif;
  font-weight: 400;
}
p,a,li,blockquote {
  font-family: "Open Sans", sans-serif;
  font-weight: 300;
}

5. Fira Sans and Lato

Fira Sans & Lato

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Fira+Sans:700|Lato:300,300italic,700');

h1,h2,h3,h4,h5,h6 {
  font-family: "Fira Sans", sans-serif;
  font-weight: 700;
}
p,a,li,blockquote {
  font-family: "Lato", sans-serif;
  font-weight: 400;
}

6. Cardo and Lato

Cardo & Lato

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Cardo|Lato:700,400,400italic');

h1,h2,h3,h4,h5,h6 {
  font-family: "Cardo", serif;
  font-weight: 400;
}
p,a,li,blockquote {
  font-family: "Lato", sans-serif;
  font-weight: 400;
}

7. Oswald and Lora

Oswald & Lora

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Oswald|Lora:400,700,400italic');

h1,h2,h3,h4,h5,h6 {
  font-family: "Oswald", sans-serif;
  font-weight: 400;
}
p,a,li,blockquote {
  font-family: "Lora", serif;
  font-weight: 400;
}

8. Montserrat and Vollkorn

Montserrat & Vollkorn

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Montserrat|Vollkorn:400,400italic,700');

h1,h2,h3,h4,h5,h6 {
  font-family: "Montserrat", sans-serif;
  font-weight: 400;
  text-transform: uppercase;
}
p,a,li,blockquote {
  font-family: "Vollkorn", serif;
  font-weight: 400;
}

9. Lora and Average

Lora & Average

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Lora:700|Average');

h1,h2,h3,h4,h5,h6 {
  font-family: "Lora", serif;
  font-weight: 700;
}
p,a,li,blockquote {
  font-family: "Average", serif;
  font-weight: normal;
}

10. * { font-family: “Lato”; }

Lato & Lato

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@import url('https://fonts.googleapis.com/css?family=Lato:400,400italic,700,300');

h1,h2,h3,h4,h5,h6 {
  font-family: "Lato", sans-serif;
  font-weight: 300;
}
p,a,li,blockquote {
  font-family: "Lato", sans-serif;
  font-weight: 400;
}

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, 😜