# uname -a


lundi 17 juillet 2017

Mémo rsync pour mes collègues

Un rappel de l'usage pratique de rsync pour mes collègues qui oublient tout le temps les commandes à taper.

Lire la suite...

mardi 11 juillet 2017

Configure Wordpress for Performance and Stability

Wordpress is a very common CMS nowadays, and works well out-of-the-box. But when it comes to Performance and Security, its default options are not hardening it enough.

This topic has been discussed a lot on Internet, but here are my tips, as a web developer and sysadmin.

Performance : the main culprits

On a public websites, the slowness can com from :

  • Network : your provider has as slow network, a huge traffic load, or the user simply has a bad connection
  • Database access : the provider's database may be under load, you query's sizes may be too important, or the access time between the script and the datbase is just "usually slow".
  • Disk access : the disk where is stored your files may be slow, or does not have proper in-ram caching
  • CPU : the CPU of the machine where you site is hosted may be slow, or you are on a low-cost VPS

There is no "miracle solution" for a badly designed website, but in the vast majority of cases, we could help a bit with simple solutions.

Security : the main threats

The main threat in a Wordpress installation is the updates execution. You should update your modules, themes, and core as soon as possible.

Custom and unmaintained modules and themes can also become a threat as they are not updated anymore, and can contain exploitable leaks.

There are several way to prevent your site from leaking too many informations on its "healthiness". It can give you some time to update your website before its exploitation by hackers.

Lire la suite...

samedi 30 juillet 2016

Sample public calendar for ownCloud using ICS parser

When ownCloud removed the ability to share a calendar publicly, I had no other choice than forcing my acquaintances to register to my ownCloud.

I didn't want that, so I implemented my own solution.

Lire la suite...

mercredi 27 juillet 2016

Drupal 8 : create a custom Rule Action

Warning : the Rule plugin for Drupal 8 was not considered stable when I wrote this post.

1. Drupal 8: the new modules paradigm

Drupal 8 modules structure changed, and many modules are now using the new API.

No more plain old functions name like hook_something, no more obscurous PHP for menu entries. Instead, Object Oriented programming, YAML configuration files, magic comments, and Symfony routing.

Let's give it a try, let's make our first simplest module.

2. Base module configuration

If you already know how to do this, jumb to next section.

Create a directory for your module, for instance mymodule.

Create an info file in YAML format : mymodule/mymodule.info.yaml:

name: 'My Module'
type: module
core: 8.x
package: Custom

You don't need more! You don't need routing as you will plug into Rules.

3. File names and Namespaces

Creates the RulesAction directory and its parents: mymodule/src/Plugin/RulesAction/

Creates a PHP file for your class: MyAction.php. The class will be loaded with the autoload system.

Edit the file you just created, and specify the namespace at the beginning of the file:

 * @file
 * Contains \Drupal\mymodule\Plugin\RulesAction\MyAction.
namespace Drupal\mymodule\Plugin\RulesAction;
use Drupal\rules\Core\RulesActionBase;

The namespace must correspond to your module name and class name!

4. Rule Action specifications and parameters

Comments are very important as they are also specifications. You will define your Action id, description, and parameters. For instance, here is a copied sample from the predefined action DataSet:

 * Provides a 'My action' action.
 * @RulesAction(
 *   id = "rules_myaction",
 *   label = @Translation("Set a data value"),
 *   category = @Translation("Data"),
 *   context = {
 *     "data" = @ContextDefinition("any",
 *       label = @Translation("Data"),
 *       description = @Translation("Specifies the data to be modified using a data selector, e.g. 'node:author:name'."),
 *       allow_null = TRUE,
 *       assignment_restriction = "selector"
 *     ),
 *     "value" = @ContextDefinition("any",
 *       label = @Translation("Value"),
 *       description = @Translation("The new value to set for the specified data."),
 *       default_value = NULL,
 *       required = FALSE
 *     )
 *   }
 * )

The Rule id is rules_myaction.

The category of the action in the dropdown menu is Data and it will be labeled Set a data value.

The current action will have two parameters : the data that will be changed, and the corresponding value.

5. Rule Action callback

Again, no more plain callback, the function doExecute will be called to execute your Action:

class MyAction extends RulesActionBase {

   * Executes the Plugin.
   * @param mixed $data
   *   Original value of an element which is being updated.
   * @param mixed $value
   *   A new value which is being set to an element identified by data selector.
  protected function doExecute($data, $value) {
    $typed_data = $this->getContext('data')->getContextData();

   * {@inheritdoc}
  public function autoSaveContext() {
    // Saving is done at the root of the typed data tree, for example on the
    // entity level.
    $typed_data = $this->getContext('data')->getContextData();
    $root = $typed_data->getRoot();
    $value = $root->getValue();
    // Only save things that are objects and have a save() method.
    if (is_object($value) && method_exists($value, 'save')) {
      return ['data'];
    return [];


The class name has to correspond to your file name.

In this sample, the parameter $value will be set to $data.

6. Troubleshooting

Uncaught PHP Exception Drupal\\Component\\Plugin\\Exception\\PluginException: "Plugin (rules_myaction) instance class "Drupal\\tbh_system\\Plugin\\RulesAction\\MyAction" does not exist."

Your namespace/classname/filename/directoryname is probably wrong.


Drupal 8 Rules Action documentation

mercredi 22 juin 2016

Debian 8 : Configure Nginx and Passenger to supercharge your PuppetMaster

The Puppet master comes by default with a basic WEBrick server. It allow a quick start for those that are not familiar with Puppet, but when the number of Puppet nodes grows, the performances of the default WEBrick server are going down quickly.

The Puppet documentation show how to configure Apache and Passenger to replace the default WEBrick server, but what if you have a lot of nodes ? What if you want to apply your configuration within minutes, instead of the default half-hour threshold before the agent asks the master if something changed ?

Or you may just want a fancy Nginx instead of your plain-old-reliable Apache.

Here is how.

Lire la suite...

- page 1 de 11