Custom Heroku domain will not reflect upgrade from HTTP to HTTPS - ruby-on-rails

I am using Automated Certificate Management that Heroku makes available for apps with paid dynos. my_app.herokuapp.com accurately reflects the SSL certificate and loads as a HTTPS:// page.
But my custom domain, www.my_app.com doesn't load as HTTPS://
My custom domain is from Google Domains and here is the CNAME mapping -
Custom Resource Records
www is mapped to www.my_app.com.herokudns.com.
Subdomain forward
my_app.com --> https://www.my_app.com
Any thoughts on where I could be going wrong? I can't seem to find step-by-step instruction anywhere, please point me to any resources you all found to be useful.

Related

How to do DNS Set up / cname flattening with heroku and Godaddy

I have application deployed in Heroku with Godaddy domain.
After trying several methods done dns setup.
Add CNAME www with value DNS target provided by heroku.
This is working fine for domain with www. But I like to open domain without www(naked domain). which is not working currently.
What I have already tried and nothing worked for me.
Add CNAME with name(naked domain) and value(heroku app url)
(a) Add a Domain with naked domain name(domain name without www)
(b) Add CNAME with name(naked domain) and value(heroku app DNS Target
value from(a))
Add Forwarding https:// with www.domain-name
Then tried configure DNS setup in cloudflare there everything problems got resolved, But there website's speed got slow and even some JS was not working. Tried several code changes and deployment, Nothing worked so finally back to GoDaddy for DNS Setup.
Somewhere got to know that CloudFlare provide CName flattening which GoDaddy not. Due to CName Flattering Redirection works fine with CloudFlare.
Please suggest me steps to resolve this. domain URL
Got response from Heroku team.
Redirecting from root domain [http://mysite.in/] to sub domain [http://www.mysite.in/] can be done at application level or on your DNS provider [GoDaddy] settings. Heroku or any other similar platforms won't have such an option.
Heroku recommends you to point the root domain to its DNS target with an ALIAS/ANAME record type. Unfortunately, Godaddy doesn't give that option. The root domain's DNS target can be an IP address as well, but the IP addresses of your application on Heroku keeps changing, at least once a day, so you can't use that as DNS target. We have an article on how you should set up the domains for a Heroku app, please give it a read https://devcenter.heroku.com/articles/custom-domains and let me know if you have any question there.
So the options you are left with is to make use of an add-on like Quotaguard which will give you a static IP address against your Heroku application, this IP can be used as DNS targets or change the DNS provider, we have a list of DNS providers which support ALIAS/ANAME record type.

Point Domain Registered Through iPage to Heroku App

I've got a domain (and hosting account) with iPage.
I'd like to point this domain example.com and www.example.com to my heroku app - which is currently available at example.herokuapp.com.
I've set up a CNAME (Alias) as follows:
host: www
points to: example.herokuapp.com
I've gone through Heroku's documentation for custom domain names; however, I've been unable to make it work.
What do I need to do differently?
The reason you are not able to access your site at www.example.com even after setting up the DNS correctly is you have not updated your application setting inside Heroku. You need to provide Heroku with the web address want to host your site, this you can do inside your Application Settings page.
Heroku does not support apex domain so you might want to setup a redirect from example.com to www.example.com, I don't see why you would want to run your site on two web address. But you really want to run your site on two addresses you can try zerigo dns addon on heroku. Zerigo dns can also help you setup the redirect.
https://devcenter.heroku.com/articles/apex-domains

Rails tenanted app with CloudFlare and subdomains

I'm building a tenanted Rails application on Heroku which uses subdomains for each tenanted instance. The problem is I can't seem to get CloudFlare to properly cache a subdomain.
I have my Application hosted on heroku at say whatever.herokuapp.com
And using CloudFlare I'm pointing my main application at heroku's CNAME (whatever.herokuapp.com) and that works fine.
I'm using a wild cards *.mydomain.com on Heroku and then using CloudFlare again to point at them.
So say I create an app myinstance.mydomain.com on CloudFlare -> whatever.herokuapp.com
because I'm using the *.mydomain.com on Heroku it works fine.
BUT when I try to turn on the Acceleration (CloudFlare caching) it immediately breaks and all I see is a CloudFlare error Error 1001 telling me:
Most likely: if the owner just signed up for CloudFlare it can take a few minutes for the website's information to be distributed to our global network.
From their help desk:
Fundamentally in a standard set up the domain needs to be added to
CloudFlare in order for us to understand how to route traffic for that
domain.
If you wanted a setup where anybody in the world could CNAME to your
CloudFlare configuration, that is possible but it's an Enterprise
feature. We call it "Managed CNAME" - if that's something you're
interested in do let me know and I can put you in touch.
FYI, CloudFlare Enterprise averages at $5,000 a month.
CloudFlare is great in that it just works without much customization starting at zero cost, but unless your multi-tenanted app is for Bank of America or other Fortune 500 company I'd suggest something like Fastly ($5-50/month) or some other DIY caching solution that allows you to setup caching as you need rather than a one-size-fits-all top down solution.
https://devcenter.heroku.com/articles/fastly
Works directly with Heroku but there might be other solutions that work equally well.
That error can also occur if you're pointing a domain/subdomain not on CloudFlare to a domain that is on CloudFlare (creates a DNS resolution lookup error). I would probably contact CloudFlare support for additional assistance and troubleshooting.

Cloudflare + Heroku SSL

I have a rails app that is running on heroku and am using Cloudflare Pro with their Full SSL to encrypt traffic between: User <-SSL-> Cloudflare <-SSL-> Heroku, as detailed in: http://mikecoutermarsh.com/adding-ssl-to-heroku-with-cloudflare/ .
I am also using the rack-ssl-enforcer gem to force all http requests to go through https.
This is working properly, except I have the following issues, by browser:
1) Firefox. I have to add a security exception the first visit to the site, getting the "This site is not trusted" warning. Once on the site, I also have the warning in the address bar:
2) Chrome: page loads first time, but the lock in the address bar has a warning triangle on it, when clicked displays:
Your connection is encrypted with 128-bit encryption. However, this
page includes other resources which are not secure. These resources
can be viewed by others while in transit, and can be modified by an
attacker to change the look of the page. The connection uses TLS 1.2.
The connection is encrypted and authenticated using AES_128_GCM and
uses ECDHE_RSA as the key exchange mechanism.
Safari: initially loads with https badge, but it immediately drops off
Is there a way to leverage Cloudflare SSL + piggyback of Heroku native SSL without running into these security warnings? If not, I don't see much value in the configuration.
My apologies for slinging erroneous accusations against Cloudflare and Heroku :-)
Turns out the issue was not the fault of either, but instead that images on the app (being served from AWS S3) were being served up without https.
If anyone runs into this situation, lessons learned across a wasted day:
S3 only lets you serve up content via https if you serve from your bucket's dedicated url: s3.amazonaws.com/your-bucket-name/etc..
a) I tried setting the bucket up for static website hosting, so I could use the url "your-bucket-name.your-url.s3-website-us-east-1.amazonaws.com/etc...", and then set up a CNAME within my DNS that sends "your-bucket-name.your-url" to "your-bucket-name.your-url.s3-website-us-east-1.amazonaws.com/etc...", to pretty up urls
b) this works, but AWS only lets you serve via https with your full url (s3.amazonaws.com/your-bucket-name/etc..) or *.s3-website-us-east-1.amazonaws.com/etc...", which doesnt work if you have a dot in your bucket name (your-bucket-name.your-url), which was required for me to do the CNAME redirect
If you want to use AWS CDN with https, on your custom domain, AWS' only option is CloudFront with a SSL certificate, which they charge $600/mo, per region. No thanks!
In the end, I sucked it up and have ugly image URLs that looks like: https://s3-website-us-east-1.amazonaws.com/mybucketname...", and using paperclip, I specify https: with ":s3_protocol => :https," in my model. Other than that all is working properly now.

Multiple domains powered by one rails app

I am creating a blogging-like application where we allow our customers to use their own custom domain names such as domainexample.com, so each different domain serves the same application but with different content.
However I am struggling to figure out how to set this up on a production server. If my production server has a static IP then I can surely just set an a-record on each domain to the ip of the production server.
But what if the production server does not have a static IP. For example if we want to host it on heroku or engineyard? I have seen a few solutions online that require using rewrite rules but they require server restarts and cant really dynamically add and remove new domains as new users sign up. Does anyone know any good solutions to let multiple domains hit one rails app?
Heroku isn't your only option. If you can anticipate your customer's domains, have a look at this. If you can't, Rails routes constraints and a combination of the accepted answer to the question linked above should get you where you need to be going. Sounds like you wouldn't want to restart your server--so no editing of the routes. You might also make domains part of your models, or distinguish at the controller level or use URL rewriting in your web-server layer.
The problem, as I see it, is that Rails breaks its mantra of opinion over configuration here. There are many ways of serving up from multiple domains. That might be an intrinsic complexity, but the Rails Guides could at least document one possible solution.
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.
Alternatively, there have been a few services like this recently that allow you to add custom domains to your app without running the infrastructure yourself.
If you need more detail you can DM me on Twitter #dragocrnjac

Resources