Ce blog — désormais archivé — est en lecture seule. Rendez-vous sur mon nouveau site personnel.

Prendre un Café

L'espace d'expression de Nicolas Perriault

Aller au contenu | Aller au menu | Aller à la recherche

Keyword - bestpractices

Fil des billets

dimanche 29 avril 2007

Symfony, Admin-Generator et Composants

Dans un précédent billet, nous avons vu comment créer un weblog basique avec l'admin-generator de Symfony. Nous allons reprendre là où nous en étions et ajouter la liste des commentaires à notre back-office de gestion des billets grâce à un simple appel de composant, qui n'est autre qu'un template partiel associé à un contrôleur dédié.

Création du module de gestion des commentaires en back-office

Si ce n'est déjà fait, on crée notre module de gestion des commentaires

# symfony propel-init-admin back comments Comment

Création du composant qui va lister les commentaires d'un billet

Bien. On va maintenant créer un composant postcomments qui affichera la liste des commentaires associés à un objet Post, en créant un nouveau fichier apps/back/modules/posts/actions/components.class.php et en y insérent le contenu ci-dessous :

 php
<?php
class postsComponents extends sfComponents 
{
  
  /**
   * List comments for a given Post
   * 
   */
  public function executePostcomments()
  {
    $post_id = $this->getRequestParameter('id');
    if (!is_null($post_id))
    {
      $c = new Criteria();
      $c->add(CommentPeer::POST_ID, $post_id);
      $c->addDescendingOrderByColumn(CommentPeer::CREATED_AT);
      $this->comments = CommentPeer::doSelect($c);
    }
  }
  
}

On crée maintenant le template partiel associé au contrôleur, dans le fichier apps/back/modules/posts/templates/_postcomments.php :

 php
<?php if (isset($comments)): ?>
  <?php if (count($comments) > 0): ?>
    <?php use_helper('Comment', 'Text') ?>
    <dl>
    <?php foreach ($comments as $comment): ?>
      <dt>
        <?php echo sprintf('Posté le <strong>%s</strong> par <strong>%s</strong> :', 
                           format_date($comment->getCreatedAt(), 'd/MM/yyyy à H:m'),
                           format_comment_author($comment->getAuthor(),
                                                 $comment->getSite())) ?>
      </dt>
      <dd>
        <?php echo simple_format_text($comment->getContent()) ?>
      </dd>
      <dd>
        [<?php echo link_to('Éditer', 'comments/edit?id='.$comment->getId()) ?>]
        [<?php echo link_to('Supprimer', 
                            'comments/delete?id='.$comment->getId(),
                            'confirm=Êtes-vous sûr ?') ?>]
      </dd>
    <?php endforeach; ?>
    </dl>
  <?php else: ?>
    <p>No comment yet.</p>
  <?php endif; ?>
<?php endif; ?>

Utilisation d'un helper pour des tâches courantes de templating

La fonction format_comment_author est un helper maison, que nous définissons dans un nouveau fichier lib/helper/CommentHelper.php :

 php
<?php
/**
 * Returns a formatted html string for author including website link if any
 * 
 * @param  string   $name
 * @param  string   $site
 * @param  boolean  $nofollow
 * @return string 
 */
function format_comment_author($name, $site=null, $nofollow=true)
{
  if (!is_null($site) && preg_match('/^http/i', $site))
  {
    return sprintf('<a href="%s"%s>%s</a>', 
                   $site, 
                   $nofollow === true ? ' rel="nofollow"' : '',
                   $name);
  }
  else
  {
    return $name;
  }
}

Mise à jour du back-office de gestion des billets

Ceci fait, modifions le fichier de configuration du back-office d'administration des billets créé précemment et situé dans le fichier apps/back/modules/posts/config/generator.yml, afin d'appeller notre nouveau composant postcomments pour la vue d'édition d'un billet :

  [...]

    # Customisation du formulaire d'ajout/édition
    edit:
      
      [...]

      # Affichage d'une sélection de champs
      display:         [author_id, title, excerpt, body, post_sections, ~postcomments]

Vous noterez le caractère ~ précedant le nom du composant : encore une convention Symfony qui nous simplifie la vie :)

Gestion de l'échappement

Vous avez tous déjà entendu parler des failles XSS ? Pour nous en prémunir partiellement, nous allons activer l'échappement automatique des contenus passés à une vue, en ajoutant ces directives dans le fichier apps/back/config/settings.yml :

all:
  .settings:
    escaping_strategy: both
    escaping_method:   ESC_ENTITIES

Ainsi, dans notre cas toutes les chaînes seront échappées en entités HTML pour plus de sécurité. Pour plus d'information, rendez-vous dans la section dédiée de la documentation officielle.

Au final, voici ce que ça donne quand on édite un billet :

Affichage des commentaires d'un billet

Champs virtuels

Notre liste de billets, pour l'instant, ne nous informe pas pour chacun le nombre de commentaires associés. On va y remédier simplement en créant un getter ad-hoc dans notre objet de donnée Post et en appellant le champs virtuel associé. Dans le fichier lib/model/Post.php, on rajoute la méthode suivante :

 php
  public function getCommentsNumber()
  {
    return $this->countComments();
  }

Et dans le fichier apps/back/modules/posts/config/generator.yml, on affiche le champs virtuel comments_number dans la vue en liste :

  [...]

    # Customisation des colones de la vue en liste
    list:
      display:         [=title, excerpt, Author, comments_number, created_at, updated_at]

Voici ce que ça donne :

Liste des billets, avec nombre de commentaires associés

En conclusion

Voila, notre application prend forme doucement. On pourrait passez des heures à ajouter des détails par-ci par-là, mais je vous laisse le faire en compagnie de la documentation :)

samedi 28 avril 2007

Gagnez du temps avec Symfony 1.0 et son générateur de back-office

Lors du dernier petit-déjeuner Clever Age que j'ai animé sur les frameworks PHP, j'ai effectué une démonstration des fonctionnalités de génération de back-office existantes dans Symfony : la plupart des gens présents - pour la plupart découvrant la notion même de framework - ont été très impressionnés par la facilité déconcertante avec laquelle il était possible de développer une application complète en très peu de temps et d'étapes techniques grâce au générateur d'admin...

Personnellement, je suis tellement habitué à travailler avec de tels outils désormais que j'oublie parfois comme la vie est plus difficile sans eux... Je vais donc faire une démonstration afin que chacun puisse se faire son idée, sur sa propre machine :)

Pour faire très original, on va créer une petite application sommaire de gestion de weblog, doté des fonctionnalités suivantes :

  • Un auteur par billet
  • Billets multi-catégoriques (on pourrait aussi parler de tags)
  • Commentaires pour chaque billet

L'avantage est que la plupart des frameworks web proposent ce type de tutoriaux, donc ainsi vous pourrez plus aisément comparer :)

Installation de Symfony

Je vous renvoie à la documentation officielle ou à ce tutoriel pour installer Symfony sur votre machine et configurer un vhost apache pour votre nouveau projet. On partira sur la version 1.0.2, soit la dernière version stable disponible à l'heure où sont écrites ces quelques lignes.

Création d'un nouveau projet

Imaginons que votre projet soit créé dans /var/www :

$ sudo -s
# cd /var/www
# mkdir sftest && cd sftest
# symfony init-project sftest

Note: Si la page web par défaut du projet n'affiche pas d'images, il se peut que votre vhost ne trouve pas les éléments médias génériques de Symfony ; dans ce cas, un lien symbolique comme ci-dessous devrait régler le problème :

# ln -s /usr/share/php/data/symfony/web/sf web/sf

Note : Vous pourriez tout autant utiliser un alias apache dans votre vhost.

Créons maintenant nos deux applications front et back qui recevront le front-office et la console d'administration de notre projet :

# symfony init-app front 
# symfony init-app back

On crée une base de données dédiée au projet :

# mysql -uroot -p
> CREATE DATABASE sftest CHARACTER SET utf8 COLLATE utf8_general_ci;
> GRANT ALL ON sftest.* TO sftest@localhost IDENTIFIED BY '1234567'
> FLUSH PRIVILEGES;
> \q

Configuration de l'accès à la base de données

D'abord, on renseigne notre DSN MySQL dans le fichier config/databases.yml :

all:
  propel:
    class:          sfPropelDatabase
    param:
      dsn:          mysql://sftest:1234567@localhost/sftest

On fait la même chose pour Propel, dans le fichier config/propel.ini :

propel.database.url = mysql://sftest:1234567@localhost/sftest

Configuration du modèle de données

On crée le schéma de base notre de données, dans le fichier config/schema.yml :

propel:

  blog_authors:
    _attributes:    { phpName: Author }
    id: 
    name:           varchar(255)
    email:          varchar(255)

  blog_posts:
    _attributes:    { phpName: Post }
    id: 
    title:          varchar(255)
    excerpt:        longvarchar
    body:           longvarchar
    author_id:
    created_at:
    updated_at:
  
  blog_comments:
    _attributes:    { phpName: Comment }
    id: 
    post_id:
    author:         varchar(255)
    email:          varchar(255)
    site:           varchar(255)
    content:        longvarchar
    created_at:

  blog_sections:
    _attributes:    { phpName: Section }
    id: 
    name:           varchar(255)

  blog_posts_sections:
    _attributes:    { phpName: PostSection }
    id: 
    post_id:
    section_id:

Il y a beaucoup de magie dans la syntaxe de ce fichier. Retenez juste que les champs id, *_id et *_at sont nommés en vertus de conventions Symfony pour gérer automatiquement clés primaires, clés étrangères et les champs de type DATETIME.

Création d'un jeu de données de test

De même et parce qu'on est des gens sérieux (mais surtout parceque c'est pratique), on crée d'emblée un jeu de données de test (ou fixtures), dans un nouveau fichier data/fixtures/data.yml :

Author:
  NiKo:
    name:    NiKo
    email:   tepafou@fai.com

Post:
  FirstPost:
    title:   Mon premier post !
    excerpt: Un premier billet prometteur...
    body: >
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer 
      consectetuer congue diam. Sed eu enim. Cras fringilla, erat et pretium 
      tincidunt, elit nibh imperdiet lectus, vel viverra erat velit in  
      metus. Ut ipsum ante, ornare luctus, hendrerit in, ultricies id, est.
    author_id: NiKo
  
  SecondPost:
    title:   Mon deuxième billet
    excerpt: Un deuxième billet tout aussi savoureux.
    body: >
      Suspendisse potenti. Mauris id risus. Cras urna. Etiam vel enim nec 
      dui ultrices condimentum. Curabitur bibendum ultrices quam. Nulla 
      sodales risus eget nunc.
    author_id: NiKo

Section:
  Humeurs:
    name:    Humeurs
  Geek: 
    name:    Geek
  Ubuntu:
    name:    Ubuntu

PostSection:
  # First post categories
  FirstPost_Humeurs:
    post_id: FirstPost
    section_id: Humeurs
  FirstPost_Geek: 
    post_id: FirstPost
    section_id: Geek

  # Second post categories
  SecondPost_Geek:
    post_id: SecondPost
    section_id: Geek
  SecondPost_Geek: 
    post_id: SecondPost
    section_id: Ubuntu

Comment:
  Comment1:
    post_id: FirstPost
    author:  Jean-Paul
    email:   "jp@fai.com"
    site:    "http://blog.jeanpaul.com"
    content: Bravo, belle intervention.

  Comment2:
    post_id: SecondPost
    author:  Jean-Luc
    email:   "jl@fai.com"
    site:    "http://blog.jeanluc.org"
    content: Exactement, vous avez raison.

Ceci fait, on va lancer la génération du fichier SQL et des classes représentant notre modèle, créer les tables physiquement dans notre base et insérer notre jeu de données de test :

# symfony propel-build-all-load back

Vous noterez qu'un seule ligne de commande est à appeller, ce qui simplifie grandement les phases de prototypage.

Note : En cas de modification profonde du modèle de données, il est vivement conseillé de vider le cache symfony :

# symfony cc

Ajout des méthodes __toString() aux objets de données

Afin d'avoir facilement un descripteur texte pour notre objet Author, nous allons implémenter une méthode __toString() dans sa classe associée située dans le fichier lib/model/Author.php :

 php
class Author extends BaseAuthor
{
  public function __toString()
  {
    return $this->getName();
  }
}

Cette méthode retournera le contenu du champs name de l'enregistrement de la table blog_authors correspondant pour identifier l'objet PHP sous la forme d'une chaîne de caractère descriptive. Vous pouvez aussi adapter ce principe pour les objets Post et Section, par exemple.

Génération d'un back-office d'administration des billets

Maintenant, on va générer une interface d'administration de nos objets Post, accessible par un contrôleur /posts depuis notre application back :

# symfony propel-init-admin back posts Post

L'interface d'administration est maintenant accessible via /back_dev.php/posts derrière la racine de l'url de votre instance projet Symfony :-)

Administration des billets

C'est un peu sec par défaut et les sections associées aux billets du blog ne sont pas gérées, il nous faut donc adapter le fichier de configuration du générateur d'admin de Symfony pour ce module, situé dans le fichier apps/back/modules/posts/config/generator.yml :

generator:
  class:               sfPropelAdminGenerator
  param:
    model_class:       Post
    theme:             default

    # Customisation des colones de la vue en liste, lien d'édition sur le titre
    list:
      display:         [=title, excerpt, Author, created_at, updated_at]

    # Customisation du formulaire d'ajout/édition
    edit:
    
      # Champs personnalisés
      fields:
        # Création d'un champs d'administration des sections associées
        post_sections: { type: admin_check_list, params: through_class=PostSection }
    
      # Spécification des champs de formulaire à afficher
      display:         [author_id, title, excerpt, body, post_sections]

Un raffraîchissement des interfaces en mode développement (en appellant le contrôleur back_dev.php dans l'url) affichera nos interfaces modifiées en conséquences. Si vous utilisez le contrôleur de production (/back.php), n'oubliez pas de vider le cache symfony pour visualiser vos modifications :

# symfony cc

On reproduira exactement la même opération pour nos autres objets à administrer (Author, Comment et Section):

# symfony propel-init-admin back authors Author
# symfony propel-init-admin back sections Section
# symfony propel-init-admin back comments Comment

Voila, une vingtaine de minutes nous auront suffit pour générer une application en ligne relativement complète. Il restera à gérer notamment :

Amusez-vous bien :-)

mercredi 7 février 2007

Créer un projet Symfony à partir des dépôts Subversion sous Ubuntu

Un des gros avantages du framework Symfony, c'est qu'il est régulièrement mis à jour. En ce sens, l'utilisation de liaisons externes Subversion permet de s'affranchir des opérations récurrentes de mise à jour manuelles du code du framework.

Seul prérequis pour mettre en oeuvre la technique décrite ci-après, avoir accès à un dépôt Subversion pour y stocker son propre projet personnel.

Voyons donc comment créer un projet Symfony from scratch à partir des sources du dépôt officiel, sous Ubuntu par exemple...

Conventions

Nous admettrons que nous avons mis en place un dépôt Subversion et que celui-ci est accessible à l'URL http://trac.mondomaine.tld/svn/monprojet.

Création du projet subversion

$ mkdir monprojet  && cd monprojet

On versionne notre projet nouvellement créé dans Subversion et on en fait un checkout en suivant :

$ echo "Mon projet README" > README
$ svn import -m "Initial import" . http://trac.mondomaine.tld/svn/monprojet
$ rm README && svn co http://trac.mondomaine.tld/svn/monprojet .

Liaison des sources de Symfony

On récupère le contenu intégral du trunk de Symfony dans un répertoire virtuel vendor/symfony, grâce à un svn:externals :

$ mkdir vendor && svn add vendor
$ svn propset svn:externals "symfony http://svn.symfony-project.com/trunk/" vendor

On commite :

$ svn commit -m "Added svn:externals to sf trunk in vendor/" vendor/

On oublie pas d'updater :

$ svn up

L'intégralité du trunk de Symfony est alors téléchargé en local (cela peut prendre un peu de temps).

Création du projet Symfony

Pour bien utiliser les capacités de Subversion par la suite, on créé un répertoire trunk dans lequel nous allons initialiser notre projet Symfony :

$ mkdir trunk && cd trunk
$ ../vendor/symfony/data/bin/symfony init-project monprojet

De même, on crée en même temps les traditionnels répertoires branches et tags :

$ cd ..
$ mkdir branches tags

Pour l'heure, un ls -l nous donne à la racine du projet subversion :

$ ls -l
total 20
drwxr-xr-x  2 niko niko 4096 2007-02-07 17:02 branches
-rw-r--r--  1 niko niko   95 2007-02-07 16:47 README
drwxr-xr-x  2 niko niko 4096 2007-02-07 17:02 tags
drwxr-xr-x 13 niko niko 4096 2007-02-07 16:59 trunk
drwxr-xr-x  4 niko niko 4096 2007-02-07 16:56 vendor

Configuration du projet Symfony

Il faut maintenant configurer le projet Symfony pour qu'il sâche trouver les librairies de base que nous avons précédemment récupéré - et surtout que le projet soit portable -, en éditant le fichier trunk/config/config.php :

$sf_symfony_lib_dir  = dirname(__FILE__).'/../../vendor/symfony/lib';
$sf_symfony_data_dir = dirname(__FILE__).'/../../vendor/symfony/data';

On teste l'installation en lançant la commande ./symfony -T depuis la racine du projet Symfony :

$ cd trunk
$ ./symfony -T

Si ça marche, on ajoute tout ce qui est nouveau fichier, et on commite en suivant :

$ cd ..
$ svn stat | grep ? | awk '{ print $2 }' | xargs svn add
$ svn commit -m "File structure created, sf project initialized" .

On pourra également faire un lien symbolique vers le répertoire web/sf, ou bien le définir en tant qu'alias dans le vhost apache :

<VirtualHost toto.monprojet.tld>
  (...)
  alias /sf /path/to/vendor/data/web/sf
  (...)
</VirtualHost>

Conclusion

L'avantage de toutes ces manipulations est que désormais, un svn up mettra à jour non seulement les fichiers de notre application, mais également le framework en lui-même. Les éternels grincheux crieront au loup quand au danger de lier une version de développement (trunk), je leur répondrai qu'un svn:externals peut tout aussi bien pointer vers une révision ou un tag particulier.

Par exemple, si vous désirez éviter de lier le trunk de Symfony, vous pouvez lier la version 1.0RC2 en spécifiant son url dans votre svn:externals :

$ svn propset svn:externals "symfony http://svn.symfony-project.com/tags/RELEASE_1_0_0_rc2/" vendor

Pour la suite, je vous renvoie à la documentation officielle de Symfony :-)

lundi 5 février 2007

Sécuriser son Ubuntu-server

L'intérêt d'avoir une Dedibox sur une classe C réputée niche à boulets, c'est qu'on est confronté à de nombreuses tentatives de hacks, DDOS et autres bruteforce quasi-quotidiennement. De quoi envisager une approche totalement paranoïaque de la sécurité du système ; voila quelques bonnes résolutions pour une Ubuntu-server.

Utilisez de vrais mots de passe

Minimum 8 caractères avec des lettres, des chiffres et de la ponctuation. Changez-en régulièrement.

Mieux, utilisez des clés SSH.

Désactiver l'accès root depuis SSH

Si quelqu'un arrivait à craquer votre accès SSH, il serait dommage qu'il arrive directement en root. Le moyen le plus simple pour éviter cela, c'est de désactiver l'accès SSH en root, en éditant le fichier /etc/ssh/sshd_config et en remplaçant la ligne :

PermitRootLogin: yes

par

PermitRootLogin: no

Changer le port SSH par défaut

Toujours dans le même fichier /etc/ssh/sshd_config, changer le numéro de port par défaut (22) par un autre :

Port 12345

Attention, ne prenez pas un numéro de port utilisé par un des autres services que vous utilisez sur le serveur (80 pour http, 25 pour smtp, 443 pour https, etc.)

Par exemple si vous déclarez le port 12345 pour SSH, vous vous connecterez ainsi sur la machine :

$ ssh user@machine.tld -p 12345

Note : Chaque modification du fichier sshd_config doit occasionner un redémarrage du service :

$ sudo /etc/init.d/ssh restart

Blacklister les IP malsaines

fail2ban est un petit utilitaire qui scanne les logs d'accès sshd et blackliste les IP depuis lesquelles émanent trop de tentatives de connexion échouées. Pour l'installer :

$ sudo apt-get install fail2ban

Plus d'infos sur la configuration et l'utilisation de fail2ban.

Interdire l'execution depuis /tmp

Le répertoire /tmp est souvent utilisé par les script-kiddies de tous poils pour y déposer leurs executables et les lancer. Une approche intelligente du phénomène est d'interdire l'execution de programme sur ce point de montage, en ajoutant la directive noexec à votre fichier /etc/fstab, comme dans cet exemple :

/dev/sda3   /tmp    ext3   noexec,nosuid     0    2

Si vous ne possédez pas de point de montage pour /tmp, pas de panique : vous allez pouvoir en créer un à l'arrache :-)

Attention :

  • Le gestionnaire de paquet apt a parfois besoin d'executer des scripts depuis cet emplacement lors de certaines mises à jour, chose que la drective noexec interdit;
  • MySQL a parfois besoin de créer des tables temporaires à cet emplacement pour traiter des requêtes coûteuses, chose que le nosuid interdit.

La manipulation décrite ci-dessus n'est donc à appliquer en connaissance de cause. (voire à ne pas appliquer du tout, en fait. Hem.)

Installer un firewall

Shorewall est un firewall simple à administrer, mais pas pour autant moins efficace que les autres. L'installation se fait par un traditionnel :

$ sudo apt-get install shorewall

Un très bon tutoriel de configuration du logiciel existe, n'hésitez pas à aller y faire un tour. L'idée est dans tous les cas de tout interdire par défaut et d'ouvrir les ports un à un en fonction de vos besoins.

Vérifier régulièrement la présence de rootkits

Chkrootkit scanne votre machine et y déniche les rootkits les plus répandus. Le programme s'installe facilement via la commande :

$ sudo apt-get install chkrootkit

Et se lance de cette façon :

$ sudo chkrootkit

Vous pouvez croner l'exécution du programme quotidiennement et vous en envoyer le résultat par email, en ajoutant cette ligne dans votre crontab :

0 3    *   *   *   chkrootkit 2>&1 | mail vous@domain.tld -s "Rapport de chkrootkit"

D'autres outils peuvent tout aussi bien faire l'affaire et peuvent être utilisés de façon complémentaires :

Ces deux outils sont disponibles dans les dépôts officiels Ubuntu et sont d'une utilisation très simple.

Note : si la commande mail est inconnue de votre système, installez le paquet mailx :

$ sudo apt-get install mailx

Emprisonnez vos programmes et utilisateurs

Chroot est un programme qui permet de littéralement emprisonner un utilisateur ou un programme dans un environnement désolidarisé du reste du système, ce qui garanti une réversibilité des dommages occasionnés.

Plus d'informations sur la commande chroot.

Encore quelques conseils de base

  • Mettez régulièrement à jour votre système
  • Utilisez toujours les dépôts officiels Ubuntu
  • N'installez jamais de softs pour tester en oubliant de les désinstaller par la suite
  • N'ouvrez de nouveaux services que si vous en avez réellement besoin
  • Surveillez vos logs
  • Surveillez régulièrement les process système
  • Monitorez votre machine, surveillez les comportements anormaux
  • Ne donnez jamais vos mots de passe
  • Touchez du bois

Les commentaires bouillent d'impatience de recevoir vos remarques, suggestions et contributions.

Edit : Prise en compte de certains commentaires judicieux.

Edit 2 : JJL pose une vraie question : Ubuntu est-elle prête pour le serveur ? Sachant que les paquets Universe contenant des choses comme Trac ou Bacula ne sont pas maintenues au niveau patches de sécurité, cela laisse songeur...

jeudi 18 janvier 2007

Synchro distante automatique via un daemon rsync sur Ubuntu

Et non ! Rsync n'est pas une voiture des années 90 mais bien un outil de synchronisation de fichiers à distance très puissant. Il peut notamment tourner en daemon afin d'autoriser les appels distants automatiques, via Cron par exemple.

Si par un hasard hallucinant vous ne disposiez pas de rsync sur votre Ubuntu, voici la démarche à suivre pour l'installer en ligne de commande :

$ sudo apt-get install rsync

Bien. Nous disposons de deux machines, la machine A - disposant d'un utilisateur jeanpierre - et la machine B - habitée par edmond. Nous devons automatiser la synchro d'un répertoire présent sur la machine A vers la machine B. On va donc installer un daemon rsync sur la machine A et le configurer en créant le fichier /etc/rsyncd.conf :

uid             = jeanpierre 
gid             = jeanpierre
use chroot      = no    
max connections = 4
syslog facility = local5
pid file        = /var/run/rsyncd.pid

[mon_partage]
  comment = Mon partage
  path = /home/jeanpierre/monpartage
  read only = yes
  list = yes
  hosts allow = *
  auth users = edmond, gerard
  secrets file = /etc/rsyncd.secrets

Je vous renvoie à cette page sur la syntaxe du fichier rsync.conf pour plus de renseignements.

On crée un fichier process vide :

jeanpierre@machineA:~$ sudo touch /var/run/rsyncd.pid

Les comptes utilisateurs se définissent dans le fichier /etc/rsyncd.secrets sous la traditionnelle forme login:motdepasse comme ci-dessous :

edmond:3dm0nd
gerard:g3r4rd

Par souci de sécurité et de confidentialité, ces fichiers ne devront pas être lisibles par un autre utilisateur que le root, donc :

jeanpierre@machineA:~$ sudo chmod 640 /etc/rsyncd.conf
jeanpierre@machineA:~$ sudo chmod 640 /etc/rsyncd.secrets

Lancer rsync en daemon sur la machine A (machinea.domain.tld) :

jeanpierre@machineA:~$ sudo rsync --daemon

Et depuis la machine B (machineb.domain.tld) :

edmond@machineB:~$ rsync -avz edmond@machinea.domain.tld::mon_partage ~/mon/repertoire/cible

La saisie du password de l'utilisateur edmond défini précedemment lancera la synchronisation effective des fichiers. Pour éviter la saisie manuelle du password, il faut envisager d'utiliser l'option --password-file=FILE. Pour se faire, il faut créer un fichier contenant juste le mot de passe en clair, par exemple dans /home/edmond/.rsync_passwd comme ceci :

3dm0nd

Ce fichier devra n'être accessible que par l'utilisateur système utilisant la commande rsync. Dans le cas de l'utilisateur connecté à la machine B :

edmond@machineB:~$ chmod 640 /home/edmond/.rsync_passwd

On peut alors lancer une synchro de cette façon :

edmond@machineB:~$ rsync -avz edmond@machinea.domain.tld::mon_partage ~/mon/repertoire/cible --password-file=/home/edmond/.rsync_passwd

L'avantage de cette ligne de commande est qu'elle peut être appellée depuis un Cron et donc ne pas nécessiter de saisie du mot de passe manuellement.

Enfin, sachez que les éventuelles erreurs d'authentification seront logguées dans le fichier /var/log/syslog.

mercredi 29 novembre 2006

Installer XDebug sur Ubuntu et l'utiliser avec Symfony

Si comme moi vous développez beaucoup avec Symfony [1] (ou avec PHP en général), les informations fournies par XDebug peuvent être très utiles. Pour installer XDebug 2.0RC1 sur une Ubuntu Edgy, voici la démarche à suivre :

$ sudo apt-get install php-pear php5-dev
$ sudo pecl install xdebug-beta

C'est dur hein ? Bon, il reste une petite manipulation : il faut activer l'extension dans votre (ou vos) fichier(s) php.ini. Par exemple chez moi, je rajoute cette ligne à la toute fin du fichier :

zend_extension="/usr/lib/php5/20051025/xdebug.so"

Et je relance Apache. Pour ceux qui connaissent la barre de débug en ligne de Symfony, vous allez voir du changement (avant / après)

Évidemment les perfs en prennent un coup, mais le jeu en vaut la chandelle quand on cherche le vilain dysfonctionnement volatile.

Merci XDebug, merci Symfony !

Edit : Ajout du paquet php_pear contenant pecl, merci Mat.

Notes

[1] Qui vient tout juste de sortir en 1.0 beta 1 !

dimanche 22 octobre 2006

Sauvegarde facile avec Hubackup

[via Jorge Castro]

Sauvegarder son répertoire /home régulièrement peut vous prémunir contre l'aliénation mentale en cas de crash disque. Pour vous aider à backuper votre système simplement, Dieu a inventé hubackup :

$ sudo apt-get install hubackup
$ hubackup

Hubackup

Vous n'avez plus qu'à insérer un CD/DVD vierge, et à le graver.

Simple, efficace, sans bavure.

Edit : Preuve (s'il en est besoin) de l'utilité de faire des backups régulièrement :-/

vendredi 21 juillet 2006

Le ridicule ne tue pas

[Via Totalement Crétin]

Certains ne se font toujours pas à l'idée que dès qu'on publie un fichier destiné à la consultation (image, vidéo, texte, etc.) sur internet, on le rend physiquement accessible à l'internaute (il est stocké sur le disque dur de la machine) ; il est donc totalement crétin inutile d'employer des techniques parfois ridicules empêchant captures d'écran ou autres clics-droit de la souris.

Pour achever de convaincre les plus sceptiques, ouvrez n'importe quel site internet depuis Firefox et faites Outils > Informations sur la page et parcourez les entrées du menu Médias... Ou encore, tappez about:cache toujours dans Firefox... Et IE n'est pas épargné, l'intégralité des fichiers téléchargés sont stockés dans le répertoire Temporary Internet Files du dossier de profil courant de l'utilisateur du système.

Moralité ? Si vous ne voulez pas que les internautes puissent disposer d'un fichier que vous publiez sur internet, NE LE PUBLIEZ PAS.

Merci de votre attention.

- page 3 de 4 -