Nextcloud AIO docker reverse proxy in separate container

Hi

I’m trying to get AIO running behind a reverse proxy in docker. I also want to host a website so I want the reverse proxy in a separte container I can use for other services.

I followed the following and got Nextcloud up and running without Talk or Imaginary:

This uses lucaslorentz/caddy-docker-proxy with labels in the destination stacks to populate the Caddy file which seems like a good way of doing it. I have not managed to find documentation which explains how to create a Caddy file manually (file name, extension and location?).
https://github.com/lucaslorentz/caddy-docker-proxy

I have attempted to add the labels and network from tmo1’s tutorial to the AIO docker-compose.yml which has resulted in this Nextcloud-AIO dockercompose.yml:

version: "3.8"

volumes:
  nextcloud_aio_mastercontainer:
    name: nextcloud_aio_mastercontainer # This line is not allowed to be changed as otherwise the built-in backup solution will not work

services:
  nextcloud:
    image: nextcloud/all-in-one:latest
    restart: always
    container_name: nextcloud-aio-mastercontainer # This line is not allowed to be changed as otherwise AIO will not work correctly
    volumes:
      - nextcloud_aio_mastercontainer:/mnt/docker-aio-config # This line is not allowed to be changed as otherwise the built-in backup solution will not work
      - /var/run/docker.sock:/var/run/docker.sock:ro # May be changed on macOS, Windows or docker rootless. See the applicable documentation. If adjusting, don't forget to also set 'WATCHTOWER_DOCKER_SOCKET_PATH'!
    #ports:
     # - 80:80 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
     # - 8080:8080
     # - 8443:8443 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
    # environment: # Is needed when using any of the options below
      # - AIO_DISABLE_BACKUP_SECTION=false # Setting this to true allows to hide the backup section in the AIO interface.
      - APACHE_PORT=11000 # Is needed when running behind a web server or reverse proxy (like Apache, Nginx and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
      - APACHE_IP_BINDING=127.0.0.1 # Should be set when running behind a web server or reverse proxy (like Apache, Nginx and else) that is running on the same host. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
      # - COLLABORA_SECCOMP_DISABLED=false # Setting this to true allows to disable Collabora's Seccomp feature. See https://github.com/nextcloud/all-in-one#how-to-disable-collaboras-seccomp-feature
      # - NEXTCLOUD_DATADIR=/mnt/ncdata # Allows to set the host directory for Nextcloud's datadir. See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir
      # - NEXTCLOUD_MOUNT=/mnt/ # Allows the Nextcloud container to access the chosen directory on the host. See https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host
      # - NEXTCLOUD_UPLOAD_LIMIT=10G # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud
      # - NEXTCLOUD_MAX_TIME=3600 # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud
      # - NEXTCLOUD_MEMORY_LIMIT=512M # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud
      # - NEXTCLOUD_TRUSTED_CACERTS_DIR=/path/to/my/cacerts # CA certificates in this directory will be trusted by the OS of the nexcloud container (Useful e.g. for LDAPS) See See https://github.com/nextcloud/all-in-one#how-to-trust-user-defiend-certification-authorities-ca
      # - NEXTCLOUD_STARTUP_APPS=deck twofactor_totp tasks calendar contacts # Allows to modify the Nextcloud apps that are installed on starting AIO the first time. See https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup
      # - NEXTCLOUD_ADDITIONAL_APKS=imagemagick # This allows to add additional packages to the Nextcloud container permanently. Default is imagemagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-os-packages-permanently-to-the-nextcloud-container
      # - NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS=imagick # This allows to add additional php extensions to the Nextcloud container permanently. Default is imagick but can be overwritten by modifying this value. See https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container
      # - NEXTCLOUD_ENABLE_DRI_DEVICE=true # This allows to enable the /dev/dri device in the Nextcloud container which is needed for hardware-transcoding. See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-transcoding-for-nextcloud
      # - TALK_PORT=3478 # This allows to adjust the port that the talk container is using.
      # - WATCHTOWER_DOCKER_SOCKET_PATH=/var/run/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. Otherwise mastercontainer updates will fail. For macos it needs to be '/var/run/docker.sock'
    # networks: # Is needed when you want to create the nextcloud-aio network with ipv6-support using this file, see the network config at the bottom of the file
      # - nextcloud-aio # Is needed when you want to create the nextcloud-aio network with ipv6-support using this file, see the network config at the bottom of the file
    networks:
      caddy:
        ipv4_address: 172.16.0.7 
    labels:
      caddy: nextcloud.example.nz
      caddy.reverse_proxy: "{{upstreams}}"
      # see: https://github.com/lucaslorentz/caddy-docker-proxy/issues/114
      caddy.header: /*
      # see: https://docs.nextcloud.com/server/23/admin_manual/installation/harden_server.html#enable-http-strict-transport-security
      caddy.header.Strict-Transport-Security: '"max-age=15552000;"'
      # see: https://docs.nextcloud.com/server/23/admin_manual/issues/general_troubleshooting.html#service-discovery
      # https://github.com/lucaslorentz/caddy-docker-proxy/issues/222
      caddy.rewrite_0: /.well-known/carddav /remote.php/dav
      caddy.rewrite_1: /.well-known/caldav /remote.php/dav
    environment:
      # See: https://hub.docker.com/_/nextcloud/
      - APACHE_DISABLE_REWRITE_IP=1
      # See: https://github.com/nextcloud/documentation/issues/7005
      # and: https://old.reddit.com/r/NextCloud/comments/s3skdn/nextcloud_behind_caddy_as_a_reverse_proxy_using/hsnj5wh/
      - TRUSTED_PROXIES=172.16.0.6
   # Optional: Caddy reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
   # You can find further examples here: https://github.com/nextcloud/all-in-one/discussions/588
networks:
  caddy:
    external: true

and this Caddy docker-compose.yml

version: "3.7"
services:
  caddy:
    # see here for guidance on which image / tag to choose:
    # https://github.com/lucaslorentz/caddy-docker-proxy#docker-images
    image: lucaslorentz/caddy-docker-proxy:2.4.0
    ports:
      - 80:80
      - 443:443
    environment:
      - CADDY_INGRESS_NETWORKS=caddy
    networks:
      caddy:
        ipv4_address: 172.16.0.6
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - caddy_data:/data
    restart: unless-stopped

networks:
  caddy:
    external: true

volumes:
  caddy_data: {}

I am receiving a redirected too many times error which I understand means Caddy is sending a http request to a https port on AIO but I don’t know how to fix it and I haven’t found a reverse proxy tutorial for AIO that I can get working.

Any help fixing this or directions to a working AIO reverse proxy tutorial preferably which doesn’t have the proxy in the same stack or on the host would be greatly appreciated.
Thanks
Craig

Hi, you cannot use docker labels to configure things. I would suggest you use the “official” caddy docker image instead of this lucaslorentz/caddy-docker-proxy:2.4.0 one.

Here is the reverse proxy documentation: all-in-one/reverse-proxy.md at main ¡ nextcloud/all-in-one ¡ GitHub

And this an example Caddy Docker Compose Example ¡ nextcloud/all-in-one ¡ Discussion #575 ¡ GitHub

Thanks Szaimen

The example at the top of Discussion #575 yeilds the following error:

root@photon-machine [ ~/docker/nextcloud-AIO ]# docker-compose up -d
Starting caddy ... error

ERROR: for caddy  Cannot start service caddy: OCI runtime create failed: container_linux.go:370: starting container process caused: process_linux.go:459: container init caused: rootfs_linux.go:59: mounting "/root/docker/nextcloud-AIO/Caddyfile" to rootfs at "/var/lib/docker/overlay2/2e3b5e5e51b1e9838b71b398e1fdcf20e8abb5e9d282688f59d3dab32874598e/merged/etc/caddy/Caddyfile" caused: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type

ERROR: for caddy  Cannot start service caddy: OCI runtime create failed: container_linux.go:370: starting container process caused: process_linux.go:459: container init caused: rootfs_linux.go:59: mounting "/root/docker/nextcloud-AIO/Caddyfile" to rootfs at "/var/lib/docker/overlay2/2e3b5e5e51b1e9838b71b398e1fdcf20e8abb5e9d282688f59d3dab32874598e/merged/etc/caddy/Caddyfile" caused: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
ERROR: Encountered errors while bringing up the project.

I have created a file called ‘Caddyfile’ in the Caddyfile folder in the same location as the docker-compose.yml file but I’m not sure this is correct.

Ok. I have deleted the Caddyfile folder (which I did not create) and replaced it with the Caddyfile file. The stack now starts successfully but Caddy is not publishing ports (acording to portainer and it errors when I try to add port 443).

I am receiving the following error on the domain:

This page isn’t working
nextcloud.example.nz is currently unable to handle this request.
HTTP ERROR 502

Note: my domain is not example.nz. I do have it configured to my actual domain.

Did you use network_mode: host for caddy like shown in the example config?

docker-compose.yml is copy and paste from the example:

services:
  caddy:
    image: caddy:alpine
    restart: unless-stopped
    container_name: caddy
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./certs:/certs
      - ./config:/config
      - ./data:/data
      - ./sites:/srv
    network_mode: "host"

  nextcloud:
    image: nextcloud/all-in-one:latest
    restart: unless-stopped
    container_name: nextcloud-aio-mastercontainer
    ports:
      - "8080:8080"
    environment:
      - APACHE_PORT=11000
    volumes:
      - nextcloud_aio_mastercontainer:/mnt/docker-aio-config
      - /var/run/docker.sock:/var/run/docker.sock:ro
    depends_on:
      - caddy

volumes:
  nextcloud_aio_mastercontainer:

I also tried it without the quotes ‘network_mode: host’ with the same error.

Caddyfile is as follows (domain omitted). The only thing I have changed is the domain:

https://nextcloud.x.nz:443 {
    header Strict-Transport-Security max-age=31536000;
    reverse_proxy localhost:11000
}

While using the above config, did you already open the AIO interface and entered your domain?

Thanks szaimen. Sorry. I got tunnel vision on the reverse proxy and didn’t check that the next step actually built the webserver.
I completed the first setup as far as confirming the domain name which failed although the domain returns a string of characters which I assume means the reverse proxy is working.
I followed the debug section to the best of my ability up to and including point 11 where I removed all the containers (docker-compose down) and volumes (Portainer). I then deleted everything other than docker-compose.yml and Caddyfile from the home sub-directory and re-ran docker-compose up -d which created a ‘nextcloud_nextcloud_aio_mastercontainer’ volume rather than a ‘nextcloud_aio_mastercontainer’ volume.
Assuming that I had missed deleting something somewhere and being frustrated with Photon OS, I shutdown the VM, built a Unbuntu VM, installed docker and ran ‘docker-compose up -d’. I have once again got a ‘nextcloud_nextcloud_aio_mastercontainer’ volume rather than a ‘nextcloud_aio_mastercontainer’ volume on what should be a clean system. I would appreciate any thoughts on why this might be happening.

Thanks
Craig

This happens if you miss the following config in the docker-compose file:

volumes:
  nextcloud_aio_mastercontainer:
    name: nextcloud_aio_mastercontainer # This line is not allowed to be changed as otherwise the built-in backup solution will not work

Aah.
Unless I’m much mistaken, the last line is missing from the example here:

True. I just corrected this. Sorry for the trouble.

Thanks @szaimen. I have it working!
For the benefit of others also not familiar with Caddy, can I suggest the following (or similar) addition to reverse-proxy.md?

Caddy (Recommended)
click here to expand
Add this to your Caddyfile:

https://:443 {
reverse_proxy localhost:11000
}
Caddyfile is a text file called ‘Caddyfile’ (no extension) which needs to be created in the same location as your ‘docker-compose.yml’ file prior to starting the container.
Of course you need to modify to the domain on which you want to run Nextcloud. Also make sure to adjust the port 11000 to match the chosen APACHE_PORT. Please note: The above configuration will only work if your reverse proxy is running directly on the host that is running the docker daemon. If the reverse proxy is running in a docker container, you can use the --network host option (or network_mode: host for docker-compose) when starting the reverse proxy container in order to connect the reverse proxy container to the host network. If that is not an option or not possible for you (like e.g. on Windows or if the reverse proxy is running on a different host), you can alternatively instead of localhost use the private ip-address of the host that is running the docker daemon. If you are not sure how to retrieve that, you can run: ip a | grep “scope global” | head -1 | awk ‘{print $2}’ | sed ‘s|/.||'. If the command returns a public ip-address, use ip a | grep “scope global” | grep docker0 | awk ‘{print $2}’ | sed 's|/.||’ instead (the commands only work on Linux)

Advice: You may have a look at this for a more complete example.

Great! PRs are welcome! Sign in to GitHub ¡ GitHub