Dans cet article, je vais vous guider pas à pas sur comment faire une installation de Nextcloud propre et fonctionnelle sous Ubuntu 23.04 en utilisant Nginx.
Pour les fervents utilisateurs de Debian, ce tutoriel fonctionne aussi sous Debian12 !
Car, selon moi, il est incomparablement mieux que Apache. Il est léger, extrêmement puissant, et lorsqu'on regarde le nombre de failles de sécurité (CVE) entre Apache et Nginx, on se rend compte qu'il est aussi bien plus sécurisé
À partir de maintenant, je suppose que vous êtes dans une console, connecté en tant que root. Si ce n'est pas le cas, exécutez la commande :
su
On met à jour notre système
sudo apt update
sudo apt full-upgrade -y
On installe Nginx ainsi que quelques autres petites choses dont on se servira
sudo apt-get -y install nginx ffmpeg mariadb-server gpg bzip2
Nginx est notre serveur web. Pour faire simple, c'est lui qui récupère toutes les connexions sur le serveur et fournit les bonnes pages web
Afin de donner la bonne valeur à Nginx, on récupère le nombre de coeurs du processeur.
sudo grep processor /proc/cpuinfo | wc -l
Puis on modifie le fichier de configuration Nginx.
sudo nano /etc/nginx/nginx.conf
Pour enregistrer et quitter sur Nano, c'est CTRL+S puis CTRL+X.
user www-data; worker_processes 2; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; types_hash_max_size 2048; server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; .....
Il est recommandé de mettre autant de worker_processes que de cœurs disponibles sur votre serveur.
server_tokens permet de masquer la version de Nginx, ce qui est une bonne pratique de sécurité.
Donc, retirez le # devant la ligne afin de la décommenter.
On se place maintenant dans le dossier qui accueillera les fichiers de Nextcloud et on les télécharge.
cd /var/www
sudo wget https://download.nextcloud.com/server/releases/latest.tar.bz2
sudo wget https://download.nextcloud.com/server/releases/latest.tar.bz2.sha256
sha256sum -c latest.tar.bz2.sha256 < latest.tar.bz2
Après l'exécution de cette dernière commande, on vérifie que le hash est bon.
latest.tar.bz2: OK
Si tout est bon, on vérifie la signature PGP
sudo wget https://download.nextcloud.com/server/releases/latest.tar.bz2.asc
sudo wget https://nextcloud.com/nextcloud.asc
gpg --import nextcloud.asc
gpg --verify latest.tar.bz2.asc latest.tar.bz2
gpg: Signature made Thu 21 Sep 2023 09:08:13 AM UTC gpg: using RSA key 28806A878AE423A28372792ED75899B9A724937A gpg: Good signature from "Nextcloud Security" [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 2880 6A87 8AE4 23A2 8372 792E D758 99B9 A724 937A
Si tout est bon, la sortie doit contenir Good signature
Enfin, on extrait l'archive
sudo tar -xvf latest.tar.bz2
sudo rm latest.tar.bz2* nextcloud.asc
Par défaut, un serveur web fait tourner tous les sites sous un utilisateur à part du système (souvent www-data). En cas de compromission d'un des sites, le pirate n'a que des accès restreints. Il ne peut, par exemple, pas visiter votre dossier personnel ni installer une application.
Mais, comme tous les sites tournent sur le même utilisateur, si un site est compromis, il peut compromettre les autres sites, accéder à vos données. C'est pourquoi, on va créer un utilisateur réservé à Nextcloud. Lui seul aura accès aux données de votre Nextcloud.
sudo adduser nextcloud
Créez un bon mot de passe. Et s'il vous plaît, ne réutilisez pas vos mots de passe. Utilisez un gestionnaire si vous le souhaitez.
(Je recommande Bitwarden).
On donne donc la propriété du dossier Nextcloud à l'utilisateur Nextcloud. Puis on retire les permissions aux autres.
sudo chown -R nextcloud:www-data /var/www/nextcloud
sudo chmod -R o-rwx /var/www/nextcloud
On télécharge php
sudo apt install php8.2-{fpm,ctype,curl,dom,gd,mbstring,posix,simplexml,xmlreader,xmlwriter,zip,mysql,bz2,intl,imap,bcmath,gmp,imap,ftp,ldap,gmp,exif,apcu,memcached,redis,imagick,phar}
On crée la configuration de php pour nextcloud
sudo nano /etc/php/8.2/fpm/pool.d/nextcloud.conf
[nextcloud]
listen = /var/run/nextcloud.sock
listen.owner = nextcloud
listen.group = www-data
user = nextcloud
group = www-data
pm = ondemand
pm.max_children = 200
pm.process_idle_timeout = 60s
pm.max_requests = 500
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
request_terminate_timeout = 3600
catch_workers_output = yes
php_flag[display_errors] = on
php_admin_value[error_log] = /var/log/fpm-php.log
php_admin_flag[log_errors] = on
Si vous observez des problèmes de stabilité, modifiez la variable pm.max_children. vous pouvez allez voir https://spot13.com/pmcalculator/
sudo systemctl edit php8.2-fpm.service
Dans ce fichier, ajoutez les lignes suivantes
[Service]
UMask=0027
Enfin, on réactive PHP
sudo systemctl reenable php8.2-fpm.service
On s'attaque maintenant à la base de données.
sudo mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY! In order to log into MariaDB to secure it, we'll need the current password for the root user. If you've just installed MariaDB, and haven't set the root password yet, you should just press enter here. Enter current password for root (enter for none):[TOUCHE ENTRER] OK, successfully used password, moving on... Setting the root password or using the unix_socket ensures that nobody can log into the MariaDB root user without the proper authorisation. You already have your root account protected, so you can safely answer 'n'. Switch to unix_socket authentication [Y/n] n ... skipping. You already have your root account protected, so you can safely answer 'n'. Change the root password? [Y/n] Y New password: Un bon mot de passe ! Re-enter new password: Password updated successfully! Reloading privilege tables.. ... Success! By default, a MariaDB installation has an anonymous user, allowing anyone to log into MariaDB without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? [Y/n] Y ... Success! Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? [Y/n] Y ... Success! By default, MariaDB comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? [Y/n]Y - Dropping test database... ... Success! - Removing privileges on test database... ... Success! Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? [Y/n] Y ... Success! Cleaning up... All done! If you've completed all of the above steps, your MariaDB installation should now be secure. Thanks for using MariaDB!
Maintenant que MariaDB est configuré, on peut créer notre base de données.
sudo mysql -u root -p
Ici, le mot de passe est le mot de passe root créé lors de mariadb_secure_installation
Puis, dans MariaDB, exécutez une par une les commandes ci-dessous.
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'motdepasse';
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost';
FLUSH PRIVILEGES;
quit;
On modifie un petit peu la configuration
sudo nano /etc/mysql/conf.d/mysql.cnf
[mysql] [mysqld] innodb_buffer_pool_size=1G innodb_io_capacity=4000
J'ai remarqué que sans l'ajout de ces lignes, nextcloud crash lorsqu'il charge de nombreux fichiers.
sudo systemctl restart mysqld
SSL est le protocole qui gère le httpS.
Nginx fonctionne avec des fichiers de configuration. Pour faire les choses proprement, un fichier par site.
On va donc créer celui de Nextcloud.
Pour ne pas se prendre la tête, on va créer une configuration vide, générer le certificat SSL, puis mettre la vraie configuration paramétrée pour fonctionner avec le SSL.
sudo nano /etc/nginx/sites-available/nextcloud
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/nextcloud/;
}
En changeant bien sûr example.com par votre domaine, ou votre sous-domaine.
Cette configuration est dans le dossier "sites-available", ce qui dit à Nginx qu'elle existe.
Pour la rendre active, on doit créer un lien vers le dossier "sites-enabled".
cd /etc/nginx/sites-enabled/
sudo ln -s ../sites-available/nextcloud .
sudo systemctl restart nginx.service
Voilà, Nginx est prêt à recevoir Certbot. On l'installe.
sudo apt-get install -y software-properties-common certbot
sudo certbot certonly --webroot -w /var/www/nextcloud --agree-tos --no-eff-email --email email@example.com -d example.com --rsa-key-size 4096
En renseignant votre adresse email et votre domaine.
Pour plus de sécurité, on va générer une clé DH de 4096 bits. La commande peut prendre beaucoup de temps en fonction de votre pc.
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Une fois que c'est fait, on lui donne le minimum de droits
sudo chmod 600 /etc/ssl/certs/dhparam.pem
Et voilà ! Nos clés SSL sont prêtes. Il suffit de mettre à jour notre configuration Nginx.
Supprimez toutes les lignes précédemment écrites et remplacer le tout.
sudo nano /etc/nginx/sites-available/nextcloud
upstream php-handler { server unix:/var/run/nextcloud.sock; } map $arg_v $asset_immutable { "" ""; default "immutable"; } server { listen 80; listen [::]:80; server_name example.com; server_tokens off; location ~ /.well-known { root /var/www/nextcloud/; allow all; } # Enforce HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; # Path to the root of your installation root /var/www/nextcloud; # Use Mozilla's guidelines for SSL/TLS settings # https://mozilla.github.io/server-side-tls/ssl-config-generator/ ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_session_tickets off; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # HSTS (ngx_http_headers_module is required) (63072000 seconds) add_header Strict-Transport-Security "max-age=63072000" always; # OCSP stapling ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; resolver 127.0.0.1; server_tokens off; # set max upload size and increase upload timeout: client_max_body_size 1G; client_body_timeout 300s; 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/wasm 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; # Pagespeed is not supported by Nextcloud, so if your server is built # with the `ngx_pagespeed` module, uncomment this line to disable it. #pagespeed off; client_body_buffer_size 512k; # HTTP response headers borrowed from Nextcloud `.htaccess` add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "noindex, nofollow" always; add_header X-XSS-Protection "1; mode=block" always; # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; index index.php index.html /index.php$request_uri; # Rule borrowed from `.htaccess` to handle Microsoft DAV clients location = / { if ( $http_user_agent ~ ^DavClnt ) { return 302 /remote.php/webdav/$is_args$args; } } location = /robots.txt { allow all; log_not_found off; access_log off; } # Make a regex exception for `/.well-known` so that clients can still # access it despite the existence of the regex rule # `location ~ /(\.|autotest|...)` which would otherwise handle requests # for `/.well-known`. location ^~ /.well-known { # The rules in this block are an adaptation of the rules # in `.htaccess` that concern `/.well-known`. location = /.well-known/carddav { return 301 /remote.php/dav/; } location = /.well-known/caldav { return 301 /remote.php/dav/; } location /.well-known/acme-challenge { try_files $uri $uri/ =404; } location /.well-known/pki-validation { try_files $uri $uri/ =404; } # Let Nextcloud's API for `/.well-known` URIs handle all other # requests by passing them to the front-end controller. return 301 /index.php$request_uri; } # Rules borrowed from `.htaccess` to hide certain paths from clients location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } # Ensure this block, which passes PHP files to the PHP process, is above the blocks # which handle static assets (as seen below). If this block is not declared first, # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php` # to the URI, resulting in a HTTP 500 error response. location ~ \.php(?:$|/) { # Required for legacy support rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; fastcgi_split_path_info ^(.+?\.php)(/.*)$; set $path_info $fastcgi_path_info; try_files $fastcgi_script_name =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $path_info; fastcgi_param HTTPS on; fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice fastcgi_param front_controller_active true; # Enable pretty urls fastcgi_pass php-handler; fastcgi_intercept_errors on; fastcgi_request_buffering off; fastcgi_read_timeout 3600; fastcgi_max_temp_file_size 0; } location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite|map)$ { try_files $uri /index.php$request_uri; add_header Cache-Control "public, max-age=15778463, $asset_immutable"; access_log off; # Optional: Don't log access to assets location ~ \.wasm$ { default_type application/wasm; } } location ~ \.woff2?$ { try_files $uri /index.php$request_uri; expires 7d; # Cache-Control policy borrowed from `.htaccess` access_log off; # Optional: Don't log access to assets } # Rule borrowed from `.htaccess` location /remote { return 301 /remote.php$request_uri; } location / { try_files $uri $uri/ /index.php$request_uri; } location ~ /\.(?!file).* { deny all; } }
Voilà notre véritable configuration pour nextcloud. Pensez à changer example.com par votre domaine ou sous domaine.
sudo systemctl reload nginx.service
sudo certbot renew --dry-run
sudo systemctl restart nginx.service
sudo systemctl restart php8.2-fpm.service
On redémarre tout pour bien prendre les configs.
Il nous reste peu de chose à faire. On va faire quelques optimisations avec le cache.
sudo nano /etc/php/8.2/fpm/php.ini
..... memory_limit=512M (ligne environ 435) ..... [opcache] (ligne environ 1787) opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.revalidate_freq=60 opcache.save_comments=1
Il faut décommenter les lignes et modifier les valeurs.
Sous Nano, pour rechercher, c'est CTRL+W.
sudo systemctl restart php8.2-fpm.service
sudo apt-get install php-apcu redis-server php-redis -y
On modifie le fichier de configuration d'apcu.
sudo nano /etc/php/8.2/mods-available/apcu.ini
extension=apcu.so
apc.enable_cli=1
Enfin, courage, la configuration est casi finie.
Rendez-vous sur votre domaine example.com
Vous devriez avoir la fenêtre de configuration de nextcloud qui s'ouvre.
Les deux premiers champs sont vos identifiants de connexion administrateur pour votre interface nextcloud.
Le répertoire des données est un dossier accessible (nextcloud:www-data).
Par exemple: /var/www/nextcloud/data
En dessous, ce sont les identifiants de la base de données:
L'utilisateur de la base de données est nextcloud
Le mot de passe est celui que vous avez définie lors de la configuration de mariaDB (à la place de motdepasse)
Le nom de la base de données est nextcloud
Et l'hôte est localhost.
Pour modifier la configuration de nextcloud, sans altérer les droits, on doit se connecter en tant que nextcloud.
su nextcloud
nano /var/www/nextcloud/config/config.php
Ajoutez les lignes suivantes en dessous de la ligne instanceid, au-dessus de ");"
'memcache.local' => '\\OC\\Memcache\\APCu', 'memcache.locking' => '\\OC\\Memcache\\Redis', 'redis' => array( 'host' => 'localhost', 'port' => 6379, ), 'loglevel' => 2, 'logtimezone' => 'Europe/Paris', 'logfile' => '/var/log/nextcloud/nextcloud.log', 'log_rotate_size' => '104857600', 'default_phone_region' => 'FR',
Puis on retourne en root
exit
On va maintenant installer Fail2Ban, un outil qui permet de bannir une partie des bots qui essaieraient d'attaquer votre site.
sudo systemctl restart php8.2-fpm.service
sudo mkdir /var/log/nextcloud
sudo chown nextcloud:www-data /var/log/nextcloud
sudo apt-get -y install fail2ban
Et on modifie sa configuration
sudo nano /etc/fail2ban/filter.d/nextcloud.conf
[Definition] failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: ''\)","level":2,"time":".*"}$ ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user,:".*","app":"no app in context".*","method":".*","message":"Login failed: '.*' \(Remote IP: ' '\)".*}$ ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: \).*}$
On crée la jail pour nextcloud
sudo nano /etc/fail2ban/jail.local
[nextcloud] enabled = true port = 80,443 protocol = tcp filter = nextcloud maxretry = 3 bantime = 3600 logpath = /var/log/nextcloud/nextcloud.log
On redémarre le service
sudo systemctl restart fail2ban.service
Et on l'active
sudo fail2ban-client start
Enfin, on modifie le fichier cron pour lancer les vérifications de Nextcloud automatiquement.
sudo crontab -u nextcloud -e
il se peut qu'il vous demande quel éditeur utilisé. Si vous ne savez pas, mettez 1.
Et on ajoute cette ligne
*/5 * * * * php -f /var/www/nextcloud/cron.php
Et on relance tout pour être sûr.
sudo systemctl restart php8.2-fpm.service
sudo systemctl restart nginx.service
Connecté sous l'utilisateur nextcloud, on installe RichDocuments
su nextcloud
cd /var/www/nextcloud
php -d memory_limit=512M occ app:install richdocumentscode
RichDocuments permet d'avoir une sorte de suite office (word powerpoint etc) directement sur son nextcloud.
Si vous ajoutez manuellement des fichiers dans le répertoire /var/www/nextcloud/data/
tout d'abord, il faut faire attention aux droits. Donc soit vous les copiez en étant connecté en tant qu'utilisateur Nextcloud.
Soit après le transfert, il faut changer les droits
su root
sudo chown -R nextcloud:www-data /var/www/nextcloud
sudo chmod -R o-rwx /var/www/nextcloud
Ensuite, il faut indiquer à Nextcloud qu'il doit les prendre en compte !
Pour ça, on fait un scan avec la commande suivante :
su nextcloud
cd /var/www/nextcloud
php occ files:scan --all
Si vous vous retrouvez limité par le système anti-intrusion de Nextcloud (en vous trompant trop de fois de mot de passe),
exécutez ces commandes pour vous débannir.
su nextcloud
cd /var/www/nextcloud
php occ security:bruteforce:reset ip