---
categories: web webapp saas
title: Howto WordPress
...

* Documentation : <https://wordpress.org/support/>

[WordPress](https://wordpress.org/) est une application web libre de gestion de contenu, historiquement utilisé pour faire un blog.
C'est l'application web la plus utilisée au monde avec plus de 30% des sites web qui l'utilise.

## Installation

Nous préconisons d'utiliser WordPress avec [Apache-ITK](HowtoApache) et [MariaDB](HowtoMySQL).

Pour [Apache-ITK](HowtoApache) on désactive la gestion des droits désactivés pour faciliter les mises à jour :

~~~
AssignUserID example example
~~~

Et également la configuration suivante pour le *DocumentRoot* :

~~~
<Directory /home/example/www/>
    Options +SymLinksIfOwnerMatch
    AllowOverride AuthConfig Limit FileInfo Options
    Require all granted
</Directory>
~~~

Nous préconisons aussi de désactiver l'accès à `xmlrpc.php` sauf si vous en avez vraiment besoin :

~~~
<Files "xmlrpc.php">
Require all denied
</Files>
~~~

Nous utilisons l'outil [WP-CLI](https://wp-cli.org/fr/) :

~~~{.bash}
$ curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
$ php wp-cli.phar --info
$ php wp-cli.phar core download --path=$HOME/www
$ php wp-cli.phar core config --dbname=example --dbuser=example --dbpass=PASSWORD --dbhost=127.0.0.1 --path=$HOME/www
$ php wp-cli.phar core is-installed --path=$HOME/www
$ php wp-cli.phar core install --url=blog.example.com --title="TITRE" --admin_user="admin" --admin_password=PASSWORD --admin_email="blog@example.com" --skip-email --path="$HOME/www"
~~~

## Mise à jour

Les mises à jour sont très importantes car WordPress est très utilisé dans le monde, et il y a donc de nombreuses attaques sur les versions non à jour.

Par défaut, si les droits le permettent, le core de WordPress se met à jour automatiquement pour les versions mineures, cf <https://codex.wordpress.org/Configuring_Automatic_Background_Updates>

Vous pouvez faire les mises à jour directement depuis l'interface d'admin ou alors avec [WP-CLI](https://wp-cli.org/fr/) :

~~~{.bash}
$ cd $HOME/www
$ php $HOME/wp-cli/wp-cli.phar core download --force
$ php $HOME/wp-cli/wp-cli.phar core check-update
$ php $HOME/wp-cli/wp-cli.phar core update
~~~

### Mise à jour par l'interface d'admin via SSH

**Cette méthode n'est pas recommandée si évitable. Préférez la méthode par défaut (`FS_METHOD` = `direct` et pas de séparation des droits par itk) quand possible.**

Si les droits ne le permettent pas, vous pouvez activer les mises à jour via l'interface d'admin avec SSH.

Tutoriel détaillé : <http://kbeezie.com/secure-wordpress-ssh2/>

**Important** : Installer le plugin wordpress [ssh-sftp-updater-support](https://wordpress.org/plugins/ssh-sftp-updater-support). Sa présence résoud bon nombre de problèmes. 

1. Vérifier que le module PHP `ssh2` est installé.
1. Activer `allow_url_fopen` dans la configuration du vhost.
1. Assurez-vous que l'option `define('FS_METHOD','direct')` n'est pas définie, on peut la forcer à ssh2 si nécessaire.
1. Vérifier la correspondance des droits avec le module ITK d'Apache (directive `AssignUserID`) et l'accès à la clé privé SSH.

~~~
# vhost=siteweb
# install -d -o www-${vhost} -g $vhost -m 750 /home/${vhost}/sshkeys
# ssh-keygen -f /home/${vhost}/sshkeys/wordpress
# chown www-${vhost}: /home/${vhost}/sshkeys/wordpress*
# cat /home/${vhost}/sshkeys/wordpress.pub >> /home/${vhost}/.ssh/authorized_keys
# sudo -u www-${vhost} ssh -i /home/${vhost}/sshkeys/wordpress ${vhost}@127.0.0.1
~~~

Modifier le fichier `wp-config.php` en conséquence:

~~~
define( 'FS_METHOD', 'ssh2' );
define( 'FTP_USER', '$vhost' );
define( 'FTP_HOST', '127.0.0.1' );
define( 'FTP_PUBKEY', '/home/$vhost/sshkeys/wordpress.pub' );
define( 'FTP_PRIKEY', '/home/$vhost/sshkeys/wordpress' );
~~~

Il reste plus qu'a se rendre sur le backoffice du site à la page qui liste les modules et en mettre un à jour pour tester.

**Wordpress 4.3 et 4.8**, la mise à jour via ssh est cassée et il faudra appliquer ce fix : <https://web.archive.org/web/20190630102647/https://www.lekernelpanique.fr/2015/09/08/wordpress-4-3-casse-la-mise-a-jour-via-sshsftp/>


## Administration

### Utilisateurs

Créer un utilisateur admin :

~~~
$ php $HOME/wp-cli/wp-cli.phar user create admintest john@example.com --role=administrator
Success: Created user 3.
Password: XXXXXXX
~~~

Si temporaire, ne pas oublier de le supprimer :

~~~
$ php $HOME/wp-cli/wp-cli.phar user list
+----+------------+---------------+----------------------+----------------------+---------------+
| ID | user_login | display_name  | user_email           | user_registered      | roles         |
+----+------------+---------------+----------------------+----------------------+---------------+
| X  | admintest  | admintest     | johndoe@example.com  | 2016-10-17 17:40:26  | administrator |

$ php $HOME/wp-cli/wp-cli.phar user delete X
~~~



## plugins

On peut vérifier la liste des plugins installés sur Wordpress :

~~~{ .sql }
SELECT * FROM wp_options WHERE option_name = 'active_plugins';
~~~

### W3 Total Cache

Le plugin W3 Total Cache améliore les performances d'un « site/blog » propulsé par Wordpress ainsi que la rapidité du chargement des pages pour une meilleure expérience utilisateur et un meilleur référencement !

Pour cela W3 Total Cache met en cache différents éléments : renforcement du cache navigateur, cache des pages, des objets et des requêtes SQL. Il propose aussi différentes fonctions tel que le html/css/js minify et la gestion de CDN.

La configuration se passe dans le tableau de bord de Worpdress, dans l'onglet « Performance ».
Cliquer sur le bouton « Compatiblity Check », pour vérifier que votre serveur dispose de tous les modules nécessaire.


## Sécurité

Nous préconisons de restreindre l'accès à l'interface d'admin par IP :

~~~
<LocationMatch "^/wp-(admin|login)">
Require ip 192.0.2.42
</LocationMatch>
~~~

et nous préconisons aussi de bloquer l'exécution de PHP dans wp-contents/uploads (attention, cela risque de casser certains plugins « sales ») :

~~~
<Directory /home/SITE/www/wp-content/uploads/>
    <FilesMatch "\.php$">
      Require all denied
    </FilesMatch>
</Directory>
~~~

### Fail2Ban

Si l'on ne peut pas restreindre l'accès à l'interface d'admin, nous préconisons d'utiliser [HowtoFail2Ban]().

Par ordre de préférence, nous conseillons d'utiliser :

- [HowtoFail2Ban#wordpress-avec-plugin-fail2ban](Wordpress avec plugin Fail2Ban)
- [HowtoFail2Ban#wordpress-avec-plugin-simple](Wordpress avec plugin simple)
- [HowtoFail2Ban#wordpress-sans-plugin](Wordpress sans plugin)

### WPScan

[WPSscan](https://wpscan.org/) est un outil de scan de vulnérabilités en boite noire dédié à WordPress. Il va détecter la version de WordPress, lister d'éventuelles vulénrabilités connues pour cette version, répertorier les thèmes et plugins utilisés avec leur failles et pointer des défauts de configuration de l'installation.

Pour l'installer, vous pouvez suivre les instructions de [la documentation](https://github.com/wpscanteam/wpscan#install)

Nous conseillons de l'installer sur une machine distante, et pas directement sur le serveur qui héberge WordPress.

Avant la première utilisation, et de manière régulière, il faut mettre à jour WPScan, cela lui permet de récupérer la liste des dernière vulnérabiliés. Vous pouvez le faire avec la commande suivante :

~~~
$ ruby wpscan.rb --update
~~~

Pour « scanner » un site, l'opération est simple, il suffit juste de donner l'adresse du site à WPScan. Vous optiendrez alors un compte rendu complet de la situation.

~~~
$ ruby wpscan.rb --url example.net
~~~


## FAQ

### Gestion des redirections

Lister les redirections déjà présentes :

~~~{.bash}
$ php $HOME/wp-cli/wp-cli.phar rewrite list --format=csv
~~~

Lister selon url donné (ex: SERVERNAME/fr_FR) :

~~~{.bash}
$ php $HOME/wp-cli/wp-cli.phar --url=blog.example.com rewrite list --format=csv --match=fr_FR
~~~

### Forcer les droits

Nous conseillons de désactiver la gestion des droits grâce à Apache-ITK (cf Installation).

Si vous ne faites pas cela, sachez que WordPress surcharge l'umask défini par Apache/PHP et écrit par défaut les fichiers et dossiers en 750.

Il faut rajouter ces 2 lignes dans `wp-config.php` pour avoir des droits corrects :

~~~
define( 'FS_CHMOD_DIR', ( 0770 & ~ umask() ) );
define( 'FS_CHMOD_FILE', ( 0660 & ~ umask() ) );
~~~

### Problème de "Live preview" sur les thèmes

S’il y a un problème pour generer un "live preview" d'un thèmes, ou si on a une erreur php de ce type dans les logs :

PHP Fatal error:  Call to undefined function submit_button() in $HOME/www/wp-content/plugins/ssh-sftp-updater-support/sftp.php on line 249

Il faut ajouter cette option dans le fichier wp-config.php :

~~~
define( 'FS_METHOD', 'direct' );
~~~

Il faut placer cette option avant toutes les autres, en début de fichier.

> **Note** : Attention, ne pas faire ceci si apache tourne avec un autre utilisateur (tel que le module ITK).

### Erreur lors de mise a jour : Impossible de localiser le dossier racine de WordPress (wp-content)

Il faut ajouter ce hack à la fin du fichier *wp-config.php* :

~~~
if(is_admin()) {
add_filter('filesystem_method', create_function('$a', 'return "direct";' ));
define( 'FS_CHMOD_DIR', 0751 );
}
~~~

> **Note** : Attention, ne pas faire ceci si apache tourne avec un autre utilisateur (tel que le module ITK).

### Erreur lors de la publication d'une page

Si vous rencontrez l'erreur 404 suivante dans les logs lors de la publication d'une page :

~~~
POST /wp-json/wp/v2/pages/xx?_locale=user HTTP/1.1" 404
~~~

Cela vient probablement des permaliens. Il suffit de les mettre à jour dans la partie Réglages > permaliens du panneau d'administration en cliquant sur "Enregistrer les modifications".

### WordPress multisite

<https://codex.wordpress.org/Nginx#WordPress_Multisite_subdomains_rules>

### HTTP -> HTTPS

Si l'on veut passer en HTTPS un site précédemment en HTTP, outre la configuration Apache / redirection automatique, il faut aussi remplacer
dans la configuration toutes les URLs en HTTPS. Pour faire cela, on peut faire une dump de la table `wp_options` puis faire des remplacements avec un éditeur :

~~~
$ mysqldump wp_options --no-create-db --replace --extended-insert=FALSE --where="option_value LIKE '%http:%'" > https.sql
~~~

> **Note** : Attention, gardez bien le dump original pour restaurer les lignes originales en cas de besoin
