Some time ago I deployed a new Rails 6 application to a subdirectory within a micro service architecture. Rails documentation provides some information on this but doesn't go into great details what each setting is affecting to. This post will fill in some gaps in the documentation and show one way to deploy Rails application to a subdirectory (also known as relative path). The exact version of Rails here was 22.214.171.124.
First they say you should set the following configuration (or alternatively the
RAILS_RELATIVE_URL_ROOT environment variable):
config.relative_url_root = "/app1"
(Update: I noticed that this configuration does not work if it is set in an initializer file. It only had the desired effect when set in
According to the docs
Rails will now prepend "/app1" when generating links.
Well that is true for the asset links but doesn't actually affect the path helpers (e.g.
root_path). Those will still return paths directly under the document root
/ without the subdirectory and break the page. So how to fix that? Here the Rails docs implicitly assume the reader is somewhat familiar with web server interfaces, in this case Rack as Rails is a Rack application. The key web server variable here is the
SCRIPT_NAME which can be found from the Rack spec. It is often set by the web server or reverse proxies like
If you're wondering the name of this variable, it comes from the good old times when web pages were actually served with dedicated scripts.
So how to set
SCRIPT_NAME? Rails docs shows some example configurations for different servers but nowhere explicitly states that the critical part is the
SCRIPT_NAME. Depending on your setup, you need to ensure that this variable is present when
run Rails.application is called in your
In our case, however, we didn't want to chage our server setup but instead have the
SCRIPT_NAME set up within the Rails application itself. It turned out that the easiest way to achieve that was to wrap the Rails application itself into a very short Rack application. This can be achieved with the
map method of Rack as suggested here:
# configu.ru map '/app1' do run Rails.application end
I suspected this would alter the
SCRIPT_NAME variable and indeed, by looking at the source code of Rack I found the following lines:
# In urlmap.rb#call path = env[PATH_INFO] script_name = env[SCRIPT_NAME] # ... env[SCRIPT_NAME] = (script_name + location) env[PATH_INFO] = rest
So we can see that the
SCRIPT_NAME is appended with the
location variable which holds the
map argument value (
'/app1' in the example).
After this your Rails app will have both the assets paths and path helpers configured for serving your Rails application from a subdirectory.