Improved connector for Nginx proxy to Railo
I have been working with Nginx quite a bit in the last week and I have had a little time to fine-tune my configuration a bit. Here is my stock Railo configuration. I have saved the settings to their own file and include the connector in each separate server configuration that requires Railo. This also remaps the standard Railo administrator to a more secure location and optionally sets basic authentication.
# /etc/nginx/railo_connector.conf
# Block default Railo admin
if ($request_uri ~* ^/railo-context){
return 404;
}
# Hide the Railo Administrator and optionally lock down with password
location ~ ^/hardtoguesslocation/(.*)$ {
#auth_basic $host;
#auth_basic_user_file /path/to/htpasswd;
if($request_uri ~^/railo-context/admin){
return 404;
}
location ~^/hardtoguesslocation/{
rewrite ^/hardtoguesslocation/(.*)$ /railo-context/admin/$1 last;
}
}
# Main Railo proxy handler
location ~ \.(cfm|cfml|cfc|jsp|cfr)(.*)$ {
proxy_pass http://127.0.0.1:8888;
proxy_redirect off;
proxy_set_header Host $host;
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;
proxy_set_header X-Real-IP $remote_addr;
}
Also, Nginx allows you to use variables in your server configuration so it allows you to easily create a “catch all” virtual host. You can quickly add a new website just by adding it to your server.xml in Railo with no additional configuration required unless you require domain specific rewrites etc. Here is an example server configuration with a default virtual host and a separate domain configured:
server {
#Catchall vhost
listen 80; ## listen for ipv4
server_name _;
root /var/www/$host;
index index.cfm;
access_log /var/logs/nginx/$host-access.log;
# Do not log missing favicon.ico errors
location = /favicon.ico { access_log off; log_not_found off; }
# Do not serve any .hidden files
location ~ /\. { access_log off; log_not_found off; deny all; }
include /etc/nginx/railo_connector.conf;
# End of catch-all Server Configuration
}
server {
#A domain with custom handling
listen 80; ## listen for ipv4
server_name mydomain.com www.mydomain.com;
root /var/www/mydomain.com;
index index.cfm;
access_log /var/logs/nginx/mydomain.com-access.log;
# Do not log missing favicon.ico errors
location = /favicon.ico { access_log off; log_not_found off; }
# Do not serve any .hidden files
location ~ /\. { access_log off; log_not_found off; deny all; }
# Handle FW/1 style SES urls (i.e. http:/domain.com/main/default/key/value)
location /{
try_files $uri $uri/ @ses;
}
location @ses{
rewrite ^/index.cfm/$uri last;
}
include /etc/nginx/railo_connector.conf;
# End of custom Server Configuration
}
If you want the X-Real-IP reported correctly on the Railo server you will also need to add the RemoteIP valve to your Tomcat configuration.
Overall Nginx makes a very nice front-end to Railo and as always I welcome any comments or suggestions to make it better.
Good timing…I’m about to move my last cf applications off of an aging windows box to a linux vm. I’ve always wondered why the X-Real-IP didn’t seem to make any difference on my previous attempts at using it
That little gotcha gave me a headache. It works like a champ now.
The SES rewrite isn’t that good. in general “if” conditions shouldn’t be used in nginx.
So instead of this
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.cfm/$1 last;
break;
}
I prefer this:
# SES if file not exists
location / {
try_files $uri $uri/ @ses;
}
location @ses {
rewrite ^ /index.cfm/$uri last;
}
Also blocking all request to “railo-context” isn’t really best practice
If you do that, the captcha image won’t be displayed. So i would block all request to “railo-context/admin” instead.
This way you won’t block railos functionality.
if ($request_uri ~ ^/railo-context/admin) {
return 404;
}
location ~ ^/hardtoguess/ {
rewrite ^/hardtoguess/(.*)$ /railo-context/admin/$1 last;
}
Thanks for the comments Marco! I have updated the posting using your suggestions. I will be the first to admit my nginx-ese is not the greatest.
Where would the default catch all config go?
Would I just create a standard mywebsite.com file in sites-available and use the catchall information in there?