{"id":27186,"date":"2018-10-30T06:54:39","date_gmt":"2018-10-29T21:54:39","guid":{"rendered":"https:\/\/jirak.net\/wp\/nginx-unit-now-supports-tls-and-javascript-apps-with-node-js\/"},"modified":"2018-10-30T07:34:38","modified_gmt":"2018-10-29T22:34:38","slug":"nginx-unit-now-supports-tls-and-javascript-apps-with-node-js","status":"publish","type":"post","link":"https:\/\/jirak.net\/wp\/nginx-unit-now-supports-tls-and-javascript-apps-with-node-js\/","title":{"rendered":"NGINX Unit Now Supports TLS and JavaScript Apps with Node.js"},"content":{"rendered":"<p>NGINX Unit Now Supports TLS and JavaScript Apps with Node.js<\/p>\n<p>.ngx_blockquote {<br \/>\n    color: #009639;<br \/>\n    font-size: 25px;<br \/>\n    line-height: 35px;<br \/>\n    font-family: Roboto;<br \/>\n    font-style: italic;<br \/>\n    position: relative;<br \/>\n    padding-left: 30pt;<br \/>\n    padding-right: 30pt;<br \/>\n}<\/p>\n<p>When our engineering team showed me the initial code for TLS support a few weeks ago, I blocked off a few hours to get through the configuration and set&#8209;up steps. It turned out to be so easy, I finished in about half an hour.<\/p>\n<p>On <span>September 20, 2018<\/span>, we released <span>NGINX Unit 1.4<\/span>, adding TLS support, certificate storage, and the new <strong>\/config<\/strong> URL path for configuration objects. In <span>NGINX Unit 1.5<\/span>, released on October&nbsp;25, we add support for Node.js applications. Take a look at the complete change list at <a target=\"_blank\" href=\"https:\/\/unit.nginx.org\/CHANGES.txt\"><strong>https:\/\/unit.nginx.org\/CHANGES.txt<\/strong><\/a>.<\/p>\n<p>In this post we cover the configuration of <a href=\"#tls\">TLS certificates<\/a> and <a href=\"#node-js\">Node.js applications<\/a> in detail.<\/p>\n<h2 id=\"tls\">Dynamic Configuration of SSL\/TLS Certificates<\/h2>\n<p>Security and encryption is a must for every production application. Application connectivity today requires proper and rapid configuration and reconfiguration. For applications of a more dynamic nature, constant changes to their connectivity and security certificates are common.<\/p>\n<p>NGINX&nbsp;Unit is configured on the fly, without relying on static configuration files and requiring process reloads. Now we extend this philosophy to TLS certificates as well. With NGINX&nbsp;Unit, you can upload certificates, apply them to or remove them from listeners, and replace old certificates&nbsp;&ndash; all dynamically, with zero downtime and no changes to the application processes.<\/p>\n<p>Besides quick and easy configuration, use of TLS with NGINX&nbsp;Unit relieves Go and Node.js engineers from the burden of implementing encryption in the application code itself. Now all apps, including Go and Node.js, can be deployed into a larger production environment faster, more safely, and with no downtime.<\/p>\n<p class=\"ngx_blockquote\">With NGINX&nbsp;Unit, you can add, change, and remove certificates without reloading application processes<\/p>\n<p>The following example of the initial control API response from <span>NGINX Unit 1.5<\/span> shows that there is now a <code>certificates<\/code> object in addition to the existing configuration structure with listener and application objects:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">curl --unix-socket \/run\/control.unit.sock http:\/\/localhost\/<\/span>\r\n{\r\n      \"certificates\": {},\r\n      \"config\": {\r\n            \"listeners\": {},\r\n            \"applications\": {}\r\n      }\r\n}<\/code><\/pre>\n<p>Certificates and keys are represented in a different format from other configuration objects in the API: we upload them to the certificate store in PEM format as the body of a <code>PUT<\/code> request.<\/p>\n<p class=\"ngx_blockquote\">You upload certificates and keys to the certificate store in PEM format as the body of a PUT request<\/p>\n<h3>Generating a Certificate<\/h3>\n<p>To try this out with a simple self&#8209;signed certificate, we first run this command to generate one:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">openssl req -x509 -subj \/CN=localhost -days 365 -set_serial 2 -newkey rsa:4096 -keyout cert.key -nodes -out cert.pem<\/span><\/code><\/pre>\n<p>Notice that we placed the certificate and the key in separate files. Let\u2019s combine them:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">cat cert.key cert.pem &gt; chain.pem<\/span><\/code><\/pre>\n<p>For a production environment, it&#8217;s a best practice to obtain a full certificate chain from a provider such as <a target=\"_blank\" href=\"https:\/\/letsencrypt.org\/\">Let&#8217;s Encrypt<\/a>. The resulting file looks similar to this:<\/p>\n<pre><code class=\"config\">-----BEGIN CERTIFICATE-----\r\nMIIDHDCCAgQCCQCVgasbCyT1BjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJV\r\n...\r\nvyYJp0qUWRWeYm1CTZaudpR74cZVhz\/RKGFfXkK2bD6Vv8uHI0hbK0p3KlKZ333j\r\nkMSJ9yD+dF9quUbvS9yJUEHcF+96ZcmFVGRnwvnwXUE=\r\n-----END CERTIFICATE-----\r\n-----BEGIN RSA PRIVATE KEY-----\r\nMIIEpAIBAAKCAQEAqb8VkMnAKqqIERHwNklelCE6gzfMd99yX+YoeerB9QVKZkx\/\r\n...\r\nqhtqYRlezYQOUbMGAsREtKqZCn+urL8Bql2IbPQ9vwSfioxNUNyHod+2E\/JDoEF8\r\nOzsBSkR8H7NcSaHCbZCMKtIvGZGM4ODRqP484\/KiXpqjhq8BOtTKJA==\r\n-----END RSA PRIVATE KEY-----<\/code><\/pre>\n<p>If we have intermediate certificates or a CA certificate (or both), we concatenate them with the certificate and key as well.<\/p>\n<h3>Uploading a Certificate Chain<\/h3>\n<p>Then we upload the entire chain via the <span>NGINX Unit API<\/span>. You can use any HTTP tool to upload certificates and update the configuration. Here, we use <code>curl<\/code>:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">curl -X PUT --data-binary @path\/to\/chain.pem --unix-socket \/run\/control.unit.sock 'http:\/\/localhost\/certificates\/mychain'<\/span><\/code><\/pre>\n<p>This creates a new chain that we can check out at the <strong>\/certificates\/mychain<\/strong> URL path. In our self&#8209;signed certificate example, the configuration looks like this:<\/p>\n<pre><code class=\"config\">{\r\n      \"key\": \"RSA (4096 bits)\",\r\n      \"chain\": [\r\n            {\r\n                  \"subject\": {\r\n                        \"common_name\": \"localhost\"\r\n                  },\r\n\r\n                  \"issuer\": {\r\n                        \"common_name\": \"localhost\"\r\n                  },\r\n\r\n                  \"validity\": {\r\n                        \"since\": \"Oct 25 18:59:18 2018 GMT\",\r\n                        \"until\": \"Oct 25 18:59:18 2019 GMT\"\r\n                  }\r\n            }\r\n      ]\r\n}<\/code><\/pre>\n<h3>Applying the Certificate to a Listener<\/h3>\n<p>Now we apply the newly created certificate to a listener&nbsp;&ndash; either an existing one or one created by the command&nbsp;&ndash; by including a <code>tls<\/code> object with the <code>certificate<\/code> parameter in the listener&#8217;s configuration:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">curl -X PUT --data-binary '{\"application\":\"myapp\",\"tls\":{\"certificate\":\"mychain\"}}' --unix-socket \/run\/control.unit.sock 'http:\/\/localhost\/config\/listeners\/*:8043'<\/span><\/code><\/pre>\n<p>A listener configuration with the new <code>tls<\/code> object results:<\/p>\n<pre><code class=\"config\">\"*:8043\": {\r\n      \"application\": \"myapp\",\r\n      \"tls\": {\r\n            \"certificate\":\"mychain\"\r\n      }\r\n}<\/code><\/pre>\n<p>To summarize, the full configuration of a TLS&#8209;enabled application is as follows:<\/p>\n<pre class=\"scrollable jq_custom_scroll_dark\"><code class=\"config\">{\r\n      \"certificates\": {\r\n            \"mychain\": {\r\n                  \"key\": \"RSA (4096 bits)\",\r\n                  \"chain\": [\r\n                        {\r\n                              \"subject\": {\r\n                                    \"common_name\": \"localhost\"\r\n                              },\r\n\r\n                              \"issuer\": {\r\n                                    \"common_name\": \"localhost\"\r\n                              },\r\n\r\n                              \"validity\": {\r\n                                    \"since\": \"Oct 25 18:59:18 2018 GMT\",\r\n                                    \"until\": \"Oct 25 18:59:18 2019 GMT\"\r\n                              }\r\n                        }\r\n                  ]\r\n            }\r\n      },\r\n\r\n      \"config\": {\r\n            \"settings\": {},\r\n            \"listeners\": {\r\n                  \"*:8043\": {\r\n                        \"application\": \"myapp\",\r\n                        \"tls\": {\r\n                              \"certificate\":\"mychain\"\r\n                        }\r\n\r\n                  }\r\n            },\r\n\r\n            \"applications\": {\r\n                  \"myapp\": {\r\n                        \"type\": \"php\",\r\n                        \"root\": \"\/path\/to\/php\",\r\n                        \"script\": \"index.php\"\r\n                  }\r\n            }\r\n      }\r\n}<\/code><\/pre>\n<p>Learn more about configuring TLS with NGINX&nbsp;Unit at <a target=\"_blank\" href=\"https:\/\/unit.nginx.org\/configuration\/#ssl-tls-and-certificates\"><strong>https:\/\/unit.nginx.org\/configuration\/#ssl-tls-and-certificates<\/strong><\/a>.<\/p>\n<h2 id=\"node-js\">Support for Node.js Applications<\/h2>\n<p><span>NGINX Unit 1.5<\/span> adds Node.js (JavaScript) to the set of languages we support.<\/p>\n<p>Node.js and Go apps are similar in that you essentially create your own server when you build an application. The application is launched as a separate process&nbsp;&ndash; either directly or through a process manager. <\/p>\n<p>In many environments, NGINX (or another load balancer) is placed in front of Node.js and Go apps.  This additional software often complicates the environment. With NGINX&nbsp;Unit, you can configure this functionality using just one software server through one consistent and easy&#8209;to&#8209;use API.<\/p>\n<p>Here are two examples, in Go and Node.js respectively:<\/p>\n<pre><code class=\"config\">http.ListenAndServe(\":8000\", nil)<\/code><\/pre>\n<pre><code class=\"config\">var http = require('http');\r\nhttp.createServer(function (req, res) {\r\n\/\/ ...\r\n}).listen(8080);<\/code><\/pre>\n<h3>Installing the <code>unit&#8209;http<\/code> Package<\/h3>\n<p>To run a Node.js application in NGINX&nbsp;Unit, we add a special package (module) so the external runtime can communicate with NGINX&nbsp;Unit&#8217;s router process instead of listening on a port directly. NGINX&nbsp;Unit launches the app and communicates with it through shared memory. To reflect this difference from other app types, we have elevated our concept of these apps to a higher level, referring to them as <span><code>\"type\":<\/code> <code>\"external\"<\/code><\/span>.<\/p>\n<p>For Node.js, the relevant package is called <span style=\"font-weight:bold\">unit-http<\/span>, and it&#8217;s now available on NPM at <a target=\"_blank\" href=\"https:\/\/www.npmjs.com\/package\/unit-http\"><strong>https:\/\/www.npmjs.com\/package\/unit-http<\/strong><\/a>.<\/p>\n<p>After installing NGINX&nbsp;Unit, we first install the prerequisite <span style=\"font-weight:bold\">unit-dev<\/span> package (the command shown is for Debian and Ubuntu systems), and then use NPM to install the <span style=\"font-weight:bold\">unit-http<\/span> package:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">apt-get install unit-dev\r\nnpm install unit-http<\/span><\/code><\/pre>\n<p>We then make two changes to the code for our Node.js app:<\/p>\n<ul>\n<li>We make it executable by adding a line at the top of the file with the shebang (<code>#!<\/code>) followed by the path to the launcher. (We also run the <span><code>chmod<\/code> <code>+x<\/code><\/span> shell command on the file.)<\/li>\n<li>We change the required package from <code>http<\/code> to <span><code>unit-http<\/code><\/span>.<\/li>\n<\/ul>\n<p>Here a simple &#8220;Hello World&#8221; application with the two changes:<\/p>\n<pre><code class=\"config\"><strong>#!\/usr\/bin\/env node<\/strong>\r\nvar unit = require('<strong>unit-http<\/strong>');\r\nvar server = unit.createServer(function(request, response) {\r\n    response.writeHead(200, {\"Content-Type\": \"text\/html\"});\r\n    response.end(\"Read more at unit.nginx.org\");\r\n\r\n});\r\nserver.listen();<\/code><\/pre>\n<h3>Configuring the App in NGINX&nbsp;Unit<\/h3>\n<p>We add the app to NGINX&nbsp;Unit via the control API, in the same way as for a Go application. A minimal application configuration looks like this:<\/p>\n<pre><code class=\"config\">\"mynodeapp\": {\r\n      \"type\": \"external\",\r\n      \"executable\": \"\/path\/to\/app.js\"\r\n}<\/code><\/pre>\n<p>To add this configuration code with the <span>NGINX Unit API<\/span>, we run:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">curl -X PUT --data-binary '{\"type\":\"external\", \"executable\":\"\/path\/to\/app.js\"}' --unix-socket \/run\/control.unit.sock 'http:\/\/localhost\/config\/applications\/mynodeapp'<\/span><\/code><\/pre>\n<p>We can now reference this application in a listener object&nbsp;&ndash; either an existing one, or a new one created by the command:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">curl -X PUT --data-binary '{\"application\":\"mynodeapp\"}' --unix-socket \/run\/control.unit.sock 'http:\/\/localhost\/config\/listeners\/*:8071'<\/span><\/code><\/pre>\n<p>When we have the Node.js app configured, we can scale it up with NGINX&nbsp;Unit&#8217;s dynamic process management to increase performance:<\/p>\n<pre><code class=\"terminal\"><span style=\"color:#66ff99;font-weight: bold\">curl -X PUT --data-binary '{\"max\":10, \"spare\":5}' --unix-socket \/run\/control.unit.sock 'http:\/\/localhost\/config\/applications\/mynodeapp\/processes'<\/span><\/code><\/pre>\n<p>The complete configuration looks like the following:<\/p>\n<pre><code class=\"config\">{\r\n      \"settings\": {},\r\n      \"listeners\": {\r\n            \"*:8071\": {\r\n                  \"application\": \"mynodeapp\"\r\n            }\r\n      },\r\n\r\n      \"applications\": {\r\n            \"mynodeapp\": {\r\n                  \"type\": \"external\",\r\n                  \"executable\": \"\/path\/to\/app.js\",\r\n                  \"processes\": {\r\n                        \"max\": 10,\r\n                        \"spare\": 5\r\n                  }\r\n            }\r\n      }\r\n}<\/code><\/pre>\n<p>For more information on configuring Node.js with NGINX&nbsp;Unit, see <a target=\"_blank\" href=\"https:\/\/unit.nginx.org\/configuration#go-node-js-applications\"><strong>https:\/\/unit.nginx.org\/configuration#go-node-js-applications<\/strong><\/a>.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this blog post, we reviewed the latest features of <span>NGINX Unit 1.4<\/span> and&nbsp;1.5, configured encryption with SSL\/TLS for an existing application, and showed how to add a Node.js app to the NGINX&nbsp;Unit configuration.<\/p>\n<p>Learn more about configuring NGINX&nbsp;Unit at <a target=\"_blank\" href=\"https:\/\/unit.nginx.org\/configuration\/\"><strong>unit.nginx.org<\/strong><\/a>.<\/p>\n<p>The post <a rel=\"nofollow\" href=\"https:\/\/www.nginx.com\/blog\/nginx-unit-1-5-available-now\/\">NGINX Unit Now Supports TLS and JavaScript Apps with Node.js<\/a> appeared first on <a rel=\"nofollow\" href=\"https:\/\/www.nginx.com\">NGINX<\/a>.<\/p>\n<p>Source: <a href=\"https:\/\/www.nginx.com\/blog\/nginx-unit-1-5-available-now\/\" target=\"_blank\">NGINX Unit Now Supports TLS and JavaScript Apps with Node.js<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>NGINX Unit Now Supports TLS and JavaScript Apps with Node.js .ngx_blockquote { color: #009639; font-size: 25px; line-height: 35px; font-family: Roboto; font-style: italic; position: relative; padding-left: 30pt; padding-right: 30pt; } When our engineering team showed me the initial code for TLS support a few weeks ago, I blocked off a few hours to get through the configuration and set&#8209;up steps. It turned out to be so easy, I finished in about half an hour. On September 20, 2018, we released NGINX Unit 1.4, adding TLS support, certificate storage, and the new \/config URL path for configuration objects. In NGINX Unit 1.5, released on October&nbsp;25, we add support for Node.js applications. Take a look at the complete change list at https:\/\/unit.nginx.org\/CHANGES.txt. In this post we cover the configuration of TLS certificates and Node.js applications in detail. Dynamic Configuration of SSL\/TLS Certificates Security <a class=\"mh-excerpt-more\" href=\"https:\/\/jirak.net\/wp\/nginx-unit-now-supports-tls-and-javascript-apps-with-node-js\/\" title=\"NGINX Unit Now Supports TLS and JavaScript Apps with Node.js\">[ more&#8230; ]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[169],"tags":[652],"class_list":["post-27186","post","type-post","status-publish","format-standard","hentry","category-news","tag-nginx"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts\/27186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/comments?post=27186"}],"version-history":[{"count":1,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts\/27186\/revisions"}],"predecessor-version":[{"id":27187,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts\/27186\/revisions\/27187"}],"wp:attachment":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/media?parent=27186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/categories?post=27186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/tags?post=27186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}