nextcloud / cms_pico

🗃 Integrate Pico CMS and let your users manage their own websites
https://apps.nextcloud.com/apps/cms_pico
GNU Affero General Public License v3.0
135 stars 42 forks source link

Publish website under another domain #83

Open avanc opened 5 years ago

avanc commented 5 years ago

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).

PhrozenByte commented 5 years ago

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!).

zerojay commented 4 years ago

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.

PhrozenByte commented 4 years ago

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.

OpenSourceMarketing commented 4 years ago

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.

doftnet commented 4 years ago

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.

julianwachholz commented 4 years ago

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.

leolivier commented 4 years ago

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

dumblob commented 4 years ago

@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:.

julianwachholz commented 4 years ago

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

dumblob commented 4 years ago

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!

TobjasR commented 3 years ago

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.)

szaimen commented 3 years ago

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

szaimen commented 3 years ago

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

TobjasR commented 3 years ago

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

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

dumblob commented 3 years ago

@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?

szaimen commented 3 years ago

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.)

dumblob commented 3 years ago

@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?

PhrozenByte commented 3 years ago

@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.

cm-t commented 3 years ago

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

goodretail commented 2 months ago

I am new to PicoCMS and Nextcloud but I think this platform is a fantastic idea. ChatGPT has been pivotal in my PHP / programming journey.

Where I got to so far with this, until I have seen this thread is setting up a vhosts file, which as I understand it would require further server access than what I currently have on my hosting plan.

I had tried a number of htaccess configurations on both the nextcloud installation and the unique domain used for displaying the PicoCMS website.

After all the attempts and speaking with both ChatGPT and my hosting providers AI and live customer support, it seems the conclusion is that VPS level hosting is required and the following vhosts file is needed.

Is anyone able to confirm the following is still required or what level of access to the server is needed for a better / easier solution instead?

<VirtualHost *:80> ServerName uniquedomain.com ServerAlias www.uniquedomain.com

# Redirect all HTTP requests to HTTPS
Redirect permanent / https://uniquedomain.com/

<VirtualHost *:443> ServerName uniquedomain.com ServerAlias www.uniquedomain.com

DocumentRoot /path/to/your/nextcloud/.htezxmhvzrx197.data/nextcloud/files/unique_blog/content

SSLEngine on
SSLCertificateFile /path/to/your/ssl/certificate.crt
SSLCertificateKeyFile /path/to/your/ssl/private.key
SSLCertificateChainFile /path/to/your/ssl/chainfile.crt

<Directory /path/to/your/nextcloud/.htezxmhvzrx197.data/nextcloud/files/unique_blog/content>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

ErrorDocument 404 /404.html

LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/uniquedomain.com_error.log
CustomLog ${APACHE_LOG_DIR}/uniquedomain.com_access.log combined

goodretail commented 2 months ago

I am new to PicoCMS and Nextcloud but I think this platform is a fantastic idea. ChatGPT has been pivotal in my PHP / programming journey.

Where I got to so far with this, until I have seen this thread is setting up a vhosts file, which as I understand it would require further server access than what I currently have on my hosting plan.

I had tried a number of htaccess configurations on both the nextcloud installation and the unique domain used for displaying the PicoCMS website.

After all the attempts and speaking with both ChatGPT and my hosting providers AI and live customer support, it seems the conclusion is that VPS level hosting is required and the following vhosts file is needed.

Is anyone able to confirm the following is still required or what level of access to the server is needed for a better / easier solution instead?

<VirtualHost *:80> ServerName uniquedomain.com ServerAlias www.uniquedomain.com

# Redirect all HTTP requests to HTTPS
Redirect permanent / https://uniquedomain.com/

<VirtualHost *:443> ServerName uniquedomain.com ServerAlias www.uniquedomain.com

DocumentRoot /path/to/your/nextcloud/.htezxmhvzrx197.data/nextcloud/files/unique_blog/content

SSLEngine on
SSLCertificateFile /path/to/your/ssl/certificate.crt
SSLCertificateKeyFile /path/to/your/ssl/private.key
SSLCertificateChainFile /path/to/your/ssl/chainfile.crt

<Directory /path/to/your/nextcloud/.htezxmhvzrx197.data/nextcloud/files/unique_blog/content>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

ErrorDocument 404 /404.html

LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/uniquedomain.com_error.log
CustomLog ${APACHE_LOG_DIR}/uniquedomain.com_access.log combined

So, just a quick update to this post, that I have posted also in the other thread server/issues/27473 because it also mentions this discussion and so I posted the following comment:

Hi all, I'm posting the link to my post in the thread 83 I have discovered a workaround is likely possible through the use of the vhosts file and mapping the domain to the PicoCMS website content directory. I have checked with both my hosting provider and ChatGPT and done a thorough check after exhausting all possibilities through HTACCESS. Obviously that was all before discovering the discussion about it here. Could anyone confirm if the solution of using the Vhosts file would please?

Also, I forgot to say that there is also a redirect required through the update of the htaccess setup in Nextcloud also.

The below is the HTACCESS update to the existing HTACCESS already available in the /nextcloud/ folder. So i'm just at the point whether I should sign up to a VPS server to test this out.

Obviously if this solution works I am likely to take this route, but if not I might go for a headless CMS solution instead, and there are few I am testing out. Headless CMS seems to be really taking the stage in a big way.

RewriteEngine On # Force HTTPS for subdomain RewriteCond %{HTTPS} off RewriteCond %{HTTP_HOST} ^(www\.)?nextcloud\.parentdomain\.uk$ [NC] RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # Redirect jaega_digital_blog URL to uniquedomain.com RewriteCond %{HTTP_HOST} ^(www\.)?nextcloud\.parentdomain\.uk$ [NC] RewriteCond %{REQUEST_URI} ^/index.php/apps/cms_pico/pico/uniquedomain_blog(/.*)?$ [NC] RewriteRule ^ https://jaegadigital.com [R=301,L] # General rule to handle other requests RewriteCond %{HTTP_HOST} ^(www\.)?nextcloud\.parentdomain\.uk$ [NC] RewriteCond %{REQUEST_URI} !^/nextcloud/ [NC] RewriteRule ^ /nextcloud/index.php [L]