0

I have nextcloud running on https://cloud.museumsstrasse.at but since we will use nextcloud primarily for opening data to the public I would like that this nextcloud root url leads to a public nextcloud folder directly, e.g. to use this one: https://cloud.museumsstrasse.at/s/Ytpcwos3o9o33kL but so that the public would not need the url with the share sub-url but only type in https://cloud.museumsstrasse.at where this public folder would be opened. As for logging in and synchronizing with nextcloud I would then like to use another sub url such as this for example: https://cloud.museumsstrasse.at/internal

Is this possible and how?

My setup:

I got nextcloud running with docker on a Ubuntu 20.04 Server. Since other services are running on this server too, I set up a reverse proxy solution all with docker too including these images: nginx, jwilder/docker-gen:0.7.3, jrcs/letsencrypt-nginx-proxy-companion which do the reverse proxy and also generate the config files for reverse proxy. The docker-compose.yml for all this is this:

version: '3'

services:

  service_nginx:
    image: nginx:1.13.1
    container_name: container_nginx
    ports:
      - "80:80"
      - "443:443"
    networks:
      - network_nginx
    volumes:
      - ./volumes/nginx/conf:/etc/nginx/conf.d
      - ./volumes/nginx/vhost:/etc/nginx/vhost.d
      - ./volumes/nginx/html:/usr/share/nginx/html
      - ./volumes/nginx-letsencrypt/certs:/etc/nginx/certs
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"

  service_nginx-dockergen:
    image: jwilder/docker-gen:0.7.3
    container_name: container_nginx-dockergen
    depends_on:
      - service_nginx
    command: -notify-sighup container_nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
    networks:
      - network_nginx
    volumes:
      - ./volumes/nginx/conf:/etc/nginx/conf.d
      - ./volumes/nginx/vhost:/etc/nginx/vhost.d
      - ./volumes/nginx/html:/usr/share/nginx/html
      - ./volumes/nginx/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
      - ./volumes/nginx-letsencrypt/certs:/etc/nginx/certs
      - /var/run/docker.sock:/tmp/docker.sock:ro

  service_nginx-letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: container_nginx-letsencrypt
    depends_on:
      - service_nginx
      - service_nginx-dockergen
    environment:
      NGINX_PROXY_CONTAINER: container_nginx
      NGINX_DOCKER_GEN_CONTAINER: container_nginx-dockergen
    networks:
      - network_nginx
    volumes:
      - ./volumes/nginx/conf:/etc/nginx/conf.d
      - ./volumes/nginx/vhost:/etc/nginx/vhost.d
      - ./volumes/nginx/html:/usr/share/nginx/html
      - ./volumes/nginx-letsencrypt/certs:/etc/nginx/certs
      - /var/run/docker.sock:/var/run/docker.sock:ro

  service_nc_db:
    image: mariadb
    container_name: container_nc_db
    volumes:
      - ./volumes/nc_db:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
    networks:
      - network_nc_prod
    environment:
      - MYSQL_ROOT_PASSWORD=XXX
      - MYSQL_PASSWORD=XXX
      - MYSQL_DATABASE=XXX
      - MYSQL_USER=XXX
    restart: unless-stopped

  service_nc:
    image: nextcloud:latest
    container_name: container_nc
    depends_on:
      - service_nc_db
      - service_nginx
      - service_nginx-dockergen
      - service_nginx-letsencrypt
    networks:
      - network_nc_prod
      - network_nginx
    volumes:
      - ./volumes/nc/html:/var/www/html
      - ./volumes/nc/config:/var/www/html/config
      - ./volumes/nc/custom_apps:/var/www/html/custom_apps
      - ./volumes/nc/data:/var/www/html/data
      - ./volumes/nc/themes:/var/www/html/themes
      - /etc/localtime:/etc/localtime:ro
    environment:
      - VIRTUAL_HOST=cloud.museumsstrasse.at
      - LETSENCRYPT_HOST=cloud.museumsstrasse.at
      - LETSENCRYPT_EMAIL=XXX
    restart: unless-stopped

networks:
  network_ca_prod:
  network_nc_prod:
  network_nginx:

What I have tried so far is pushing the html code of nextcloud into a subfolder and fiddling around with settings such as overwritewebroot or overwritehost in config.php and various experimentation on nginx reverse proxying, but it all failed so far. What I have tried to follow were discussions such as these for example:

https://github.com/nextcloud/docker/issues/401

https://stackoverflow.com/questions/54716909/nextcloud-installation-in-subfolder-redirect-in-apache2

Nextcloud behind Ngnix reverse proxy in a subdir url

What does not work:

For example what doesn't work is if I add to config.php these two lines:

  'overwritehost' => 'cloud.museumsstrasse.at',
  'overwritewebroot' => '/internal'

Then opening cloud.museumsstrasse.at with the browser would get redirected to cloud.museumsstrasse.at/internal but in the meantime the code in /var/www/html/internal/<nextcloud_code> got deleted and overwritten with nextcloud code in /var/www/html/<nextcloud_code> which I then can not open because the browser would redirect me to cloud.museumsstrasse.at/internal again.

However even if something with overwritewebroot were working, how could I avoid this redirection from cloud.museumsstrasse.at to cloud.museumsstrasse.at/internal? Because the former should be the public face and the latter our internal nextcloud side. Hence I want no redirection but two different urls for different purposes.

I assume if a pragmatic way would be to adapt nextcloud's docker image logic to point it to /var/www/html/internal/ and then adapt the this docker's internal apache to show cloud.museumsstrasse.at while serving content from the public foldercloud.museumsstrasse.at/s/Ytpcwos3o9o33kL ? However I'm at a loss of how to do this...

Can someone help me here please?

Cheers, Stefan

steffres
  • 51
  • 6

1 Answers1

0

Alright, I got it working - at the expense of quite some pain.

Firstly, what I tried and what did not work (or what I could not get working):

  • Moving the nextcloud code into sub-folder (the nc image would always overwrite)
  • Creating virtual host by the apache server within the nc image. I could get correct redirections, but the target urls were always visible, which I wanted to avoid.
  • Creating redirections on the nginx reverse proxy layer.

Now, what I did instead was:

  • 1.) "moved" nextcloud to subpath by symbolic linking
  • 2.) recreate the reverse proxy stack with traefik

Details:

1.) "moved" nextcloud to subpath

In order to reach nextcloud under the url cloud.museumsstrasse.at/intern (before I had it called 'internal') I did the following steps:

1.1.

Created symbolic linking within the container:

ln -s /var/www/html/ /var/www/html/intern
chown www-data:root -h /var/www/html/intern
1.2.

Then opened nextcloud in a browser, registered an admin user, provided db credentials.

This step is necessary since afterwards some config files are auto generated which will be modified in the next steps.

1.3.

In /var/www/html/.htaccess is the auto-generated code-block where RewriteBase must be modified:

Without this step I got an ERR_TOO_MANY_REDIRECTS error.

<IfModule mod_rewrite.c>
  ....
  RewriteBase /intern # <-- changed from auto generated `RewriteBase /`
  ....
</IfModule>

1.4.

Now it would work mostly already, except for the fact that the web login and client authentication form freeze (somehow related to the reverse proxying). This issue is discussed here: https://github.com/nextcloud/server/issues/19091 and to fix it, the following must be added to /var/www/html/config/config.php:

...
'overwriteprotocol' => 'https' 
...

After these steps, the nextcloud instance can be reached with the desired subpath cloud.museumsstrasse.at/intern

A helpful discussion can be found here: https://github.com/nextcloud/docker/issues/401

2.) traefik reverse proxy

Now in order to show a selected public folder under the root url of cloud.museumsstrasse.at traefik can be used to replace paths on the fly while hiding the targeted urls from the visitor so that no matter what subpath is returned under cloud.museumsstrasse.at the url will always remain.

For this in traefik v2 a middleware must be defined. Since I'm using docker-compose only, I did this via these labels on the proxied service:

# defines the middleware:
- "traefik.http.routers.service_nextcloud.middlewares=custom_repath" 

# the regex which the rule should match (double dollar signs for escaping):
- "traefik.http.middlewares.custom_repath.replacepathregex.regex=^/$$"

# the replacement value (the subpath of a selected public folder):
-"traefik.http.middlewares.custom_repath.replacepathregex.replacement=/intern/s/63KFWGkziffJR8j"

3.) The full docker-compose.yml

services:

  service_traefik:
    image: "traefik:v2.2"
    container_name: container_traefik
    networks:
      - network_traefik
    command:
      # an explicit reference to the docker network must be passed when multiple networks exist:
      - "--providers.docker.network=docker_network_traefik"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=XXX"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
      - "8080:8080"
    volumes:
      - "./volumes/traefik/letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  service_nc_db:
    image: mariadb
    container_name: container_nc_db
    volumes:
      - ./volumes/nc_db:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
    networks:
      - network_nc
    environment:
      - MYSQL_ROOT_PASSWORD=XXX
      - MYSQL_PASSWORD=XXX
      - MYSQL_DATABASE=XXX
      - MYSQL_USER=XXX

  service_nc:
    image: nextcloud:latest
    container_name: container_nc
    depends_on:
      - service_traefik
      - service_nc_db
    networks:
      - network_traefik
      - network_nc
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.service_nextcloud.rule=Host(`cloud.museumsstrasse.at`)"
      - "traefik.http.routers.service_nextcloud.entrypoints=websecure"
      - "traefik.http.routers.service_nextcloud.tls.certresolver=myresolver"
      - "traefik.http.routers.service_nextcloud.middlewares=custom_repath"
      - "traefik.http.middlewares.custom_repath.replacepathregex.regex=^/$$"
      - "traefik.http.middlewares.custom_repath.replacepathregex.replacement=/intern/s/63KFWGkziffJR8j"
    volumes:
      - ./volumes/nc/html:/var/www/html

networks:
  network_nc:
  network_traefik:

4.) versions

Currently I got this running with nextcloud 19.0.1 and as seen in the docker-compose.yml with traefik 2.2

steffres
  • 51
  • 6