cms_pico icon indicating copy to clipboard operation
cms_pico copied to clipboard

Publish website under another domain

Open avanc opened this issue 5 years ago • 21 comments

Is it possible to make the pico page accessible under another domain? I want to edit the content within Nextcloud (e.g. nextcloud.mydomain.org) but the site shall be accessible under another domain (e.g. www.mydomain.org).

avanc avatar Oct 10 '19 11:10 avanc

This isn't possible at the moment. However, I'll mark this issue as enhancement, so we might implement it in a future version of Pico CMS for Nextcloud.

As an alternative you could install a separate instance of Pico (http://picocms.org/) and mount Pico's content directory as external storage in your Nextcloud. However, please note that this would be completely independent of Pico CMS for Nextcloud, i.e. you couldn't use any of this app's features, including XSS protection (even though this doesn't matter so much if you're hosting it under a completely different domain; be careful nevertheless!).

PhrozenByte avatar Oct 10 '19 13:10 PhrozenByte

Can we not use Apache redirection or something along those lines to have it done invisibly? I'm intending on hosting on the same domain, but that instead of the site being at /sites/sitename, I would want it to be at the root of the domain.

zerojay avatar Dec 08 '19 23:12 zerojay

You might use mod_proxy together with the mod_proxy_html module to replace URLs in-place. As an alternative you could also create a Pico plugin to change the base_url directive accordingly. But still, this isn't supported natively.

PhrozenByte avatar Dec 09 '19 07:12 PhrozenByte

It would be awesome if we will be able to do that through NextCloud in the future. A pretty simple short term fix can be just doing a forward and mask to the Pico URL from your domain provider.

OpenSourceMarketing avatar Dec 12 '19 00:12 OpenSourceMarketing

This is my workaround for the issue, but requires additional DNS setup, an extra php script outside of Nextcloud/Pico, and a couple config options added to my Apache config. Eventually, if some of this functionality were built in to Nextcloud/Pico, that would be lovely but for now this is my ball of duct tape and superglue:

I have my server set up such that all the Pico sites are accessible via the usual https://my.cloud.server/sites/sitename URL but also have a wildcard dns record pointing to the cloud server and a matching wildcard SSL certificate - this reduces the administrative overhead if more sites get created, but having specific DNS records and matching SAN entries on the SSL certificate works just fine too. ~~The Nextcloud trusted URL option doesn't seem to affect Pico CMS for the purposes of serving up sites so that's convenient.~~

EDIT: Since I first wrote this, an update seems to have changed the trusted domain thing so I now have to include any domains that I want to serve sites with in Nextcloud's trusted_domains configuration option. *.my.domain works to and subdomains of my.domain, but my.domain must be included separately if you intend to serve sites from there.

In my apache config, I have:

Alias "/redirect/" "/path/to/redirect/directory/"
<If "%{HTTP_HOST} != 'my.cloud.server'">
  # If it's just asking for index.php, it'll redirect to the main Nextcloud script
  RedirectMatch 307 ^/index.php$ https://my.cloud.server/ #
  # if it matches this regex, send it to the redirect script to get redirected to the proper site.
  RedirectMatch 307 ^/(?!(sites/.+|redirect/index.php.*|apps/.*|index.php/(css|apps).*|core/.*))(\?.*)?.*$ /redirect/index.php$1
</If>

The regex doesn't match URIs that are part of a site, the redirect script (elsewise we'd just end up in a redirect loop), and a few URIs that Pico/Nextcloud needs to pass through to function properly. I haven't the slightest idea what an equivalent nginx configuration would look like..

My redirect php file checks for any GET values that might give it a clue about where to send it based on old links to some of my long-dead sites, and then checks if there is a specific site for a specific http_host:

if (strtolower($_SERVER["HTTP_HOST"]) == "other.domain" || strtolower($_SERVER["HTTP_HOST"]) == "www.other.domain" ) {
        header("Location: https://other.domain/sites/sitename", TRUE, 307);
        exit;
}

This, of course, requires me to manually edit the script if my mappings need to change.

For anything that doesn't have a specific mapping, it treats the hostname as the site name:

$parts = explode('.',$_SERVER["HTTP_HOST"],2);  // splits the http_host into hostname and domain name
if (strtolower($parts[1]) == 'cloud.server') {
  header("Location: https://" . $parts[0] . "." . $parts[1] . "/sites/" . $parts[0] . "/",TRUE,307);  // redirects to the site matching the hostname
  exit;
}

With this, if someone attempts to browse to https://mysite.cloud.server/ it gets redirected to the redirect script which then sends it to https://mysite.cloud.server/sites/mysite/. If a site doesn't exist, it'll show the usual "site not found" page in. With a bit of additional scripting, I imagine I could have it look up in the Nextcloud DB if a site by that name exists first and if not, redirect to my landing page, but that's a tweak for another day.

Limitations: It doesn't work on private sites because the site domain doesn't match the cloud server's main domain and so it doesn't know you're logged in so you'll just get the "access forbidden" page. The wildcard redirect doesn't handle subdomains as written - everything before the first . is considered the site name and if the rest doesn't match the base domain, I have it redirect to a landing page. Also, Apache cries about in invalid request for site names that have an _ because that's not allowed in hostnames, apparently. Edit: As mentioned above, any domains you intend to serve sites from now need to be included in Nextcloud's trusted_domains configuration option.

In the end, everything still ends up being served up with the /sites/sitename path on it, but at least the domain name is customized.

doftnet avatar Jan 03 '20 20:01 doftnet

I built on @PhrozenByte's suggestion to use mod_proxy_html and got it to work flawlessly in NGINX (with sub_filter) with no modifications required to PHP code. My setup includes a primary domain where each subdomain maps to a Pico site created in Nextcloud. E.g. foobar.mydomain.com shows the PicoCMS site named website-foobar.

All that's needed is this bit of nginx configuration (after setting up the short urls on nextcloud as well):

server {
  server_name ~^(?<domain>.+).mydomain.com$;

  # required for theme files (css etc)
  location /apps/cms_pico/ {
    proxy_pass http://nextcloudhost.com;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

  location / {
    proxy_pass http://nextcloudhost.com/apps/cms_pico/pico_proxy/website-$domain/;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # don't pass unnecessary nextcloud cookies
    proxy_hide_header "set-cookie";
    
    # rewrite links to keep to the domain root
    sub_filter "/sites/website-$domain/" "/";
    sub_filter_once off;
  }
}

This way nginx knows which site to proxy to based on the subdomain directly, no further vhosts required.

julianwachholz avatar Feb 21 '20 08:02 julianwachholz

Hi My own very simple workaround working on Apache: In my nextcloud.conf, I added below my nextcloud.mydomain.tld vhost, another vhost named blog.mydomain.tld containing:

# for all resources outside of the cms pico directory (incl. the cms pico app itself)
ProxyPass /apps/ https://nextcloud.mydomain.tld/apps/
ProxyPassReverse /apps/ https://nextcloud.mydomain.tld/apps/
# needed for assets that keeps being referred as /sites/something
ProxyPass /sites/ https://nextcloud.mydomain.tld/index.php/apps/cms_pico/pico_proxy/
ProxyPassReverse /sites/ https://nextcloud.mydomain.tld/index.php/apps/cms_pico/pico_proxy/
# for blog files themselves
ProxyPass / https://nextcloud.mydomain.tld/index.php/apps/cms_pico/pico_proxy/
ProxyPassReverse / https://nextcloud.mydomain.tld/index.php/apps/cms_pico/pico_proxy/

Obviously, you'll need to have a dns record for this blog domain with the same IP as the one of the nexcloud domain. I tested it on a very simple blog so I'm not sure it's 100% working...

I tried to do the same with Locations but didn't succeed.

Edit: you'll access your blog site name myblog through https://blog.mydomain.tld/myblog

leolivier avatar Jun 01 '20 18:06 leolivier

@julianwachholz server_name ~^(?<domain>.+).mydomain.com$; suggests your setup doesn't support mydomain.com showing picoCMS site named website- (no, it's not a typo) instead of the Nextclouds web interface (which could be proxied e.g. to cloud.mydomain.com or if easier to mydomain.com/cloud/).

If this gets solved, then picoCMS could become "next big thing" Nextcloud can - namely "web hosting" :wink:.

dumblob avatar Sep 01 '20 20:09 dumblob

@dumblob you are correct. but nothing is stopping you from adding the bare domain there as well. :)

julianwachholz avatar Sep 01 '20 20:09 julianwachholz

True :wink:. I'm now starting to lean towards the solution from @brasofilo (https://github.com/nextcloud/cms_pico/issues/57#issuecomment-626093968 ). Thanks for pioneering!

dumblob avatar Sep 01 '20 21:09 dumblob

thanks @leolivier , your solution fixed all my issues. with those ProxyPasses I was even able to use a separate domain / virtualhost ( sepdom.conf -> sepdom.tld ) .

@ all: if you dont't wanna access you nextcloud via sepdom.tld then you might use the following RewriteRules for your *:443 virtualhost (I tested them, they should work):

        RewriteEngine on
        RewriteCond %{REQUEST_URI} ^/login [NC]
        RewriteRule ^ https://cloud.mydomain.tld%{REQUEST_URI} [END,NE,R=permanent]
	RewriteCond %{REQUEST_URI} ^/s/ [NC]
        RewriteRule ^ https://cloud.mydomain.tld%{REQUEST_URI} [END,NE,R=permanent]

(and leave @leolivier 's SSLProxyEngine part as is.)

TobjasR avatar Dec 09 '20 13:12 TobjasR

I guess to make this fully work, it would be great if there was a way to enter a custom domain here: image

szaimen avatar Mar 01 '21 13:03 szaimen

BTW: this feature will soon be available in the NcVM: https://github.com/nextcloud/vm/pull/1867

szaimen avatar Mar 01 '21 14:03 szaimen

BTW: this feature will soon be available in the NcVM: nextcloud/vm#1867

wow, that's fantastic news! 🍻 can't wait for it 🤖

TobjasR avatar Mar 01 '21 15:03 TobjasR

@szaimen thanks! I've skimmed it and it looks pretty complicated - any plans to support "update" by simply re-running the installation scripts any time like in cloudinabox?

dumblob avatar Mar 01 '21 18:03 dumblob

any plans to support "update" by simply re-running the installation scripts any time like in cloudinabox?

I am not excactly sure what you mean. It is only meant to run in the NcVM. But of course you can modify it to make it work in cloudinabox. 👍 (Though please respect the license terms if you want to redistribute it.)

szaimen avatar Mar 01 '21 18:03 szaimen

@PhrozenByte what are your thoughts on what @szaimen posted above:

BTW: this feature will soon be available in the NcVM: nextcloud/vm#1867

Could support for this "domain renaming" be made (at least partially) part of cms_pico rather then relying on some kungfu in one of the many NC installation automation frameworks/scripts?

dumblob avatar Mar 03 '21 14:03 dumblob

@PhrozenByte what are your thoughts on what @szaimen posted above:

My thoughts: Great work! :rocket: :heart:

Hosting websites on different domains is going to be part of Pico CMS for Nextcloud v1.1 (see #99) as its major feature. However, implementing this isn't as easy as one might think, because with an proxy you can easily ensure that one can only request website resources (by simply just proxying a sub-directory), but for a built-in solution this is a huge security-sensitive task.

PhrozenByte avatar Mar 03 '21 15:03 PhrozenByte

@PhrozenByte You are right, and that's why (not sure i did right) i have opened this issue at nextcloud server

cm-t avatar Jun 11 '21 11:06 cm-t