Migrating a Nextcloud and providing 2 ways to access it

Nextcloud version on old/prod system: 18.0.3
PHP: 7.3.16
Apache: 2.4.41

Nextcloud version on new/target system: 18.03 in docker container, image “nextcloud:18.0.3”
Operating system of docker host: Debian 10.3

The issue you are facing:

I am migrating an existing nextcloud-18.0.3 installation from a non-docker installation into a docker-compose stack. That stack runs behind a HAproxy on pfsense … and it works so far.

My issue/question:

old nextcloud is reached via:

https://mail.my.tld/nextcloud

new nextcloud runs at:

https://cloud.my.tld

The old links should stay valid … for example calendar links like:

https://mail.my.tld/nextcloud/remote.php/dav/calendars/stefan@my.tld/persönlich/

should be kept working while this should also work:

https://cloud.my.tld/remote.php/dav/calendars/stefan@my.tld/persönlich/

I assume there are multiple ways to solve that, and I wonder if someone could help me to find the most elegant and reliable solution.

I assume it should/could be solved within .htaccess or the apache vhost config?

In the old nextcloud installation I find a line:

RewriteBase /nextcloud

That came from the initial owncloud installation somehow … maybe that was wrong from the start back then.

relevant part of old/productive config.php file in /path/to/nextcloud :

        "overwrite.cli.url": "https:\/\/mail.my.tld\/nextcloud",
        "htaccess.RewriteBase": "\/nextcloud",

By “old links should stay valid,” do you mean you want the old URLs to still work and go to the new system? Or they should still access the old Nextcloud?

If you want them to redirect to the new one, that’s easily done by editing the old vhosts and making them redirect clients to the new URL.

http://httpd.apache.org/docs/2.2/mod/mod_alias.html#Redirect

Redirect to new.

The dozens of mail-clients with subscribed calendars etc shouldn’t notice the move to the new system. Over time only the new links will be deployed to them step by step, but we want to keep the old URLs for now.

There will be no parallel 2 installations after migration, no.

So I need

Redirect /nextcloud https://cloud.my.tld

in .htaccess on the new box? Nothing else?

I assume I should remove any of the overwrite_* parameters as well.

(for sure both A-records point to the same machine, I have valid certs installed and the new nextcloud has both names in trusted_domains).

I try that with my test installation and 2 names “mail2” and “cloud”.

Modified .htaccess and reloaded apache.

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTP_USER_AGENT} DavClnt

[..]

  RewriteRule ^(?:\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
 
# last line here, maybe it should be placed higher?
  Redirect "/nextcloud/" "https://cloud.my.tld/"
</IfModule>

I then added a calendar to my thunderbird with URL:

https://mail2.my.tld/nextcloud/remote.php/dav/calendars/stefan/personal/

That worked and I could add an event, but then the connection “broke” and I wasn’t able to edit that event anymore. Lightning just tells me to reload as the event has been edited on the server … which isn’t the case IMO. So I can’t edit/write that event anymore.

The nextcloud log doesn’t show any particular error while I try that.

thanks, Stefan

You could try redirecting with a rewrite rule instead of a plain redirect. The difference is that the redirect tells the client to access the new URL. The rewrite rule would simply serve the other site transparently and pretend the URL is still the old one.

More info here: https://stackoverflow.com/questions/12399505/understanding-difference-between-redirect-and-rewrite-htaccess

To be honest, I’m not sure what impact this will have on calendars or contacts or various client software.

Hi,

The easiest way to do this is probably with pfSense and HAProxy.

You define your new server as a backend (To_Nextcloud).
In your frontend, you put ACLs and Actions for both names to use that same backend :
ACL would be something like :
Old_Name Host matches mail.my.tld
New_Name Host matches cloud.my.tld

Use Backend To_Nextcloud for Old_Name
Use Backend To_Nextcloud for New_Name

For that to work, you need to configure your HAProxy’s IP address as a trusted proxy in config.php. You also need to save there the two valid names to be used for your service.

Be sure you have valid SSL certificates for both names in your HAProxy config.

Sure, I have such a setup already with pfsense, that works!
The open question is that Redirect/Rewrite. I will look into Rewrite instead of Redirect next, as mentionedby @KarlF12

You can also search in your MariaDB for the old values.
Perhaps you can change them with db-manipulations.
Perhaps dumping db, “sed” or other global replace with regular expressions and then restore.

Basically this is my issue, I think:

I think the Rewrite has to happen twice:
once for the condition of a WebDAV Client, second rewrite for the “normal” browser.

I try around with stuff like:

RewriteCond %{HTTP_USER_AGENT} DavClnt
  RewriteRule ^nextcloud/(.*) /$1 [L]

but no success so far.

EDIT:

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTP_USER_AGENT} DavClnt
# sgw
  #RewriteRule ^/nextcloud/caldav(.*)$ /remote.php/dav/ [R=301,L]
  #RewriteRule ^/nextcloud/carddav(.*)$ /remote.php/dav/ [R=301,L]
  RewriteRule ^/nextcloud/(.*) /$1 [L]
# sgw
  RewriteRule ^$ /remote.php/webdav/ [L,R=302]
  RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
  RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L]
  RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L]
  RewriteRule ^\.well-known/webfinger /public.php?service=webfinger [QSA,L]
  RewriteRule ^\.well-known/nodeinfo /public.php?service=nodeinfo [QSA,L]
  RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
  RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
  RewriteRule ^remote/(.*) remote.php [QSA,L]
  RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
  RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
  RewriteRule ^(?:\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
</IfModule>

My test accesses (via Thunderbird, Lightning Addon) look like this in apache log:

# bad one, should be rewritten
192.168.220.254 - - [24/Apr/2020:08:06:56 +0000] "PUT /nextcloud/remote.php/dav/calendars/Administrator/pers%C3%B6nlich/ HTTP/1.1" 302 613 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0 Lightning/68.6.0"

# good one, works
192.168.220.254 - Administrator [24/Apr/2020:08:06:56 +0000] "PUT /remote.php/dav/calendars/Administrator/pers%c3%b6nlich/ HTTP/1.1" 412 1592 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0 Lightning/68.6.0"

I don’t see the need to do so … as far as I know the URLs etc aren’t stored in the database.

I cancelled the approach with Apache Redirect etc
Instead I looked at the possibilities of HAproxy and it seems I was able to solve it there.

Tests will show in the next few hours.
I will post my solution as soon as I am happy with it.

I was able to successfully rewrite the URL with HAproxy.

But Thunderbird/Lightning did not like that very much, to me it seems that some kind of cookie doesn’t match then anymore. I think Lightning expects the calendar object to relate to a cookie with a path containing “/nextcloud” (in my case) and the nextcloud instance writes these cookies with path “/”. This leads to issues, we couldn’t edit the events in Lightning etc

I’d appreciate an explanation of the details!

The solution now is a plain alias in the apache vhost:

Alias /nextcloud /var/www/html

This makes both old and new URLs work with calendars etc

It doesn’t rewrite the URL, but this isn’t priority one here.
People get a new bookmark into their browsers, done.

The main goal was not to break existing DAV-connections.

thanks, regards, Stefan