11

So, essentially I am running Joomla in a Docker php7-fpm container, then I have an nginx container where a joomla.conf file is defined as follows:

#https://docs.joomla.org/nginx

server {
  listen 8081;

  error_log  /var/log/nginx/error.log;
  access_log /var/log/nginx/access.log;

  server_name php-docker.local;

  root /usr/src/joomla;
  index index.php index.html index.htm default.html default.htm;

  location / {
    try_files $uri $uri/ /index.php?$args;
  }

  # deny running scripts inside writable directories
  location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ {
    return 403;
    error_page 403 /403_error.html;
  }

  location ~ \.php$ {
    fastcgi_pass  joomla:9000;
    fastcgi_index index.php;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    include fastcgi_params;
    #include /etc/nginx/fastcgi.conf;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
  }
}

And this works as expected... going to http://:8081 loads everything correctly.

Now, 8081 is just temporarily exposed in the nginx container, what I essentially want to do is setup a reverse proxy such that http:///joomla will be the final endpoint.

For this, I am struggling with the following conf file:

server{

  listen 80;
  server_name _;

  location /joomla/ {
    proxy_pass          http://localhost:8081/;

    proxy_set_header    Referer           $http_referer;
    proxy_set_header    X-Forwarded-Port  $server_port;
    proxy_set_header    X-Forwarded-Proto $http_x_forwarded_proto;
    proxy_set_header    Host              $host;
    proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Host  $host;
  }

}

What happens is that the HTML is served correctly, however, none of the assets are. This is because the URLs in Joomla are generated by a JURI class, which seems to rely on $request_uri, which by when it appears to arrive to Joomla is already lost.

https://github.com/joomla/joomla-cms/blob/6ab2a6e9010e7e04c260b9eba17dc76e866dd3e6/libraries/joomla/uri/uri.php#L87

So every link or reference to a file, script, or css renders like this:

http://localhost/login

http://localhost/images/headers/maple.jpg

Instead of:

http://localhost/joomla/login

http://localhost/joomla/images/headers/maple.jpg

However, when I access the second set of URL, I can access the link/asset without a problem... but of course once again, no images, templates, js or links being rendered correctly.

I prefer not to touch joomla.conf unless something is wrong, as for site.conf I would only like to translate URI segments to map requests to other applications, e.g.:

/joomla -> localhost:8081
/phpbb -> localhost:8082
/someapp -> localhost:8083
dukeofgaming
  • 3,108
  • 4
  • 28
  • 35
  • Have you tried accessing as this from your browser? : `http:///joomla/` (with ending /). – Robert Jul 02 '17 at 23:34
  • 1
    Your nginx configurations are not going to influence how Joomla generates the links. If your client facing nginx is only forwarding `/joomla/` to the upstream Joomla nginx, then it won't ever pass `/images/headers/maple.jpg` or `/login`. If you will always be accessing Joomla at `/joomla/` on the client facing nginx then your only option is to change the Joomla configuration. – Andy Shinn Jul 03 '17 at 04:17
  • 1
    You have tried to change $live_site parameter in joomla configuration file? – Rinos Jul 03 '17 at 09:35
  • OP, would you be so kind to review the answers, and award a bounty? If you perform no action, at least half of the bounty will go to waste. Thanks. P.S. If you decide to go the referrer route, and have any issues with nginx.conf, let me know. – cnst Jul 10 '17 at 17:34

4 Answers4

5

The cleanest solution would be to modify your upstreams to provide unique paths for all the resources.

It is generally a much easier task to remove parts of a URL from the upstream (with a unique prefix) than to add extra parts to a non-unique one. This is because you can always catch the longer URL and know exactly what it refers to, subsequently returning a 301 or 302 redirect to a shorter and more concise version.

On the other hand, faced with a short request URL, like /, it would be difficult to know for sure which app it may refer to (unless you look into the $http_referer variable, too, and then conditionally issue the redirect based on where the URL request comes from), or unless you implement some sort of spaghetti rules to detect which individual URLs refer to which applications (if you go this route, the map directive may come in handy).

Additionally, consider that, security-wise and when cookies get involved, it is not the best practice to run multiple independent applications on a single domain — a compromise in one application can easily lead to security violations in all the other ones.

cnst
  • 25,870
  • 6
  • 90
  • 122
  • Can you provide an example?; on your other point, do you mean it is the best practice to separate apps by subdomain? – dukeofgaming Jul 06 '17 at 17:12
  • Yes, the best idea would be to separate by subdomain. If you do want to go the referrer route, you could have some `if` statements within applicable locations (e.g., have `if ($http_referer ~ ^/joomla)` in the `/` location (not in the `/joomla` location, such as to not create a loop)), which would `return 302 /joomla/$request_uri;`. Let me know if you need any further help (it'd also help to see the access_log/error_log, as well as the applicable filesystem layout, and nginx.conf, for the best hack). – cnst Jul 09 '17 at 03:46
4

As Rinos said, you need to configurate the $live_site var in configuration.php, as this:

public $live_site = '/joomla/';

I've made a complete example in Github that works well after editing that file, and it uses your configs.


enter image description here


 Becomes:


enter image description here

Community
  • 1
  • 1
Robert
  • 33,429
  • 8
  • 90
  • 94
  • well, this actually seems to work, but rather breaks the application. Try installing Joomla with demo content and you will see the behavior is weird. The admin panel works without a hitch, but most of the article links throw a 404 (some linked in the home content do not, and I find that even weirder)... e.g. this [http://localhost/joomla/using-joomla/extensions/components/content-component/article-category-list/8-beginners] will load while this [http://localhost/joomla/using-joomla/extensions/components/content-component/single-article] throws 404 – dukeofgaming Jul 05 '17 at 06:03
  • How do you reach that link? – Robert Jul 05 '17 at 13:50
  • @dukeofgaming, can you please give me more information on how to reproduce what you say? – Robert Jul 07 '17 at 12:31
1

You could try use sub_filter how it mentioned in this answer.

So in your case your nginx config should looks like this one:

server{

  listen 80;
  server_name _;

  location /joomla/ {
    proxy_pass          http://localhost:8081/;

    proxy_set_header    Referer           $http_referer;
    proxy_set_header    X-Forwarded-Port  $server_port;
    proxy_set_header    X-Forwarded-Proto $http_x_forwarded_proto;
    proxy_set_header    Host              $host;
    proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Host  $host;
    sub_filter "http://your_server/" "http://your_server/joomla/";
    sub_filter_once off;
  }

}
0

I know this is old but here's my answer. You shouldn't change the configuration.php file, basically because you should keep your services (web and proxy) completely separated (A problem generated by a service implementation should be solved in that service), that will make your service architecture more flexible. You have to filter the assets urls and some Location headers changing the following proxy settings.

server {
    #... other settings

    location /joomla/ {
        # Main redirect
        proxy_pass http://joomla_service/;

        # Set the Host Header
        proxy_set_header Host $host;

        # When Joomla redirects a Location Header
        # For example when you log in, Joomla retrieves you a response with a Location Header = localhost
        # we don't want this.
        proxy_redirect http://localhost/ http://localhost/joomla/;
        proxy_redirect / /joomla/;

        # Some content rewriting
        sub_filter_types text/javascript application/javascript;

        # Html redirection
        sub_filter '="/' '="/joomla/';
        sub_filter '="http://localhost/' '="/joomla/';
        sub_filter '\'http://localhost/administrator/' '\'/joomla/administrator/';
        sub_filter 'url(\'/media' 'url(\'/joomla/media';

        # Some json data
        sub_filter '"root":""' '"root":"\/joomla"';
        sub_filter '"uri":"\/index.php' '"uri":"\/joomla\/index.php';
        sub_filter '"jdragdrop":"\/media' '"jdragdrop":"\/joomla\/media';
        sub_filter '"plg_quickicon_privacycheck_url":"http:\/\/localhost' '"plg_quickicon_privacycheck_url":"\/joomla';
        sub_filter '"plg_quickicon_privacycheck_ajax_url":"http:\/\/localhost' '"plg_quickicon_privacycheck_ajax_url":"\/joomla';
        sub_filter '"content_css":"\/templates' '"content_css":"\/joomla\/templates';

        sub_filter_once off;
    }
}

For some reason Joomla is not doing a good support if we talk about implement a reverse proxy. I created an example with more details, you can see it here.

  • Since you are a Joomla dev and can provide Joomla support, please join [joomla.se] Stack Exchange and see if you can support that dedicated community as well. Cheers. – mickmackusa May 16 '21 at 22:19