Contexte : cloud de fichiers, d'agendas et de contacts auto-hébergé, déployé avec Docker Compose et publié en HTTPS derrière un reverse proxy Nginx · Testé sur : Nextcloud 34 (image
nextcloud:34, PHP 8.4) et MariaDB 10.11, Docker Compose v2, dans un conteneur LXC Proxmox VE · Dernière vérification : 01/10/2026 (fichier Compose de référence en production ; installation complète non rejouée)
Déployer Nextcloud et sa base MariaDB avec Docker Compose, en gardant les mots de passe dans un fichier .env, puis publier le service en HTTPS derrière un reverse proxy Nginx installé sur la même machine ou sur une autre. La page couvre aussi le réglage de la taille maximale des fichiers envoyés.
docker compose) : voir Installer Docker ou la documentation officielle de Docker (https://docs.docker.com/engine/install/).<DOMAINE> (par exemple cloud.exemple.fr), qui pointe vers votre adresse IP publique, avec les ports 80 et 443 redirigés vers le reverse proxy.<IP_REVERSE_PROXY>)..env et dans le coffre-fort (voir Utiliser Bitwarden ou Bien gérer ses mots de passe).Vérifiez que Docker et Compose fonctionnent :
sudo docker run hello-world
docker compose version
Docker Compose v1 (
docker-compose1.29, installé avecpip, que décrivait une ancienne version de cette page) est obsolète. Utilisez le plugin Compose v2, installé avec Docker Engine :docker compose, sans tiret.
Créez le dossier du projet et celui des données des utilisateurs. Ce dernier, /srv/nextcloud/data dans cette page, est à adapter à votre stockage (en reportant le chemin dans la suite) :
sudo mkdir -p /opt/nextcloud
sudo mkdir -p /srv/nextcloud/data
Générez deux mots de passe différents, un pour le compte root de MariaDB et un pour l'utilisateur nextcloud :
openssl rand -base64 32
Créez le fichier /opt/nextcloud/.env, lisible par root uniquement :
sudo nano /opt/nextcloud/.env
sudo chmod 600 /opt/nextcloud/.env
MYSQL_ROOT_PASSWORD=<MOT_DE_PASSE_ROOT_DB>
MYSQL_PASSWORD=<MOT_DE_PASSE_DB>
Docker Compose lit ce fichier automatiquement et remplace ${MYSQL_ROOT_PASSWORD} et ${MYSQL_PASSWORD} dans le fichier Compose : aucun mot de passe n'apparaît dans docker-compose.yml.
Créez /opt/nextcloud/docker-compose.yml :
services:
db:
image: mariadb:10.11
container_name: nextcloud-db
restart: always
command: >-
--transaction-isolation=READ-COMMITTED
--binlog-format=ROW
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
volumes:
- db_data:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "mariadb -h127.0.0.1 -unextcloud -p\"$$MYSQL_PASSWORD\" -e 'SELECT 1' nextcloud >/dev/null 2>&1 || exit 1"]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
app:
image: nextcloud:34
container_name: nextcloud
restart: always
depends_on:
db:
condition: service_healthy
ports:
- "8080:80"
volumes:
- nextcloud_html:/var/www/html
- /srv/nextcloud/data:/var/www/html/data
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- PHP_MEMORY_LIMIT=512M
- PHP_UPLOAD_LIMIT=512M
volumes:
db_data:
nextcloud_html:
Points à retenir :
nextcloud:34 suit les correctifs de la version 34 sans changer de version majeure à votre insu ; évitez latest.healthcheck et depends_on).READ-COMMITTED, journal binaire au format ROW et jeu de caractères utf8mb4, recommandés pour Nextcloud."127.0.0.1:8080:80" pour que Nextcloud ne soit joignable que par lui. Sinon, filtrez le port 8080 sur le pare-feu pour n'autoriser que <IP_REVERSE_PROXY>.version: en tête de fichier, présente dans les anciens exemples, est inutile avec Compose v2.Docker dans un conteneur LXC Proxmox VE : si les conteneurs refusent de démarrer à cause d'AppArmor ou de seccomp, ajoutez à chacun des deux services le bloc suivant, que requiert notre installation de référence. Il réduit l'isolation des conteneurs : ne l'ajoutez qu'en cas de besoin.
security_opt:
- seccomp=unconfined
- apparmor=unconfined
cd /opt/nextcloud
sudo docker compose up -d
sudo docker compose ps
Suivez le premier démarrage (copie des fichiers de Nextcloud, installation) avec sudo docker compose logs -f app, puis quittez avec Ctrl+C.
Ouvrez http://<IP_SERVEUR>:8080 dans un navigateur. La base de données est déjà configurée par les variables d'environnement : l'assistant ne demande que l'identifiant et le mot de passe du compte administrateur. Choisissez un mot de passe robuste, conservé dans votre gestionnaire de mots de passe.
Sur la machine du reverse proxy, installez Certbot et son greffon Nginx :
sudo apt install certbot python3-certbot-nginx
Créez le fichier /etc/nginx/sites-available/<DOMAINE> avec un premier bloc en HTTP, que Certbot complétera :
server {
listen 80;
server_name <DOMAINE>;
# Taille maximale des envois (voir l'étape 8)
client_max_body_size 10G;
location / {
proxy_pass http://<IP_SERVEUR_NEXTCLOUD>:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Découverte automatique des agendas et contacts
location = /.well-known/carddav { return 301 $scheme://$host/remote.php/dav; }
location = /.well-known/caldav { return 301 $scheme://$host/remote.php/dav; }
}
Activez le site, testez la configuration et rechargez Nginx :
sudo ln -s /etc/nginx/sites-available/<DOMAINE> /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Obtenez le certificat Let's Encrypt. Certbot ajoute lui-même au bloc l'écoute en HTTPS (port 443) et les chemins du certificat, et crée la redirection de HTTP vers HTTPS :
sudo certbot --nginx -d <DOMAINE> --redirect
Contrôlez le résultat, puis rechargez Nginx :
sudo nginx -t
sudo systemctl reload nginx
Certbot renouvelle ensuite le certificat automatiquement, sans arrêter Nginx. Vous pouvez aussi ajouter l'en-tête HSTS dans le bloc HTTPS :
add_header Strict-Transport-Security "max-age=31536000" always;.
Tant que le domaine n'est pas approuvé, Nextcloud affiche ce message :
Accès à partir d'un domaine non approuvé
Veuillez contacter votre administrateur. Si vous êtes un administrateur, éditez la variable
"trusted_domains" dans le fichier config/config.php comme l'exemple dans le fichier config/config.sample.php.
Déclarez le domaine, le reverse proxy et l'usage de HTTPS avec l'outil en ligne de commande occ, depuis le dossier du projet :
cd /opt/nextcloud
sudo docker compose exec -u www-data app php occ config:system:set trusted_domains 1 --value="<DOMAINE>"
sudo docker compose exec -u www-data app php occ config:system:set trusted_proxies 0 --value="<IP_REVERSE_PROXY>"
sudo docker compose exec -u www-data app php occ config:system:set overwriteprotocol --value="https"
sudo docker compose exec -u www-data app php occ config:system:set overwrite.cli.url --value="https://<DOMAINE>"
Ces réglages s'appliquent immédiatement. Dans config/config.php, la liste des domaines approuvés ressemble alors à ceci :
'trusted_domains' =>
array (
0 => 'localhost:8080',
1 => '<DOMAINE>',
),
Vous pouvez aussi modifier ce fichier à la main (avec sudo docker exec -it nextcloud bash, le fichier se trouve dans /var/www/html/config/config.php) ; redémarrez alors le conteneur avec sudo docker compose restart app.
Trois limites s'appliquent aux envois, de l'extérieur vers l'intérieur :
| Couche | Réglage | Valeur par défaut |
|---|---|---|
| Reverse proxy Nginx | client_max_body_size |
1 Mo |
| PHP, dans l'image Nextcloud | variable PHP_UPLOAD_LIMIT (règle upload_max_filesize et post_max_size) |
512 Mo |
| Apache, dans l'image Nextcloud | variable APACHE_BODY_LIMIT, en octets (0 = illimité) |
1 Gio |
Pour autoriser des fichiers de 10 Go, par exemple :
client_max_body_size 10G; doit se trouver dans le bloc server HTTPS du site (c'est le cas avec la configuration de l'étape 6 ; sinon, ajoutez-la après les directives du certificat). Après toute modification, testez et rechargez Nginx :sudo nginx -t
sudo systemctl reload nginx
docker-compose.yml, adaptez les variables du service app : - PHP_UPLOAD_LIMIT=10G
- APACHE_BODY_LIMIT=0
docker restart ne relit pas les variables d'environnement :cd /opt/nextcloud
sudo docker compose up -d
Les clés
upload_max_sizeetpost_max_sizequ'une ancienne version de cette page ajoutait dansconfig.phpn'ont aucun effet : Nextcloud ne les lit pas. Ce sont des réglages PHP, pilotés dans l'image officielle parPHP_UPLOAD_LIMIT.
Les clients de synchronisation (ordinateur et mobile) envoient les gros fichiers par morceaux : la limite PHP gêne surtout les envois non découpés. La limite du reverse proxy, elle, bloque tout envoi un peu volumineux tant qu'elle reste à 1 Mo. Tenez compte aussi des capacités du serveur (espace disque, mémoire) avant d'augmenter ces limites.
healthy :cd /opt/nextcloud
sudo docker compose ps
curl -s https://<DOMAINE>/status.php
La réponse contient
"installed":trueet"maintenance":false.
sudo docker compose exec -u www-data app php occ status
| Symptôme | Cause probable | Solution |
|---|---|---|
| « Accès à partir d'un domaine non approuvé » | Domaine absent de trusted_domains |
Étape 7 |
Erreur 413 Request Entity Too Large |
Limite du reverse proxy atteinte | client_max_body_size (étape 8) |
Liens en http://, boucle de redirection ou avertissement sur le proxy |
Nextcloud ignore qu'il est servi en HTTPS derrière un proxy | trusted_proxies et overwriteprotocol (étape 7) |
| L'installation échoue sur le dossier de données | Dossier des données non accessible en écriture au serveur web du conteneur (utilisateur www-data, UID 33) |
sudo chown -R 33:33 /srv/nextcloud/data, puis relancer |
Un réglage de docker-compose.yml n'est pas pris en compte |
Conteneur redémarré sans être recréé | sudo docker compose up -d |
| Conteneurs bloqués au démarrage dans un conteneur LXC | Restrictions AppArmor ou seccomp | Bloc security_opt (étape 3) |
occ : sudo docker compose exec -u www-data app php occ <commande>, depuis /opt/nextcloud.docker-compose.yml, puis :cd /opt/nextcloud
sudo docker compose pull
sudo docker compose up -d
nextcloud_html (qui contient config.php) et le dossier des données sont à sauvegarder ensemble, de préférence avec le mode maintenance activé (voir la documentation d'administration de Nextcloud).Une ancienne version de cette page utilisait l'image Nextcloud All-in-One. Son conteneur maître pilote Docker par le socket de l'hôte et crée lui-même les autres conteneurs (Nextcloud, base de données, cache…). Exemple de fichier Compose de l'époque :
services:
nextcloud:
image: nextcloud/all-in-one:latest
restart: always
container_name: nextcloud-aio-mastercontainer # nom imposé par AIO
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config # nom de volume imposé par AIO
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "10080:80"
- "10443:8443"
environment:
- NEXTCLOUD_UPLOAD_LIMIT=50G
- NEXTCLOUD_STARTUP_APPS=deck tasks # applications installées au démarrage, séparées par des espaces
volumes:
nextcloud_aio_mastercontainer:
name: nextcloud_aio_mastercontainer
Cette variante n'est pas celle retenue ici. Si vous la choisissez, suivez la documentation officielle d'AIO pour les ports à publier, l'accès à l'interface d'administration AIO et la publication derrière un reverse proxy (variable APACHE_PORT), qui évoluent d'une version à l'autre.
occ : https://docs.nextcloud.com/server/latest/admin_manual/occ_command.html