Intermediaire 11 min de lecture · 2 252 mots

Nextcloud sur Proxmox : au-delà de l’installation – performances, apps et maintenance

Nextcloud installé dans un LXC Proxmox, mais lent et sans optimisations. Voici ce que j'ai fait pour passer d'une instance poussive à un setup qui tient la route : Redis, APCu, preview generator, Collabora, NFS et maintenance automatisée.

Nextcloud sur Proxmox : au-delà de l’installation – performances, apps et maintenance
Intermediaire · 2026.07.22

L’installation de base de Nextcloud, c’est une chose. La sortir du mode « démo lente le week-end » pour en faire un vrai remplaçant de cloud personnel, c’en est une autre. Après avoir suivi mon propre article d’installation (article 8 de la série « 10 services auto-hébergés sur Proxmox »), je me suis retrouvé avec une instance fonctionnelle mais pénible : login à 2 secondes, galerie photo qui spike le CPU au scroll, et Collabora qu’on ne peut pas ajouter sans se battre avec les trusted domains. J’ai passé deux soirées à corriger tout ça.

Ce que j’avais avant

LXC 106 sur heighliner (MS-01, i9-13900H, Proxmox VE 8.3) : Debian 12 Bookworm, PHP 8.2-fpm, MariaDB 10.11 en local dans le conteneur, Nextcloud 29.0.3. 2 GB de RAM alloués, 4 vCPU. Nginx Proxy Manager (LXC 102) fait office de reverse proxy, certificat Let’s Encrypt via NPM.

Ce qui manquait à cette config de base : Redis pour le cache de sessions et le verrouillage de fichiers, APCu pour le cache local PHP, la pré-génération de miniatures, et un accès aux fichiers du NAS Synology DS414 depuis l’interface Nextcloud.

Redis : le changement le plus immédiat

Sans Redis, Nextcloud stocke les sessions PHP dans des fichiers et utilise un mécanisme de locking en base de données pour éviter les conflits d’accès fichiers. C’est lent et ça ne passe pas à l’échelle, même pour un usage solo.

Dans le LXC 106 :

apt install redis-server php8.2-redis -y

Configuration minimale dans /etc/redis/redis.conf :

bind 127.0.0.1
port 6379
maxmemory 256mb
maxmemory-policy allkeys-lru
unixsocket /var/run/redis/redis.sock
unixsocketperm 770

J’ai ajouté www-data au groupe redis :

usermod -aG redis www-data

Puis dans /var/www/nextcloud/config/config.php :

'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'timeout' => 1.5,
],

Résultat mesuré : le login est passé de ~2s à ~0.8s. Ce n’est pas un benchmark rigoureux – j’ai chronométré à la main une dizaine de fois avant/après – mais la différence est perceptible immédiatement dans l’usage quotidien. La page d’accueil après login se charge aussi plus vite car les données de session sont en RAM plutôt que lues depuis le disque.

APCu pour le cache PHP local

APCu est distinct de Redis : il cache les données en mémoire partagée au niveau du processus PHP-FPM, ce qui le rend plus rapide que Redis pour les objets fréquemment accédés par la même requête. Nextcloud l’utilise via memcache.local.

apt install php8.2-apcu -y

Dans /etc/php/8.2/fpm/conf.d/20-apcu.ini :

extension=apcu.so
apc.enabled=1
apc.shm_size=128M
apc.ttl=7200

OPcache était déjà actif via PHP 8.2-fpm par défaut. J’ai vérifié dans /etc/php/8.2/fpm/conf.d/10-opcache.ini que opcache.enable=1 était bien présent.

Redémarrage :

systemctl restart php8.2-fpm

PostgreSQL vs MariaDB : mon choix

J’utilise MariaDB et je n’ai pas l’intention de migrer. La documentation officielle de Nextcloud recommande PostgreSQL pour les instances avec plus de 50 utilisateurs, en raison de la gestion des transactions et des performances sous forte concurrence. Pour un homelab à usage solo ou familial (quelques utilisateurs), MariaDB 10.11 fait parfaitement l’affaire.

La migration MariaDB vers PostgreSQL existe via occ db:convert-type, mais c’est une opération risquée que je ne ferai pas sans bonne raison. Si tu pars de zéro et que tu prévois un usage multi-utilisateurs, PostgreSQL est un choix raisonnable dès le départ.

Preview generator : ne génère pas à la volée

Le problème que j’avais : scroller dans la galerie photo provoquait des spikes CPU à 80-90% sur le LXC. Nextcloud génère les miniatures à la demande par défaut, ce qui signifie que chaque nouvelle image dans le viewport déclenche un redimensionnement PHP.

La solution : pré-générer toutes les miniatures via un job cron, et désactiver partiellement la génération à la volée.

Installation de l’app Preview Generator via OCC :

php /var/www/nextcloud/occ app:install previewgenerator

Première génération (peut prendre du temps selon le volume de fichiers) :

php /var/www/nextcloud/occ preview:generate-all -vvv

Cette commande peut durer plusieurs heures sur une grande bibliothèque photo. Lance-la dans un `screen` ou `tmux`.

Dans config.php, j’ai limité les tailles de preview générées pour éviter de saturer le disque :

'preview_max_x' => 2048,
'preview_max_y' => 2048,
'jpeg_quality' => 60,
'enabledPreviewProviders' => [
    'OC\Preview\PNG',
    'OC\Preview\JPEG',
    'OC\Preview\GIF',
    'OC\Preview\HEIC',
    'OC\Preview\MP4',
],

Le job de mise à jour est ensuite géré par le cron systemd (voir section Maintenance).

Cron systemd, pas cron PHP/web

C’est une erreur classique : laisser Nextcloud en mode « Ajax » pour le cron interne, ce qui signifie que les tâches de fond ne s’exécutent que quand quelqu’un visite l’interface. En homelab, l’instance n’est pas toujours visitée.

Dans l’interface admin de Nextcloud, passer le mode d’exécution en arrière-plan sur « Cron ». Puis créer un timer systemd :

/etc/systemd/system/nextcloud-cron.service :

[Unit]
Description=Nextcloud background jobs

[Service]
User=www-data
ExecStart=/usr/bin/php -f /var/www/nextcloud/cron.php

/etc/systemd/system/nextcloud-cron.timer :

[Unit]
Description=Nextcloud background jobs timer

[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Persistent=true

[Install]
WantedBy=timers.target
systemctl enable nextcloud-cron.timer
systemctl start nextcloud-cron.timer

Vérifie que le cron tourne bien avec `systemctl status nextcloud-cron.timer` et regarde la date de dernier déclenchement.

J’ai ajouté la génération de previews au même timer en créant un second service nextcloud-preview.service avec ExecStart=/usr/bin/php /var/www/nextcloud/occ preview:pre-generate et un timer à 15 minutes. Comme ça, les nouvelles photos ajoutées via l’app mobile sont pré-rendues rapidement sans attendre.

Montage NFS : le stockage externe depuis le DS414

Le Synology DS414 expose un share NFS sur le réseau Stockage (VLAN 40). Dans l’interface DSM, j’ai activé le service NFS et ajouté une règle pour l’IP du LXC 106 avec droits Read/Write, Map to root, squash No mapping.

Dans le LXC, montage NFS :

apt install nfs-common -y
mkdir -p /mnt/nas/photos

Dans /etc/fstab :

192.168.40.10:/volume1/photos /mnt/nas/photos nfs rw,hard,intr,rsize=8192,wsize=8192,timeo=14 0 0
mount -a

Dans Nextcloud, j’ai ensuite ajouté ce partage via Paramètres > Administration > Stockage externe. Type : NFS. J’ai renseigné l’IP du NAS et le chemin du partage. L’app « External Storage Support » doit être activée.

Utilise NFS plutôt que SMB si le LXC est sous Linux. La latence est plus faible et il n’y a pas de négociation de protocole SMB à gérer.

L’accès au NAS depuis l’interface Nextcloud fonctionne maintenant en lecture/écriture. Les fichiers restent sur le DS414 et ne sont pas déplacés dans la data dir de Nextcloud.

Collabora Online (CODE) : le plus pénible

Collabora Online est l’équivalent LibreOffice dans le navigateur, intégré à Nextcloud. J’ai utilisé l’image CODE (Collabora Online Development Edition), qui est l’intégration embarquée pour les petites instances.

Déploiement dans un LXC dédié ou directement via Docker dans le LXC Nextcloud. J’ai choisi Docker dans le LXC 106 pour limiter le nombre de conteneurs Proxmox.

apt install docker.io -y
docker run -d \
  --name collabora \
  -p 127.0.0.1:9980:9980 \
  -e "aliasgroup1=https://nextcloud\\.you\\.arewel\\.com" \
  -e "extra_params=--o:ssl.enable=false --o:ssl.termination=true" \
  --restart always \
  collabora/code:latest

Dans Nextcloud, activer l’app « Nextcloud Office » (anciennement Collabora Online). Dans Paramètres > Administration > Nextcloud Office, entrer l’URL WOPI du serveur CODE : https://nextcloud.you.arewel.com/collabora/ (via le reverse proxy).

Configuration Nginx Proxy Manager pour proxifier /collabora/ vers 127.0.0.1:9980. Ça, c’est la partie qui m’a pris le plus de temps.

Ce qui a coincé : les trusted domains

Collabora doit connaître le domaine Nextcloud pour autoriser les connexions WOPI. J’ai passé une heure à me battre avec des erreurs {"kind":"error"} dans les logs CODE parce que le regex aliasgroup1 ne matchait pas correctement l’URL.

La variable d’environnement attend un regex échappé. Le point dans le domaine doit être échappé : \\. et non .. J’avais copié un exemple avec un point simple, ce qui autorisait n’importe quel caractère à la place du point dans le domaine.

Côté Nextcloud, il y a un autre piège : trusted_domains dans config.php doit inclure le domaine Nextcloud ET le domaine depuis lequel Collabora fait ses requêtes WOPI. Dans mon cas :

'trusted_domains' => [
    0 => 'localhost',
    1 => 'nextcloud.you.arewel.com',
],
'trusted_proxies' => ['172.16.0.0/12', '10.0.0.0/8', '127.0.0.1'],
'overwriteprotocol' => 'https',
'overwrite.cli.url' => 'https://nextcloud.you.arewel.com',

trusted_proxies doit inclure toutes les plages IP susceptibles de faire office de proxy (le réseau Docker interne, le réseau LXC). Si Nextcloud voit des requêtes arriver depuis une IP non listée dans trusted_proxies, il les considère comme directes et les en-têtes X-Forwarded-For sont ignorés, ce qui casse l’authentification WOPI.

Apps installées et utilisées

Collabora Online (Nextcloud Office) : édition de documents .docx/.odt/.xlsx directement dans le navigateur. Ça marche, avec quelques secondes de chargement la première fois.

Talk : vidéo/audio en P2P pour les appels familiaux. Nécessite un serveur TURN/STUN si on est derrière un NAT strict. J’utilise coturn installé sur heighliner directement.

Calendar et Contacts : synchronisés via DAVx5 sur Android. La configuration dans DAVx5 demande juste l’URL du compte Nextcloud et les identifiants. Le calendrier et les contacts apparaissent dans les apps système Android en quelques secondes.

Notes : remplacement correct de Google Keep pour les notes rapides. L’app mobile Nextcloud Notes (Android/iOS) synchronise bien.

L’app Nextcloud pour iOS et Android gère la synchronisation des fichiers. La synchronisation automatique des photos depuis le mobile fonctionne en Wi-Fi. Sur mon réseau local, j’obtiens ~200 fichiers/s de synchronisation, limité par le NAS DS414 et non par Nextcloud.

Accès externe et headers de sécurité

J’expose Nextcloud via Traefik (que j’ai déployé en remplacement de NPM sur certains services). Pour Nextcloud, les headers HTTP sont critiques : scan.nextcloud.com note l’instance sur ces critères.

Dans la configuration Traefik, middleware headers pour Nextcloud :

middlewares:
  nextcloud-headers:
    headers:
      customResponseHeaders:
        X-Robots-Tag: "noindex, nofollow"
        X-Content-Type-Options: "nosniff"
        X-Frame-Options: "SAMEORIGIN"
        Referrer-Policy: "no-referrer"
        Permissions-Policy: "camera=(), microphone=(), geolocation=(self)"
        Strict-Transport-Security: "max-age=15552000; includeSubDomains"

Avec cette configuration et Redis/APCu en place, scan.nextcloud.com affiche un score A+. Les points contrôlés sont les headers HTTP, la configuration HTTPS, la présence du cache distribué, et la version de Nextcloud.

Mise à jour via occ

Les mises à jour Nextcloud via l’interface web fonctionnent mais ont tendance à planter sur des instances LXC avec peu de RAM ou des temps de réponse PHP longs. Je préfère la voie CLI :

php /var/www/nextcloud/occ maintenance:mode --on
# télécharger la nouvelle version dans /var/www/nextcloud
php /var/www/nextcloud/occ upgrade
php /var/www/nextcloud/occ maintenance:mode --off
php /var/www/nextcloud/occ db:add-missing-indices

Toujours faire un snapshot Proxmox du LXC 106 avant une mise à jour majeure. La restauration prend moins de 30 secondes.

Le nettoyage des fichiers temporaires et des chunks d’upload abandonnés se fait via :

php /var/www/nextcloud/occ files:cleanup
php /var/www/nextcloud/occ trashbin:cleanup --all-users

J’ai intégré ces commandes dans un script hebdomadaire lancé par un timer systemd.

Ce que je ferais différemment

Si c’était à refaire, je déploierais Nextcloud avec PostgreSQL dès le départ. Pas parce que c’est nécessaire pour un usage solo, mais parce que la migration ultérieure est fastidieuse et que PostgreSQL gère mieux les transactions longues lors des scans de fichiers.

Je séparerais aussi MariaDB/PostgreSQL dans un LXC dédié plutôt que de le faire tourner dans le même conteneur que Nextcloud. Ça simplifie les sauvegardes PBS et permet d’allouer les ressources indépendamment.

Pour Collabora, un LXC Docker dédié avec accès réseau isolé serait plus propre. Mélanger Docker et les services PHP dans le même LXC complique la gestion des logs et le suivi des ressources dans Grafana.

La prochaine étape sur cette instance : Authentik comme fournisseur SSO (LXC 107 est déjà en service) pour remplacer l’auth native Nextcloud par OIDC. Ça centralisera la gestion des utilisateurs sur tous les services du homelab.

Une remarque, un retour ?

Cet article est vivant - corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.

Laisser un commentaire