From 448848eb706a7bd7afc814b09812f067a1299209 Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Thu, 10 Nov 2016 11:12:20 -0500 Subject: [PATCH 1/4] nginx + supervisor --- deploy/nginx.md | 143 +++++++++++++++++++++++++++++++++++++++++++ deploy/supervisor.md | 60 ++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 deploy/nginx.md create mode 100644 deploy/supervisor.md diff --git a/deploy/nginx.md b/deploy/nginx.md new file mode 100644 index 00000000..16ccabac --- /dev/null +++ b/deploy/nginx.md @@ -0,0 +1,143 @@ +# Deploying with Nginx + +Nginx is an extremely fast, battle tested, and easy-to-configure HTTP server and proxy. While Vapor supports directly serving HTTP requests with or without TLS, proxying behind Nginx can provide increased performance, security, and ease-of-use. + +> Note: We recommend proxying Vapor HTTP servers behind Nginx. + +## Overview + +What does it mean to proxy an HTTP server? In short, a proxy acts as a middleman between the public internet and your HTTP server. Requests come to the proxy and then it sends them to Vapor. + +An important feature of this middleman proxy is that it can alter or even redirect the requests. For instance, the proxy can require that the client use TLS (https), rate limit requests, or even serve public files without talking to your Vapor application. + +### More Detail + +The default port for receiving HTTP requests is port `80` (and `443` for HTTPS). When you bind a Vapor server to port `80`, it will directly receive and respond to the HTTP requests that come to your server. When adding a proxy like Nginx, you bind Vapor to an internal port, like port `8080`. + +> Note: Ports greater than 1024 do not require `sudo` to bind. + +When Vapor is bound to a port besides `80` or `443`, it will not be accessible to the outside internet. You then bind Nginx to port `80` and configure it to route requests to your Vapor server bound at port `8080` (or whichever port you've chosen). + +And that's it. If Nginx is properly configured, you will see your Vapor app responding to requests on port `80`. Nginx proxies the requests and responses invisibly. + +## Install Nginx + +The first step is installing Nginx. One of the great parts of Nginx is the tremendous amount of community resources and documentation surrounding it. Because of this, we will not go into great detail here about installing Nginx as there is almost definitely a tutorial for your specific platform, OS, and provider. + +Tutorials: +- [How To Install Nginx on Ubuntu 14.04 LTS](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-14-04-lts) +- [How To Install Nginx on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04) +- [How to Deploy Nginx on Heroku](https://blog.codeship.com/how-to-deploy-nginx-on-heroku/) +- [How To Run Nginx in a Docker Container on Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-run-nginx-in-a-docker-container-on-ubuntu-14-04) + + +### APT + +Nginx can be installed through APT. + +```sh +sudo apt-get update +sudo apt-get install nginx +``` + +Check whether Nginx was installed correctly by visiting your server's IP address in a browser + +```sh +http://server_domain_name_or_IP +``` + +### Service + +Ther service an be started or stopped. + +```sh +sudo service nginx stop +sudo service nginx start +sudo service nginx restart +``` + +## Booting Vapor + +Nginx can be started an stopped with the `sudo service nginx ...` commands. You will need something similar to start and stop your Vapor server. + +There are many ways to do this, and they depend on which platform you are deploying to. Check out the [Supervisor](supervisor.md) instructions to add commands like `sudo start ...` for controller your Vapor app. + +## Configure Proxy + +The configuration files for enabled sites can be found in `/etc/nginx/sites-enabled/`. + +Create a new file or copy the example template from `/etc/nginx/sites-available/` to get started. + +Here is an example configuration file for a Vapor project called `Hello` in the home directory. + +```conf +server { + server_name hello.com; + listen 80; + + root /home/vapor/Hello/Public/; + + location @proxy { + proxy_pass http://127.0.0.1:8080; + proxy_pass_header Server; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass_header Server; + proxy_connect_timeout 3s; + proxy_read_timeout 10s; + } +} +``` + +This configuration file assumes the `Hello` project binds to port `8080` when started in production mode. + +### Serving Files + +Nginx can also serve public files without asking your Vapor app. This can improve performance by freeing up the Vapor process for other tasks under heavy load. + +```conf +server { + ... + + # Serve all public/static files via nginx and then fallback to Vapor for the rest + try_files $uri @proxy; + + location @proxy { + ... + } +} +``` + +### TLS + +Adding TLS is relatively straightforward as long as the certificates have been properly generated. To generate TLS certificates for free, check out [Let's Encrypt](https://letsencrypt.org/getting-started/). + +```conf +server { + ... + + listen 443 ssl; + + ssl_certificate /etc/letsencrypt/live/hello.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/hello.com/privkey.pem; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_prefer_server_ciphers on; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:50m; + ssl_stapling on; + ssl_stapling_verify on; + add_header Strict-Transport-Security max-age=15768000; + + ... + + location @proxy { + ... + } +} +``` + +The configuration above are the relatively strict settings for TLS with Nginx. Some of the settings here are not required, but enhance security. diff --git a/deploy/supervisor.md b/deploy/supervisor.md new file mode 100644 index 00000000..4ecbe77a --- /dev/null +++ b/deploy/supervisor.md @@ -0,0 +1,60 @@ +# Supervisor + +[Supervisor](http://supervisord.org) is a process control system that makes it easy to start, stop, and restart your Vapor app. + +## Install + +```sh +sudo apt-get update +sudo apt-get install supervisor +``` + +## Configure + +Each Vapor app on your server should have its own configuration file. For an example `Hello` project, the configuration file would be located at `/etc/supervisor/conf.d/hello.conf` + +```conf +[program:hello] +command=/home/vapor/hello/.build/release/App serve --env=production +directory=/home/vapor/hello/ +user=www-data +stdout_logfile=/var/log/supervisor/%(program_name)-stdout.log +stderr_logfile=/var/log/supervisor/%(program_name)-stderr.log +``` + +This assume the `Hello` project is located in the home folder for the user `vapor`. Make sure `directory` points to the root directory of your project where the `Config/` folder is. + +The `--env=production` flag is important as it will disable verbose logging and choose the `Config/production` sub folder of your configuration files. + +### Environment + +You can export variables to your Vapor app with sueprvisor. + +```sh +environment=PORT=8123 +``` + +Exported variables can be used in Vapor's configuration files with the `$` prefix. + +`Config/production/servers.json ` +```json +{ + "my-server": { + "port": "$PORT" + } +} +``` + +The above config file will start a server named `my-server` on the port number exported by supervisor. This is a great way to control how Vapor starts from the supervisor config scripts. Feel free to name the server whatever you like. + +## Start + +You can now load and start your app. + +```sh +supervisorctl reread +supervisorctl add hello +supervisorctl start hello +``` + +> Note: The `add` command may have already started your app. From 861d3456a5dcd8cf8230b864fe97e6c2fdb5fe23 Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Thu, 10 Nov 2016 11:29:58 -0500 Subject: [PATCH 2/4] style fixes --- couscous.yml | 13 ++++++++++++- deploy/nginx.md | 12 +++++++++--- deploy/supervisor.md | 7 ++++++- template/styles/main.css | 2 +- template/styles/main.sass | 2 +- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/couscous.yml b/couscous.yml index cd1000d2..2f5d84fc 100644 --- a/couscous.yml +++ b/couscous.yml @@ -152,8 +152,19 @@ menu: relativeUrl: websockets/custom.html testing: - name: testing + name: Testing items: testing-basic: text: Basic relativeUrl: testing/basic.html + + + deploy: + name: Deploy + items: + deploy-nginx: + text: Nginx + relativeUrl: deploy/nginx.html + deploy-supervisor: + text: Supervisor + relativeUrl: deploy/supervisor.html diff --git a/deploy/nginx.md b/deploy/nginx.md index 16ccabac..5a4b3864 100644 --- a/deploy/nginx.md +++ b/deploy/nginx.md @@ -1,3 +1,7 @@ +--- +currentMenu: deploy-nginx +--- + # Deploying with Nginx Nginx is an extremely fast, battle tested, and easy-to-configure HTTP server and proxy. While Vapor supports directly serving HTTP requests with or without TLS, proxying behind Nginx can provide increased performance, security, and ease-of-use. @@ -10,6 +14,8 @@ What does it mean to proxy an HTTP server? In short, a proxy acts as a middleman An important feature of this middleman proxy is that it can alter or even redirect the requests. For instance, the proxy can require that the client use TLS (https), rate limit requests, or even serve public files without talking to your Vapor application. +![nginx-proxy](https://cloud.githubusercontent.com/assets/1342803/20184965/5d9d588a-a738-11e6-91fe-28c3a4f7e46b.png) + ### More Detail The default port for receiving HTTP requests is port `80` (and `443` for HTTPS). When you bind a Vapor server to port `80`, it will directly receive and respond to the HTTP requests that come to your server. When adding a proxy like Nginx, you bind Vapor to an internal port, like port `8080`. @@ -70,7 +76,7 @@ Create a new file or copy the example template from `/etc/nginx/sites-available/ Here is an example configuration file for a Vapor project called `Hello` in the home directory. -```conf +```sh server { server_name hello.com; listen 80; @@ -96,7 +102,7 @@ This configuration file assumes the `Hello` project binds to port `8080` when st Nginx can also serve public files without asking your Vapor app. This can improve performance by freeing up the Vapor process for other tasks under heavy load. -```conf +```sh server { ... @@ -113,7 +119,7 @@ server { Adding TLS is relatively straightforward as long as the certificates have been properly generated. To generate TLS certificates for free, check out [Let's Encrypt](https://letsencrypt.org/getting-started/). -```conf +```sh server { ... diff --git a/deploy/supervisor.md b/deploy/supervisor.md index 4ecbe77a..0cae4dac 100644 --- a/deploy/supervisor.md +++ b/deploy/supervisor.md @@ -1,3 +1,8 @@ +--- +currentMenu: deploy-supervisor +--- + + # Supervisor [Supervisor](http://supervisord.org) is a process control system that makes it easy to start, stop, and restart your Vapor app. @@ -13,7 +18,7 @@ sudo apt-get install supervisor Each Vapor app on your server should have its own configuration file. For an example `Hello` project, the configuration file would be located at `/etc/supervisor/conf.d/hello.conf` -```conf +```sh [program:hello] command=/home/vapor/hello/.build/release/App serve --env=production directory=/home/vapor/hello/ diff --git a/template/styles/main.css b/template/styles/main.css index 42465e8c..7170e42d 100644 --- a/template/styles/main.css +++ b/template/styles/main.css @@ -25,7 +25,7 @@ h1, h2, h3, h4, h5, h6 { h1 { font-size: 38px; - font-weight: 200; } + font-weight: 300; } @media screen and (min-width: 720px) { h1 { font-size: 42px; } } diff --git a/template/styles/main.sass b/template/styles/main.sass index 4249a2d2..185c934a 100644 --- a/template/styles/main.sass +++ b/template/styles/main.sass @@ -31,7 +31,7 @@ h1 font-size: 38px @media screen and (min-width: $tablet) font-size: 42px - font-weight: 200 + font-weight: 300 h2 font-size: 30px From a628085eb07cbddd5b9896495d2d4a79c2583ebe Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Thu, 10 Nov 2016 11:36:05 -0500 Subject: [PATCH 3/4] typos --- deploy/nginx.md | 2 +- deploy/supervisor.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/nginx.md b/deploy/nginx.md index 5a4b3864..c2398554 100644 --- a/deploy/nginx.md +++ b/deploy/nginx.md @@ -66,7 +66,7 @@ sudo service nginx restart Nginx can be started an stopped with the `sudo service nginx ...` commands. You will need something similar to start and stop your Vapor server. -There are many ways to do this, and they depend on which platform you are deploying to. Check out the [Supervisor](supervisor.md) instructions to add commands like `sudo start ...` for controller your Vapor app. +There are many ways to do this, and they depend on which platform you are deploying to. Check out the [Supervisor](supervisor.md) instructions to add commands for starting and stopping your Vapor app. ## Configure Proxy diff --git a/deploy/supervisor.md b/deploy/supervisor.md index 0cae4dac..efc3e12c 100644 --- a/deploy/supervisor.md +++ b/deploy/supervisor.md @@ -29,7 +29,7 @@ stderr_logfile=/var/log/supervisor/%(program_name)-stderr.log This assume the `Hello` project is located in the home folder for the user `vapor`. Make sure `directory` points to the root directory of your project where the `Config/` folder is. -The `--env=production` flag is important as it will disable verbose logging and choose the `Config/production` sub folder of your configuration files. +The `--env=production` flag will disable verbose logging and prioritize the `Config/production` sub folder of your configuration files. ### Environment From 12e5b2797adfb65c59a03e528b93090a2ffa77a7 Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Thu, 10 Nov 2016 12:38:22 -0500 Subject: [PATCH 4/4] wording change --- deploy/supervisor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/supervisor.md b/deploy/supervisor.md index efc3e12c..9b3a3a86 100644 --- a/deploy/supervisor.md +++ b/deploy/supervisor.md @@ -27,7 +27,7 @@ stdout_logfile=/var/log/supervisor/%(program_name)-stdout.log stderr_logfile=/var/log/supervisor/%(program_name)-stderr.log ``` -This assume the `Hello` project is located in the home folder for the user `vapor`. Make sure `directory` points to the root directory of your project where the `Config/` folder is. +As specified in our configuration file the `Hello` project is located in the home folder for the user `vapor`. Make sure `directory` points to the root directory of your project where the `Config/` folder is. The `--env=production` flag will disable verbose logging and prioritize the `Config/production` sub folder of your configuration files.