Libricks

Installation Nextcloud 13

Cette page va nous montrer comment mettre en place un serveur LAMP + Nextcloud sous Debian 9 / Ubuntu 16.04 & 18.04 avec NGINX.

Nextcloud est une plate-forme de partage de fichiers et de communication open source, auto-hébergée accédez et synchronisez vos fichiers, vos contacts, vos calendriers et communiquez et collaborez depuis tous vos appareils. Vous décidez de ce qui se passe avec vos données, où elles se trouvent et qui peuvent y accéder !

Sommaine

Prérequis

Avoir un nom de domaine avec les enregistrements DNS pointant sur votre serveur

Installation du serveur LAMP

La première étape est de se connecter au serveur puis de mettre à jour celui-ci

apt-get update && apt-get upgrade

On passe ensuite à l'installation de la base de donnée avec MariaDB

apt-get install mariadb-server
mysql_secure_installation

Au lancement de la seconde commande une série de questions vous sera posé :

  • Set root password ? Pour définir un mot de passe à l'utilisateur root pour la connexion à MariaDB
  • Remove anonymous user ? Par défaut, une installation de MariaDB a un utilisateur anonyme, ce qui permet à n'importe qui pour se connecter à MariaDB sans avoir besoin de crée un compte d'utilisateur. Le mieux est donc d'entrée "Y"
  • Disallow root login remotely ? Si vous souhaitez désactiver l'accès à distance sur MariaDB pour l'utilisateur root
  • Remove test database and access to it ? Par défaut une base de test ou n'importe qui peut accéder est créer par MariaDB le mieux est de la supprimer en tapant "Y"
  • Reload privilege tables now? Pour recharger les privilèges de MariaDB

On passe ensuite à l'installation de NGINX et des modules PHP nécessaire pour Nextcloud, certains modules comme curl ou intl sont facultatifs mais recommandé car ils permettent soit d'améliorer les performances soit ils sont nécessaires pour certaines fonctionnalités.

Si vous installez un nouveau plugin sur Nextcloud il faudra vérifier que celui-ci ne requiert pas de modules PHP supplémentaire par exemple php-ldap pour utiliser la connexion à Nextcloud avec authentification via LDAP

apt-get install nginx
apt-get install php-cli php-json php-curl php-imap php-gd php-mysql php-xml php-zip php-intl php-imagick php-mbstring php-fpm php-apcu

Pour des raisons de sécurité il est recommandé de désactiver l’envoi d’informations telles que le numéro de version de votre Nginx. Pour cela, décommentez la directive "server_tokens off" en ouvrant le fichier "/etc/nginx/nginx.conf"

[...]
    server_tokens off; 
[...]

Création de la base de données

On passe à la création de la base de données en se connectant a MariaDB

mysql -u root -p

Le mot de passe est celui que vous avez entré à la configuration de MariaDB plus tôt. On crée la base Nextcloud

CREATE DATABASE nextcloud;

Si vous voulez utiliser des caractères UTF8 de 4 octets comme des emojis sur votre serveur, la base de données doit être créée avec le jeu de caractères utf8mb4 comme ceci :

CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

On crée ensuite l'utilisateur et on lui applique les droits sur la base de données :

CREATE USER "nextcloud"@"localhost";
SET password FOR "nextcloud"@"localhost" = password('mon_password');
GRANT ALL PRIVILEGES ON nextcloud.* TO "nextcloud"@"localhost" IDENTIFIED BY "mon_password";
FLUSH PRIVILEGES;
EXIT

Installation de Nextcloud

On va maintenant télécharger la dernière archive de nextcloud

cd /var/www
wget https://download.nextcloud.com/server/releases/latest.tar.bz2

On peut télécharger le SHA256 afin de vérifier l'intégrité de l'archive

wget https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256
sha256sum -c latest.tar.bz2.sha256 < latest.tar.bz2

La commande doit alors retourner un "OK"

On décompresse l'archive et on la supprime

tar -xvf latest.tar.bz2
rm latest.tar.bz2*

Dans la documentation de Nextcloud il est recommandé de placer le dossier contenant les data dans un autre répertoire (Il est recommandé de placer le dossier en dehors du Web Root donc /var/www), nous allons juste simplement créer un autre dossier pour notre part dans /var/www

cd /var/www
mkdir nextcloud_data

Si vous optez pour un upgrade manuel de Nextcloud plus tard il est préférable de renommer votre dossier nextcloud en y ajoutant son numéro de version puis de créer un lien symbolique.

mv nextcloud nextcloud_{VersionNextcloud}
ln -s /var/www/nextcloud_{VersionNextcloud} /var/www/nextcloud

On applique les bon droits aux dossiers

chown -R www-data:www-data nextcloud_{version}
find nextcloud_{version}/ -type d -exec chmod 750 {} \;
find nextcloud_{version}/ -type f -exec chmod 640 {} \;
chown -R www-data:www-data nextcloud_data

Grâce à cette technique, cas d'upgrade manuel il ne sera pas nécessaire de modifier les vHosts créer de plus de manière générale la maintenance de Nextcloud est simplifié

Création du vHost NGINX

Dans les étapes suivantes il faudra remplacer {domaine}.tld par votre nom de domaine.

On va créer le vHost pour Nextcloud en crée un fichier dans le dossier /etc/nginx/sites-available. Dans ce vHost on va utiliser HTTP2 et limiter le SSL au TLS1.2.

nano /etc/nginx/sites-available
upstream php-handler {
        server unix:/run/php/php7.2-fpm.sock;
}

    #------------------------------------------------------------------------
    # REDIRECTION HTTPS
    #

    server {
     listen 80 default_server;
     listen [::]:80 default_server;
     server_name {domaine}.tld;
     return 301 https://{domaine}.tld$request_uri;
     }

    #------------------------------------------------------------------------
    # BLOCK SERVEUR HTTPS
    #
    server {

     listen 443 ssl http2;
     server_name {domaine}.tld;
     root /var/www/nextcloud;
     index index.php index.html index.htm;

    #------------------------------------------------------------------------
    # SECURITY
     add_header Content-Security-Policy "default-src 'self' https://*.gstatic.com https://*.googleapis.com data: 'unsafe-inline' 'unsafe-eval'; report-uri https://report-uri.io/report/monurl";
     add_header Content-Security-Policy-Report-Only "default-src 'self' https://*.gravatar.com https://*.gstatic.com https://*.googleapis.com https://ssl.google-analytics.com https://s-static.ak.facebook.com https://www.google-analytics.com data: 'unsafe-inline' 'unsafe-eval'";;
     add_header X-Content-Type-Options nosniff;
     add_header X-XSS-Protection "1; mode=block";

    #------------------------------------------------------------------------
    # SSL
    #
     ssl_certificate /etc/letsencrypt/live/{domaine}.tld/fullchain.pem;
     ssl_certificate_key /etc/letsencrypt/live/{domaine}.tld/privkey.pem;

     ssl_protocols TLSv1.2;
     ssl_dhparam /etc/nginx/ssl/dhparam4.pem;
     ssl_ecdh_curve secp384r1;
     ssl_prefer_server_ciphers on;
     ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256";

     # ssl optimizations
     ssl_session_timeout 5m;
     ssl_session_cache shared:SSL:10m;
     ssl_session_tickets off;
     add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
     ssl_stapling on;
     ssl_stapling_verify on;
     ssl_trusted_certificate /etc/letsencrypt/live/{domaine}.tld/chain.pem;
     resolver 80.67.169.12 80.67.169.40 valid=300s;
     resolver_timeout 15s;

    #------------------------------------------------------------------------
    # LOCATION SECURITY
    #

    # On interdit les dotfiles
    location ~ /\. { deny all; }

    #------------------------------------------------------------------------
    # LOCATION NEXTCLOUD
    #

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    location / {
        rewrite ^ /index.php$uri;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
    }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js and css files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff|svg|gif)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control "public, max-age=15778463";
        add_header X-Frame-Options SAMEORIGIN;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        access_log off;
    }

    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        access_log off;
    }
}

Vous pouvez remplacer les {domaines}.tld avec la commande suivante :

sed -i -e "s/cloud.votre-domaine.fr/{domaine}.tld/g" /etc/nginx/sites-available/nextcloud

On n'oublie pas de créer le lien symbolique

ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/

Il faudra ensuite créer les certificats SSL et créer une clé d'échange diffie-hellman, pour ce faire on va utiliser certbot pour nous créer des certificats SSL let's encrypt, les commandes suivantes sont effectuées sous Debian 9, vous pouvez trouver les commandes pour votre OS sur le site de certbot : https://certbot.eff.org/ en sélectionnant "NGINX" et votre OS

apt-get install python-certbot-nginx -t stretch-backports

On génère ensuite le certificat pour votre domaine, il faudra d'abord stopper NGINX

service nginx stop
certbot certonly --standalone -d cloud.{domaine}.fr

On génère ensuite la clé diffie-hellman, celà peut prendre du temps !

mkdir /etc/nginx/ssl
openssl dhparam -out /etc/nginx/ssl/dhparam4.pem 4096
chmod 600 /etc/nginx/ssl/dhparam4.pem

Notre configuration devrait être OK on peut le vérifier avec la commande suivante

nginx -t

Si tout est ok on peut redémarrer NGINX et PHP-FPM

service nginx start
service php7.2-fpm restart

Avec cette configuration vous obtiendrez un jolie A+ sur le site de SSL Labs

Configuration de Nextcloud

En vous rendant sur votre domaine cloud.{domaine}.fr vous devriez voir la page d'installation de Nextcloud, il vous faudra créer un compte administrateur, modifier le répertoire des datas en mettant celui que vous avez crée précédemment, pour ma part /var/www/nextcloud_data, ensuite entrer les informations relatives à la base de données puis cliquer sur "Terminer l'installation" !

Votre instance Nextcloud est maintenant en place.

On modifie la config globale de PHP pour coller aux requierements de Nextcloud en modifiant le fichier /etc/php/7.2/fpm/pool.d/www.conf

clear_env = no

Et on décommente et on modifie les lignes suivantes dans le fichier /etc/php/7.2/fpm/php.ini

opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1

On va effectuer quelques réglages en modifiant le fichier de configuration de Nextcloud pour activer l'anti-bruteforce et le cache local

L'anti-bruteforce de Nextcloud ne banni pas d'IP, il rend seulement les tentatives de connexion de plus en plus lente

nano /var/www/nextcloud/config/config.php

Ajouter les lignes suivantes avant la dernière parenthèse

'installed' => true,
'logtimezone' => 'Europe/Paris',
'logfile' => '/var/www/data/nextcloud.log',
'loglevel' => 2,
'log_authfailip' => true,
'auth.bruteforce.protection.enabled' => true,
'memcache.local' => '\OC\Memcache\APCu',

Renouvellement des certificats

Pour renouveler vos certificats on utilisera un script exécuté par une tâche cron tous les X temps.
Donc dans votre contab :

sudo crontab -e

Placer y ceci à la fin :

30 2 * * 1 /usr/local/bin/letsencrypt-auto renew 1>/dev/null 2>&1

Ce qui exécutera notre script placé dans /usr/local/bin tous les 7 jours à 2h30 du matin

Ensuite on créer un fichier pour notre script sudo vim /usr/local/bin/letsencrypt-auto

Et on y met le contenu suivant :

#!/bin/bash

if [ $# -lt 1 ]
then
  echo "Syntax error: $0 renew"
  exit 1
fi

do_renew() {
  SERVICE_HTTP=""
  SERVICE_HTTP=$(systemctl is-active nginx)

  if [ "${SERVICE_HTTP}" = "active" ]
  then
    systemctl stop nginx
    sleep 2
  fi

  certbot renew --dry-run
  certbot renew

  SERVICE_HTTP=""
  SERVICE_HTTP=$(systemctl is-active nginx)

  if [ "${SERVICE_HTTP}" != "active" ]
  then
    systemctl start nginx
    sleep 2
  fi
}

case "$1" in
  renew)
    do_renew
  ;;
  *)
    echo "Usage: $0 {renew}"
    exit 2
  ;;
esac

Voila votre installation de Nextcloud est maintenant terminé :)

Mise à jour automatique de Nextcloud

Pour mettre automatiquement à jour votre Nextcloud il vous suffira de cliquer sur votre profil puis de sélectionner Paramètres > Paramètres de base puis en bas de la page si une mise à jour est disponible vous pourrez cliquer sur le bouton pour effectuer la mise à jour.

Mise à jour manuel de Nextcloud

Avant de mettre à jour manuellement notre serveur Nextcloud il faut mettre celui-ci en maintenance avec la commande suivante

sudo -u www-data php occ maintenance:mode --on

Puis on effectue un backup de la base de données

mysqldump --single-transaction -h 127.0.0.1 -u root -p[password] [db_name] > nextcloud-sqlbkp_`date +"%Y%m%d"`.bak

On arrête le serveur web

service nginx stop

On se place dans notre répertoire web et on télécharge la dernière archive de Nextcloud, on renomme l'archive et on recrée le lien symbolique

cd /var/www
rm -R nextcloud
wget https://download.nextcloud.com/server/releases/latest.tar.bz2
wget https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256
sha256sum -c latest.tar.bz2.sha256 < latest.tar.bz2
tar -xvf latest.tar.bz2
rm latest.tar.bz2*
mv nextcloud nextcloud_{version}
ln -s /var/www/nextcloud_{VersionNextcloud} /var/www/nextcloud

On récupère l'ancien fichier de configuration

cp /var/www/nextcloud_{old_version}/configs/config.php /var/www/nextcloud_{new_version}/configs

Si vous avez installé des plugins sur votre instance nextcloud il faudra les copiers du dossier /apps de votre ancienne instance nextcloud dans la nouvelle, ne copier que les plugins qui ne sont pas dans la nouvelle instance
On modifie les droits du dossier

chown -R www-data:www-data nextcloud_{version}
find nextcloud_{version}/ -type d -exec chmod 750 {} \;
find nextcloud_{version}/ -type f -exec chmod 640 {} \;

On redémarre le serveur web

service nginx start

Et on lance l'upgrade en ligne de commande de Nextcloud

sudo -u www-data php occ upgrade

La mise à jour manuel de Nextcloud est terminé