Originally posted on January 7, 2016. The article was updated May 31, 2017 based on the many wonderful updates to Let’s Encrypt and Elixir/Phoenix.
Let’s Encrypt continues to promising, and a year since I first wrote this article looks like a lot has changed. First, there’s much better support for Nginx (so my other article is now very out of date).
Before we get started, you will need a few things installed first, I have provided links to installation scripts for Ubuntu 16.04 if you don’t already have an environment up and running.
Older versions might still work, so don’t go upgrading just yet; try things out and let me know if you run into problems.
Let’s create a new app and configure it for port 80
echo "Y" | mix phx.new isafe
vi config/dev.exs # and/or config/prod.exs
Change the port from 4000 to 80. Please note this isn’t an article about a production deploy of your application (refer here for that). Let’s start up your server
MIX_ENV=PROD mix phx.server
You should now see your site live (on port 80)
Next, we will need to tweak our routes to enable webroot authorization of Lets Encrypt. Let’s edit our endpoint.ex
We need to allow anything from .well-known to route through Plug.Static for Let’s Encrypt authentication.
at: "/", from: :isafe, gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt .well-known)
Restart your server!
MIX_ENV=prod mix phx.server
Note that I updated the instructions to work with prod, as there were some issues with renewals as noted on StackOverflow). The major change is that assets (aka images, JSON, .well-known files) will be drawn from the _build directory. Let’s test our change:
mkdir -p ./_build/prod/lib/isafe/priv/static/.well-known
(cd ./_build/prod/lib/isafe/priv/static && \
echo "hello world" > .well-known/XXXYYY.html)
Open your browser to that page, and you should see the text below.
If you see an error like the following then something went awry (maybe you didn’t restart your server, or didn’t edit the correct file).
Now that we have our application ready, let’s install Let’s Encrypt certbot.
If you are running Ubuntu 16.04, the script probably still looks like the following:
(apt-get install -y software-properties-common && \
add-apt-repository -y ppa:certbot/certbot && \
apt-get update && \
apt-get install -y certbot)
Let’s write our configs to a file (so that we don’t need to remember all the options).
Here is a template for what to put in there. Here is the documentation about all available settings.
rsa-key-size = 4096
email = email@example.com
domains = yourdomain.com, www.yourdomain.com
text = True
authenticator = webroot
preferred-challenges = http-01
webroot-path = /src/isafe/_build/prod/lib/isafe/priv/static
Don’t forget to update your domain, email and source path. Once configured we can generate our certificates
echo "A"| certbot certonly --config /etc/letsencrypt/letsencrypt.ini
If everything worked you should see something like
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/yourdomain.com/fullchain.pem. Your cert
will expire on 2017-08-30. To obtain a new or tweaked version of
this certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
- If you like Certbot, please consider supporting our work by:Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Let’s add the https information to your config (e.g config/prod.exs)
config :isafe, Isafe.Web.Endpoint,
http: [port: 80],
https: [port: 443,
Restart your server and TADA, your are running HTTPS (note that the screenshot is from a test domain, you will want to try your domain).
Last piece of the puzzle is to configure your application to always use HTTPS. To do this, you will need to configure force_ssl, and ensure that your url’s host is configured properly. Below is one of the many ways based on Plug.SSL configurations.
config :isafe, Isafe.Endpoint,
url: [host: "yourdomain.com", port: 443],
http: [port: 80],
force_ssl: [hsts: true],
https: [port: 443,
Now your site is being served up only through SSL directly through Phoenix (no Nginx required).