Redirecting Uppercase URLs to Lowercase in a Dokku Powered App

By default, Dokku Nginx's config doesn't redirect uppercase urls to their lowercase version.

SEO experts say it might not be good having the same page served by two distinct urls like: and Let's see how we can do that.

Override Nginx configuration

We need to override Nginx default configuration so we can change it.

Check the version of Dokku running on your server:

$ dokku --version
dokku version 0.21.4

Download Nginx default config on (replace 0.21.4 by your version number) and put its content in a file nginx.conf.sigil in the root of your app.

Add the following location directive inside the corresponding ssl server (before the main location /), commit and deploy:

server {
  # ...
  location ~ [A-Z] {
    set_by_lua $request_uri_low "return ngx.arg[1]:lower()" $request_uri;
    rewrite ^ https://$host$request_uri_low permanent;

  location    / {
    # ...

If you see the error below when deploying, it's because you don't have the lua module installed.

remote: nginx: [emerg] unknown directive "set_by_lua" in /home/dokku/youapp/nginx.conf:30
remote: nginx: configuration file /etc/nginx/nginx.conf test failed

You can confirm by checking that 50-mod-http-lua.conf is missing between enabled modules:

$ ls /etc/nginx/modules-enabled/
50-mod-http-image-filter.conf  50-mod-http-xslt-filter.conf  50-mod-mail.conf  50-mod-stream.conf

Install nginx-extras

Let's install nginx-extras to have the lua module:

$ sudo apt-get install nginx-extras

Restart Nginx:

$ service nginx restart

Great, you can check everything is ok by testing the Nginx config now:

$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If you list the enabled modules again, there we have it:

$ ls /etc/nginx/modules-enabled/
10-mod-http-ndk.conf          50-mod-http-echo.conf        50-mod-http-headers-more-filter.conf  50-mod-http-subs-filter.conf     50-mod-mail.conf
50-mod-http-auth-pam.conf     50-mod-http-fancyindex.conf  50-mod-http-image-filter.conf         50-mod-http-uploadprogress.conf  50-mod-nchan.conf
50-mod-http-cache-purge.conf  50-mod-http-geoip.conf       50-mod-http-lua.conf                  50-mod-http-upstream-fair.conf   50-mod-stream.conf
50-mod-http-dav-ext.conf      50-mod-http-geoip2.conf      50-mod-http-perl.conf                 50-mod-http-xslt-filter.conf

Finally, it's always good making a request to confirm we are redirecting with 301 Moved Permanently:

$ curl
<head><title>301 Moved Permanently</title></head>
<center><h1>301 Moved Permanently</h1></center>

That's all.

Written on January 1, 2021