Voici un article qui va me servir à rassembler les différentes documentations dont je me sert à chaque fois que j’installe un serveur Web. Là, j’ai pris un serveur virtuel chez OVH (à 3 € HT par mois, pour 2 GO de RAM et 10 GO d’espace disque), sur lequel j’ai installé une distribution Ubuntu 16.04.
Une fois l’installation terminée, on reçoit un email avec le mot de passe root. Commençons donc par nous logguer sur la machine.
Installations de base
Installons quelques outils utiles :
# apt-get install tree htop iftop make screen subversion git
Créons un nouvel utilisateur, et ajoutons-le au groupe sudo (pour qu’il puisse exécuter des commandes en tant que root) :
# adduser toto # usermod -aG sudo toto
Éditons la configuration SSH pour empêcher la connexion avec l’utilisateur root. Pour cela, il faut ouvrir le fichier /etc/ssh/sshd_config et éditer la ligne suivante :
PermitRootLogin no
Firewall
Créons ensuite un firewall minimal. Ouvrir le fichier /etc/init.d/firewall :
#!/bin/sh ### BEGIN INIT INFO # Provides: firewall # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start firewall at boot time # Description: Enable service provided by daemon. ### END INIT INFO # vidage des regles iptables -F iptables -X iptables -t nat -F # garde les connexions ouvertes iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # autorise les connexions SSH entrantes iptables -A INPUT -p tcp --dport 22 -j ACCEPT # autorise le ping entrant iptables -A INPUT -p icmp -j ACCEPT # autorise les connexions HTTP et HTTPS entrantes iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT # bloque les connexions entrantes iptables -P INPUT DROP iptables -P FORWARD DROP # bloque les SYN floods iptables -N syn_flood iptables -A INPUT -p tcp --syn -j syn_flood iptables -A syn_flood -m limit --limit 100/s --limit-burst 150 -j RETURN iptables -A syn_flood -j DROP # autorise loopback iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT
On exécute le script, puis on fait en sorte qu’il soit exécuté au démarrage du serveur :
# chmod +x /etc/init.d/firewall # /etc/init.d/firewall # update-rc.d firewall start 01 2 .
Si vous le souhaitez, vous pouvez installer les locales françaises :
# apt-get install language-pack-fr
Installation de NTP
# apt-get install openntpd ntpdate
Édition du fichier /etc/openntpd/ntpd.conf :
server fr.pool.ntp.org
Redémarrage :
# ntpdate fr.pool.ntp.org # service openntpd restart
Changement de nom de machine
# hostname nomdelamachine
Modifier le fichier /etc/hostname pour y mettre le nouveau nom.
Ajouter le nom de machine à la boucle locale dans le fichier /etc/hosts :
127.0.0.1 localhost nomdelamachine
Installation MySQL
# apt-get install mysql-server # mysql_secure_installation
Pour le second script, l’idée est de mettre à jour le mot de passe root, de supprimer le compte anonyme et d’interdire la connexion root distante.
Installation Apache
# apt-get install apache2 # a2enmod headers # a2enmod rewrite # a2enmod expires
Modification du fichier /etc/apache2/apache2.conf (pour diminuer certains timeout pour réduire la charge inutile sur le serveur) :
Timeout 150 KeepAliveTimeout 3
Modification du fichier /etc/apache2/conf-available/security.conf (pour réduire les informations fournies par le serveur) :
ServerTokens Prod ServerSignature Off <DirectoryMatch "/\.svn"> Require all denied </DirectoryMatch> <DirectoryMatch "/\.git"> Require all denied </DirectoryMatch>
Modification du fichier /etc/apache2/conf-available/charset.conf :
AddDefaultCharset UTF-8
Modification du fichier /etc/apache2/mods-available/mime.conf :
AddType application/x-truetype-font .ttf AddType application/vnd.ms-fontobject .eot AddType font/otf .otf AddType application/x-woff .woff AddType text/x-component .htc
Modification du fichier /etc/apache2/mods-available/deflate.conf :
AddOutputFilterByType DEFLATE application/x-truetype-font application/vnd.ms-fontobject font/otf application/x-woff
Création du fichier /etc/apache2/mods-available/expires.conf :
<IfModule mod_expires.c> ExpiresActive On # images ExpiresByType image/gif "access 20 days" ExpiresByType image/jpg "access 20 days" ExpiresByType image/jpeg "access 20 days" ExpiresByType image/png "access 20 days" ExpiresByType image/x-icon "access 20 days" # CSS et javascript ExpiresByType text/css "access 20 days" ExpiresByType application/javascript "access 20 days" ExpiresByType text/javascript "access 20 days" ExpiresByType application/x-javascript "access 20 days" # fontes ExpiresByType application/x-truetype-font "access 20 days" ExpiresByType application/vnd.ms-fontobject "access 20 days" ExpiresByType font/otf "access 20 days" ExpiresByType application/x-woff "access 20 days" </IfModule>
Création du fichier /etc/apache2/mods-available/headers.conf :
<IfModule mod_headers.c> <FilesMatch "\.(ttf|otf|eot|woff|svg)$"> Header set Access-Control-Allow-Origin "*" </FilesMatch> </IfModule>
Création de liens :
# cd /etc/apache2/mods-enabled # ln -s ../mods-available/expires.conf # ln -s ../mods-available/headers.conf
Vérification de la configuration :
# apache2ctl -t
Installation PHP
# apt-get install php7.0 php7.0-cli php7.0-curl php7.0-dev php7.0-gd php7.0-imap php7.0-intl php7.0-json php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-opcache php7.0-soap php7.0-tidy php7.0-xml php7.0-zip php-imagick php-memcached php-redis # apt-get install libapache2-mod-php7.0
Vous pouvez ajouter des librairies PHP supplémentaires, en fonction de vos besoins. Voici quelques-unes de celles qu’il m’arrive d’installer :
# apt-get install smarty3 smarty-gettext # apt-get install libmarkdown-php # apt-get install php-fpdf libfpdf-tpl-php libfpdi-php php-pdfparser # apt-get install php-geoip # apt-get install php-getid3 # apt-get install php-geshi
Redémarrage Apache
# apache2ctl restart
Installation Memcached
Si vous avez besoin d’un serveur de cache pour vos applications web :
# apt-get install memcached
Si vous souhaitez augmenter la mémoire allouée au cache (disons à 2 GO) et permettre la connexion au cache depuis d’autres machines, éditez le fichier /etc/memcached.conf :
-m 2048 -l 0.0.0.0
Installation Redis
Si vous avez besoin d’un serveur noSQL :
# apt-get install redis-server
Installation Apache status
Si vous voulez voir comment les processus Apache sont utilisés, vous pouvez utiliser le module mod_status. Pour l’ajouter :
# a2enmod status
Il faut ensuite créer un virtual host Apache qui « hébergera » cette page. Vous pouvez vous inspirer de cette configuration :
<VirtualHost *:80> ServerName www.mondomaine.fr DocumentRoot /chemin/vers/site/www <Directory /> Options FollowSymLinks AllowOverride All </Directory> <Location /server-status> SetHandler server-status Order allow,deny Allow from all </Location> LogLevel warn ErrorLog /var/log/apache2/www.mondomaine.fr-error.log CustomLog /var/log/apache2/www.mondomaine.fr-access.log combined </VirtualHost>
HTTPS
Si vous souhaitez supporter le HTTPS, il faut commencer par activer l’extension :
# a2enmod ssl
Pour le reste de la configuration SSL, vous pouvez regarder le billet que j’avais écrit sur le sujet (qui est maintenant un peu ancien, mais globalement encore valable).
Serveur emails
Envoi d’emails
Pour permettre au serveur d’envoyer des emails (mais pas d’en recevoir), le plus simple est d’installer un serveur SMTP en mode « send-only ». Pour cela, il en existe plusieurs, mais voici comment faire avec Exim :
# apt-get install exim4-daemon-light
Puis exécuter la commande suivante :
# dpkg-reconfigure exim4-config
Répondre aux questions (cf. http://library.linode.com/email/exim/send-only-mta-ubuntu-9.10-karmic) :
- Choisir « Distribution directe par SMTP (site Internet) ».
- Mettre un nom de domaine qui vous appartient (à défaut laissez « localhost »).
- Laisser l’adresse IP de loopback (« 127.0.0.1 ; ::1 ») qui est proposée par défaut, car on ne souhaite pas recevoir d’email venant de l’extérieur.
- Vider complètement la liste des domaines locaux de destination finale.
- Ne pas mettre de domaine à relayer (choix par défaut).
- Ne pas mettre d’adresse IP à relayer (choix par défaut).
- Répondre « non » à la question du cache DNS (choix par défaut).
- Choisir le stockage « mbox ».
- Répondre « non » à la question de la séparation de la configuration en plusieurs fichiers.
- Vous pouvez mettre une adresse email externe, vers laquelle seront acheminés les messages à destination des utilisateurs root et postmaster du serveur.
Envoi et réception d’emails
Si par contre vous souhaitez gérer aussi bien l’envoi que la réception des messages, il faut installer un serveur SMTP complet. Voici la marche à suivre avec Exim, auquel on va ajouter Spamassassin pour filtrer les spams et CourierIMAP pour la consultation des emails via le protocole IMAP4. On va même passer par la base de données MySQL pour gérer les comptes qui peuvent envoyer et recevoir des emails (ainsi il n’y a pas besoin de créer un utilisateur Unix pour chaque compte email).
# apt-get install exim4-daemon-heavy sa-exim spamassassin courier-imap courier-authlib-mysql
Pour la configuration de courier-imap, répondre non à la question relative à la création de sous-répertoires de configuration.
Configuration de Spamassassin
Editer le fichier /etc/default/spamassassin :
ENABLED=1 CRON=1
Démarrer le démon spamd :
# service spamassassin start
Mise-à-jour des règles de spam :
# spamassassin -D --lint # sa-update # sa-compile # sa-update -D channel-dns # spamassassin -D --lint
Editer le fichier /etc/spamassassin/local.cf :
report_safe 1 use_bayes 1 bayes_auto_learn 1 bayes_ignore_header X-Bogosity bayes_ignore_header X-Spam-Flag bayes_ignore_header X-Spam-Status
Editer le fichier /etc/spamassassin/v310.pre et décommenter cette ligne :
loadplugin Mail::SpamAssassin::Plugin::AntiVirus
Redémarrer Spamassassin :
# service spamassassin restart
Configuration Exim
Editer le fichier /etc/exim4/sa-exim.conf. Commenter la ligne :
SAEximRunCond: 0
Editer le fichier /etc/exim4/update-exim4.conf.conf :
dc_eximconfig_configtype='internet' dc_other_hostnames='domaine1.com:domaine2.com:domaine3.com' dc_local_interfaces='127.0.0.1:XX.XX.XX.XX' dc_use_split_config='true' #dc_localdelivery='mail_spool'
Editer le fichier /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs :
local_interfaces = 0.0.0.0.25
Editer le fichier /etc/exim4/conf.d/auth/30_exim4-config_examples :
plain_server: driver = plaintext public_name = PLAIN server_condition = ${lookup mysql{ SELECT IF(COUNT(*)=1,'yes','no') FROM tUser WHERE use_s_email='${quote_mysql:$auth2}' AND use_s_password='${quote_mysql:$auth3}'}} server_set_id = $auth2 server_prompts = : .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}} .endif login_server: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" server_condition = ${lookup mysql{ SELECT IF(COUNT(*)=1,'yes','no') FROM tUser WHERE use_s_login='${quote_mysql:$auth1}' AND use_s_password='${quote_mysql:$auth2}'}} server_set_id = $auth1 .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}} .endif
Editer le fichier /etc/exim4/conf.d/main/01_exim4-config_listmacrosdefs :
hide mysql_servers = localhost/projet/site AUTH_SERVER_ALLOW_NOTLS_PASSWORDS="true" domainlist local_domains = localhost:domaine1.com:domaine2.com:domaine3.com
Editer le fichier /etc/exim4/conf.d/main/02_exim4-config_options :
rfc1413_query_timeout = 0s
Créer le fichier /etc/exim4/conf.d/router/999_exim4-config_mysql_user :
virtual_user: driver = redirect allow_fail allow_defer data = ${lookup mysql{ SELECT use_s_maildir_path FROM tUser WHERE use_s_login='${quote_mysql:${local_part}}' LIMIT 1}}${if def:h_X-Spam-Flag {.Junk/}} directory_transport = address_directory
Editer le fichier /etc/exim4/conf.d/transport/30_exim4-config_maildir_home. Remplacer les lignes :
delivery_date_add envelope_to_add return_path_add maildir_format
Par :
delivery_date_add envelope_to_add return_path_add maildir_format mode = 0660 user = mail group = mail
Remplacer la ligne :
directory_mode = 0700
Par :
directory_mode = 0770
Commenter la ligne :
#mode = 0600
Editer le fichier /etc/exim4/conf.d/transport/30_exim4-config_mail_spool. Remplacer les lignes :
file = /var/mail/$local_part delivery_date_add envelope_to_add return_path_add
Par :
directory = /var/vmail/${local_part}/Maildir/${if def:h_X-Spam-Flag {.Junk/}} maildir_format delivery_date_add envelope_to_add return_path_add user = mail
Editer le fichier /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp. Ajouter les lignes (en remplaçant MONSERVEUR par le nom du serveur, et XX.XX.XX.XX par l’adresse IP d’expédition par défaut) :
helo_data = MONSERVEUR interface = ${lookup{$sender_address_domain}lsearch{/etc/exim4/interfaces} {$value}{XX.XX.XX.XX}}
Editer le fichier /etc/exim4/interfaces. Ajouter une ligne pour chaque nom de domaine d’expédition, avec l’adresse IP équivalente :
domaine1.fr: X.X.X.X domaine2.com: Y.Y.Y.Y
Editer le fichier /etc/exim4/conf.d/transport/35_exim4-config_address_directory. Ajouter les lignes :
mode = 0600 user = mail group = mail
Mettre le nom du serveur dans le fichier /etc/mailname.
Redémarrage du démon :
# service exim4 restart
Configuration de Courier-IMAP
Editer le fichier /etc/courier/authdaemonrc. Changer la ligne :
authmodulelist="authpam"
Par :
authmodulelist="authmysql"
Editer le fichier /etc/courier/authmysqlrc :
MYSQL_SERVER localhost MYSQL_USERNAME dbuser MYSQL_PASSWORD dbpassword MYSQL_DATABASE dbtable MYSQL_USER_TABLE users #MYSQL_CRYPT_PWFIELD crypt MYSQL_CLEAR_PWFIELD password DEFAULT_DOMAIN mondomaine.fr MYSQL_UID_FIELD uid MYSQL_GID_FIELD gid MYSQL_LOGIN_FIELD email MYSQL_HOME_FIELD home_path MYSQL_NAME_FIELD display_name
Editer le fichier /etc/courier/imapd :
MAXDAEMONS=250 MAXPERIP=250
Redémarrage du démon :
# service courier-imap restart # service courier-authdaemon restart
Salut Amaury, toute cette documentation prendrait encore plus de sens en s’incarnant dans une « recette » Ansible/Salt/Puppet, si celle-ci est utilisée régulièrement, non ?
Oui, c’est effectivement une bonne idée.
Je ne le ferai pas pour deux raisons :
1. J’ai mis plusieurs règles optionnelles (envoi/réception d’emails, Redis, Memcache, HTTPS, …). Difficile d’écrire une recette systématisable, mais on pourrait en écrire plusieurs pour tous les usages possibles.
2. En ce moment j’aurais plutôt tendance à vouloir faire du serverless à base d’AWS Lambda… 😉
salut, je n’ai pas lu tout l’article-tuto, mais de nos jours, je pense que Dovecot est plus à conseiller que Courier-imapd.
Ces dernières années, mes migrations/évolution de notre plate-forme mail ont été dans ce sens. La principale raison est qu’au contraire de Courier, dovecot est un serveur avec cache. Mais d’autres raisons peuvent motiver ce choix, en vrac et non exhausif : plus respecteux des standards, plus sécurisé, plus activement développé et suivi, plus configurable, supporte mieux la montée en charge (mon hébergement est avec proxies + backends), fourni avec des outils d’administration (doveadm…).
Quelques infos :
http://imapwiki.org/Benchmarking
http://imapwiki.org/ImapTest/ServerStatus
http://www.dovecot.org/
Pour le MTA, je préfère aussi postfix, mais bon, je crois savoir que certains préfèrent exim pour sa facilité de configuration apparente.
J’utilise moi-même le paquet exim-light-daemon sur les serveurs qui ne reçoivent pas de messages (le canal #postfix sur Freenode et et la doc postfix appellent ça null client).
Après, je ne dis pas que courier ne « fait pas le job » pour une petite installation avec des utilisateurs « raisonnables » quant à l’utilisation de cet outil.
OK, merci pour ces précisions. C’est vrai que je n’ai jamais pris le temps de regarder Dovecot de plus près. Est-ce qu’il gère l’authentification en passant par une base de données MySQL ?
oui, j’ai oublié de préciser que même ça, c’est bien meilleur. Il supporte même plusieurs base d’authentification appelées « passdb » (pour password database bien sûr) et pour SQL, il est possible de déclarer plusieurs serveurs, et ça, c’est mieux pour la continuité de service et la haute dispo. Je dis que c’est mieux car Courier utilise cyrus-sasl qui est vraiment une plaie à côté :
http://wiki.dovecot.org/PasswordDatabase
Merci pour tous les billets forts intructifs clairs et de top qualité.
Perso j’ajoute fail2ban, logwatch et monitorix.
Avec fail2ban je me sens un peut plus rassurer, logwatch me sert à me rappeler de ce que j’ai fait ou pas fait sur le serveur, et monitorix pour voir la santé du serveur dans le temps en un coup d’oeil puisque ce sont de petits graphiques très parlants.