Thursday, December 31, 2015

Elixir (Phoenix) App Custom Domain Redirect on Heroku Not Working Properly

TL;DR If your custom domain is [partly] working, but still redirects you to the herokuapp.com URL, you may need to remove force_ssl: [...] and change your scheme: "https" to "http" in your config/prod.exs. That said, if you're serving any sensitive data (i.e. user login, credit cards, etc.), DO NOT FOLLOW THIS :) Use SSL.

The other day I decided to make a personal site with a brief "Who am I" and resume.  Not that I'm looking for a job, but more so because I wanted something to do in Elixir and couldn't think of anything else that I could knock out in a couple hours.  I made the static site using using the Phoenix framework and pushed it to Heroku following Phoenix's awesome documentation.  Easy peasy!

The only old holdup I had was getting my custom domain to work properly.  I set up the CNAME and @ records as described in a well written StackOverflow post, albeit outdated, it did the trick for the most part.  Going to markevans.io redirected to my Heroku app as expected, but instead of the URL being markevans.io, it redirected to the herokuapp.com URL.  Ugh. I began to scour the internets and followed every post I could find about setting up DNS records on NameCheap and Heroku.  Spoiler alert, they all say pretty much the same thing and 99% of them are for Ruby/Rails apps.  The good thing is, as a Ruby developer, I can understand what's being done and how to translate it to my bare-bones Elixir/Phoenix app.

So what was the problem/solution?  The problem was SSL.  Phoenix's Heroku deployment documentation shows you how to deploy a secure app, which is great.  But my site isn't handling any sensitive data, there's no login, nothing to purchase... nada.  So really, I don't need SSL at this point and I don't want to spend any money on SSL certs (if your site handles *any* secure data, don't do what I did.  Set it up to work with SSL).

The solution, similar to a Rails app, is to not force SSL in your app.  As per the Phoenix-Heroku deployment documentation, your prod.exs should look like this:

config/prod.exs

config :myapp, Myapp.Endpoint,
  http: [port: {:system, "PORT"}],
  url: [scheme: "https", host: "bla-bla-bla.herokuapp.com", port: 443],
  force_ssl: [rewrite_on: [:x_forwarded_proto]],
  cache_static_manifest: "priv/static/manifest.json",
  secret_key_base: System.get_env("SECRET_KEY_BASE")


This setup works great if you're serving over SSL, but if you're not and don't plan to, it'll mess up your domain forwarding. Your custom domain will work, but you'll be redirected to the secure URL (Heroku's URL). To fix this, remove force_ssl: [rewrite_on: [:x_forwarded_proto]], and replace url: [scheme: "https",...] with url: [scheme: "http",...]. When you're done, your prod.exs should look like this:

config/prod.exs

config :myapp, Myapp.Endpoint,
  http: [port: {:system, "PORT"}],
  url: [scheme: "http", host: "bla-bla-bla.herokuapp.com", port: 443],
  cache_static_manifest: "priv/static/manifest.json",
  secret_key_base: System.get_env("SECRET_KEY_BASE")


Now git add . && git commit -m "removed force_ssl from production config", then deploy to Heroku. You should be good to go!

Wednesday, February 4, 2015

What is PATH in Linux and MacOS?

You know all those commands you can automagically summon from any directory on the command line?  Like:
  
$ git <args>

$ apt-get <args>

$ irb

You're probably well aware that each of those commands is a program that could also be executed with:
  
$ ./path/to/git <args>

$ ./path/to/apt-get <args>

$ ./path/to/irb

Without PATH you'd have to execute any program not in your current directory by explicitly declaring the program's path... hence the name. Think of it as a postal system for your shell.  You give your shell a message to deliver to a program.  Your shell flips through its Rolodex of paths known to contain programs to find the recipient and execute it with your message.

Run the following to see where your shell is looking for programs:
  
$ echo $PATH

You should see something similar to:
  
/Users/username/.rbenv/shims:/Users/username/.rbenv/bin:/usr/local/bin:
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin:
/Users/username/.gem/ruby/1.8/bin:/opt/nginx/sbin:/usr/local/sbin

Each path (separated by ':') is where your shell looks for a program to fulfill your ever wish. And in the rare times when your trusty old pal shell can't come through, at least she/he has a sense of humor:
  
$ make love

>> make: *** No rule to make target `love'.  Stop.

This blog is really just a regurgitation of Exercism.io's Understanding PATH so that I retain this awesome knowledge. If you want know how to edit your PATH, visit their article and scroll halfway down.