开发者

Custom domains in a Rails App

开发者 https://www.devze.com 2023-01-20 07:40 出处:网络
I want users开发者_如何学Python of my service to be able to add their own custom domains. For example, www.[their domain].com should be able to access their application\'s index and show pages. My ser

I want users开发者_如何学Python of my service to be able to add their own custom domains. For example, www.[their domain].com should be able to access their application's index and show pages. My service is implemented in Rails 3.

I've seen apps like Tumblr offer this functionality for their front facing blogs. Although I have seen apps for Rails that implement sub domains in the way that Basecamp does, I have not found a resource for fully custom domains.


They'll need to create an A record in their DNS to point to your app servers IP. You'll need to know what domain they have pointed to your server and log it against their account, and also set your web servers config in such a way as to channel the requests from other domains to your app. You can then use the request object to look up their account in your application_controller.


I just answered a similar question so I decided to chime in here too. @Codebeef gave a good answer but this won't work anymore in the world where HTTPS is a must in most modern browsers.

This is the full picture of how to handle custom domains for your app.

If your customers just CNAME to your domain or create the A record to your IP and you don't handle TLS termination for these custom domains, your app will not support HTTPS, and without it, your app won't work in modern browsers on these custom domains.

You need to set up a TLS termination reverse proxy in front of your webserver. This proxy can be run on a separate machine but you can run it on the same machine as the webserver.

CNAME vs A record

If your customers want to have your app on their subdomain, e.g. app.customer.com they can create a CNAME app.customer.com pointing to your proxy.

If they want to have your app on their root domain, e.g. customer.com then they'll have to create an A record on customer.com pointing to your proxy's IP. Make sure this IP doesn't change, ever!

How to handle TLS termination?

To make TLS termination work, you'll have to issue TLS certificates for these custom domains. You can use Let's Encrypt for that. Your proxy will see the Host header of the incoming request, e.g. app.customer1.com or customer2.com etc., and then it will decide which TLS certificate to use by checking the SNI.

The proxy can be set up to automatically issue and renew certificates for these custom domains. On the first request from a new custom domain, the proxy will see it doesn't have the appropriate certificate. It will ask Let's Encrypt for a new certificate. Let's Encrypt will first issue a challenge to see if you manage the domain, and since the customer already created a CNAME or A record pointing to your proxy, that tells Let's Encrypt you indeed manage the domain, and it will let you issue a certificate for it.

To issue and renew certificates automatically, I'd recommend using Caddyserver, greenlock.js, OpenResty (Nginx).

tl;dr on what happens here; Caddyserver listens on 443 and 80, it receives requests, issues, and renews certificates automatically, proxies traffic to your backend.

How to handle it on my backend

Your proxy is terminating TLS and proxying requests to your backend. However, your backend doesn't know who is the original customer behind the request. This is why you need to tell your proxy to include additional headers in proxied requests to identify the customer. Just add X-Serve-For: app.customer.com or X-Serve-For: customer2.com or whatever the Host header is of the original request.

Now when you receive the proxied request on the backend, you can read this custom header and you know who is the customer behind the request. You can implement your logic based on that, show data belonging to this customer, etc.

More

Put a load balancer in front of your fleet of proxies for higher availability. You'll also have to use distributed storage for certificates and Let's Encrypt challenges. Use AWS ECS or EBS for automated recovery if something fails, otherwise, you may be waking up in the middle of the night restarting machines, or your proxy manually.

If you need more detail you can DM me on Twitter @dragocrnjac

0

精彩评论

暂无评论...
验证码 换一张
取 消