Skip to content

Commit 2475549

Browse files
Updated docs to reflect new changes
Updated backend docs to reflect changes to how server configuration works and added a short document about how we deployed the application to Heroku.
1 parent 11550a9 commit 2475549

File tree

4 files changed

+103
-41
lines changed

4 files changed

+103
-41
lines changed

docs/backend.rst

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -257,51 +257,46 @@ Server Configuration
257257
-------------------------
258258
There is some information that Kvasir needs in order to function outside of information that it could access from the middleware.
259259

260-
The configuration file is small, but contains necessary information for Kvasir to run properly.
260+
Originally, Kvasir used a configuration file which was just a JavaScript file that exported an object containing all of the info. The configuration file is hidden from the git repository because the configuration file contains secret keys that you don't want to expose. The problem with this approach is that for many third-party hosting sites (such as Heroku) use a git repository to pull in the necessary source files for your application. Every file that you want uploaded has to be contained in the repository, so having a hidden configuration file is not helpful.
261261

262-
A sample configuration file looks like this:
263-
.. code-block:: javascript
264-
265-
var config ={};
266-
267-
config.cookie_secret = "<SOME_RANDOM_JUMBLE_OF_LETTERS_AND_NUMBERS>";
268-
config.middleware_uri= "https://<address_to_your_middleware>";
269-
config.middleware_secret = "<SOME_RANDOM_JUMBLE_OF_LETTERS_AND_NUMBERS>";
262+
What these sites offer instead is the ability to set environment variables, which still provides us the ability to configure our environment with information that Kvasir needs to run without exposing that information to unwanted parties.
270263

271-
config.port = 3000;
264+
Environment Variables
265+
~~~~~~~~~~~~~~~~~~~~~~~
266+
All of the environemtn variables that Kvasir uses start with KVASIR. This isolates it's environment variables from any other applications.
272267

273-
// wepay client_id and client_secret are needed for certain calls
274-
config.client_id = "<YOUR_WEPAY_CLIENT_ID>";
275-
config.client_secret = "<YOUR_WEPAY_CLIENT_SECRET>";
268+
This is the entire list of environment variables:
269+
- **KVASIR_COOKIE_SECRET**: the secret key used to "encrypt" cookies set in the browser
270+
- **KVASIR_MIDDLEWARE_URI**: the uri to the middleware which connects to your database
271+
- **KVASIR_MIDDLEWARE_SECRET**: the secret key used in the `Authorization` header when making requests to the middleware
272+
- **KVASIR_CLIENT_ID**: your WePay client id
273+
- **KVASIR_CLIENT_SECRET**: your WePay client secret
274+
- **KVASIR_SSL_PRIVATE_KEY**: *(optional)* the name of the file that contains your SSL private key
275+
- **KVASIR_SSL_CERTIFICATE**: *(optional)* the name of the file that contains your SSL certificate
276+
- **KVASIR_HTTP_OVERRIDE**: *(optional)* boolean to tell Kvasir to launch under an HTTP server instead of an HTTPS server
276277

277-
config.ssl = {
278-
privateKey: "<PATH_TO_KEY>/<KEY_FILE>",
279-
certificate: "<PATH_TO_KEY>/<CERTIFICATE_FILE>"
280-
};
281-
282-
module.exports = config;
283-
284-
It must be saved in the root directory of Kvasir and be named **config.js**.
278+
.. note::
279+
You must supply either KVASIR_HTTP_OVERRIDE as `True` **or** supply both KVASIR_SSL_CERTIFICATE and KVASIR_SSL_PRIVATE_KEY.
285280

286-
The configuration contains two secret keys:
287-
- cookie_secret: a secret key to hash your cookie session with
288-
- middleware_secret: a secret key to use when making requests to your middleware. It is placed in an *Authorization* header with each request.
281+
Environment File
282+
~~~~~~~~~~~~~~~~~~~
283+
An environment file can still be defined to set the values of the different environment variables. Some third party hosting services (such as the Google App Engine) will take all files in your current directory and upload those instead of using a git repository. These types of services don't always provide a way to set environment variables remotely, so the hidden file works in those cases.
289284

290-
The *middleware_secret* should be shared with your middleware so that it can validate that the requests it is receiving are actually from Kvasir and not from someone else.
285+
.. note::
286+
If you are adding additional functionality into Kvasir (in other words, you are actively developing Kvasir), then you should define use the `.env` file. It makes testing and manipulating the environment variables a little easier.
291287

292-
It also needs the address of your middleware. This provides it some flexibility in the event that the address changes. This way you don't have to manipulate the source code.
288+
Kvasir will check for the presence of the environment file using the `dotenv <https://www.npmjs.com/package/dotenv>`_ package which will then set all of the environment variables accordingly. This way, the other parts of Kvasir don't have to worry about where the configuration values are coming from. It will check the enviornment variables and pull them into an object that all of it's routes and functions are free to reference.
293289

294-
The configuration also requires your WePay *client_id* and *client_secret*. There are certain WePay API requests that require this info in place of an access token. Providing it in the config file lets Kvasir access it when necessary.
290+
The file should be named `.env` and be placed in the same directory as `server.js`.
295291

296-
The total list of configuration options is:
297-
- **cookie_secret**: the secret key used to hash cookies set in the browser
298-
- **middleware_uri**: the uri to the middleware which connects to your database
299-
- **middleware_secret**: the secret key used in the `Authorization` header when making requests to the middleware
300-
- **client_id**: your WePay client id
301-
- **client_secret**: your WePay client secret
302-
- **ssl**: the ssl configuration which includes
303-
* *privateKey*: the name of the file that contains your SSL private key
304-
* *certificate*: the name of the file that contains your SSL certificate
292+
A sample environment file looks like this:
293+
.. code-block::
294+
KVASIR_COOKIE_SECRET = YOUR_COOKIE_SECRET
295+
KVASIR_MIDDLEWARE_URI = https://your.middle.ware/
296+
KVASIR_MIDDLEWARE_SECRET = YOU_MIDDLEWARE_SECRET
297+
KVASIR_CLIENT_ID = YOUR_WEPAY_CLIENT_ID
298+
KVASIR_CLIENT_SECRET = YOUR_WEPAY_CLIENT_SECRET
299+
KVASIR_HTTP_OVERRIDE = TRUE_OR_FALSE
305300
306301
Generating Secret Keys
307302
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -319,16 +314,27 @@ Copy the output and paste it into the config file. It is important that you **d
319314

320315
Serving Over HTTPS
321316
~~~~~~~~~~~~~~~~~~~~~~
322-
In order to securely pass data around this system, we require that the server use HTTPS. You can do it with any existing SSL certificates that you have or you can generate a self signed certificate.
317+
In order to securely pass data around this system, we require that the server use HTTPS. You can do it with any existing SSL certificates that you have or you can generate a self signed certificate.
323318

324319
.. note::
325320
If you use a self signed certificate, your users will get a warning from the browser saying that the site is not trusted. They can ignore the error and enter.
321+
But we **highly** recommend you use a certificate signed by a certificate authority.
326322

327-
The config file allows you to specify where the certificate and key are stored. The path should be **relative to the server.js file**.
323+
The enviroment variables allow you to specify where the certificate and key are stored. The path should be **relative to the server.js file**.
328324

329325
If you need help creating a self-signed SSL certificate, you can follow this tutorial:
330326
https://devcenter.heroku.com/articles/ssl-certificate-self
331327

328+
Load Balancers and Third Party Hosting
329+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
330+
Some load balancers (such as nginx) and third party hosting services (such as Google App Engine) can implement the HTTPS connection for you and sometimes have difficulty communicating with their underlying processes if they require HTTPS. For example, when we tried to do a test deployment to the Google App Engine, it was having trouble communicating with the underlying NodeJs server. We were able to trace the issue back to the fact that the GAE was not expecting the underlying processes to be running on HTTPS so it was unable to communicate with it and there are no apparent configuration options to allow us to force it to expect that.
331+
332+
But the GAE (and even Heroku) implement HTTPS by default. All communication with the client is done over HTTPS, but communication to it's underlying processes (since they often fire off multiple instances of your application) is done via HTTP. It is important to make sure that the connection to the end user is done over HTTPS to make sure the information you are sending to them cannot be intercepted and used by another party.
333+
334+
The `KVASIR_HTTP_OVERRIDE` environment variable is used to tell Kvasir to run using HTTP instead of HTTPS. This is meant to be used in conjuction with a load balancer or thrid party hosting site that can make sure the connection to the end user is done over HTTPS.
335+
336+
If you are not using a load balancer or third party hosting site, then make sure you are providing `KVASIR_SSL_PRIVATE_KEY` and `KVASIR_SSL_CERTIFICATE` so that Kvasir can enable HTTPS.
337+
332338
Templating Engine
333339
~~~~~~~~~~~~~~~~~~~~
334340
Kvasir uses `EJS <https://www.npmjs.com/package/ejs>`_ for our templating engine. The main purpose of the templating engine is to allow us to embed the server side generated CSRF token in the HTML.

docs/herokudeploy.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Deploying to Heroku
2+
====================
3+
This page explains the process we took to deploy Kvasir on Heroku.
4+
You can follow a similar approach for any third party hosting service but some of the particulars will be dependent on which service you chose to use.
5+
6+
Purpose
7+
--------
8+
The point of deploying on Heroku was to validate that our system could easily be deployed. We wanted to make sure that all modules were included in our `package.json` file and that Kvasir could function outside the comfort of our development environment.
9+
10+
Our first attempt was less than glamorous. There were a lot of changes made in order to get the deployment to work, but we ended up with a better system overall.
11+
The idea for using environment variables instead of a configuration file came from this process.
12+
13+
Following the Tutorial
14+
--------------------------
15+
We are not the first people to deploy a NodeJS application to Heroku. Not even close.
16+
17+
There is a very good tutorial for `deploying a NodeJS app on Heroku <https://devcenter.heroku.com/articles/getting-started-with-nodejs#introduction>`_.
18+
This document will be more notes on the pitfalls that we encountered specific to Kvasir and what steps we took to climb out of them.
19+
20+
Procfile
21+
~~~~~~~~~
22+
The Heroku tutorial mentions that you can use a Procfile to specify how to launch the application; however, Heroku will also try and run commands present in the `scripts` section of the `package.json` file. Kvasir includes the commands for how to start the NodeJS server and build the front-end JavaScript library in the `package.json` file, so the Procfile is not necessary.
23+
24+
Setting Environment Variables
25+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26+
Heroku will only launch with files include in the git repository that you push to it. Assuming that you didn't make any changes to Kvasir's `.gitignore` file, then the `.env` file that includes all of the environment variable configuration, but is hidden from git, will not be included in the source code uploaded to Heroku. This presents a problem because Kvasir needs those configuration values, but the file that you put them in is no longer accessible.
27+
28+
The solution is to set environment variables on the Heroku server.
29+
30+
Depending on what version of Heroku toolbelt that you have installed on your machine you will use either `heroku config:add` or `heroku config:set` followed by the name of the environment variable and it's corresponding value.
31+
32+
For example, to set the cookie secret:
33+
>>> herkou config:set KVASIR_COOKIE_SECRET=YOUR_COOKIE_SECRET
34+
35+
You have to run this for each environment variable that you want to set, and the Heroku server will restart for each variable that is added or changed.
36+
37+
Scripting Makes Life Easier
38+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
If you already have a `.env` file defined (which you generally should during development), then you can use this Python script to set all of the environment variables on Heroku for you.
40+
41+
..code-block:: python
42+
43+
from subprocess import call
44+
45+
command = ['heroku', 'config:set', '']
46+
with open(".env", "r") as f:
47+
for line in f:
48+
command[-1] = line.rstrip().replace(" ", '')
49+
call(command)
50+
51+
What this script does is open the `.env` file, and then for each line in that file, it will strip any trailing whitespace (including new lines) and remove any spaces from the line and send the command via the command line to heroku to add the environment variable and value.
52+
53+
The reason we have to remove any spaces is because spaces will mess up how the command line parses the command. If your `KVASIR_MIDDLEWARE_URI` has spaces in it, make sure you replace those with *%20*.
54+

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Contents
7474
frontend
7575
backend
7676
middleware
77+
herokudeploy
7778

7879
Indices and tables
7980
====================

server.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ var express = require("express");
2222

2323
// load app configuration settings
2424
// pull all of the environment variables down into a dictionary
25-
require("dotenv").config();
2625
console.log("ENVIROMENT VARIABLES: ", process.env);
2726
var app_config = {
2827
"cookie_secret": process.env.KVASIR_COOKIE_SECRET,
@@ -32,10 +31,12 @@ var app_config = {
3231
"client_id": process.env.KVASIR_CLIENT_ID,
3332
"client_secret": process.env.KVASIR_CLIENT_SECRET,
3433
"http_override":process.env.KVASIR_HTTP_OVERRIDE
34+
"ssl": {
35+
"privateKey": process.env.KVASIR_SSL_PRIVATE_KEY,
36+
"certificate": process.env.KVASIR_SSL_CERTIFICATE
37+
}
3538
}
3639

37-
console.log("APP CONFIG: ", app_config);
38-
3940
// create the express app and define what port this is open on
4041
var app = new (express)();
4142
var port = app_config.port;

0 commit comments

Comments
 (0)