Subdomain blocking in Rails 5 typically stems from misconfigured domain constraints, incorrect CORS headers, or firewall rules that inadvertently restrict access to non-root domains. This issue often manifests as a 403 Forbidden error or a blank page when navigating to
app.example.com instead of
example.com. The root cause usually lies in how the application interprets request origins and validates hostnames against its internal routing table.
Understanding Domain Constraints
Rails uses the
constraints method in your
config/routes.rb file to limit which requests reach specific controllers. A common mistake is defining a constraint that only accepts the root domain, effectively blocking all subdomains. For instance, if you have a route defined like this:
get '/dashboard', to: 'dashboard#index', constraints: { host: 'www.example.com' }
This configuration explicitly rejects any request where the host header does not match
www.example.com. If a user visits
admin.example.com, the router will fail to find a matching route, resulting in a "No route matches" error or a blocked response depending on your middleware stack. To fix this, you must ensure your constraints are inclusive of the desired subdomains or use regular expressions to match patterns.
constraints(host: /.*\.example\.com$/) do
get '/dashboard', to: 'dashboard#index'
end
The regex
/.*\.example\.com$/ allows any subdomain (e.g.,
blog,
api,
admin) followed by
.example.com. This approach provides flexibility while maintaining security boundaries for your main domain. It is crucial to test these routes locally using
rails server with different host headers to verify they resolve correctly before deploying to production.
CORS and Preflight Requests
Another frequent culprit for subdomain issues is Cross-Origin Resource Sharing (CORS). Browsers enforce strict policies regarding cross-origin requests. If your frontend application resides on
app.example.com and your API backend is on
api.example.com, the browser will block requests unless the server explicitly permits them via CORS headers. Rails applications often use gems like
rack-cors to manage these headers.
If the
AllowedOrigins configuration in your
config/initializers/cors.rb file is set incorrectly, subdomain requests will be intercepted by the browser's security model. You should verify that your CORS configuration includes the specific subdomains or uses wildcards appropriately.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'app.example.com', 'admin.example.com'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
Using wildcard origins (
*) can be convenient but poses security risks. It is safer to explicitly list trusted subdomains. Additionally, ensure that your server is responding to
OPTIONS preflight requests with the correct
Access-Control-Allow-Origin header. If you are experiencing intermittent blocks, check the browser's developer console for specific CORS errors, which will indicate whether the origin is being rejected.
For more information on configuring storage services that might interact with subdomains, see
ActionText - How to Configure ActiveStorage Service.
Firewall and Network Level Blocking
Sometimes the issue is not within Rails at all but at the network level. Cloud providers like AWS, DigitalOcean, or Heroku often have firewall rules or load balancer configurations that restrict traffic based on domain names. If your subdomain is newly added, it might take time to propagate through DNS caches, leading to temporary blocking or resolution failures.
Check your DNS records to ensure the subdomain points to the correct IP address. Use tools like
dig or
nslookup to verify propagation. If the DNS is correct but the site remains inaccessible, inspect your cloud provider's security groups. Ensure that inbound traffic rules allow HTTP (port 80) and HTTPS (port 443) traffic for the associated IP ranges.
In some cases, SSL certificates issued by Let's Encrypt or other providers may not cover subdomains unless specifically requested. If you are using a self-signed certificate or an expired one, browsers will display a security warning that effectively blocks user interaction. Verify that your SSL certificate covers
*.example.com or the specific subdomain in question.
Middleware and Security Headers
Rails middleware can also interfere with subdomain access. Custom middleware that inspects the
Host header might reject requests if they do not match an expected format. Review your
config/application.rb and
config/environments/production.rb for any custom middleware classes that perform host validation.
Additionally, security headers like
X-Frame-Options or
Content-Security-Policy can impact how subdomains interact with the main application. If your CSP policy restricts frames or scripts to the root domain, embedded content from subdomains may be blocked. Adjust these policies to include your subdomains if necessary.
config.content_security_policy do |policy|
policy.default_src :self, :https
policy.frame_ancestors :self, 'https://example.com', 'https://app.example.com'
end
Ensuring that your environment variables are correctly set for each subdomain is also vital. Misconfigured environment variables can lead to unexpected behavior, such as connecting to the wrong database or using incorrect API keys. Always double-check your
.env files or platform-specific configuration settings.
Frequently Asked Questions
Why does my subdomain work locally but not in production?
Local development servers often run on
localhost, bypassing strict domain constraints and CORS policies that apply in production. Production environments enforce stricter security rules, including DNS propagation delays and firewall restrictions. Always test with the actual domain name in a staging environment before going live.
Can I use a wildcard subdomain in Rails routes?
Yes, you can use regular expressions in the
constraints option of your routes to match any subdomain. However, be cautious of security implications, as this allows any arbitrary subdomain to access your application. It is best practice to whitelist specific subdomains whenever possible to prevent unauthorized access.
How do I debug CORS errors for subdomains?
Open your browser's developer tools and navigate to the Network tab. Look for failed requests marked with a red status code and check the Console for CORS-related error messages. These messages will specify which origin is being blocked and what headers are missing. Adjust your CORS configuration accordingly.
Is it safe to use wildcard origins in CORS configuration?
Using wildcard origins (
*) is generally unsafe because it allows any website to make requests to your API. This can expose your application to cross-site request forgery attacks. Instead, explicitly list the trusted domains and subdomains that need access to your resources.
What should I do if my SSL certificate doesn't cover the subdomain?
You must obtain a new SSL certificate that includes the subdomain, either by adding it individually or requesting a wildcard certificate for
*.example.com. Most certificate authorities provide easy tools to generate and install these certificates. Until the certificate is installed, browsers will continue to block secure connections to the subdomain.