├── favicon.ico
├── .well-known
└── acme-challenge
│ ├── BPgVqxFMZAg29d7KfHwS2xGvRa79EKblxgWDn_44_N0
│ ├── FJ76sYmjUGa6JLc5s2J_QeQzqcBnmO2AAV6wr4sWe5E
│ ├── T4XE4bNn2nrblyobGQyqEsLY2GvcDUYeMPYfKl5neWw
│ ├── WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0
│ ├── _-SyF07cuWWE6OgqWRRq-QCWDfG2NOxqm_U5gT-7L8A
│ ├── iTMP1u9ugjJG3m7xHpd7JNxF6EPREu--7jzK5qjVmxU
│ └── qN0VkWVSSAqFmDkV90s_gZKkFYXbmbXG53nbfVeeXqE
├── .gitignore
├── package.json
├── index.html
├── update_stack.py
├── README.md
├── elixir-phoenix-app-deployment.md
└── SSL-certificate-step-by-step-setup-instructions.md
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dwyl/learn-heroku/HEAD/favicon.ico
--------------------------------------------------------------------------------
/.well-known/acme-challenge/BPgVqxFMZAg29d7KfHwS2xGvRa79EKblxgWDn_44_N0:
--------------------------------------------------------------------------------
1 | BPgVqxFMZAg29d7KfHwS2xGvRa79EKblxgWDn_44_N0.NqTSciiSqnBus5ylE1wdT7QOgICWBgpA_OHhYIuyCxI
--------------------------------------------------------------------------------
/.well-known/acme-challenge/FJ76sYmjUGa6JLc5s2J_QeQzqcBnmO2AAV6wr4sWe5E:
--------------------------------------------------------------------------------
1 | FJ76sYmjUGa6JLc5s2J_QeQzqcBnmO2AAV6wr4sWe5E.NqTSciiSqnBus5ylE1wdT7QOgICWBgpA_OHhYIuyCxI
--------------------------------------------------------------------------------
/.well-known/acme-challenge/T4XE4bNn2nrblyobGQyqEsLY2GvcDUYeMPYfKl5neWw:
--------------------------------------------------------------------------------
1 | T4XE4bNn2nrblyobGQyqEsLY2GvcDUYeMPYfKl5neWw.NqTSciiSqnBus5ylE1wdT7QOgICWBgpA_OHhYIuyCxI
--------------------------------------------------------------------------------
/.well-known/acme-challenge/WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0:
--------------------------------------------------------------------------------
1 | WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0.kURQ5HbILtRXEwJA2QI4W5TdBkjnZNqH2_RHORvmN6w
--------------------------------------------------------------------------------
/.well-known/acme-challenge/_-SyF07cuWWE6OgqWRRq-QCWDfG2NOxqm_U5gT-7L8A:
--------------------------------------------------------------------------------
1 | _-SyF07cuWWE6OgqWRRq-QCWDfG2NOxqm_U5gT-7L8A.NqTSciiSqnBus5ylE1wdT7QOgICWBgpA_OHhYIuyCxI
--------------------------------------------------------------------------------
/.well-known/acme-challenge/iTMP1u9ugjJG3m7xHpd7JNxF6EPREu--7jzK5qjVmxU:
--------------------------------------------------------------------------------
1 | iTMP1u9ugjJG3m7xHpd7JNxF6EPREu--7jzK5qjVmxU.NqTSciiSqnBus5ylE1wdT7QOgICWBgpA_OHhYIuyCxI
--------------------------------------------------------------------------------
/.well-known/acme-challenge/qN0VkWVSSAqFmDkV90s_gZKkFYXbmbXG53nbfVeeXqE:
--------------------------------------------------------------------------------
1 | qN0VkWVSSAqFmDkV90s_gZKkFYXbmbXG53nbfVeeXqE.NqTSciiSqnBus5ylE1wdT7QOgICWBgpA_OHhYIuyCxI
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 |
10 | pids
11 | logs
12 | results
13 |
14 | npm-debug.log
15 | node_modules
16 | .DS_Store
17 | apps.txt
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learn-heroku",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "http-server": "^0.9.0",
6 | "live-server": "^1.2.0"
7 | },
8 | "engines": {
9 | "node": "6.10.x"
10 | },
11 | "scripts": {
12 | "start": "node node_modules/.bin/http-server",
13 | "local": "node_modules/.bin/live-server --port=8080"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Learn Heroku - Hello World!
6 |
7 |
8 | Hello World!
9 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/update_stack.py:
--------------------------------------------------------------------------------
1 | # update the stack of your heroku apps. github.com/dwyl/learn-heroku/issues/43
2 | import os
3 |
4 | os.system("echo Fetching List of Apps from Heroku")
5 | os.system('heroku apps:table --filter="STACK=cedar-14" >> apps.txt')
6 | file = open('apps.txt', 'r')
7 | Lines = file.readlines()
8 |
9 | # Strips the newline character
10 | for line in Lines:
11 | parts = line.split(" ")
12 | app = parts[0].strip()
13 | print("updating: " + app)
14 | os.system("heroku stack:set heroku-18 -a " + app)
15 |
16 | import sys
17 | sys.exit()
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learn (How to Deploy a Web Application on) Heroku
2 |
3 | 
4 |
5 | ## Why?
6 |
7 | You know how to _create_ a web application,
8 | but that knowledge is only _useful_
9 | if you know how to _show_ the app to people!
10 |
11 | ## What?
12 |
13 | Easily deploy your node.js web application to Heroku
14 | so you can start testing it with end-users as soon as possible!
15 |
16 | You'll have a _public_ URL for your app in 5 minutes which you can share
17 | with real people and get feedback/validation for your idea!
18 |
19 | ### "Top 7" Key Benefits:
20 |
21 | + Basic apps are ***Free***!! (_e.g. Demo, Hackathon or "Low Traffic"
22 | Personal "Blog" or Portfolio site_)
23 |
24 | + _***Quick and Easy Deployment***_ from your development machine or GitHub!
25 | A couple of clicks or a single command is all it takes!
26 |
27 | + Excellent **knowledge base** / documentation for
28 | both simple and advanced topics!
29 | (_if you get stuck,
30 | [**ask a question**](https://github.com/dwyl/learn-heroku/issues)
31 | we can/will help!_)
32 |
33 | + ***Continuous Deployment*** is easy from a GitHub repository using "Hooks".
34 | (_see step-by-step tutorial below!_)
35 |
36 | + Great Range of "**Addon Services**" you can use with your app
37 | in a couple of clicks (_e.g: PostgreSQL, ElasticSearch, Monitoring etc._)
38 | and most have a "free tier"
39 | so you can get started without spending a penny!
40 | See: https://elements.heroku.com/addons
41 |
42 | + "_Industry Standard_" ***Service Quality*** is _really_ good
43 | (_under the hood Heroku uses Amazon Web Services
44 | but they do all the "plumbing" so you don't have to waste time on "DevOps"
45 | until you're ready to scale, at which point just pay for a pro!_)
46 |
47 | + **Cost-effective** for your ***first 10k users***
48 | (_don't waste your time on "DevOps" till you have validated your App Idea
49 | with real people!_)
50 |
51 |
52 | ## Who?
53 |
54 | _Anyone_ building for the web who values their _time_ and wants/needs
55 | a _painless_ way to ***deploy, monitor and automatically scale***
56 | an app!
57 |
58 |
59 | ## How?
60 |
61 | ### Beginner: Basic Heroku Deployment of Node.JS App in 5 Minutes
62 |
63 | #### Pre-requisites:
64 | + **Computer** with a ***Web Browser***
65 | + **Internet Connection**
66 | + ***GitHub Account*** ... if you don't have one see:
67 | [github.com/dwyl/github-reference#how-to-**sign-up**](https://github.com/dwyl/github-reference#how-to-sign-up)
68 | + Heroku account ... if you don't have one, sign up now: https://signup.heroku.com (_it's free! and **no credit card required**!_)
69 |
70 | #### No Experience/Knoweldge Required
71 | + No Node.js or other knowledge required
72 | + All web-based (_no command line, we can learn that "CLI" later!_)
73 |
74 | #### 1. Fork this repository on GitHub!
75 |
76 | In your web browser navigate to:
77 | [github.com/dwyl/**learn-heroku**](https://github.com/dwyl/learn-heroku)
78 | (_if you aren't already on the page_)
79 |
80 | After you have starred the repository,
81 | click the "fork" button:
82 | 
83 |
84 | You should now see something similar to this:
85 | 
86 |
(_with your GitHub username in place of mine_)
87 |
88 |
89 | #### 2. Log into your Heroku Account and Create a New App
90 |
91 | > **Note**: if you don't already have a Heroku account set one up now!
92 |
93 | Visit: https://dashboard.heroku.com/new and create your new app.
94 | _example_:
95 | 
96 | (_you will need to give your app a **different name**;
97 | all heroku apps are **unique**._)
98 |
99 |
100 | #### 3. Use Heroku (Web) UI to Deploy the Application
101 |
102 | Once you create your app in Heroku you will be shown the "***Deploy***" screen:
103 |
104 | 
105 |
106 | Connect your Heroku app to the GitHub Repository you created (_by forking_)
107 | in step 1 (_above_).
108 |
109 | ##### Steps:
110 |
111 | + Click on the "Connect to GitHub" button
112 | + Search for the repository `learn-heroku` in our case
113 | + Click on "Connect" button.
114 |
115 | Now click "**Enable Automatic Deploys**" to ensure that
116 | any changes made on GitHub are automatically deployed on Heroku:
117 |
118 | 
119 |
120 | #### 4. Test The Deployment Works by Updating a File in the Forked Repo
121 |
122 | Back in GitHub, use the Web user interface (UI) to edit one of the files
123 | in your fork of `learn-heroku`.
124 |
125 | My suggestion is update (_increment_) the version number
126 | in the `package.json` file:
127 |
128 | Click the edit icon:
129 | 
130 |
131 | In the edit view, increment the version number:
132 | 
133 |
134 | Now scroll down to the **Commit changes** section of the edit view:
135 |
136 | 
137 |
138 | write a descriptive commit message and click the "**Commit changes**" button.
139 |
140 | > Note: we typically don't encourage people to `commit` directly to `master`
141 | but given that this is your personal fork you can do it this one time.
142 |
143 | You should see something like this:
144 | 
145 |
146 | That will trigger the Heroku deployment of the Hello World Application!
147 |
148 | #### 5. Visit the Heroku App in your Web Browser
149 |
150 | > In my case the URL for my app is: https://hello-world-heroku-node.herokuapp.com
151 |
152 | You should expect to see:
153 | 
154 |
155 | ### Congratulations! You just _deployed_ your first app on Heroku!
156 |
157 |
158 |
159 |
160 | ### Intermediate: Detailed Step-by-Step Instructions a "Real" App
161 |
162 | See: [elixir-phoenix-app-deployment.md](https://github.com/dwyl/learn-heroku/blob/master/elixir-phoenix-app-deployment.md)
163 |
164 | ### Intermediate: Environment Variables on Heroku
165 |
166 | See: [github.com/dwyl/learn-environment-variables#**environment-variables-on-heroku**](https://github.com/dwyl/learn-environment-variables#environment-variables-on-heroku)
167 |
168 | ### Intermediate: Using a Custom Domain Name on Heroku
169 |
170 | To use a custom domain name on your heroku app, the first thing to do is to purchase your domain name. There are a number of services you can use for this (we like [iwantmyname.com](https://iwantmyname.com)).
171 |
172 | The next step is to add this domain to your heroku app. You can do this using the command line interface, or the settings dashboard on heroku.com.
173 |
174 |
175 |
176 | Once you've added your domain, you should see a DNS target:
177 |
178 |
179 |
180 | This is what you need to give to your DNS provider (which is most likely the site you purchased your domain from).
181 |
182 | If your domain starts with `www.`, you will need to add the DNS target as a `CNAME` record with a name of `www`
183 |
184 | If your domain just consists of the domain name and the top level domain (eg. `github.com` instead of `www.github.com`; This is known as the root domain), you might be able to add it as a `CNAME`, but will most likely need to add it as an `ANAME` or an `ALIAS` record. In this case, either leave the name blank, or use `@`
185 |
186 | Some services will not allow you to add the root domain as a `CNAME`, and will not have `ANAME` or `ALIAS` as an option, instead requiring you to give an IP address as the `A` record. This is not possible with heroku, as they use dynamic IP addresses, meaning they will change regularly and your DNS record will no longer be correct.
187 |
188 | However, if you still want people to be able to access your site using the root domain, there are still a few things you can do.
189 |
190 | Some services (iwantmyname.com included) have a feature where they will automatically configure DNS records for popular web services (tumblr, squarespace, heroku etc.).
191 |
192 | Another alternative is to just add the `www` DNS record, and to add a redirect (it may also be known as forwarding) from your root domain to that. This does mean that the `www` will show in the browser address bar, but both addresses will lead to your site.
193 |
194 | See the [heroku docs](https://devcenter.heroku.com/articles/custom-domains) or your DNS providers help page for specific instructions.
195 |
196 |
210 |
211 | ## Background Reading
212 |
213 | - https://devcenter.heroku.com/articles/getting-started-with-nodejs
214 | - http://build-podcast.com/heroku
215 |
216 | ## Frequently Asked/Ansered Questions (FAQ)
217 |
218 | ### Isn't Heroku "_Expensive_" for the CPU/RAM You're Getting?
219 |
220 | Heroku costs more per unit of computing resource than the equivalent
221 | _infrastructure_ provider
222 | (_e.g: AWS / DigitalOcean / GoogleCloud / Azure / etc._)
223 | but it's _cheap_ if you factor ***developer's time***
224 | as your **biggest cost/constraint**!
225 | Setting up deployment to AWS with all the benefits/features Heroku has
226 | out-of-the-box will take _hours_. So unless your developer's time is _free_
227 | _or_ you _are_ the developer and want to spend a day on deployment
228 | instead of building features to solve the end-user's problem,
229 | use Heroku and focus on _building_ the product!
230 | See: https://github.com/dwyl/learn-heroku/issues/3
231 |
--------------------------------------------------------------------------------
/elixir-phoenix-app-deployment.md:
--------------------------------------------------------------------------------
1 | # Deploying an Elixir/Phoenix App to Heroku
2 |
3 | 
4 |
5 |
6 | ## Why?
7 |
8 | You want to deploy your Web Application with Database to Heroku
9 | as _fast_ as possible while still _understanding_ all the steps!
10 |
11 |
12 | ## What?
13 |
14 | A _step-by-step_ guide to deploying a (Phoenix) Web App on Heroku.
15 |
16 | We _created_ this walkthrough/tutorial while _deploying_ our
17 | "beginner phoenix example":
18 | https://github.com/dwyl/phoenix-chat-example
19 | So we _know_ it works! Try it: https://phxchat.herokuapp.com
20 |
21 | > _**Note**: most of this is applicable to **any** App_
22 | (_Node.js, Python, Ruby, etc._)
23 | > Even if you are deploying a totally different Language/Framework,
24 | it's still worth "_skimming_".
25 |
26 | ## Who?
27 |
28 | _Anyone_ who wants a _quick, easy and "**free**"_
29 | way to _deploy_ a demo app!
30 |
31 |
32 | ## _How_?
33 |
34 | _First_, let's do the setup on Heroku:
35 |
36 | ### 1. _Create_ a New App
37 |
38 | Once you have logged into your Heroku account
39 | and are viewing your "dashboard": https://dashboard.heroku.com
40 |
41 | 1.1 Click on the `New` button, then
42 | 1.2 Click on `Create new app`:
43 |
44 | 
45 |
46 | ### 2. Give Your New App a _Name_
47 |
48 | Input your desired name
49 | (_if it's available; otherwise get **creative**!_):
50 | 
51 | In this case we are creating an App called `phxchat`.
52 | (_short for `Phoenix Chat`,
53 | because **obviously** `phoenixchat` is "taken"..._)
54 |
55 | Leave the rest of the options to the "default" options
56 | (_unless you have specific needs_).
57 |
58 | > _**Note**: don't worry about the "Add to pipeline" option for now,
59 | we will come back to it later_.
60 |
61 | Click on the `Create app` button.
62 |
63 | You will be directed to the "Deploy" tab for your app:
64 | 
65 |
66 | ### 3. Create "Deployment Pipeline"
67 |
68 | On the "Deploy" tab of your app, scroll down
69 | till you see the "Deployment Method" section:
70 |
71 | 
72 |
73 | 1. Click on "GitHub"
74 | 2. Select the "Owner" of the App you want to deploy
75 | (_usually your own GitHub username_)
76 | 3. Type (_or copy-paste_) the name of your App.
77 | 4. Click `Search` to find the repo.
78 | 5. Click "Connect" button.
79 |
80 | You should see:
81 | 
82 |
83 |
84 | ### 4. Add the PostgreSQL Database "Add-on"
85 |
86 | Given that our Phoenix App uses a Postgres database to store it's data,
87 | let's add it as an "Add-on".
88 |
89 | Scroll to the top of the dashboard and click on the "Resources" tab:
90 |
91 | 
92 |
93 | On the "Resources" page, scroll down till you See "Add-ons"
94 |
95 | 
96 |
97 | 1. Type: "post" (_in the add-on search input box_)
98 | 2. Select "Heroku Postgres" from the list.
99 |
100 | This will open a "Modal" for you to _confirm_:
101 | 
102 |
103 | Leave the _default_ "Hobby Dev - Free"
104 | and _click_ the "**Provision**" button.
105 |
106 | You should now see (_something similar to_) the following:
107 | 
108 |
109 |
110 | ### 5. Create a `elixir_buildpack.config` File
111 |
112 | In the root directory of the App you are trying to deploy,
113 | create a file called `elixir_buildpack.config`
114 |
115 | _Paste_ the following lines into the file:
116 |
117 | ```yml
118 | # Latest version of Erlang/OTP see: https://git.io/Je5k6
119 | erlang_version=22.2
120 |
121 | # Latest Elixir Version see: https://github.com/elixir-lang/elixir/releases
122 | elixir_version=1.9.4
123 |
124 | # Always rebuild from scratch on every deploy?
125 | always_rebuild=false
126 |
127 | # Set the path the app is run from
128 | runtime_path=/app
129 | ```
130 |
131 | This file overrides the default options defined
132 | by adding the buildpack in **Step 9** (_below_).
133 | For more detail on the configuration options
134 | for your `elixir_buildpack.config` file
135 | see:
136 | https://github.com/HashNuke/heroku-buildpack-elixir#configuration
137 |
138 |
139 | ### 6. Create a `Procfile` File
140 |
141 | Also in the root directory of your App,
142 | create a file called `Procfile`
143 |
144 | _Paste_ this line in the file:
145 |
146 | ```sh
147 | web: MIX_ENV=prod mix ecto.migrate && mix phx.server
148 | ```
149 | That will ensure that your database tables/schema is up-to-date
150 | _before_ trying to launch the app.
151 |
152 |
153 | ### 7. Update Your `prod.exs` File
154 |
155 | This section "_borrows liberally_" from:
156 | https://hexdocs.pm/phoenix/heroku.html#making-our-project-ready-for-heroku
157 |
158 | #### 7.1 Configure the `Endpoint` Section
159 |
160 | The default looks something like this:
161 | ```elixir
162 | config :chat, ChatWeb.Endpoint,
163 | load_from_system_env: true,
164 | url: [host: "example.com", port: 80],
165 | cache_static_manifest: "priv/static/cache_manifest.json"
166 | ```
167 |
168 | Update the following params: `url`, `force_ssl` and `secret_key_base`:
169 | ```elixir
170 | config :chat, ChatWeb.Endpoint,
171 | load_from_system_env: true,
172 | url: [scheme: "https", host: "phxchat.herokuapp.com", port: 443],
173 | force_ssl: [rewrite_on: [:x_forwarded_proto]],
174 | cache_static_manifest: "priv/static/cache_manifest.json",
175 | secret_key_base: Map.fetch!(System.get_env(), "SECRET_KEY_BASE")
176 | ```
177 | Where:
178 | + The first line remains the same (_dependent on the name of your app_)
179 | + The `url` should be your heroku app name (_in our case `phxchat`_)
180 |
181 |
182 | #### 7.2 Create a `Repo` Section
183 |
184 | By default `prod.exs` does _not_ have a `Repo` section,
185 | so we need to _create_ one. Here's a "template"
186 |
187 | ```elixir
188 | # Configure your database
189 | config :hello, Hello.Repo,
190 | adapter: Ecto.Adapters.Postgres,
191 | url: System.get_env("DATABASE_URL"),
192 | pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
193 | ssl: true
194 | ```
195 |
196 | The one for our "chat" application is:
197 | ```elixir
198 | # Configure your database
199 | config :chat, Chat.Repo,
200 | adapter: Ecto.Adapters.Postgres,
201 | url: System.get_env("DATABASE_URL"),
202 | pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
203 | ssl: true
204 | ```
205 | All that changes is the _first_ line which is the name of your app.
206 |
207 |
208 | #### 7.3 Comment out Last Line in `prod.exs`
209 |
210 | Given that we are storing our "secrets" as Environment Variables on Heroku.
211 | We can _safely_ comment out the line in `prod.exs`:
212 |
213 | ```elixir
214 | import_config "prod.secret.exs"
215 | ```
216 | becomes:
217 |
218 | ```elixir
219 | # import_config "prod.secret.exs"
220 | ```
221 |
222 | ### 8. Generate the `SECRET_KEY_BASE` String
223 |
224 | The `SECRET_KEY_BASE` is the key that your app will use to
225 | digitally sign request tokens. It's vital to keep it a _secret_
226 | to avoid "_compromising_" your app.
227 | Therefore we will store it in an Environment Variable on Heroku.
228 |
229 | #### 8.1 Run the `mix phx.gen.secret` Command
230 |
231 | On your `localhost` (_terminal_), run the following command:
232 | ```sh
233 | mix phx.gen.secret
234 | ```
235 | That will output a **64 character** String such as:
236 | ```
237 | khaO4IJvSa+AFJHGFzlsgVlOuNNLgrUg9D4PCD943tKqersy3YNtABh/zmqd/v7y
238 | ```
239 | _Copy_ that string to your clipboard.
240 | (_we will use it in the next step_)
241 |
242 | #### 8.2 Define the `SECRET_KEY_BASE` Environment Variable on Heroku
243 |
244 | > _**Note**: if you are `new` to Environment Variables,
245 | we recommend you read our "**complete beginner**" **tutorial**_:
246 | [github.com/dwyl/**learn-environment-variables**](https://github.com/dwyl/learn-environment-variables)
247 |
248 | Open the "Settings" Tab of your App's Heroku Dashboard:
249 | 
250 |
251 | Now _scroll_ down to the "Config Variables"
252 | and click on the "***Reveal Config Vars***" button:
253 |
254 | 
255 |
256 | This will display your _existing_ variable `DATABASE_URL`
257 | and allow the creation of new Environment Variables.
258 |
259 | 
260 |
261 | 1. **Set** the "key" for the variable: `SECRET_KEY_BASE`
262 | 2. **Paste** the value generated in step 8.1 (_above_)
263 | 3. **Click** the "Add" button
264 |
265 |
266 | ### 9. Add the Elixir "Buildpack"
267 |
268 | Still in the "Settings" Tab of the Heroku Dashboard for the App,
269 | Scroll down to the "**Buildpacks**" section:
270 |
271 | 
272 |
273 | Click on the "Add buildpack" button.
274 |
275 | > A "Buildpack" tells Heroku _how_ to run your app.
276 | > In the case of an elixir app it defines how to get the dependencies
277 | and what the app expects/requires.
278 | For more detail, see: https://devcenter.heroku.com/articles/buildpacks
279 |
280 | When the "Modal" opens:
281 |
282 | 
283 |
284 | 1. Paste the value:
285 | https://github.com/HashNuke/heroku-buildpack-elixir.git
286 | into the field.
287 | 2. Click on "Save change" button
288 |
289 | You should now see the following:
290 |
291 | 
292 |
293 | #### 9.1 _Repeat_
294 |
295 | In order to compile any "_static assets_" (JS/etc.)
296 | we need to add a _second_ buildpack:
297 | https://github.com/gjaldon/heroku-buildpack-phoenix-static.git
298 |
299 | Repeat the process you just went through but this time
300 | add the `heroku-buildpack-phoenix-static` buildpack.
301 |
302 | Great! Now onto the _final_ step!
303 |
304 | ### 10. (_Manually_) Deploy
305 |
306 | > _Don't worry_, you only have to do this _once_.
307 | All _subsequent_ deploys are automatic!
308 |
309 | Back on the "Deploy" tap of your App's Dashboard,
310 | Scroll down to the "Manual deploy" section:
311 |
312 | 
313 |
314 | Click on the "**Deploy Branch**" button.
315 |
316 | This will _start_ the build process.
317 | Heroku will show you the "build log":
318 |
319 | 
320 |
321 | Once the build is complete,
322 | click on the "Open App" button in the top-right of your Heroku dashboard:
323 | 
324 |
325 | You should see _your_ app running in the browser!
326 |
327 | In _our_ case the app is: https://phxchat.herokuapp.com
328 | 
329 |
330 | `done()`
331 |
332 |
333 |
334 |
335 | ### Why _Not_ use the "Official" Deployment Guide?
336 |
337 | We are **aware** of (and have read) the
338 | "Deploying on Heroku" guide:
339 | https://hexdocs.pm/phoenix/heroku.html
340 | It's a _good_ guide for people with "intermediate" Heroku skills,
341 | however it's **longer** (more steps) than this tutorial,
342 | uses the Heroku "Toolbelt" (Command Line Interface "CLI"),
343 | which _most_ "beginners" _don't have_ installed
344 | and does not setup a "deployment pipeline" so it's a "manual" job
345 | (_running the deploy command each time_).
346 |
347 | With that said, it is a _good_ reference, so if you are stuck,
348 | that is a good place to look for "trouble-shooting".
349 |
350 |
351 | ## References & Background Reading
352 |
353 | + "Official" Heroku Deployment guide: https://hexdocs.pm/phoenix/heroku.html
354 | + Basic deployment: https://medium.com/@yasserhussain1110/how-to-deploy-phoenix-app-to-heroku-95d4bef32322 also uses Heroku CLI and doesn't setup a deployment pipeline. But good section on `config/prod.exs` changes.
355 | + Migrating a Phoenix App on Heroku: https://blog.learnphoenix.io/strategies-for-migrating-a-phoenix-app-on-heroku-ed0ea3aee4e5 _confirmed_ that `mix ecto.migrate` works in `Procfile`. (_Thanks @SamCorcos_)
356 |
--------------------------------------------------------------------------------
/SSL-certificate-step-by-step-setup-instructions.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Step-by-Step Setup Instructions for Let's Encrypt _Free_ SSL
4 |
5 | > _Note: These instructions are only applicable to web apps
6 | with a **custom domain** name_.
7 |
8 |
9 | ## Why?
10 |
11 | You have a custom domain for your Heroku app
12 | and now you want an SSL Certificate
13 | to Secure/Encrypt all communications between users and your app.
14 |
15 | ## What?
16 |
17 | Let's Encrypt offers a ***Free*** _Automated_ SSL Certificate Service
18 | brought to you by the **_non-profit_
19 | Internet Security Research Group** (ISRG).
20 | see: https://letsencrypt.org/about/
21 |
22 | ### Instructions Valid for Apps Written in _Any_ Language/Framework!
23 |
24 | The instructions in this tutorial/guide are applicable
25 | to an app written in ***any language or framework***.
26 | You will _temporarily_ deploy a Node.js `http-server` to your Heroku app
27 | which will allow Let's Encrypt to _verify_ that you "_own_" the app/domain.
28 |
29 | > _**Note**: No Node.js knowledge is assumed or required. You won't be
30 | writing a single line of JS code._
31 |
32 | Once you have set up SSL you can deploy what ever kind of app you like.
33 | (_in our case the app is written in [Elixir/Phoenix!](https://github.com/dwyl/technology-stack/#the-pete-stack) ...
34 | node.js is just an easy way to get this working in a **generic** way._)
35 |
36 | ## How?
37 |
38 | "**certbot**" is the script that _automates_ the certificate creation process.
39 |
40 | ### Step 1: Clone this Repository to get the Setup Code
41 |
42 | ```
43 | git clone https://github.com/dwyl/learn-heroku.git
44 | cd learn-heroku
45 | ```
46 |
47 | ### Step 2: Set Git Remote
48 |
49 | Check what your _current_ `origin` remote is:
50 | ```sh
51 | git remote -v
52 | ```
53 | 
54 |
55 | Set it to what ever the git url is for the app you are setting up SSL for. e.g:
56 | ```sh
57 | git remote set-url origin git@github.com:healthlocker/healthlocker.git
58 | ```
59 |
60 | Push your current branch to the GitHub repo:
61 | ```sh
62 | git push --set-upstream origin letsencrypt-temporary-server
63 | ```
64 |
65 | ### Step 3: _Temporarily_ Change the Branch Heroku Deploys from
66 |
67 | 
68 |
69 | Change it to the name of your branch e.g:
70 |
71 | 
72 |
73 | It should look something like this:
74 |
75 | 
76 | remember to (_temporarily_) _dissable_ the checkbox `Wait for CI to
77 | pass before deploy`
78 | (_we have no tests for this temporary server!_).
79 |
80 |
81 | ### Step 4: Install `certbot`
82 |
83 | > `certbot` installation instructions for various platforms:
84 | https://letsencrypt.org/getting-started
85 |
86 | ```sh
87 | brew install certbot
88 | ```
89 | 
90 |
91 | (_it might take a few minutes to install on a slower internet connection...
92 | be patient..._)
93 |
94 | ### Step 4: Run `certbot` Command (_Manual Setup_)
95 |
96 | Once you've installed `certbot` run the following command:
97 | ```sh
98 | sudo certbot certonly --manual
99 | ```
100 |
101 | Remember to use both the domain a `www` subdomain. (_separated by a space_) e.g:
102 |
103 | ```
104 | example.com www.example.com
105 | ```
106 |
107 | Our app was:
108 | ```
109 | healthlocker.uk www.healthlocker.uk
110 | ```
111 |
112 | Follow the steps and **pay _close_ attention**!
113 |
114 | When you reach the screen that looks like this:
115 |
116 | 
117 |
118 | _**DON'T** `continue` until you have completed **Step 5**_.
119 |
120 | Instructions printed by `certbot`:
121 | (_for reference ONLY see below for sub-set of instructions_)
122 | ```
123 | mkdir -p /tmp/certbot/public_html/.well-known/acme-challenge
124 | cd /tmp/certbot/public_html
125 | printf "%s" WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0.kURQ5HbILtRXEwJA2QI4W5TdBkjnZNqH2_RHORvmN6w > .well-known/acme-challenge/WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0
126 |
127 | # run only once per server:
128 | $(command -v python2 || command -v python2.7 || command -v python2.6) -c \
129 | "import BaseHTTPServer, SimpleHTTPServer; \
130 | s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \
131 | s.serve_forever()"
132 | ```
133 |
134 | You _wont_ be _able_ to run shell commands on a Heroku instance
135 | so we need to use a _temporary_ node.js server to achieve our objective.
136 |
137 | In your `current working directory` (_on your localhost_)
138 | run the following command to create the `.well-known/acme-challenge` directory:
139 |
140 | #### Step 4.1 Create the `.well-known/acme-challenge` Directory (_if it doesn't exist_)
141 |
142 | ```
143 | mkdir -p .well-known/acme-challenge
144 | ```
145 |
146 | #### Step 4.2 Create a File for the Token Verification
147 |
148 | Now ***copy-paste*** the `printf` command from the `certbot` instructions:
149 | they should look _something_ like this:
150 |
151 | ```
152 | printf "%s" WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0.kURQ5HbILtRXEwJA2QI4W5TdBkjnZNqH2_RHORvmN6w > .well-known/acme-challenge/WgFpodyij_PDzkU0MZ3CzKCI05hjLOcq2tP-1rs6ko0
153 | ```
154 | The tokens will be _specific_ to you so make sure you get the correct tokens.
155 | (_there is one token per domain_)
156 |
157 | #### Step 4.3: Commit Your Changes (_the token file_) and Push to GitHub
158 |
159 | Make a commit on your local branch so you can push to github
160 | (_and trigger the heroku build_)
161 |
162 | ```
163 | git add .
164 | git commit -m 'add letsencrypt verification file'
165 | git push
166 | ```
167 | That will deploy the file you created in Step 4.2 to Heroku.
168 |
169 | ### Step 5: Visit the Endpoint in your Browser to _Confirm_ it _Worked_:
170 |
171 | Visit your app in a web browser to confirm the deploy worked.
172 | e.g: http://example.com/.well-known/acme-challenge
173 |
174 | The url for _our_ app was: http://healthlocker.uk/.well-known/acme-challenge
175 |
176 | 
177 |
178 | It should _download_ a text file to your computer
179 | when you visit the endpoint in the browser.
180 |
181 | ### Step 6: Continue with the Certbot process
182 |
183 | Hit the enter key in the terminal window to `continue` the `certbot` process:
184 |
185 | 
186 |
187 | If if it worked, you should see something like that output in your terminal.
188 | If not scroll down to Trouble-Shooting section below
189 |
190 | ### Step 7: Conclude the process on Heroku
191 |
192 | You're _amost_ there, this is the _easy_ part!
193 |
194 | #### Step 7.1: `GOTO` Heroku "Settings" Tab and Click "***Configure SSL***"
195 |
196 | Navigate to the settings section of _your_ app on Heroku Dashboard e.g:
197 |
198 | 
199 |
200 | Scroll down to the "**Domains and certificates**" section
201 | and click on "***Configure SSL***" button:
202 |
203 | 
204 |
205 | #### Step 7.2: Click the link to _Paste_ the File Contntes
206 |
207 | Click on the link to paste the certificate:
208 | 
209 |
210 | #### Step 7.3: Copy the _Pulbic_ Certificate from your Machine
211 |
212 | Recall from above that the certificate generated by `certbot`
213 | was saved to `/etc/letsencrypt/live/healthlocker.uk/` (_your domain will be different_)
214 |
215 | You can _copy_ the contents of the file (_without "leaking" it_)
216 | by running the following command in your terminal:
217 |
218 | ```
219 | sudo cat /etc/letsencrypt/live/healthlocker.uk/fullchain.pem | pbcopy
220 | ```
221 | > Note: `sudo` is required because the `certbot` runs as admin
222 | for explanation of the `pbcopy` command see:
http://superuser.com/questions/113529/how-can-i-load-a-files-contents-into-the-clipboard
223 |
224 | #### Step 7.4: _Paste_ the _Pulbic_ Certificate
225 |
226 | Paste the `Public` Key (`cert.pem` _you copied above_)
227 | into the `