<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Https on Noetic Nought</title>
    <link>https://punchagan.muse-amuse.in/tags/https/</link>
    <description>Recent content in Https on Noetic Nought</description>
    <generator>Hugo</generator>
    <language>en-US</language>
    <copyright>© 2006-2026 CC-BY-SA-4.0</copyright>
    <lastBuildDate>Thu, 14 Mar 2019 13:03:00 +0530</lastBuildDate>
    <atom:link href="https://punchagan.muse-amuse.in/tags/https/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Heroku apps with custom-domain and Cloudflare SSL</title>
      <link>https://punchagan.muse-amuse.in/blog/heroku-apps-custom-domain-cloudflare-ssl/</link>
      <pubDate>Thu, 14 Mar 2019 13:03:00 +0530</pubDate>
      <guid>https://punchagan.muse-amuse.in/blog/heroku-apps-custom-domain-cloudflare-ssl/</guid>
      <description>&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;&#xA;&lt;p&gt;I have a bunch of small (toy?) apps hosted on Heroku. They are probably used by&#xA;a few dozen people, at most. For these apps, I&amp;rsquo;d like the following setup:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Use a custom domain for the apps&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Heroku provides domains of the form &lt;code&gt;appname.herokuapp.com&lt;/code&gt; for all apps.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;But, it also has the option to add one or more custom domains&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I usually already have a domain under which I want to add a sub-domain,&#xA;where these apps would run.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Use HTTPS for all connections&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The domains or the sub-domains usually don&amp;rsquo;t already already have an SSL&#xA;certificate. With lets-encrypt, I guess this can change in future.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Heroku provides SSL certificates for the default domain&#xA;(&lt;code&gt;appname.herokuapp.com&lt;/code&gt;) for free.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;They also have an option to buy SSL certificates for custom domains, but&#xA;they are expensive!&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I&amp;rsquo;m going to use &lt;a href=&#34;https://www.cloudflare.com/ssl/&#34;&gt;Cloudflare&amp;rsquo;s free SSL service&lt;/a&gt; instead. I&amp;rsquo;d like to have&#xA;SSL for the full domain, and not just the app&amp;rsquo;s subdomain.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Redirect all the requests to the Heroku domain to the custom domain&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Nobody should really be using the &lt;code&gt;appname.herokuapp.com&lt;/code&gt; domain, in case&#xA;I&amp;rsquo;d like to move away from it.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A few lines of app (Flask) code can do this for us.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;&#xA;&lt;h3 id=&#34;setup-dns-to-use-cloudflare&#34;&gt;Setup DNS to use Cloudflare&lt;/h3&gt;&#xA;&lt;p&gt;Since we plan to use Cloudflare for the SSL certificates, we need to change DNS&#xA;settings at our domain registrar to use Cloudflare. We first need to create a&#xA;Cloudflare account, and &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/201720164-Step-2-Create-a-Cloudflare-account-and-add-a-website&#34;&gt;let Cloudflare do a DNS scan&lt;/a&gt; to add all the existing&#xA;domain settings automatically. Next we point to the &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/205195708&#34;&gt;Cloudflare DNS servers&lt;/a&gt; on&#xA;our domain registrar.&lt;/p&gt;&#xA;&lt;h3 id=&#34;enable-https-always-in-cloudflare&#34;&gt;Enable HTTPS always in Cloudflare&lt;/h3&gt;&#xA;&lt;p&gt;Using &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/218411427#always-use-https&#34;&gt;page rules in Cloudflare&lt;/a&gt;, add a rule for the whole domain to &amp;ldquo;Always use&#xA;HTTPS&amp;rdquo;. For example, use the url &lt;code&gt;http://*example.com/*&lt;/code&gt; and select the &lt;code&gt;Always use HTTPS&lt;/code&gt; option.&lt;/p&gt;&#xA;&lt;h3 id=&#34;select-the-ssl-option-to-use&#34;&gt;Select the SSL option to use&lt;/h3&gt;&#xA;&lt;p&gt;Cloudflare provides &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/200170416-What-do-the-SSL-options-mean-&#34;&gt;different options for the SSL setting&lt;/a&gt; which changes whether&#xA;or not traffic is encrypted between Cloudflare and the Heroku app.&lt;/p&gt;&#xA;&lt;p&gt;Choose &lt;code&gt;Full (strict)&lt;/code&gt; to enable encryption between Cloudflare and Heroku.&lt;/p&gt;&#xA;&lt;p&gt;If you are not so concerned about encryption between Cloudflare and Heroku, you&#xA;could select the &lt;code&gt;Flexible&lt;/code&gt; option too.&lt;/p&gt;&#xA;&lt;h3 id=&#34;add-a-custom-domain-in-heroku&#34;&gt;Add a custom domain in Heroku&lt;/h3&gt;&#xA;&lt;p&gt;Add a &lt;a href=&#34;https://devcenter.heroku.com/articles/custom-domains&#34;&gt;custom domain&lt;/a&gt; &amp;ndash; &lt;code&gt;app.example.com&lt;/code&gt; &amp;ndash; in Heroku&amp;rsquo;s settings.&lt;/p&gt;&#xA;&lt;p&gt;Heroku provides a DNS Target that needs to be used as the destination for a&#xA;CNAME setting in the DNS provider (Cloudflare). The DNS Target looks something&#xA;like &lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;If you chose &lt;code&gt;Full (strict)&lt;/code&gt; SSL option, this DNS target cannot be used and can&#xA;be ignored.&lt;/p&gt;&#xA;&lt;h3 id=&#34;add-a-cname-for-the-subdomain&#34;&gt;Add a CNAME for the subdomain&lt;/h3&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/360019093151-#h%5F60566325041543261564371&#34;&gt;Add a new CNAME setting&lt;/a&gt; in Cloudflare for &lt;code&gt;app.example.com&lt;/code&gt; and use the&#xA;app&amp;rsquo;s Heroku domain name (&lt;code&gt;appname.herokuapp.com&lt;/code&gt;) as the destination value/IP&#xA;address.&lt;/p&gt;&#xA;&lt;p&gt;It is important to use the &lt;code&gt;appname.herokuapp.com&lt;/code&gt; value if the SSL settings you&#xA;chose above was &lt;code&gt;Full (strict)&lt;/code&gt;. Using the DNS Target provided by Heroku instead&#xA;(&lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;) would give an &lt;a href=&#34;https://support.cloudflare.com/hc/en-us/articles/200278659&#34;&gt;SSL Handshake error&lt;/a&gt; since the&#xA;SSL certificate provided by Heroku only works for the &lt;code&gt;appname.herokuapp.com&lt;/code&gt;&#xA;domain, and not for &lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you chose &lt;code&gt;Flexible&lt;/code&gt;, though, you can use the DNS Target provided by Heroku&#xA;&amp;ndash; &lt;code&gt;foo-bar-123abcdef.herokudns.com&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Also, ensure that the Cloudflare Proxy Toggle is toggled on &amp;ndash; &lt;em&gt;the cloud icon&#xA;is orange, not grey&lt;/em&gt;!&lt;/p&gt;&#xA;&lt;h3 id=&#34;redirect-all-requests&#34;&gt;Redirect all requests&lt;/h3&gt;&#xA;&lt;p&gt;We redirect all the requests coming to the old domain to the new one.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@app.before_request&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;redirect_heroku&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Redirect herokuapp requests.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;urlparts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urlparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urlparts&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;netloc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;appname.herokuapp.com&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;urlparts_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlparts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;urlparts_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;app.example.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;redirect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlunparse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlparts_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;301&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;enforce-https-on-heroku&#34;&gt;Enforce HTTPS on Heroku&lt;/h2&gt;&#xA;&lt;p&gt;If you don&amp;rsquo;t care about a custom domain and just wish to enforce SSL for the&#xA;Heroku domain (&lt;code&gt;appname.herokuapp.com&lt;/code&gt;), &lt;code&gt;Flask-SSLify&lt;/code&gt; is the way to go. The&#xA;app can be hosted on Heroku and we can use the certs provided for free.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;flask_sslify&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SSLify&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Flask&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DYNO&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;environ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Always use SSL if the app is running on Heroku (not locally)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sslify&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SSLify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve done this setup, or some parts of it quite a few times, but each time I&#xA;seem to need to look up the documentation. Every time, it seems to take longer&#xA;than it needs to! Hopefully, this post will make it quick and reproducible.&lt;/p&gt;&#xA;</description>
    </item>
  </channel>
</rss>
