Transfert incrémental avec rsync

13/01/2009

Pour faire suite à l’article où je vous expliquais comment transférer des données entre deux serveurs avec scp, voici un autre utilitaire du même genre qui permet de faire un transfert incrémental, ce qui signifie que seul ce qui a été modifié est transféré.

Je vous recommande également pour cette commande de mettre en place une authentification par clé entre les deux serveurs afin d’éviter d’avoir à retaper le mot de passe à chaque transfert.

La syntaxe de la commande est semblable à scp:

rsync -avz -e ssh remoteuser@remoteserveur:/repertoire/distant .

Quelques mots sur les options utilisées:

  • -a: mode archive; copie récursive, conserve les liens symbloliques, les permissions, les timestamps des fichiers, les uid et gid originaux
  • -v: mode verbeux; les actions réalisées sont envoyées sur stdout
  • -z: compresse les données durant le transfert
  • -e ssh: force le transfert en utilisant ssh

La commande réalise ici une copie récursive du répertoire /repertoire/distant situé sur remoteserveur vers le répertoire courant.

Système ,

Backup automatique de toutes les bases MySQL

12/01/2009

La mise en place de backups est une étape cruciale et incontournable en tant que pocesseur d’un serveur dédié. Vous devez pouvoir repartir le plus vite possible en cas de crash disque, avec des pertes de données réduites au minimum.

Pour MySQL, il existe deux possibilités:

  • la mise en place d’un deuxième serveur, en réplication maître/esclave; le serveur esclave se synchronisant à intervalles réguliers sur le serveur maître;
  • la réalisation périodique de dumps des bases et leur transfert en lieu sûr.

C’est la deuxième solution que nous allons explorer aujourd’hui, en réalisant un script bash dont le but est de réaliser un dump par base existante, en sachant que cette liste peut bien évidemment évoluer de jour en jour; le script devra donc gérer cet aspect du problème. Une fois le script réalisé, il vous sera alors possible de l’intégrer à votre crontab afin d’automatiser son exécution. Nous nous limiterons dans cet article à la réalisation du dump en lui-même, le transfert des données en lieu sûr dépend des possibilités qui vous sont offertes. Il est possible de réaliser un transfert via scp vers un autre serveur, d’uploader les données par FTP, de les envoyer à une adresse e-mail, …

Les bases de données sont stockées dans le répertoire /var/lib/mysql, chaque base étant contenue dans un répertoire portant son nom. Pour obtenir la liste des bases de données, il suffit donc de faire un ls de ce répertoire et de vérifier que l’entrée retournée est un répertoire. Ensuite, à l’aide de la commande mysqldump et d’un user spécialement créé pour le backup, nous réaliserons un fichier compressé pour chaque base de données. L’utilisateur créé pour le backup aura des privilèges communs à toutes les bases : le select, forcément, mais aussi la possibilité de verrouiller les tables pendant leur sauvegarde, on s’assure ainsi que les données backupées seront cohérentes.

Mais, me diriez-vous, pourquoi ne pas directement sauvegarder les fichiers présents dans /var/lib/mysql ? Tout simplement parce qu’un seul octect corrompu lors du transfert ou de la copie rendrait le backup totalement inutilisable. Un dump réalisé par la commande mysqldump contient l’ensemble des requêtes permettant de recréer la base du début, c’est à dire les requêtes « create table » et « insert », qu’il suffit de rejouer en cas de besoin.

La première étape est de créer l’utilisateur dédié au backup, que nous appelerons tout simplement « backup ». Original, non ? Vous pouvez faire cela via PhpMyAdmin, ou directement en console en entrant les requêtes suivantes après que vous vous soyez connecté en root au serveur MySQL:

CREATE USER 'backup'@'localhost' IDENTIFIED BY 'mot de passe de votre choix';
REVOKE ALL  PRIVILEGES  ON  *.* FROM  'backup'@'localhost';
REVOKE GRANT  OPTION  ON  *.*  FROM  'backup'@'localhost';
GRANT SELECT, LOCK TABLES ON *.*
    TO 'backup'@'localhost'
    WITH
        MAX_QUERIES_PER_HOUR 0
        MAX_CONNECTIONS_PER_HOUR 0
        MAX_UPDATES_PER_HOUR 0
        MAX_USER_CONNECTIONS 0 ;

N’oubliez pas de mettre un mot de passe particulièrement robuste; en effet cet user a un privilège global de selection sur toutes les bases de données. Vous pouvez par exemple utiliser mon générateur de mots de passe.

Ensuite, avec votre éditeur de texte préféré, créez un fichier que vous nommerez par exemple backup.sh et mettez-y le contenu suivant:

#!/bin/sh
backup=/home/backup
sqlusr="backup"
sqlpwd="password"
sqlhost="localhost"
date=`date +%Y-%m-%d`

for db in `ls /var/lib/mysql`; do
 if [ -d /var/lib/mysql/$db ]; then
  if [ ! -e $backup/$date-db-$db.tar.bz2 ]; then
   nice mysqldump --host=$sqlhost --user=$sqlusr --password=$sqlpwd \
    --quote-names --extended-insert --skip-disable-keys --quick $db \
    > $backup/$date-db-$db.sql
   nice tar cjf $backup/$date-db-$db.tar.bz2 $backup/$date-db-$db.sql
   rm backup/$date-db-$db.sql
  fi
 fi
done

La variable backup est le répertoire cible où seront créés les fichiers .tar.bz2; ce répertoire doit permettre l’écriture et la lecture à l’utilisateur qui réalise le backup, les autres utilisateurs du système ne devraient y avoir aucun accès. N’oubliez pas de renseigner le mot de passe de l’utilisateur backup. Pour l’explication des différentes options apportées à la commande mysqldump, lisez la page de manuel correspondante. La commande nice mise en début de ligne permet de limiter la priorité du processus de backup, afin de ne pas surcharger votre machine par un script gourmant. Notez aussi que durant le backup, les tables sont lockées une à une, ce qui pourrait affecter le fonctionnement des sites en dépendant; faites donc cette opération pendant la nuit…

Autre chose très importante: ce fichier ne devrait pas être lisible par les autres utilisateurs, sinon ils seraient en possession du mot de passe de l’utilisateur backup. Mettez donc le fichier en chmod 700; ce qui le rend au passage exécutable.

Un fichier sera donc généré pour chaque base, sous la forme AAA-MM-JJ-nomDeLaBase.tar.bz2. Il ne vous reste plus qu’à le transférer dans un lieu sûr, et à importer le dump dans votre serveur MySQL en cas de crash.

Si vous ne désirez sauvegarder qu’une liste de bases présices, mettez leur nom (un par ligne) dans un fichier texte, par exemple /root/dblist. Remplacez dans le script la ligne

for db in `ls /var/lib/mysql`; do

par

for db in `cat /root/dblist`; do

Ceci peut par exemple être utilisé pour réaliser un backup plus régulier de certaines bases précises tout en laissant le backup de toutes les bases existantes à une fréquence moins importante.

MySQL ,

Transfert de données entre deux serveurs avec scp

11/01/2009

Aujourd’hui je vais vous exliquer comment transférer des répertoires de manière récursive, en conservant les permissions et les dates des fichiers, et le tout de manière cryptée.  De manière récursive, cela signifie que l’on prend tous les sous répertoires d’un répertoire donné, ainsi que leurs sous répertoires à eux et ainsi de suite.

Une commande sous linux permet de faire cela facilement : scp. Si vous réalisez régulièrement des transferts entre deux serveurs précis, je vous recommande de mettre en place une authentification par clé, afin de ne pas toujours devoir donner les mots de passes, en suivant la procédure expliquée ici.

La syntaxe de base est la suivante:

scp -rp user@serveurdistant.com:/home/user/repertoire .

Les switchs rp permettent respectivement de travailler de manière récursive et de conserver les temps d’accès, de modification ainsi que la valeur du chmod original. Ensuite, nous spécifions l’utilisateur distant utilisé (avant l’@), le nom ou l’ip de la machine distante. Après les deux points, c’est le répertoire de base sur la machine distante. Suit enfin, le répertoire de destination sur la machine locale. Le point indique « ici », mais vous pouvez bien entendu spécifier le répertoire de votre choix.

Comme précisé au début de l’article, le transfert est crypté, réalisé sur base du protocole SSH, à contrario de FTP où toutes les informations (données et mots de passe) circulent en clair sur le réseau, permettant à chacun de se servir allégrement.

Je vous invite à consulter la page de manuel de scp si vous désirez obtenir plus d’informations sur cet utilitaire très utile.

Dans un prochain article, nous verrons comment réaliser des sauvegarders incrémentales.

Système ,

Générer un certificat autosigné pour Apache

10/01/2009

Pour des panels d’administrations ou des choses que vous êtes le seul à utiliser, on peut se contenter d’utiliser un certificat SSL autosigné; c’est à dire qu’il génèrera un warning à la navigation disant qu’il n’a pas été signé par une autorité de certification reconnue; il vous suffira alors de le whitelister dans votre navigateur. Dès le moment où des utilisateurs lambda doivent accéder au site, c’est à proscrire, le simple fait de voir un warning fera qu’ils n’iront pas plus loin.

Voici la commande permettant de générer le certificat, valide 10 ans:

openssl req -x509 -nodes -days 3650 -newkey rsa:1024 \
-out /etc/apache2/server.crt -keyout /etc/apache2/server.key

Cette commande peut bien évidemment être tapée sur une ligne en enlevant le \ à la fin de la première ligne.

Répondez aux différentes questions; pour « Common Name (eg, YOUR name) []« , vous devez mettre le nom du site, sous-domaine éventuel compris.

Ensuite, il faut activer le module SSL pour apache, avec la commande a2enmod ssl. Dans votre fichier apache2.conf, rajoutez NameVirtualHost ip:443 (n’oubliez pas de mettre votre adresse ip à la place de ip :-p). Ensuite, dans le virtual host à protéger, rajouter les lignes suivantes :

SSLEngine on
SSLCertificateFile /etc/apache2/server.crt
SSLCertificateKeyFile /etc/apache2/server.key

Le Virtual host en question doit contenir la définition de l’ip dans sa définition, qui est donc du type <VirtualHost ip:443>. Notez que le wildcard * ne fonctionnera pas… Tous les virtual hosts doivent donc éventuellement être adaptés pour inclure la déclaration de l’ip, vu qu’il n’est pas possible de mixer les déclaration de type *:port et ip:port.

Vérifiez aussi que le fichier ports.conf contient bien la ligne Listen 443.

Vous pouvez ensuite redémarrer apache et tester le bon fonctionnement du site concerné.

Notez que si vous désirer utiliser plusieurs virtual hosts en SSL, vous êtes limités à un virtual host SSL par adresse IP, il faut donc accrocher d’avantages d’ip à votre machine.

Apache ,

Reset du mot de passe root de MySQL

09/01/2009

En cas d’oubli du mot de passe root de MySQL, il est possible de trouver une solution sans s’arracher les cheveux. Il est en effet possible, via la console ssh, de se connecter à MySQL sans qu’il ne contrôle le mot de passe et d’y injecter une requête modifiant la table users afin d’attribuer un nouveau mot de passe à l’utilisateur.

Voici les commandes à taper sur votre terminal :

/etc/init.d/mysql stop
   (On stopppe MySQL)
mysqld_safe –skip-grant-tables –skip-networking &
   (On relance MySQL en ignorant les privilèges et en refusant
    les connexions ne venant pas de localhost)
mysql -u root mysql
   (On se connecte à MySQL, à la table mysql, celle qui contient
    les privilèges, en utilisant l'utilisateur root)
UPDATE user SET Password=PASSWORD('mot de passe') WHERE User='root'; 
   (On donne un nouveau mot de passe)
exit
   (on se déconnecte de mysql)
killall mysqld_safe && /etc/init.d/mysql start
   (on relance MySQL en version "normale")

Il est à noter que dès le moment où vous lancez MySQL en ignorant les privilèges, tous les utilisateurs sont de facto root sur le serveur MySQL. Il est donc conseillé de couper Apache ou tout autre software accédant à MySQL le temps de la maintenance afin d’éviter qu’une requête mal formée ou un utilisateur mal intentionné profite des quelques secondes de brèche pour mettre la pagaille sur votre machine !

MySQL ,

Apache: sous domaine commun à tous les virtual hosts

08/01/2009

Il est parfois utile de configurer un même sous domaine pour tous les virtual hosts du serveur, par exemple pour un webmail ou pour un panel d’administration.

Créer un virtual host pour chacun des domaines est long et fastidieux. Heureusement, il est possible de créer un alias, en mettant les lignes suivantes dans le virtual host principal:

ServerName webmail.domaineprincipal.tld
ServerAlias webmail.*

Ainsi, pour tous les domaines ayant un record webmail pointant vers la même ip que webmail.domaineprincipal.tld, il n’est plus nécessaire de créer un virtual host spécifique.

Apache

Classement du courrier côté serveur avec Sieve

06/01/2009

Lorsque vous consultez votre courrier en IMAP depuis plusieurs clients différents (webmail et client sur le PC, par exemple) et que vous avez implémenté sur votre PC des règles de tri de courrier, le classement n’est pas fait lorsque vous consultez votre courrier sur le Webmail et que celui-ci n’a pas encore été classé par votre PC qui devrait resté allumé pour classer en temps réel.

La solution est de réaliser le classement directement côté serveur, afin que votre MDA (Mail Delivery Agent) réalise directement ce classement. Ainsi, peu importe l’endroit où vous vous connectez, le classement sera toujours réalisé.

Un langage, Sieve défini par la RFC 5228 permet de réaliser facilement ces traitements, sur base des en-têtes du courrier reçu. Ainsi, il est facile de vérifier la valeur d’un en-tête (l’expéditeur du mail, son destinataire, le sujet, …) ou son existence (est-ce que l’antispam a placé l’en-tête indiquant le caractère indésirable du courrier ?).

En utilisant le MDA de Dovecot, un plugin nommé cmusieve est disponible. Il suffit de l’activer dans le fichier /etc/dovecot/dovecot.conf, dans la section lda, de la manière suivante:

protocal lda {
  mail_plugins = cmusieve
}

Ensuite, après avoir redémarré dovecot, pour les utilisateurs nécessitant un filtrage, rajouter à la racine de leur boîte mail un fichier nommé .dovecot.sieve (qui doit appartenir à l’utilsateur utilisé pour le mail, généralement vmail). A chaque modification du fichier, dovecot créera une version compilée, nommé .dovecot.sievec. En cas de problème avec votre fichier (erreur de syntaxe), un fichier .dovecot.sieve.err sera créé.

Ce fichier contient les règles propres à chaque utilisateur. En voici quelques exemples :

Classement du spam dans le folder Junk:

require "fileinto";

if exists "X-Spam-Flag" {
  fileinto "Junk";
}

Marquer le courrier provenant de l’adresse mail@example.org comme lu:

require "imapflags";

if address :is ["From"] "mail@example.org" {
  setflag "\\Seen";
}

Supprimer le courrier provenant de l’adresse mail@example.org:

if address :is ["From"] "mail@example.org" {
  discard;
}

Dans le cas du classement du courrier dans un folder précis, il est indispensable de configurer votre client mail pour qu’il idle sur tous les folders (par défaut ce n’est que sur la Inbox principale).

Il est possible de définir des script globaux à tous les utilisateurs et de créer des répondeurs. Nous verrons cela dans un prochain article.

Courrier électronique , ,

Apache: Ne pas loguer certaines requêtes

05/01/2009

Pour poursuivre dans la lignée de l’article d’hier qui expliquait comment ignorer les erreurs 404 dans les logs Apache, voici comment ignorer les requêtes en fonction du type de fichier, afin, par exemple, de ne pas enregistrer celles concernant des fichiers javascript ou css.

L’astuce est de définir une variable d’environnement si l’URI correspond à un pattern précis. Dans le virtual host concerné, rajoutez les lignes suivantes:

SetEnvIfNoCase Request_URI "\.(js|css)$" dontlog
CustomLog chemin/vers/le/fichier/log combined env=!dontlog

Vous adaptez le pattern à votre besoin, en rajoutant les extensions qui vous conviennent. Gardez à l’esprit que légalement vous devez garder la trace des accès à votre site, donc ne supprimez pas les appels à des pages de contenu.

Apache

Ignorer les erreurs 404 dans les logs d’erreur d’Apache

04/01/2009

Si vous avez défini un log d’erreur pour Apache, vous avez sûrement déjà remarqué que celui-ci grossit à vue d’oeil en raison des erreurs 404 générées depuis vos différents sites.

Cela peut avoir comme conséquence un blocage d’Apache si le fichier atteint la taille de 2Go avant que logrotate fasse sont travail.

Une solution toute simple à cela est de modifier dans votre fichier /etc/apache2/apache2.conf la directive LogLevel et de la positionner sur crit.

Apache

Connexion entre 2 serveurs sans mot de passe

03/01/2009

Le but de cet article est d’arriver à établir une liaison SSH entre deux serveurs sans devoir entrer manuellement de mot de passe à la connexion. L’intérêt est double :

  • lors de la réalisation d’un backup lancé en crontab, ou même de simple transfert de fichiers lancés par vous en console;
  • lorsque vous passez d’une machine à l’autre régulièrement.

Dans le premier cas cité, il est impossible de rentrer manuellement le mot de passe, l’intérêt du crontab étant précisément de ne pas intervenir. Dans les deux autres, c’est simplement par pur confort.

Se connecter sans mot de passe, c’est bien, mais c’est la porte ouverte à des dérives. Il faut donc un autre moyen de s’identifier pour autoriser l’accès à des données parfois confidentielles. La réponse à se problème est l’utilisation d’un couple de clés, l’une privée et l’autre publique. Le but de l’article n’est pas de faire un cours sur le fonctionnement de la paire de clé, mais pour donner le background nécessaire, je dirai simplement que la clé publique est stockée sur le serveur distant et que vous utilisez la clé privée pour vous y connecter. Un contrôle supplémentaire sur l’adresse IP utilisée peut également facilement être mis en place pour éviter tout problème en cas de vol de votre clé privée.

Pour la suite de l’article, le scénario est le suivant : le serveur A se connecte au serveur B.

Sur le serveur A, connectez-vous au nom de l’utilisateur qui sera utilisé pour se connecter au serveur B. Tapez les commandes qui suivent sur l’invite de commande. Vous devrez répondre à quelques questions. Nous laissons le fichier par défaut pour le fichier dans lequel sauver la clé; nous ne mettons pas de passphrase.

ssh-keygen -t rsa -b 4096
cd ~/.ssh
cat idrsa.pub

S’affichera alors votre clé publique, que vous copiez dans votre presse-papier pour utilisation future.

Sur le serveur B, connectez-vous au nom d’utilisateur qui recevra la connexion du serveur A et tapez-y les commandes suivantes:

mkdir -p ~/.ssh
cd ~/.ssh

Editez ensuite le fichier authorized_keys2 (qui n’existe peut-être pas), et ajoutez-y la ligne suivante, où X représente la clé publique du serveur A se trouvant dans votre presse-papiers.

from="ip du serveur A" X

Vérifiez que la clé publique du serveur A ne contient pas de retours à la ligne. Ensuite, faites en console

chmod -R 600 ~./ssh

afin de donner les bonnes permissions au fichier créé ainsi qu’au répertoire le contenant.

Le serveur A peut maintenant se connecter au serveur B sans devoir entrer de mot de passe. Si vous devez également réaliser une connexion du serveur B vers le serveur A, il est nécessaire de reprendre cette procédure dès le début, en inversant A et B.

Système