Ubuntu 20.04, Nginx, Redmine, Ruby, and Passenger-Phusion confusion

Redmine, Ruby, Passenger-Phusion, and Nginx makes for an extremely confusing situation with dependencies, installation “instructions”, and “mismatching” package versions.

Redmine wants Ruby x, your Linux distribution has Ruby y, Passenger-Phusion only works with Ruby z, and you quite often end up in a loop somewhere. This article will not do anything to help that confusion I’m afraid.

On Passenger-Phusion’s website, there’s an interesting explanation as to why you need to let Passenger-Phusion build Nginx for you, unless you can actually use everything pre-packaged, which you cannot if you want to use Ubuntu 20.04.LTS and Redmine 4.1.

Before you begin, you should know that installing Passenger in its Nginx integration mode involves extending Nginx with code from Passenger. However, Nginx does not support loadable modules. This means that in order to install Passenger’s Nginx integration mode, it is necessary to recompile Nginx from source. And that is exactly what we will do in this installation guide.

Now, if you head on over to the Nginx blog, you can read:

NGINX Open Source 1.11.5 and NGINX Plus Release R11 introduced binary compatibility for dynamic modules. This article explains how to compile third‑party modules for use with NGINX Open Source and NGINX Plus in a development environment.

That statement was made for Nginx 1.11. They are, at the time of this writing, at 1.19.

So basically, if you want to run Redmine 4.1 on Ubuntu 20.04.LTS, which ships with Ruby 2.7, and a Passenger-Phusion module that requires Ruby 2.7, you’re on your own since Redmine 4.1 does not support Ruby 2.7. If you use RVM to installed Ruby 2.6.x, you need to manually handle Passenger-Phusion, which eventually requires re-compiling Nginx, regardless of it supporting “dynamic modules”.

There is one small glimmer of hope:
Installing Passenger as a normal or dynamic Nginx module

Using Ubuntu 18.04.LTS, the included Passenger, Nginx, and Ruby all work with Redmine 4.1.x, so that may be a smoother path to take before this is all “fixed”, if it gets fixed.

Troubleshooting WordPress re-directs (301)

While trying to configure some internal URL re-writing in nginx for a WordPress site, I ran across an annoying issue:

Regardless of my re-writing efforts, WordPress would issue a re-direct (301) header (?!)

This wouldn’t have been such a big deal if I didn’t want the URL to stay the same in the browser’s address bar. If I didn’t have that requirement, I would naturally have used a simple re-direct.

After spending some time troubleshooting this, and making sure nginx was actually doing what I wanted it to do, I ran across a few posts talking about disabling “canonical redirects” (sic) in WordPress. So adding this snippet to the end of the active theme’s functions.php:

remove_filter('template_redirect','redirect_canonical');

got rid of WordPress re-directs. Unfortunately, another plugin “stepped in” and started doing it instead (this time, it was the Polylang plugin). I’m sure there are a number of other plugins that exhibit this behavior, and it may be possible to circumvent this in many/most/all of them by using something similar to the above snippet, but I still haven’t solved the actual problem.

Using cURL to debug URL re-writing and URL re-direction can save you a lot of time, like this:

curl -I https://yourwebsite.foo

(Please note that the issues I have experienced here are not related to nginx. This would happen in Apache too as the re-directs are issued by the WordPress stack. Once control is handed off to PHP, there’s little the web server can do.)

If you’re playing with nginx, PHP-FPM, and URL re-writing, you may also find this post of interest: URL re-writing with nginx, PHP, and WordPress

URL re-writing with nginx, PHP, and WordPress

There are many posts about nginx, re-directs, PHP, and WordPress. There are somewhat fewer posts that talk about (internal) re-writes, where the request by the web browser is mangled to be served by another resource than the one requested.

For example, I may want a request for https://mysite.foo/cool/penguin to actually be served by https://mysite.foo/coolstuff.php?id=penguin, or simply setup an alias such as https://mysite.foo/cool/penguin to be served by https://mysite.foo/cool/linux, but preserve the URL in the browser address bar.

With PHP-FPM and nginx, you run into an additional problem, which is the fastcgi_parm variables that are passed from nginx to PHP-FPM. So even if you have really fancy URL re-writing configured (and working), the end result may not be passed on to PHP-FPM from nginx.

So solve this, you should look into this construct, which is present in many nginx configurations as a default setup:

fastcgi_param REQUEST_URI $request_uri;

Since your needs probably differ from mine, I wont make this post any longer than it has to be, but that fastcgi_param line above may be a good starting point if you’re experiencing problems with nginx, PHP-FPM, and URL re-writing.

Good luck!