Autohébergement d’un serveur nextcloud sur raspberry pi de scratch

1 Introduction

J’autohéberge un serveur owncloud depuis quelques années maintenant sur un vieux nettop. Et puis owncloud périclite, son fork nextcloud devient la nouvelle référence, les raspberry pi se démocratisent avec un consommation encore plus faible (~5W) que les nettop (~20W), et bien d’autres avantages (taille, bruit, coût).

J’ai donc récemment sauté le pas pour me mettre au goût du jour et comme je suis content du résultat, je partage. J’ai personnellement opté pour le raspberry pi 2B parce qu’il consomme un petit peu moins que le 3 et que je n’avais aucune utilité ni du wifi ni du bluetooth.

Comme je me suis allègrement servi, je rends à César ce qui appartient à César en citant mes sources principales :

Cet article s’adresse à des personnes qui ont un minimum de connaissance de linux.

NB : Dans cet article j’utilise des dénominations du type “myuser” ainsi que des mots de passes d’exemple. Je ne saurais que vous recommander de personnaliser ces dénominations génériques et d’éviter des noms évidents ! Il va de soit que les mots de passes doivent aussi être personnalisés et sécurisés.

2 Préliminaires

2.1 Préparation de la carte SD

Télécharger la distribution raspbian lite (https://www.raspberrypi.org/downloads/raspbian/) et suivre les instructions pour écrire l’image téléchargée sur la carte SD (https://www.raspberrypi.org/documentation/installation/installing-images/README.md).

Après avoir créé un fichier vide nommé ssh dans la partition boot de la carte SD pour activer le ssh au premier démarrage, il faut démonter la carte SD, même si

La vie est trop courte pour retirer le périphérique USB en toute sécurité

et la mettre dans le raspberry pi avant de brancher ce dernier sur le réseau et au secteur.

2.2 Se connecter en SSH

Pour trouver l’IP attribuée par le DHCP au raspberry pi ainsi que adresse MAC, scanner le réseau :

$ sudo nmap -sP 192.168.0.0/24

Starting Nmap 7.40 ( https://nmap.org ) at 2017-03-05 20:57 CET
Nmap scan report for 192.168.0.100
Host is up (0.014s latency).
MAC Address: XX:XX:XX:XX:XX:XX (Raspberry Pi Foundation)
...

Pour cet exemple l’IP est 192.168.0.100. Se connecter en SSH avec l’utilisateur pi et le mot de passe raspberry :

$ ssh pi@192.168.0.100

2.3 Utilitaire de configuration

On commence doucement avec l’utilitaire de configuration développé pour le raspberry pi :

$ sudo raspi-config

qui ouvre une interface semi-graphique dans laquelle on règles les paramètres suivants :

  • Choisir Internationalisation Options puis Change Locale.
    • Sélectionner fr_FR.UTF-8 UTF-8 puis OK.
    • Choisir fr_FR.UTF-8 UTF-8.
  • Choisir Internationalisation Options puis Change Timezone.
    • Choisir Europe, puis Paris.
  • Choisir Advanced Options puis Hostname.
    • Taper le nom de la machine, myserver dans le cadre de cet exemple.
  • Choisir Advanced Options puis Memory Split.
    • Taper 16.
  • Choisir Advanced Options puis SSH puis yes.
  • Choisir <Finish> puis yes pour redémarrer.

Une fois redémarré, on se reconnecte en ssh (le mot de passe est toujours raspberry) :

pi@raspberrypi:~ $ Connection to 192.168.0.100 closed by remote host.
Connection to 192.168.0.100 closed.
$ ssh pi@192.168.0.100

2.4 Mens sana in corpore sano

Une petite mise à jour le système pour partir sur de bons rails :

$ sudo apt update
$ sudo apt upgrade
$ sudo reboot

Se reconnecter au SSH.

3 Sortez couverts

3.1 Préserver la carte SD

Pour mettre les fichiers temporaires en mémoire vive, on rajoute les deux lignes suivantes dans /etc/fstab :

tmpfs /tmp tmpfs defaults,noatime,nosuid,size=100m 0 0
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,size=30m 0 0

L’utilitaire log2ram permet de placer les logs en mémoire vive et de ne les sauvegarder que toutes les heures :

$ cd
$ mkdir download
$ cd download
$ sudo apt install git
$ git clone https://github.com/azlux/log2ram.git
$ cd log2ram
$ chmod +x install.sh
$ sudo ./install.sh

Pour indiquer au serveur apache de démarrer après log2ram, éditer le fichier /etc/systemd/system/log2ram.service :

Before=syslog.target mysql.service fail2ban.service nginx.service rsyslog.service apache2.service

Vérifier que toutes les modifications ont été prises en compte en vérifiant que vous avez bien les quatre dernières lignes après avoir redémarré :

$ df -h
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/root 15G 1012 M 13G 12% /
devtmpfs 475M 0 475M 0% /dev
tmpfs 479M 0 479M 0% /dev/shm
tmpfs 479M 6,4M 473M 2% /run
tmpfs 5,0M 4,0K 5,0M 1% /run/lock
tmpfs 479M 0 479M 0% /sys/fs/cgroup
tmpfs 30M 0 30M 0% /var/tmp
tmpfs 100M 0 100M 0% /tmp
/dev/mmcblk0p1 63M 21M 43M 34% /boot
log2ram 40M 3,1M 37M 8% /var/log

Pour corriger un bug de raspbian qui envoie des erreurs du fait qu’il n’y a pas de console graphique, éditer le fichier /etc/rsyslog.conf et commenter les lignes suivantes (à la fin du fichier) :

#daemon.*;mail.*;\
#        news.err;\
#        *.=debug;*.=info;\
#        *.=notice;*.=warn |/dev/xconsole

3.2 Sécuriser le serveur

Ajouter l’utilisateur personnalisé, dans cet exemple sera myuser, avec les droits sudo, définir un M0t#2Pass3_Compl1quE! :

$ sudo useradd -m myuser -G sudo
$ sudo passwd myuser

On peut maintenant se déconnecter de la session de l’utilisateur pi et se reconnecter avec notre utilisateur myuser fraichement créé :

$ logout
Connection to 192.168.0.10 closed.
$ ssh myuser@192.168.0.100

Et c’est avec un petit plaisir sadique qu’on supprime l’utilisateur par défaut pi et ses fichiers :

$ sudo deluser --remove-all-files pi

Peaufinons maintenant la configuration du server ssh en éditant le fichier /etc/ssh/sshd_config et en modifiant les paramètres suivants :

...
# Logging
SyslogFacility AUTH
LogLevel VERBOSE

# Authentication:
LoginGraceTime 20
PermitRootLogin no
StrictModes yes
...
#UseLogin no
MaxStartups 10:30:60
#Banner /etc/issue.net
...
# Add allowed users
AllowUsers myuser

On restreindre le service SSH à l’IPv4 et on redémarre le service ssh en vérifiant son statu :

$ echo 'AddressFamily inet' | sudo tee -a /etc/ssh/sshd_config
$ sudo systemctl restart ssh
$ sudo systemctl status ssh

Pour que notre serveur puisse nous envoyer de gentils petits courriels, nous installons nullmailer :

$ sudo apt install nullmailer mailutils

Pendant l’installation renseigner le nom de la boite mail (qui doit être une boite mail existante) :

webmaster@mydomain.com

Puis fournir les paramètres SMTP de la boite mail en question :

smtp.mydomain.com smtp --port=465 --auth-login --user=webmaster@mydomain.com --pass=M0t#2Pass3_2MaB0ate-ma1l --ssl

En cas de problème, ces informations peuvent être modifiées dans les fichiers situés dans le dossier /etc/nullmailer/.

Appliquer le fix suivant pour corriger le header des emails et le forcer l’expéditeur à webmaster@mydomain.com et ainsi éviter de se faire bouler par le serveur smtp :

$ sudo mv /usr/sbin/sendmail /usr/sbin/sendmail-bin
$ sudo echo webmaster@mydomain.com > /etc/nullmailer/forced-from

Créer un fichier /usr/sbin/sendmail dans lequel mettre :

#!/bin/bash
/usr/sbin/sendmail-bin $@ -f `cat /etc/nullmailer/forced-from` </dev/stdin

Que l’on rend exécutable :

$ chmod +x /usr/sbin/sendmail

Pour tester l’envoie de mail :

$ echo "Un mail de test" | mail -s "test nullmailer" destinataire@pourletest.com

L’utilitaire fail2ban va nous permettre d’ajouter une couche de sécurité au serveur :

$ sudo apt install fail2ban

Éditer la première ligne du fichier /etc/hosts :

127.0.0.1 localhost localhost.localdomain myserver

Créer un fichier de configuration pour fail2ban :

$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Puis éditer le fichier créé /etc/fail2ban/jail.local comme suit :

...
ignoreip = 127.0.0.1/8 192.168.0.0/24
...
# "bantime" is the number of seconds that a host is banned.
Bantime  = 3600
...
#
# Destination email address used solely for the interpolations in
# jail.{conf,local} configuration files.
destemail = webmaster@mydomain.com

#
# Name of the sender for mta actions
sendername = Fail2Ban

# Email address of the sender
sender = webmaster@mydomain.com

...

# Choose default action. To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in $
# globally (section [DEFAULT]) or per specific section
action = %(action_mwl)s

...

[ssh]
enabled = true 
port = ssh 
filter = sshd 
logpath = /var/log/auth.log maxretry = 3 

...

[pam-generic]
enabled = true 
filter = pam-generic 
port = all 
banaction = iptables-allports 
port = anyport 
logpath = /var/log/auth.log 
maxretry = 3  

Relancer le service fail2ban et vérifier que tout c’est bien passé :

$ sudo systemctl restart fail2ban
$ sudo systemctl status fail2ban

3.3 Configurer le réseau

Ci-après, c’est votre box internet que vous devez configurer. Comme il y a autant de cas que de fournisseurs d’accès et d’offres, je vous propose de vous reporter sur ce lien si vous n’arrivez pas à trouver comment faire les actions suivantes.

  1. Commencez par configurer un bail DHCP pour que l’adresse MAC du raspberry pi (XX:XX:XX:XX:XX:XX) – obtenue avec la commande nmap (souvenez-vous c’était ici) – ait une IP fixe (192.168.0.100 dans ce cas).
  2. Rediriger ensuite les ports entrant 80 (HTTP) et 443 (HTTPS) en TCP vers les mêmes ports de l’IP 192.168.0.100.
  3. Rediriger enfin le port entrant de votre choix (1234 par exemple) en TCP vers le port 22 (SSH) de l’IP 192.168.0.100. Ça permet de brouiller un peu – pas beaucoup – les pistes pour un éventuel pirate, la connexion en SSH depuis l’extérieur se faisant avec l’IP de la box que vous pouvez facilement trouver sur ce lien (exemple ou 123.456.789.12) :
$ ssh myuser@123.456.789.12 -p 1234

Maintenant il s’agit de configurer le DNS sur votre nom de domaine. Rajoutez un sous domaine (mycloud par exemple) qui pointe vers votre box internet :

mycloud.mydomain.com IN A 123.456.789.12

4 Le gros œuvre

4.1 Base de données

Installer le gestionnaire de bases de données mariadb, définir un m0t-DeuX!p4sse pour le root, et appliquer les paramètres sécurisés proposés par la seconde commande (sauf le changement du mot de passe root car celui que vous venez de définir est évidemment brillamment sécurisé) :

$ sudo apt install mariadb-server
$ sudo mysql_secure_installation

Créer la base de données et l’utilisateur pour nextcloud :

$ mysql -u root -p
Enter password:
...
MariaDB [(none)]> create database myclouddb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> create user myclouduser@localhost identified by 'S3cUr1tY_firST';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> grant all on myclouddb.* to myclouduser@localhost;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> exit;
Bye

Où la base de donnée pour nextcloud est myclouddb, l’utilisateur myclouduser et son mot de passe d’accès S3cUr1tY_firST.

Décommenter les lignes suivantes du fichier /etc/mysql/conf.d/mariadb.cnf :

default-character-set = utf8
...
character-set-server  = utf8
collation-server      = utf8_general_ci
character_set_server   = utf8
collation_server       = utf8_general_ci

Et redémarrer le service puis vérifier que tout s’est bien passé :

$ sudo systemctl restart mysql
$ sudo systemctl status mysql

4.2 Server web

Pour l’heure votre serveur ne sait toujours pas afficher une page web. Pour y remédier, installer apache et php puis relancer le service apache :

$ sudo apt install apache2 libapache2-mod-php5 php5-json php5-gd php5-mysql php5-curl php5-intl php5-mcrypt php5-imagick php5-apcu
$ sudo systemctl restart apache2
$ sudo systemctl status apache2

Testez que tout est bien installé en créant un fichier de test /var/www/html/info.php contenant :

<?php
  phpinfo();
?>

Puis ouvrir dans votre navigateur successivement les deux liens qui doivent ouvrir la même page :

  • http://192.168.0.100/info.php
  • http://mycloud.mydomain.com/info.php

Une fois cette vérification faite supprimer le fichier :

$ sudo rm /var/www/html/info.php

Modifier les paramètres suivants du fichier /etc/apache2/conf-available/security.conf :

ServerTokens Prod
ServerSignature Off

Modifier les paramètres suivants du fichier /etc/php5/apache2/php.ini :

post_max_size = 20M
upload_max_filesize = 20M
mysql.connect_timeout = 180
allow_url_fopen = Off

Éditer le fichier /etc/apache2/apache2.conf et ajouter à la fin :

# Cookie HTTP header flag with HTTPOnly & Secure to protect website from XSS attacks
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

Puis relancer le service apache et vérifier que cela c’est bien passé :

$ sudo systemctl reload apache2
$ sudo systemctl status apache2

4.3 Configurer HTTPS

Installer certbot et créer un certificat pour le sous-domaine :

$ cd
$ mkdir download
$ cd download
$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto
$ ./certbot-auto certonly --webroot -w /var/www/html -d mycloud.mydomain.com

Vérifier que le certificat est créé :

$ sudo ls -l /etc/letsencrypt/live/mycloud.mydomain.com

Ajouter ou modifier les paramètres suivants dans /etc/apache2/sites-available/default-ssl.conf :

ServerName mycloud.myserver.com
SSLCertificateFile /etc/letsencrypt/live/mycloud.myserver.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mycloud.myserver.com/privkey.pem

Puis ouvrir dans votre navigateur le lien pour vérifier que HTTPS fonctionne :

  • https://mycloud.mydomain.com/

Désactiver les virtualhost apache par défaut puis relancer le service :

$ sudo a2dissite 000-default.conf
$ sudo a2dissite default-ssl.conf
$ sudo systemctl reload apache2
$ sudo systemctl daemon-reload
$ sudo systemctl status apache2

4.4 Fichiers Nextcloud

Télécharger les fichiers et vérifier leur intégrité :

$ cd ~/download
$ wget https://download.nextcloud.com/server/releases/latest.zip
$ wget https://download.nextcloud.com/server/releases/latest.zip.sha256
$ sha256sum -c latest.zip.sha256

Si une erreur apparaît lors du checksum, il faudra peut-être renommer le fichier latest.zip par celui rechercé par latest.zip.sha256.

Décompresser le zip et mettre les fichiers au bon endroit avec les bons droits :

$ unzip latest.zip
$ sudo cp -r nextcloud /var/www/
$ sudo chown www-data:www-data /var/www/nextcloud/ -R
$ sudo mkdir /var/www/data
$ sudo chown www-data:www-data /var/www/data

4.5 Hôte Apache pour Nextcloud

Modifier le fichier /etc/apache2/apache2.conf :

<Directory /var/www/>
  Options Indexes FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>

Créer le fichier /etc/apache2/sites-available/nextcloud.conf contenant :

# Forward HTTP to HTTPS
<VirtualHost *:80>
  ServerName mycloud.mydomain.com
  Redirect / https://mycloud.mydomain.com/
</VirtualHost>

# HTTPS config
<IfModule mod_ssl.c>
  <VirtualHost *:443>
    ServerName mycloud.mydomain.com
    ServerAdmin myuser@localhost

    DocumentRoot /var/www/nextcloud

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # SSL Engine Switch:
    # Enable/Disable SSL for this virtual host.
    SSLEngine on

    # A self-signed (letsencrypt) certificate
    SSLCertificateFile /etc/letsencrypt/live/mycloud.mydomain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mycloud.mydomain.com/privkey.pem

    SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:!aNULL:!MD5
    SSLHonorCipherOrder on

    <IfModule mod_headers.c>
      Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload"
    </IfModule>

    # SSL Engine Options
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
      SSLOptions +StdEnvVars
    </FilesMatch>
    <Directory /usr/lib/cgi-bin>
      SSLOptions +StdEnvVars
    </Directory>

    # SSL Protocol Adjustments
    BrowserMatch "MSIE [2-6]" \
    nokeepalive ssl-unclean-shutdown \
    downgrade-1.0 force-response-1.0
    # MSIE 7 and newer should be able to use keepalive
    BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

  </VirtualHost>
</IfModule>

Activer ce nouvel l’hôte virtuel :

$ sudo ln -s /etc/apache2/sites-available/nextcloud.conf /etc/apache2/sites-enabled/nextcloud.conf
$ sudo a2enmod rewrite headers env dir mime
$ sudo a2enmod ssl
$ sudo a2ensite nextcloud
$ sudo systemctl reload apache2
$ sudo systemctl daemon-reload
$ sudo systemctl status apache2

5 Les finitions

5.1 Initialisation de Nextcloud

Avec votre navigateur aller sur : http://mycloud.mydomain.com.

Vérifiez que vous êtes bien redirigés sur le HTTPS et que la page d’initialisation de nextcloud s’affiche. Configurer comme suit :

  • Définissez un compte administrateur (toujours en les personnalisant) myadminnextcloud avec un MoT_dE_pAsSe_SeCuRiSe.
  • Définir le répertoire des données : /var/www/data.
  • Configurer la base de données définie plus haut.

Cliquer sur Terminer la configuration, est une fois arrivé sur l’écran de login – ça prend un peu de temps – nextcloud peut commencer à être utilisé. Peaufinez l’installation en modifiant ou ajoutant les paramètres suivants dans le fichier /var/www/nextcloud/config/config.php :

array (
  0 => 'mycloud.mydomain.com',
  1 => '192.168.0.100',
),
...
'logfile' => '/var/www/data/nextcloud.log',
'loglevel' => 2,
'log_authfailip' => true,
'memcache.local' => '\OC\Memcache\APCu',

5.2 Configurer Nextcloud

Voici comment j’ai personnellement configuré mon instance nextcloud.

J’ai installé les applications :

  • Calenda
  • Contacts
  • Default encryption module
  • Notes

Dans le menu d’administration j’ai modifié les onglets suivants.

5.2.1 Onglet paramètres serveur

Vérifier qu’il n’y a pas d’avertissement sécurité & configuration. Sélectionner cron pour les tâches cron. Ajouter une tâche cron pour nextcloud en éditant via la commande :

$ crontab -u www-data -e

Choisir l’éditeur parmi ceux proposés et ajouter les lignes :

# cron job for nextcloud
*/15 * * * * php -f /var/www/nextcloud/cron.php

5.2.2 Onglet chiffrement

Activer le chiffrement.

5.2.3 Onglet paramètres supplémentaires

Utiliser sendmail pour le mode d’envoie des emails avec l’adresse source : webmaster@mydomain.com. Envoyer un email pour tester que la configuration fonctionne.

Vérifier la politique de mots de passe et la modifier en fonction de ses souhaits de sécurité.

5.3 Restons up-to-date

Commençons par un petit peu de ménage avant d’installer cron-apt qui va permettre de maintenir le système à jour :

$ sudo apt-get autoremove && sudo apt-get autoclean
$ sudo apt install cron-apt

Éditer le fichier /etc/cron-apt/config (vide) en ajoutant :

APTCOMMAND=/usr/bin/apt-get
MAILTO="webmaster@mydomain.com"
MAILON="always"

Éditer /etc/cron-apt/action.d/3-download et supprimer le -d :

autoclean -y
dist-upgrade -y -o APT::Get::Show-Upgraded=true

Éditer /etc/cron.d/cron-apt et ajouter l’exécution de la tache tous les lundis à 1h du matin :

# Every Monday night at 1 o'clock
0 1 * * 1 test -x /usr/sbin/cron-apt && /usr/sbin/cron-apt

Pour tester l’exécution de la tache :

$ sudo cron-apt

Ensuite on programme une tache cron pour redémarrer le raspberry tous les lundis à 2h du matin et envoyer un mail à chaque démarrage :

$ sudo mkdir /var/log/cron
$ sudo crontab -e

Ajouter au début et à la fin :

MAILTO=webmaster@mydomain.com
...
# Reboot Monday night at 2 o’clock
0 2 * * 1 /sbin/shutdown -r > /var/log/cron/cron-reboot.log
@reboot echo "myserver has just reboot" | mail -s "Reboot" webmaster@mydomain.com

5.4 Tester le serveur

J’ai testé cette installation avec ces outils :

5 réflexions au sujet de « Autohébergement d’un serveur nextcloud sur raspberry pi de scratch »

  1. Bonjour,

    Merci !!! excellent tuto
    Quelques différences dans les fichier de conf avec la version “sketch” mais facile à adapter.
    Juste la partie “Certbot” qui n’a pas fonctionné mais on peu palier en allant le faire en ligne directement sur le site “https://certbot.eff.org/”

    Super encore merci

  2. Salut ! Super tuto.

    Juste une question : quid des débits de synchro ? J’ai une install peu ou proue similaire, et les débits sont affreusement lents. Je soupçonne la ram limitée du rasperry 2b+.

    Merci encore

    1. J’ai l’impression que mes débits sont corrects. Je m’en sers essentiellement pour synchroniser mes agenda et contact sur mon téléphone et occasionnellement pour partager des fichiers à mon entourage.
      Souvent l’initialisation de la connexion prend un petit peu de temps, mais une fois que le raspberry s’est réveillé, ça passe. C’est probablement dépendant aussi du fournisseur d’accès !

      1. Merci de la réponse. Pour un usage de synchro massif, je suis bien en-dessous de la bande passante de mon réseau, c’est pour ça que je pensais à la ram. J’ai souvent des erreurs quand j’upload pas mal de fichiers un peu volumunieux (quelques centaines de Mo). Pour l’agenda et les contacts, effectivement, ça ne doit pas poser de pb.

Répondre à Benoit Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *