• How to use your Movim blog as content provider for external domain

    Adrien Dorsaz – Mardi, 22 Août, 2017 - 13:27 - Jeudi, 24 Août, 2017 - 08:14


I've just been able to replace my WordPress blog with my Movim public blog on my home page. Following are steps I followed to have this working setup with Apache2 on Debian Stretch.

The hard part was to find a way to install a proxy on Movim URLs. Indeed, Movim use only one URL, like https://mov.adorsaz.ch/ to work: to decide if you want to view blog or chat for example, Movim add query strings to the URL (with HTTP GET options).

So the issue is that the Movim blog part is available to https://adorsaz.ch/?blog and such URL can't be directly used as proxy by Apache 2.

My server context

  • My own Movim pod is here: https://mov.adorsaz.ch
  • There, my public Movim blog is: https://mov.adorsaz.ch/?blog/adrien@adorsaz.ch
  • My main home page is there: https://adorsaz.ch

Show content from /?blog to /blog

First, in my Movim Apache 2 configuration I've enabled SSLProxyEngine (as all my virtual hosts use TLS) and RewriteEngine.

Then I added this RewriteRule to the Movim configuration:

RewriteRule    ^/blog(.*)$    /?blog$1    [QSA]

This rule redirect every one accessing https://mov.adorsaz.ch/blog to https://mov.adorsaz.ch/?blog . I had to use the [QSA] flag so Apache will append ?blog to the redirected URL.

(Note, that I used regular expression to copy all the chain (.*) to the query string arguments with $1)

Well, we don't want to redirect, but we want to keep user on /blog. So we need a Proxy rule to see content from /?blog directly inside /blog URL. To do so, I've simply modified the rule to:

RewriteRule    ^/blog(.*)$    /?blog$1    [QSA,P]

The [P] is for Proxy.

Set domain https://adorsaz.ch as a Proxy for https://mov.adorsaz.ch/blog/adrien@adorsaz.ch

Here, you simply need to say to Apache 2 to do a standard proxy between both URLs.

Inside the home page configuration, I enabled modules SSLEngineProxy and I've added this Proxy rule:

ProxyPass / https://mov.adorsaz.ch/blog/adrien%40adorsaz.ch/
ProxyPassReverse / https://mov.adorsaz.ch/blog/adrien%40adorsaz.ch/

Note that I've translated the @ to its URL encoded equivalent %40. The ProxyPassReverse instruction is not mandatory, it updates the Location HTTP header in the server responses.

Now, when a user read my blog, the content follow this path before coming to your browser:

https://mov.adorsaz.ch/?blog/adrien@adorsaz.ch (real Movim URLs)
↳ https://mov.adorsaz.ch/blog/adrien@adorsaz.ch (Movim URLs redirected by first step)
↳ https://adorsaz.ch/ (homepage URLs as seen by every one)

Although, they'll have some error in browser console, because cross domain requests are blocked by default. To allow fetching resources from the Movim pod domain through the homepage domain, I had to update the Movim configuration to add this rule:

Header set Access-Control-Allow-Origin "https://adorsaz.ch"

Rewrite HTML content to update blog URL

Now, users see the Movim blog on my home page, but all links inside the page targets to mov.adorsaz.ch instead of adorsaz.ch. To improve this, we can say to Apache 2 to update the content before sending it to real user.

Although, be careful, we only want to update the URLs which begins with mov.adorsaz.ch/?blog/adrien@adorsaz.ch/ as that's the only part of Movim that is behind the proxy. Indeed, all images, cache content, CSS and JavaScript sources have to be well reached from the real Movim address.

Such use case is well known on Apache 2 side as it's often needed when we set a Proxy. The substitute module documentation describes it well and even explain what's the difference between ProxyPass, ProxyPassReverse and Substitute.

To do that, I had to:

  • Enable the mod_substitute Apache 2 module with a2enmod substitute
  • Disable compression on Movim and my home page, otherwise the content can't be read and replaced by Apache2 with SetEnv no-gzip 1
  • Create a Substitute rule to update URLs.

So I added these lines to my homepage configuration:

SetEnv no-gzip 1
SSLCompression on
AddOutputFilterByType SUBSTITUTE  text/html
Substitute 's|href\s*=\s*([\'"])https://mov.adorsaz.ch/\?blog/adrien@adorsaz.ch|href=$1https://adorsaz.ch|i'

First two lines were also added to the Movim configuration.

Note, that I've enabled TLS compression to keep advantage of compression on the TLS layer as all my sites are TLS enabled. So Apache2 Proxy can replace the content easily and my clients still receive compressed datas.


Extra step: redirect every one using /?blog to /blog

Please note, that after some tests, I've seen some issues on Movim when I enabled this configuration. I think I've missed some point, so I let it here as reference, but I advise you to not use it !

This step is not necessary, but I wanted that my users see simpler URLs when they use Movim.

You can't do directly a rewrite from /?blog to /blog, because it will do an infinity loop when you server try to display /blog due to the first step.

To distinguish real users from my server, I use a rewrite condition to do the rewrite only for non-local clients. To do so, I've simplified my life by adding this line to my /etc/hosts file: mov.adorsaz.ch

Then, I've added to the Apache2 Movim configuration:

RewriteCond    %{REMOTE_ADDR}    !^127\.0\.0\.1$
RewriteCond    %{QUERY_STRING}    ^blog(.*)$ 
RewriteRule    ^/$    /blog%1    [QSD,R]

First two lines are rules to only apply the rewrite for external user wanting to access https://adorsaz.ch/?blog. In that case, Apache2 have to remove all the query string options ([QSD]) and then redirect (R) user to /blog (%1 correspond to the regexp group found inside the above RewriteCond rule).

Current adorsaz.ch Apache2 configurations

For Movim pod:

# Movim pod mov.adorsaz.ch
<VirtualHost *:443>
        SSLEngine on

        ServerName mov.adorsaz.ch

        DocumentRoot /srv/var/www/movim/

        # Movim daemon link
        ProxyPass /ws/ ws://localhost:8081/

    # Return uncompressed content and use TLS compression
        SetEnv no-gzip 1
        SSLCompression on

    # Rewrite URLs
        SSLProxyEngine On
        RewriteEngine On

        RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1$
        RewriteCond %{QUERY_STRING} ^(admin|blog|feed|login)(.*)$
        RewriteRule ^/$ /%1%2 [QSD,R]

    # Allow to read pages without needing to use query string arguments
        RewriteRule ^/(admin|blog|feed|login|help)(.*)$ /?$1$2 [QSA,P]

        <Directory /srv/var/www/movim>
                Require all granted

        # Add Access-Control to allow my home page to use the Movim pod ressources
                Header set Access-Control-Allow-Origin "https://adorsaz.ch"

                Options -Indexes
                AddType application/x-web-app-manifest json .webapp

                RewriteEngine On
                RewriteBase /

        <Directory /srv/srv/var/www/movim/config>
                Require all denied

        <FilesMatch \.php$>
                SetHandler "proxy:unix:/var/run/php/php7.0-fpm-movim.sock|fcgi://"

        CustomLog       "/var/log/apache2/mov-access.log" combined
        ErrorLog        "/var/log/apache2/mov-error.log"

Note that my regular expressions contains more than just the blog part, to have pretty URLs also for other Movim features.

For my homepage:

# Homepage adorsaz.ch
<VirtualHost *:443>
        SSLEngine on

        ServerName adorsaz.ch
        ServerAlias www.adorsaz.ch

        DocumentRoot /srv/var/www/movim

        # Rewrite content URLs
        SetEnv no-gzip 1
        SSLCompression on
        AddOutputFilterByType SUBSTITUTE  text/html
        Substitute 's|href\s*=\s*([\'"])https://mov.adorsaz.ch/\?blog/adrien@adorsaz.ch|href=$1https://adorsaz.ch|i'

        # Fetch the root directory from my blog on mov.adorsaz.ch
        SSLProxyEngine On
        ProxyPass / https://mov.adorsaz.ch/blog/adrien@adorsaz.ch/
        ProxyPassReverse / https://mov.adorsaz.ch

        CustomLog       "/var/log/apache2/www-access.log" combined
        ErrorLog        "/var/log/apache2/www-error.log"