Debian: configuration minimale d'un VPS

Debian: configuration minimale d'un VPS
Photo by Lukas / Unsplash

Après avoir remporté un VPS suite à une action de mon hébergeur préféré sur Twitter, voici une liste de « choses à faire » après l'installation de Debian Wheezy sur un VPS chez DediZones. Cette marche à suivre n'est pas la panacée et ne correspond pas à tous les usages. L'usage visé est celui d'un serveur web sur lequel je déploie un serveur XMPP (Prosody), un émetteur de mails (Exim), une pile LEMP (NGINX, MariaDB, PHP-FPM) pour faire tourner GNU Social, et quelques services en vrac sur les ports 80 et 443 (MediaGoblin, Etherpad Lite). Je ne ferai pas l'explication de tout les manipulations visant au déploiement de tous ces services, mais de comment procéder à la configuration générale de la distribution pour pouvoir commencer à construire sur les briques de base.

Avant toute chose, il s'agit de nommer sa machine. J'ai une marotte : donner aux machines que j'utilise des prénoms d'auteurs ou de philosophes. Par exemple, j'ai un Soeren (Kierkegaard) et un Gottfried (Leibniz). Et vous, quels sont les noms que vous donnez à vos machines ? Dans votre zone DNS, il faut enregistrer un A pour le serveur. On utilisera pour l'exemple serveur.domaine.tld, qu'on fera pointer sur l'IP du serveur. Dans le panel d'administration de notre hébergeur, il suffit de renommer la machine en serveur.domaine.tld et le tour est joué.

serveur 10800 IN A ip.du.serveur

Reste à se connecter au serveur par SSH. Pour l'instant, nous n'avons que le compte root, donc ssh root@ip.du.serveur ou ssh root@serveur.domaine.tld, c'est du pareil au même (je préfère la première option à ce stade, la propagation DNS du nom de la machine peut prendre un peu de temps).

D'abord, on va faire le ménage : puisqu'on a une installation en amd64 (64 bits), on va supprimer tous les paquets i386 (32 bits) qui polluent notre installation. Installons également nano, mais à chacun son éditeur préféré (VIM FTW)

apt-get update
apt-get remove --purge "dpkg --get-selections | grep i386 | awk '{print $1}'"
dpkg --remove-architecture i386
apt-get update
apt-get install nano

Avant de créer un nouvel utilisateur, une précaution s'impose : les répertoires personnels sont par défaut lisibles par tous les utilisateurs du système. Afin d'améliorer la sécurité et la confidentialité de tout nouvel utilisateur créé, nous pouvons faire en sorte que les répertoires personnels ne soient lisibles que par leurs propres propriétaires. Le comportement par défaut de Debian est catastrophique sur ce point, mais il se règle facilement.

dpkg-reconfigure adduser

Il est donc temps de créer un nouvel utilisateur, chaque minute passée connecté en root me donne des pustules. Ajoutons tout de même cet utilisateur au groupe sudo, afin de pouvoir utiliser la commande du même nom lors des opérations d'administration (mises à jour en tête).

adduser pseudo
gpasswd -a pseudo sudo

Nous y sommes presque ! Il nous reste à configurer SSH pour empêcher la connexion avec le compte root, et forcer l'authentification par clef en désactivant l'authentification par mot de passe. Sur notre ordinateur local, il faut créer une clef d'authentification et l'envoyer sur le serveur distant. Pour cela, créons un clef RSA de 2048 bits (ce sont les valeurs par défaut), et protégeons-la par un mot de passe (parce qu'on n'est pas fous non plus).

ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa): /home/user/.ssh/serveur
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/user/.ssh/serveur.
Your public key has been saved in /home/user/.ssh/serveur.pub.`

Reste à envoyer la clef publique dans la liste des clefs connues par le serveur.

ssh-copy-id -i /home/user/.ssh/serveur.pub pseudo@ip.du.serveur

Sur le serveur, nous allons éditer la configuration du démon SSH pour qu'il ne permette plus que des authentifications par clef (donc désactiver les authentifications par mot de passe), et ne plus permettre au compte root de se connecter sur le port SSH. Nous pouvons aussi changer le port d'écoute de SSH, ce qui peut être bienvenu mais pas obligatoire. Les valeurs sont à modifier dans /etc/ssh/sshd_config, ci-dessous les valeurs éditées.

Port 22 # on peut changer ici le port d'écoute
PasswordAuthentication no
PermitRootLogin no
AllowUsers pseudo

Reste à redémarrer le démon SSH, et à vérifier que la connexion passe bien (en gardant sur le côté un terminal ouvert sur la session root de SSH, qu'on utilisera comme terminal de secours si quelque chose dans la configuration déconne). Dans la session root, relancer SSH : service ssh restart. Pour vérifier si ça marche, il suffit de lancer un nouveau terminal et tenter de se connecter sur le serveur, où 22 est le port dont vous avez décidé en votre âme et conscience tout en prenant gare à ce que ce ne soit pas un port utilisé par un autre service.

ssh pseudo@ip.du.serveur:22

Ça fonctionne ? Merveilleux. Ça ne fonctionne pas ? Le terminal de secours resté en root a été gardé pour réparer les pots cassés. J'aime bien configurer SSH sur mon ordinateur local pour ne plus avoir à me soucier de l'IP, du port ou de l'utilisateur utilisé. Il suffit d'éditer .ssh/config avec une configuration ressemblant à celle-ci (même remarque pour le port 22).

Host serveur
    HostName ip.du.serveur
    Port 22
    User pseudo

Retour à la session pseudo : si elle est fonctionnelle, on peut clore la session root, nous n'en avons plus besoin (mes pustules se résorbent).

Au menu maintenant : configurer les dépôts de Debian et se donner quelques outils pratiques. Tout d'abord, il faut éditer la configuration d'apt pour ne pas installer trop de paquets et empêcher l'installation des paquets suggérés ou recommandés. Pour cela, il faut créer et éditer le fichier /etc/apt/apt.conf avec le contenu ci-dessous :

APT::Install-Recommends "0"; APT::Install-Suggests "0"; Acquire::Languages "none";

Parce que j'aime me simplifier le terminal, deux commandes bien pratiques à ajouter : bash-completion pour que les commandes soient complétées en jouant de la touche tabulation, et command-not-found qui nous dira si une commande qu'on utilise existe dans les dépôts (et dans quel paquet !).

sudo apt-get install nano bash-completion command-not-found

Pour activer la complétion du bash, il faut éditer /etc/bash.bashrc et dé-commenter les lignes idoines. L'opération se termine en "sourçant" le fichier avec source /etc/bash.bashrc pour que les changements soient effectifs. Pour mettre à jour la base de données de command-not-found, update-command-not-found comme le suggère le message d'installation.

Avant de mettre à jour la distribution, on va faire un gros ménage et supprimer les paquets inutiles pour une installation minimale (j'ai dû le lancer deux fois, il ne faut pas hésiter à insister). Suivez le guide (puisque l'installation se veut minimale, on peut mal de perdre quoi que ce soit). Supprimons aussi la liste des paquets de apt pour ne pas avoir à télécharger les index de traduction (facultatif).

sudo apt-get  purge -y -f -m apache* php5* sendmail* samba* fetchmail* procmail*  exim* mysql* bind9* courier-authlib maildrop expect openntpd ntpdate  bluez bluetooth
sudo rm -rf /var/lib/apt/lists/*

Enfin, empêchons Debian de remplacer upstart par sysvinit au cours d'une mise à jour, sombre histoire relative à la cohabitation de Wheezy avec OpenVZ.

echo upstart hold | sudo dpkg --set-selections

Encore une étape et on pourra mettre à jour le bazar. En éditant le fichier /etc/apt/source.list très peu fourni par défaut, nous aurons une Debian un poil plus à jour avec la liste suivante.

deb http://ftp.fr.debian.org/debian/ wheezy main
deb-src http://ftp.fr.debian.org/debian/ wheezy main

deb http://ftp.fr.debian.org/debian wheezy-updates main
deb-src http://ftp.fr.debian.org/debian wheezy-updates main

deb http://ftp.fr.debian.org/debian/ wheezy-proposed-updates main
deb-src http://ftp.fr.debian.org/debian/ wheezy-proposed-updates main

deb http://security.debian.org/ wheezy/updates main
deb-src http://security.debian.org/ wheezy/updates main`

On peut enfin mettre à jour et relancer command-not-found pour que notre système soit au courant des nouveaux dépôts.

sudo apt-get update; sudo apt-get dist-upgrade; sudo update-command-not-found

Maintenant que nous sommes à jour (autant que peut l'être Debian dans sa version stable, je vous entends persifler), prenons enfin le temps de reconfigurer le système. Je ne change pas grand chose, voyez plutôt. Le but de la manœuvre est d'avoir un système un peu plus verbeux à l'installation, et en français.

sudo dpkg-reconfigure debconf # ignore questions with a priority less than: medium
sudo dpkg-reconfigure locales # fr_FR.UTF-8
sudo dpkg-reconfigure tzdata # Europe/Paris`

Nous avons maintenant un système minimal et configuré, ce qui suit est de l'ordre du bonus, de briques pour configurer un système ouvert sur le web.

Afin d'avoir une session SSH plus facilement utilisable, plus belle, et qui rend le poil plus soyeux, j'utilise byobu conjointement avec tmux et zsh (prezto, en fait). Installons tout ça.

sudo apt-get install byobu tmux zsh-beta

Pour être certain que byobu est bien lancé au démarrage de la session, un petit byobu-enable et le tour est joué. Reste à installer prezto, ce qui nécessite l'installation de git. Installons-le.

sudo apt-get install git
tmux
zsh # continuer sans écrire .zshrc
git clone --recursive https://github.com/sorin-ionescu/prezto.git
"${ZDOTDIR:-$HOME}/.zprezto"
setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
    ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done

Normalement, il faudrait changer l'interpréteur de commande par défaut de l'utilisateur pour zsh (avec chsh -s /bin/zsh pseudo), mais le lancement automatique de byobu ne s'en accommode pas (en somme : il ne fonctionne pas). Nous configurerons plutôt byobu pour qu'il charge zsh une fois lancé, et non pas l'interpréteur de commande par défaut. Pour cela, créer le fichier .byobu/.tmux.conf et y inscrire la configuration ci-dessous.

set -g default-shell /bin/zsh
set -g default-command /bin/zsh

Parce que sans pare-feu notre serveur est tout nu sur l'Internet, installons apf-firewall qui a l'avantage d'être facilement configurable. Nous pouvons aussi installer denyhosts pour nous prévenir si un petit comique s'amuse à chatouiller notre port SSH (et lui claquer la porte au nez), ou fail2ban qui en plus de SSH gère bien d'autres services. À vous de voir.

sudo apt-get install apf-firewall
sudo nano /etc/default/apf-firewall # RUN="yes"
sudo nano /etc/apf-firewall/conf.apf

Quelques valeurs sont maintenant à changer. Pour trouver la nom de l'interface réseau (IFACE_IN, IFACE_OUT), sudo ifconfig tout simplement. Lançons cette commande dans un nouvel onglet de byobu en appuyant sur F2, profitons de l'occasion pour nous habituer au programme. Naviguer entre les onglets se fait avec les touches F3 et F4.

IFACE_IN="venet0" 
IFACE_OUT="venet0"

Les réglages suivants sont à effectuer en votre âme et conscience. L'argument principal est SET_MONOKERN="1" pour un VPS, le noyau est dit monolithique puisque c'est le même pour tous les serveurs virtuels déployés sur la machine. Si un module manque au noyau, demandez à votre hébergeur s'il est possible de l'activer.

SET_FASTLOAD="1"
SET_VNET="1"
SET_MONOKERN="1"
RAB="1"
BLK_MCATNET="1"
BLK_PRVNET="1"
BLK_RESNET="1"
BLK_IDENT="1"
SYSCTL_ROUTE="1"
SYSCTL_LOGMARTIANS="1"
EGF="1"
DLIST_PHP="1"
DLIST_SPAMHAUS="1"
DLIST_DSHIELD="1"
DLIST_RESERVED="1"

On active le pare-feu avec sudo apf -s. Si la connexion se bloque, s'il n'est plus possible de joindre le serveur : pas de panique, il tourne en mode de développement et dans 5 minutes il sera désactive. Si vous n'êtes pas déconnecté, on peut rééditer le fichier et changer cette dernière ligne : DEVEL_MODE="0" afin d'être sûr que le pare-feu ne se désactive plus. Reste à redémarrer APF, sudo service apf-firewall restart.

Note : les ports sont à ouvrir avec IG_TCP_CPORTS et IG_UDP_CPORTS pour les ports entrants, EG_TCP_CPORTS et EG_UDP_CPORTS pour les ports sortants. Basons-nous sur l'exemple (fonctionnel) suivant.

IG_TCP_CPORTS="21,22,25,53,80,443,110,143,6000_7000"
IG_UDP_CPORTS="20,21,53,123"
EG_TCP_CPORTS="21,25,80,443,43"
EG_UDP_CPORTS="20,21,53"

Que nous reste-t-il à faire ? Installer quelques outils qui vont bien d'abord : cron-apt pour être au courant des mises à jour, rkhunter et sa dépendance optionnelle unhide, logwatch qui par jeu de dépendances installera entre autres exim, le serveur de mails, et enfin l'antivirus clamav et son démon.

sudo apt-get install unhide rkhunter clamav-daemon clamav logwatch cron-apt

Quelques dépôts sont à ajouter à notre installation désormais. La structure de la liste suivante est aisément compréhensible me semble-t-il (notons la troisième ligne permettant d'ajouter la clef du dépôt).

/etc/apt/sources.list.d/dotdeb.list

## DotDeb
## http://www.dotdeb.org/instructions/
## wget http://www.dotdeb.org/dotdeb.gpg -O- | sudo apt-key add -
deb http://packages.dotdeb.org wheezy all
deb-src http://packages.dotdeb.org wheezy all

/etc/apt/sources.list.d/mariadb.list

## MariaDB
## https://downloads.mariadb.org/mariadb/repositories/
## sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
deb http://mirrors.linsrv.net/mariadb/repo/5.5/debian wheezy main
deb-src http://mirrors.linsrv.net/mariadb/repo/5.5/debian wheezy main

/etc/apt/sources.list.d/nginx.list

## NginX
## http://nginx.org/en/linux_packages.html#stable
## wget http://nginx.org/keys/nginx_signing.key -O- | sudo apt-key add -
deb http://nginx.org/packages/debian/ wheezy nginx
deb-src http://nginx.org/packages/debian/ wheezy nginx

/etc/apt/sources.list.d/prosody.list

## Prosody
## http://prosody.im/download/package_repository#debianubuntu
## wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add -
deb http://packages.prosody.im/debian wheezy main

Maintenant que les dépôts sont configurés, il ne reste plus qu'à installer tout ce dont nous avons besoin. Mais d'abord : mettre à jour.

sudo apt-get update; sudo apt-get dist-upgrade

Pour avoir un serveur PHP(-FPM) complet derrière NGinx, comme pour par exemple faire fonctionner une instance GNU Social, les dépendances sont les suivantes (voir l'article de Jean Baptiste).

sudo apt-get install nginx-extras php5-fpm php5-mysqlnd php5-curl php5-xmlrpc php5-gd php5-gmp php5-memcache php-gettext memcached

Envie d'un serveur de messagerie instantanée ? Rien de plus simple que Prosody sur Debian Wheezy (voir l'article pour la configuration).

sudo apt-get install lua-sec-prosody lua-socket-prosody prosody luarocks lua-event lua-zlib lua-dbi-sqlite3