Example: Docker Nextcloud-FPM + Caddy v2 webserver

The Nextcloud Quick reference on Docker Hub states that there are two versions (apache or fpm) of the Nextcloud image. The apache version contains a full Nextcloud installation including an apache web server. The fpm version must be combined with any webserver that can proxy the http requests to the FastCGI-port of the container.

In the Quick reference fpm example, an nginx container is combined with the Nextcloud-fpm image and a MariaDB database container. If you would rather use Caddy in place of nginx, below you will find an equivalent fpm example that replaces nginx with Caddy v2 as the webserver.

docker-compose.yml:

version: '2'

volumes:
  nextcloud:
  db:
  caddy_data:

services:
  db:
    image: mariadb
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: always
    volumes:
      - db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=
      - MYSQL_PASSWORD=
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  app:
    image: nextcloud:fpm
    links:
      - db
    volumes:
      - nextcloud:/var/www/html
    restart: always

  web:
    image: caddy
    ports:
      - 8080:80
    links:
      - app
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    volumes_from:
      - app
    restart: always

Caddyfile:

:80 {

        root    * /var/www/html
        file_server

        php_fastcgi app:9000
        header {
                # enable HSTS
                # Strict-Transport-Security max-age=31536000;
        }

        redir /.well-known/carddav /remote.php/dav 301
        redir /.well-known/caldav /remote.php/dav 301

        # .htaccess / data / config / ... shouldn't be accessible from outside
        @forbidden {
                path    /.htaccess
                path    /data/*
                path    /config/*
                path    /db_structure
                path    /.xml
                path    /README
                path    /3rdparty/*
                path    /lib/*
                path    /templates/*
                path    /occ
                path    /console.php
        }

        respond @forbidden 404

}

Reference: Dockerised Caddy V2 + Nextcloud-FPM to create an unsecured Nextcloud instance

1 Like

I’m using this setup but looking at expanding it to include the rewrites as shown here for caddy v1:

Similar to the rewrites in the nginx examples:

Could you expand on your setup to include these rewrites?

Although this topic is old, it is very relevant!
I am considering switching to Nextcloud-FPM (from FileRun) and switching to Caddy-docker-proxy (from Traefik) as I do everything with Docker Compose.

But I am just traumatised from spending months figuring out Traefik for all my stuff (mainly OpenOffice Documentserver was impossible to debug).

I understand Caddy (the docker-proxy version) can be as simple as adding 2 labels to your (Nextcloud) container, but the scenario of @basil needs Caddy to replace nginx as well, not just the reverse https proxy.
On top of that it needs to support Nextcloud FPM/fastcgi.

How to do that wil the caddy-docker-proxy version?

Hi @zilexa and welcome to the Caddy community!

There’s nothing to stop you using the Apache or FPM (with nginx) examples as is in the Quick reference guide together with a Caddy container. There’s no compelling reason to replace nginx with Caddy in the FPM example, other than it’s one less container to deal with.

If you choose to replace nginx with Caddy in the FPM example, then I suspect all you need to do is add the reverse proxy construct to this example’s Caddyfile.

If you choose to use the unadulterated FPM/nginx or Apache examples from the quick reference guide, and use Caddy just for the reverse proxy function, there are a couple of extra lines that you will need to include along with the reverse proxy construct in the Caddyfile. Refer to the Case study: Variations in Caddyfile design for different Nextcloud builds for further clues.

1 Like

Thanks for this
Works like a charm
It saved my sanity
New to self hosting and playing around with all kinds of 'ready 'nextcloud docker containers
LinuxUser,ownyourbits,official.
I have caddywebserver for reverse proxy and none of them worked
Cheers

1 Like

Found this super useful! I am coming from podman and I’ve used the following set-up for local HTTPS using the nextcloud-fpm container. I’ve adapted your config based on my post in HTTPS on LAN - Access via different host.

Set-up a pod

podman pod create --name nextcloud -p 4080:80 -p 4443:443

Container creation

Mariadb

podman run --detach \
  --env MYSQL_DATABASE=nextcloud \
  --env MYSQL_USER=nextcloud \
  --env MYSQL_PASSWORD= \
  --env MYSQL_ROOT_PASSWORD= \
  --volume nextcloud-db:/var/lib/mysql \
  --pod nextcloud \
  --name db \
  docker.io/library/mariadb:10

Nextcloud

podman run --detach \
  --env MYSQL_HOST=nextcloud-db \
  --env MYSQL_DATABASE=nextcloud \
  --env MYSQL_USER=nextcloud \
  --env MYSQL_PASSWORD= \
  --volume nextcloud:/var/www/html \
  --pod nextcloud \
  --name app \
  docker.io/library/nextcloud:21-fpm

Caddy

podman run --detach \
    --volume $PWD/Caddyfile:/etc/caddy/Caddyfile:Z \
    --volume nextcloud-caddy:/data \
    --name web \
    --pod nextcloud \
    --volumes-from app \
    caddy

Caddyfile

https:// {

        root    * /var/www/html
        file_server

        php_fastcgi app:9000
        header {
                # enable HSTS
                # Strict-Transport-Security max-age=31536000;
        }

	tls internal {
		on_demand
	}

        redir /.well-known/carddav /remote.php/dav 301
        redir /.well-known/caldav /remote.php/dav 301

        # .htaccess / data / config / ... shouldn't be accessible from outside
        @forbidden {
                path    /.htaccess
                path    /data/*
                path    /config/*
                path    /db_structure
                path    /.xml
                path    /README
                path    /3rdparty/*
                path    /lib/*
                path    /templates/*
                path    /occ
                path    /console.php
        }

        respond @forbidden 404

}
1 Like

CADDY DOCKER PROXY EXAMPLE
Run Nextcloud with just a few labels, nothing else!

I managed to figure out how to get Nextcloud 21 working with an A+ security rating, with the fastest options possible. There are so many nextcloud+caddy examples out there, most don’t work, are outdated or only work in a specific environment. Also, none of them use the setup simplicity docker-compose offers with docker-caddy-proxy.

This version is for everyone and contains the basics you need for the fastest Nextcloud experience. :

  • Redis for caching
  • PostgreSQL as it is the fastest database
  • FPM version of Nextcloud
  • Caddy as both reverse proxy and webserver, no need for nginx

Note: I used Nextcloud for a few days and immediately switched back to FileRun.
If you do not need calendar/contacts and all those extras, FileRun is the way to go in my opinion. Nextcloud does not even come close in speed (even with all that effort, it is still a bit slow), usability, user friendly UI etc is just much better thought through with FileRun.

Also, Nextcloud lacks proper documentation on how to install it with the fastest components + get A+ rating. Since it took quite some effort, I am sharing it here, even though I stopped using it!

(note an updated version is on github, link below)

version: "2.3"
services:
##
## To expose Nextcloud securely, Caddy is the easiest way to go.
##_____________________ Caddy [CLOUD/web-proxy]
  caddy:
    container_name: caddy-proxy
    image: lucaslorentz/caddy-docker-proxy:ci-alpine
    restart: always
    networks: 
      - web-proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - $DOCKERDIR/caddy/caddy_data:/data
      - $DOCKERDIR/caddy/config:/config
      - $DOCKERDIR/nextcloud/var/www/html:/nextcloud/var/www/html
      - $DOCKERDIR/nextcloud/var/data:/nextcloud/var/nextdata
    ports:
      - 80:80
      - 443:443
##
##____________________ NextCloud TESTED V21.0 [CLOUD/Files/NextCloud]
  nextcloud:
    image: nextcloud:21-fpm
    container_name: nextcloud
    restart: always
    mem_limit: 2048m
    mem_reservation: 512m
    networks:
      - web-proxy
      - nextcloud
    depends_on:
      - nextcloud-db
      - nextcloud-cache
    environment:
      NEXTCLOUD_DATA_DIR: /var/nextdata
      NEXTCLOUD_TRUSTED_DOMAINS: next.$DOMAIN
      NEXTCLOUD_ADMIN_USER: $USER1
      NEXTCLOUD_ADMIN_PASSWORD: $USER1PW
      POSTGRES_HOST: nextcloud-db
      POSTGRES_DB: nextcloud
      POSTGRES_USER: $USER
      POSTGRES_PASSWORD: $PW_INT
      REDIS_HOST: nextcloud-cache
      REDIS_HOST_PASSWORD: $PW_INT
      SMTP_HOST: $SMTPHOST
      SMTP_SECURE: tls
      SMTP_NAME: $SMTPUSER
      SMTP_PASSWORD: $SMTPPASS
      SMTP_FROM_ADDRESS: $EMAIL
      SMTP_PORT: 587
    volumes:
        # the actual data of the Nextcloud:
      - $DOCKERDIR/nextcloud/var/nextdata:/var/nextdata
        # Main folder needed for updating:
      - $DOCKERDIR/nextcloud/var/www/html:/var/www/html
        # local configuration
      - $DOCKERDIR/nextcloud/var/www/html/config:/var/www/html/config
        # Custom settings for php fpm to make nextcloud work. The default settings resulted in the error:
        # WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
      - $DOCKERDIR/nextcloud/etc/www-custom.ini:/usr/local/etc/php-fpm.d/zz-custom.conf
    labels:
      caddy: next.$DOMAIN
      caddy.tls: $EMAIL
      caddy.file_server: "" 
      caddy.root: "* /nextcloud/var/www/html"
      caddy.php_fastcgi: "{{upstreams 9000}}"
      caddy.php_fastcgi.root: "/var/www/html"
      caddy.php_fastcgi.env: "front_controller_active true"
      caddy.encode: gzip
      caddy.redir_0: "/.well-known/carddav /remote.php/dav 301"
      caddy.redir_1: "/.well-known/caldav /remote.php/dav 301"
      caddy.header.Strict-Transport-Security: '"max-age=15768000;includeSubDomains;preload"' # Required for Nextcloud
##____________________ NextCloud [CLOUD/Files/NextCloud/database]
  nextcloud-db:
    container_name: nextcloud-db
    image: postgres:12-alpine
    restart: always
    networks:
      - nextcloud
    environment:
      POSTGRES_USER: $USER
      POSTGRES_PASSWORD: $PW_INT
    volumes:
      - $DOCKERDIR/nextcloud/db:/var/lib/postgresql/data
      - /etc/localtime:/etc/localtime:ro
##____________________ NextCloud [CLOUD/Files/NextCloud/cache]
  nextcloud-cache:
    container_name: nextcloud-cache
    image: redis:alpine
    restart: always
    mem_limit: 2048m
    mem_reservation: 512m
    networks:
      - nextcloud
    command: redis-server --requirepass $PW_INT
#
networks:
  web-proxy:
    driver: bridge
  nextcloud:
    driver: bridge

feel free to use “volumes from” in the caddy container instead of that single nextcloud volume, see the example on github here:

1 Like