Automatically download OS-specific WebDriver executable
April 20th, 2016
Automatically download and setup OS-specific Webdriver executables.
As part of my home automation kick, I had decided to set up a “login” for my Home Assistant over SSL/TLS, so I could have a secure, reliable connection to my server at all times. With the help of a friend, I was able to use nginx and Let’s Encrypt to accomplish these goals. Although my focus in this post will be on setting up the proxy for Home Assistant on a Pi, it could probably be generalized to other servers as well.
The very first thing you should do is ensure that your router properly forwards requests to your Home Assistant instance. The steps for this process will vary per router, but essentially you’ll want to find a tab named “Port Forwarding” and set it up to forward requests received on port 8123 (later we’ll need to add ports 80 and 443 as well, so you can add those if you want; for debugging purposes, this is a good start). The protocol you should specify is TCP. Once that is done, get your public IP address (ie. type “what is my IP” in a search engine), and try to connect to it followed by the port 8123 (e.g. 1234.567.890:8123). It should take you to your server. If not, ensure Home Assistant is properly started and that your router is forwarding correctly.
Next, it would be nice if we didn’t HAVE to memorize our IP (or magically know if your ISP changed it), so we will register a domain to point at instead. Again, the steps for this vary per registrar, but you want to find a “domain registrar” for a website you want to use, and then create an “A Record” pointed at your WAN IP from earlier. You can typically specify subdomains here too if you want to, or just use ”@” for the host if you want to connect directly (e.g. via “example.com”). Once that’s saved, you should be able to connect to your site followed by the port 8123 (e.g. “example.com:8123”) to hit your server.
Bear in mind that as your IP changes, you may need to update your “A” Record. Some registrars have APIs you can hit, and some routers allow you to configure “Dynamic DNS” entries yourself. Be sure to set something up, as otherwise you may try accessing your site one day and find out it goes nowhere.
Our setup so far is good, but what would really be nice is some authentication to control access to our server. nginx can help us with this.
The first step is to install nginx as well as the apache2-utils we’ll be using later:
sudo apt-get install nginx apache2-utils
If you want to research the general nginx settings and configure them in /etc/nginx/nginx.conf, now would be the time. Otherwise, I’ll continue with the specific ones for our server in a bit.
Next we will set up the login for our server. To do this we run the htpasswd util we fetched earlier, and invoke it with:
sudo htpasswd -c /etc/nginx/.htpasswd
It should then prompt you for a password, which will complete your credentials process. You can use a different path if you want (and even a different file name), I will just assume that is the location for this tutorial.
At this point you have two options. If you have no plans to use SSL and simply want authorization, then you can stop after completing this section. If you want SSL (and only SSL), then you’ll have a different configuration that I’ll detail in the next section. Either way, since we need to set up Let’s Encrypt too, we may as well follow the plain HTTP route to ensure everything works as intended.
Edit your /etc/nginx/sites-enabled/default file to redirect requests received on port 80 to 8123:
sudo nano /etc/nginx/sites-enabled/default
# Add
server {
listen 80;
server_name example.com; # Your site
proxy_buffering off;
location / {
auth_basic "Home Assistant";
auth_basic_user_file /etc/nginx/.htpasswd; # Your .htpasswd file
proxy_pass http://127.0.0.1:8123/; # The server you want to redirect to
proxy_set_header Host $host;
}
}
You can start the server with sudo service nginx start. If you haven’t already, set up port forwarding on your router for port 80 (and 443 if you plan to set up SSL) to point at your nginx server as we did before with port 8123. If this step went well, then you should be able to connect to your site (without any port, e.g. “example.com”), and be prompted with a login. Upon success, it should redirect you to Home Assistant.
Finally, we want the nginx service to start on boot, so we can configure systemctl to do so. Run:
sudo nano /lib/systemd/system/nginx.service
then input something like these instructions.
Finally you’ll need to enable it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="dns-prefetch" href="https://assets-cdn.github.com">
<link rel="dns-prefetch" href="https://avatars0.githubusercontent.com">
<link rel="dns-prefetch" href="https://avatars1.githubusercontent.com">
<link rel="dns-prefetch" href="https://avatars2.githubusercontent.com">
<link rel="dns-prefetch" href="https://avatars3.githubusercontent.com">
<link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
<link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
<link crossorigin="anonymous" media="all" integrity="sha512-FCg44VGg5ax/5MpZ8otwiPE+/tG1/Sq67mKkl6agbqgoScZtJyXhQSFQMIJfOHMZZ+yXDINb8nEiws60SiLohg==" rel="stylesheet" href="https://assets-cdn.github.com/assets/frameworks-5aa6d9885579bb2359f66266aee26f3b.css" />
<link crossorigin="anonymous" media="all" integrity="sha512-+/hqp+gOyKak+oOrmncIDqvw8rgk69e9HtwA/O+2PG25IJgS6L+sciem4Dqu4L77m8UaEYWxYhXeRhxzzaDk3Q==" rel="stylesheet" href="https://assets-cdn.github.com/assets/github-2bf9c5ab90af2104656120603fa7ae6a.css" />
<link crossorigin="anonymous" media="all" integrity="sha512-MCkY7xCBVn707mk61oFcP8d+7twmv0QJIlpv5KvZtBwC7/SBwK0E8KEo1CcC8nxnRkiBtZFrdxhb+ovgrFdTiQ==" rel="stylesheet" href="https://assets-cdn.github.com/assets/site-a9e4b9870c7285a07575dc12a3f5eb9a.css" />
<meta name="viewport" content="width=device-width">
<title>nginx_enable · GitHub</title>
<meta name="description" content="GitHub Gist: instantly share code, notes, and snippets.">
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch-gist.xml" title="Gist">
<link rel="fluid-icon" href="https://gist.github.com/fluidicon.png" title="GitHub">
<meta property="fb:app_id" content="1401488693436528">
<meta property="og:image" content="https://avatars2.githubusercontent.com/u/7275442?s=400&v=4" /><meta property="og:site_name" content="Gist" /><meta property="og:type" content="article" /><meta property="og:title" content="nginx_enable" /><meta property="og:url" content="https://gist.github.com/ishults/882e3cc76b616b292faaca40877d1672" /><meta property="og:description" content="GitHub Gist: instantly share code, notes, and snippets." /><meta property="article:author" content="262588213843476" /><meta property="article:publisher" content="262588213843476" />
<link rel="assets" href="https://assets-cdn.github.com/">
<meta name="pjax-timeout" content="1000">
<meta name="request-id" content="763C:20C7:237FDE:2EAC00:5BC11E32" data-pjax-transient>
<meta name="selected-link" value="gist_code" data-pjax-transient>
<meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU">
<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA">
<meta name="google-site-verification" content="GXs5KoUUkNCoaAZn7wPN-t01Pywp9M3sEjnt_3_ZWPc">
<meta name="octolytics-host" content="collector.githubapp.com" /><meta name="octolytics-app-id" content="gist" /><meta name="octolytics-event-url" content="https://collector.githubapp.com/github-external/browser_event" /><meta name="octolytics-dimension-request_id" content="763C:20C7:237FDE:2EAC00:5BC11E32" /><meta name="octolytics-dimension-region_edge" content="iad" /><meta name="octolytics-dimension-region_render" content="iad" />
<meta name="analytics-location" content="/<user-name>/<gist-id>" data-pjax-transient="true" />
<meta name="google-analytics" content="UA-3769691-4">
<meta class="js-ga-set" name="dimension1" content="Logged Out">
<meta name="octolytics-dimension-public" content="true" /><meta name="octolytics-dimension-gist_id" content="35978607" /><meta name="octolytics-dimension-gist_name" content="882e3cc76b616b292faaca40877d1672" /><meta name="octolytics-dimension-anonymous" content="false" /><meta name="octolytics-dimension-owner_id" content="7275442" /><meta name="octolytics-dimension-owner_login" content="ishults" /><meta name="octolytics-dimension-forked" content="false" />
<meta class="js-ga-set" name="dimension5" content="public">
<meta class="js-ga-set" name="dimension6" content="owned">
<meta class="js-ga-set" name="dimension7" content="unknown">
<meta name="hostname" content="gist.github.com">
<meta name="user-login" content="">
<meta name="expected-hostname" content="gist.github.com">
<meta name="js-proxy-site-detection-payload" content="M2VkMTgzZDUzNDMzZGU2MmQ3NzU1M2VhZmYyZTJhMTQzNWRlYjlkODAzNjAxYWFhNzQzY2NkNzAwYzk1YmY0NHx7InJlbW90ZV9hZGRyZXNzIjoiNjYuMzcuMjM5LjE0IiwicmVxdWVzdF9pZCI6Ijc2M0M6MjBDNzoyMzdGREU6MkVBQzAwOjVCQzExRTMyIiwidGltZXN0YW1wIjoxNTM5MzgyODM1LCJob3N0IjoiZ2l0aHViLmNvbSJ9">
<meta name="enabled-features" content="DASHBOARD_V2_LAYOUT_OPT_IN,EXPLORE_DISCOVER_REPOSITORIES,UNIVERSE_BANNER,MARKETPLACE_PLAN_RESTRICTION_EDITOR,ISSUE_AND_PR_HOVERCARDS">
<meta name="html-safe-nonce" content="495a38d7bcef7202a9856ab044a35af27e6ba224">
<meta http-equiv="x-pjax-version" content="2445a9d8f1e3921e095f7142cee041b8">
<link href="/ishults.atom" rel="alternate" title="atom" type="application/atom+xml">
<link crossorigin="anonymous" media="all" integrity="sha512-276lVvjrO9uBs1FU7UaGaOySkNYW4LhdI4LPaMoFqvQjbhTqL3//QQFhhnMAJ/o/gChwAx2/qW9lirb4A85Gyw==" rel="stylesheet" href="https://assets-cdn.github.com/assets/gist-505186e2d729df6ac70c50c7e8754dbb.css" />
<meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">
<meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">
<link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#000000">
<link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://assets-cdn.github.com/favicon.ico">
<meta name="theme-color" content="#1e2327">
</head>
<body class="logged-out env-production">
<div class="position-relative js-header-wrapper ">
<a href="#start-of-content" tabindex="1" class="px-2 py-4 bg-blue text-white show-on-focus js-skip-to-content">Skip to content</a>
<div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div>
<div class="Header gist-header header-logged-out" role="banner">
<div class="container-lg px-3 clearfix">
<div class="d-flex flex-justify-between">
<div class="d-flex">
<a class="header-logo-wordmark" data-hotkey="g d" aria-label="Gist Homepage" href="/">
<svg width="78" height="28" class="octicon octicon-logo-github" viewBox="0 0 45 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M18.53 12.03h-.02c.009 0 .015.01.024.011h.006l-.01-.01zm.004.011c-.093.001-.327.05-.574.05-.78 0-1.05-.36-1.05-.83V8.13h1.59c.09 0 .16-.08.16-.19v-1.7c0-.09-.08-.17-.16-.17h-1.59V3.96c0-.08-.05-.13-.14-.13h-2.16c-.09 0-.14.05-.14.13v2.17s-1.09.27-1.16.28c-.08.02-.13.09-.13.17v1.36c0 .11.08.19.17.19h1.11v3.28c0 2.44 1.7 2.69 2.86 2.69.53 0 1.17-.17 1.27-.22.06-.02.09-.09.09-.16v-1.5a.177.177 0 0 0-.146-.18zm23.696-2.2c0-1.81-.73-2.05-1.5-1.97-.6.04-1.08.34-1.08.34v3.52s.49.34 1.22.36c1.03.03 1.36-.34 1.36-2.25zm2.43-.16c0 3.43-1.11 4.41-3.05 4.41-1.64 0-2.52-.83-2.52-.83s-.04.46-.09.52c-.03.06-.08.08-.14.08h-1.48c-.1 0-.19-.08-.19-.17l.02-11.11c0-.09.08-.17.17-.17h2.13c.09 0 .17.08.17.17v3.77s.82-.53 2.02-.53l-.01-.02c1.2 0 2.97.45 2.97 3.88zm-8.72-3.61h-2.1c-.11 0-.17.08-.17.19v5.44s-.55.39-1.3.39-.97-.34-.97-1.09V6.25c0-.09-.08-.17-.17-.17h-2.14c-.09 0-.17.08-.17.17v5.11c0 2.2 1.23 2.75 2.92 2.75 1.39 0 2.52-.77 2.52-.77s.05.39.08.45c.02.05.09.09.16.09h1.34c.11 0 .17-.08.17-.17l.02-7.47c0-.09-.08-.17-.19-.17zm-23.7-.01h-2.13c-.09 0-.17.09-.17.2v7.34c0 .2.13.27.3.27h1.92c.2 0 .25-.09.25-.27V6.23c0-.09-.08-.17-.17-.17zm-1.05-3.38c-.77 0-1.38.61-1.38 1.38 0 .77.61 1.38 1.38 1.38.75 0 1.36-.61 1.36-1.38 0-.77-.61-1.38-1.36-1.38zm16.49-.25h-2.11c-.09 0-.17.08-.17.17v4.09h-3.31V2.6c0-.09-.08-.17-.17-.17h-2.13c-.09 0-.17.08-.17.17v11.11c0 .09.09.17.17.17h2.13c.09 0 .17-.08.17-.17V8.96h3.31l-.02 4.75c0 .09.08.17.17.17h2.13c.09 0 .17-.08.17-.17V2.6c0-.09-.08-.17-.17-.17zM8.81 7.35v5.74c0 .04-.01.11-.06.13 0 0-1.25.89-3.31.89-2.49 0-5.44-.78-5.44-5.92S2.58 1.99 5.1 2c2.18 0 3.06.49 3.2.58.04.05.06.09.06.14L7.94 4.5c0 .09-.09.2-.2.17-.36-.11-.9-.33-2.17-.33-1.47 0-3.05.42-3.05 3.73s1.5 3.7 2.58 3.7c.92 0 1.25-.11 1.25-.11v-2.3H4.88c-.11 0-.19-.08-.19-.17V7.35c0-.09.08-.17.19-.17h3.74c.11 0 .19.08.19.17z"/></svg>
<svg width="40" height="28" class="octicon octicon-logo-gist" viewBox="0 0 25 16" version="1.1" aria-hidden="true"><path fill-rule="evenodd" d="M4.7 8.73h2.45v4.02c-.55.27-1.64.34-2.53.34-2.56 0-3.47-2.2-3.47-5.05 0-2.85.91-5.06 3.48-5.06 1.28 0 2.06.23 3.28.73V2.66C7.27 2.33 6.25 2 4.63 2 1.13 2 0 4.69 0 8.03c0 3.34 1.11 6.03 4.63 6.03 1.64 0 2.81-.27 3.59-.64V7.73H4.7v1zm6.39 3.72V6.06h-1.05v6.28c0 1.25.58 1.72 1.72 1.72v-.89c-.48 0-.67-.16-.67-.7v-.02zm.25-8.72c0-.44-.33-.78-.78-.78s-.77.34-.77.78.33.78.77.78.78-.34.78-.78zm4.34 5.69c-1.5-.13-1.78-.48-1.78-1.17 0-.77.33-1.34 1.88-1.34 1.05 0 1.66.16 2.27.36v-.94c-.69-.3-1.52-.39-2.25-.39-2.2 0-2.92 1.2-2.92 2.31 0 1.08.47 1.88 2.73 2.08 1.55.13 1.77.63 1.77 1.34 0 .73-.44 1.42-2.06 1.42-1.11 0-1.86-.19-2.33-.36v.94c.5.2 1.58.39 2.33.39 2.38 0 3.14-1.2 3.14-2.41 0-1.28-.53-2.03-2.75-2.23h-.03zm8.58-2.47v-.86h-2.42v-2.5l-1.08.31v2.11l-1.56.44v.48h1.56v5c0 1.53 1.19 2.13 2.5 2.13.19 0 .52-.02.69-.05v-.89c-.19.03-.41.03-.61.03-.97 0-1.5-.39-1.5-1.34V6.94h2.42v.02-.01z"/></svg>
</a>
<div class="site-search js-site-search" role="search">
<div class="header-search" role="search">
<!-- '"` --><!-- </textarea></xmp> --></option></form><form class="position-relative js-quicksearch-form" action="/search" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="✓" />
<label class="header-search-wrapper form-control js-chromeless-input-container">
<input type="text"
class="form-control js-site-search-focus header-search-input"
data-hotkey="s,/"
name="q"
placeholder="Search…"
autocorrect="off"
autocomplete="off"
autocapitalize="off">
</label>
</form></div>
</div>
<ul class="list-style-none d-flex flex-items-center text-bold pl-2" role="navigation">
<li><a class="HeaderNavlink px-2" data-ga-click="Header, go to all gists, text:all gists" href="/discover">All gists</a></li>
<li><a class="HeaderNavlink px-2" data-ga-click="Header, go to GitHub, text:GitHub" href="https://github.com">GitHub</a></li>
</ul>
</div>
<div class="header-actions" role="navigation">
<a class="btn btn-primary" data-ga-click="Header, sign up" href="/join?source=header-gist">Sign up for a GitHub account</a>
<a class="btn" data-ga-click="Header, sign in" href="https://gist.github.com/auth/github?return_to=https%3A%2F%2Fgist.github.com%2Fishults%2F882e3cc76b616b292faaca40877d1672">Sign in</a>
</div>
</div>
</div>
</div>
</div>
<div id="start-of-content" class="show-on-focus"></div>
<div id="js-flash-container">
</div>
<div role="main" class="application-main ">
<div itemscope itemtype="http://schema.org/Code">
<div id="gist-pjax-container" class="gist-content-wrapper" data-pjax-container>
<div class="gist-detail-intro gist-banner">
<div class="container">
<p class="lead">
Instantly share code, notes, and snippets.
</p>
</div>
</div>
<div class="gisthead pagehead repohead instapaper_ignore readability-menu experiment-repo-nav mb-4">
<div class="container">
<div class="container repohead-details-container">
<ul class="pagehead-actions">
<li>
<a class="btn btn-sm btn-with-count tooltipped tooltipped-n" aria-label="You must be signed in to star a gist" rel="nofollow" href="/login?return_to=https%3A%2F%2Fgist.github.com%2Fishults%2F882e3cc76b616b292faaca40877d1672">
<svg class="octicon octicon-star" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg>
Star
</a>
<a class="social-count" aria-label="0 users starred this gist" href="/ishults/882e3cc76b616b292faaca40877d1672/stargazers">
0
</a>
</li>
<li>
<a class="btn btn-sm btn-with-count tooltipped tooltipped-n" aria-label="You must be signed in to fork a gist" rel="nofollow" href="/login?return_to=https%3A%2F%2Fgist.github.com%2Fishults%2F882e3cc76b616b292faaca40877d1672">
<svg class="octicon octicon-repo-forked" viewBox="0 0 10 16" version="1.1" width="10" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>
Fork
</a>
<a class="social-count" aria-label="0 users forked this gist" href="/ishults/882e3cc76b616b292faaca40877d1672/forks">
0
</a>
</li>
</ul>
<h1 class="public css-truncate">
<img class="avatar gist-avatar" src="https://avatars2.githubusercontent.com/u/7275442?s=52&v=4" width="26" height="26" alt="@ishults" />
<span class="author"><a rel="author" class="url fn" href="/ishults"><span itemprop="author">ishults</span></a></span><!--
--><span class="path-divider">/</span><!--
--><strong itemprop="name" class="gist-header-title css-truncate-target"><a href="/ishults/882e3cc76b616b292faaca40877d1672">nginx_enable</a></strong>
<div class="d-block text-small text-gray">
Created <time-ago datetime="2016-05-22T14:40:40Z">May 22, 2016</time-ago>
</div>
</h1>
</div>
<div class="container gist-file-navigation">
<div class="float-right file-navigation-options" data-multiple>
<div class="file-navigation-option v-align-middle">
<div class="input-group js-gist-share-menu">
<div class="input-group-button">
<details class="details-reset details-overlay select-menu">
<summary class="btn btn-sm select-menu-button" data-ga-click="Repository, clone Embed, location:repo overview">
<span data-menu-button>Embed</span>
</summary>
<details-menu class="select-menu-modal position-absolute" style="z-index: 99;" aria-label="Clone options">
<div class="select-menu-header">
<span class="select-menu-title">What would you like to do?</span>
</div>
<div class="select-menu-list">
<button type="button"
class="select-menu-item width-full"
aria-checked="true"
role="menuitemradio"
tabindex="0"
value="<script src="https://gist.github.com/ishults/882e3cc76b616b292faaca40877d1672.js"></script>">
<svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg>
<div class="select-menu-item-text">
<span class="select-menu-item-heading" data-menu-button-text>
Embed
</span>
<span class="description">
Embed this gist in your website.
</span>
</div>
</button>
<button type="button"
class="select-menu-item width-full"
aria-checked="false"
role="menuitemradio"
tabindex="0"
value="https://gist.github.com/ishults/882e3cc76b616b292faaca40877d1672">
<svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg>
<div class="select-menu-item-text">
<span class="select-menu-item-heading" data-menu-button-text>
Share
</span>
<span class="description">
Copy sharable link for this gist.
</span>
</div>
</button>
<button type="button"
class="select-menu-item width-full"
aria-checked="false"
role="menuitemradio"
tabindex="0"
value="https://gist.github.com/882e3cc76b616b292faaca40877d1672.git">
<svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg>
<div class="select-menu-item-text">
<span class="select-menu-item-heading" data-menu-button-text>
Clone via
HTTPS
</span>
<span class="description">
Clone with Git or checkout with SVN using the repository’s web address.
</span>
</div>
</button>
</div>
<div class="select-menu-list" role="menu">
<a class="select-menu-item select-menu-action" href="https://help.github.com/articles/which-remote-url-should-i-use" target="_blank">
<svg class="octicon octicon-question select-menu-item-icon" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M6 10h2v2H6v-2zm4-3.5C10 8.64 8 9 8 9H6c0-.55.45-1 1-1h.5c.28 0 .5-.22.5-.5v-1c0-.28-.22-.5-.5-.5h-1c-.28 0-.5.22-.5.5V7H4c0-1.5 1.5-3 3-3s3 1 3 2.5zM7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7z"/></svg>
<div class="select-menu-item-text">
Learn more about clone URLs
</div>
</a>
</div>
</details-menu>
</details>
</div>
<input
id="gist-share-url"
type="text"
data-autoselect
class="form-control input-monospace input-sm"
value="<script src="https://gist.github.com/ishults/882e3cc76b616b292faaca40877d1672.js"></script>"
aria-label="Clone this repository at <script src="https://gist.github.com/ishults/882e3cc76b616b292faaca40877d1672.js"></script>"
readonly>
<div class="input-group-button">
<clipboard-copy for="gist-share-url" aria-label="Copy to clipboard" class="btn btn-sm zeroclipboard-button">
<svg class="octicon octicon-clippy" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3 3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H3c-.55 0-1 .45-1 1z"/></svg>
</clipboard-copy>
</div>
</div>
</div>
<div class="file-navigation-option">
</div>
<div class="file-navigation-option">
<a href="/ishults/882e3cc76b616b292faaca40877d1672/archive/98706997e570dbaeeb8b1fde0c3819bafdd4e1c2.zip"
class="btn btn-sm"
rel="nofollow"
data-ga-click="Gist, download zip, location:gist overview">
Download ZIP
</a>
</div>
</div>
<div class="float-left">
<nav class="reponav js-repo-nav js-sidenav-container-pjax"
role="navigation"
data-pjax="#gist-pjax-container">
<a class="js-selected-navigation-item selected reponav-item" aria-label="Code" data-pjax="true" data-hotkey="g c" data-selected-links="gist_code /ishults/882e3cc76b616b292faaca40877d1672" href="/ishults/882e3cc76b616b292faaca40877d1672">
<svg class="octicon octicon-code" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg>
Code
</a>
<a class="js-selected-navigation-item reponav-item" aria-label="Revisions" data-pjax="true" data-hotkey="g r" data-selected-links="gist_revisions /ishults/882e3cc76b616b292faaca40877d1672/revisions" href="/ishults/882e3cc76b616b292faaca40877d1672/revisions">
<svg class="octicon octicon-git-commit" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M10.86 7c-.45-1.72-2-3-3.86-3-1.86 0-3.41 1.28-3.86 3H0v2h3.14c.45 1.72 2 3 3.86 3 1.86 0 3.41-1.28 3.86-3H14V7h-3.14zM7 10.2c-1.22 0-2.2-.98-2.2-2.2 0-1.22.98-2.2 2.2-2.2 1.22 0 2.2.98 2.2 2.2 0 1.22-.98 2.2-2.2 2.2z"/></svg>
Revisions
<span class="Counter">1</span>
</a>
</nav>
</div>
</div>
</div>
</div>
<div class="container new-discussion-timeline experiment-repo-nav">
<div class="repository-content gist-content">
<div>
<div class="js-gist-file-update-container js-task-list-container file-box">
<div id="file-nginx_enable" class="file">
<div class="file-header">
<div class="file-actions">
<a class="btn btn-sm " href="/ishults/882e3cc76b616b292faaca40877d1672/raw/98706997e570dbaeeb8b1fde0c3819bafdd4e1c2/nginx_enable">Raw</a>
</div>
<div class="file-info">
<span class="icon">
<svg class="octicon octicon-gist" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.5 5L10 7.5 7.5 10l-.75-.75L8.5 7.5 6.75 5.75 7.5 5zm-3 0L2 7.5 4.5 10l.75-.75L3.5 7.5l1.75-1.75L4.5 5zM0 13V2c0-.55.45-1 1-1h10c.55 0 1 .45 1 1v11c0 .55-.45 1-1 1H1c-.55 0-1-.45-1-1zm1 0h10V2H1v11z"/></svg>
</span>
<a class="tooltipped tooltipped-s css-truncate" aria-label="Permalink" href="#file-nginx_enable">
<strong class="user-select-contain gist-blob-name css-truncate-target">
nginx_enable
</strong>
</a>
</div>
</div>
<div itemprop="text" class="blob-wrapper data type-text ">
<table class="highlight tab-size js-file-line-container" data-tab-size="8">
<tr>
<td id="file-nginx_enable-L1" class="blob-num js-line-number" data-line-number="1"></td>
<td id="file-nginx_enable-LC1" class="blob-code blob-code-inner js-file-line">sudo chmod +x /lib/systemd/system/nginx.service</td>
</tr>
<tr>
<td id="file-nginx_enable-L2" class="blob-num js-line-number" data-line-number="2"></td>
<td id="file-nginx_enable-LC2" class="blob-code blob-code-inner js-file-line">sudo systemctl --system daemon-reload</td>
</tr>
<tr>
<td id="file-nginx_enable-L3" class="blob-num js-line-number" data-line-number="3"></td>
<td id="file-nginx_enable-LC3" class="blob-code blob-code-inner js-file-line">sudo systemctl enable nginx</td>
</tr>
<tr>
<td id="file-nginx_enable-L4" class="blob-num js-line-number" data-line-number="4"></td>
<td id="file-nginx_enable-LC4" class="blob-code blob-code-inner js-file-line">sudo systemctl start nginx</td>
</tr>
</table>
</div>
</div>
</div>
<a name="comments"></a>
<div class="discussion-timeline gist-discussion-timeline js-quote-selection-container" data-quote-markdown=".js-comment-body">
<div class="js-discussion js-socket-channel" data-channel="marked-as-read:gist:35978607">
<!-- Rendered timeline since 2016-05-22 07:40:40 -->
<div id="partial-timeline-marker"
class="js-timeline-marker js-updatable-content"
data-url="/ishults/882e3cc76b616b292faaca40877d1672/show_partial?partial=gist%2Ftimeline_marker&since=1463928040"
data-last-modified="Sun, 22 May 2016 14:40:40 GMT"
>
</div>
<div class="discussion-timeline-actions">
<div class="flash flash-warn mt-3">
<a rel="nofollow" class="btn btn-primary" href="/join?source=comment-gist">Sign up for free</a>
<strong>to join this conversation on GitHub</strong>.
Already have an account?
<a rel="nofollow" href="/login?return_to=https%3A%2F%2Fgist.github.com%2Fishults%2F882e3cc76b616b292faaca40877d1672">Sign in to comment</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-backdrop js-touch-events"></div>
</div><!-- /.container -->
</div>
</div>
</div>
<div class="footer container-lg px-3" role="contentinfo">
<div class="position-relative d-flex flex-justify-between pt-6 pb-2 mt-6 f6 text-gray border-top border-gray-light ">
<ul class="list-style-none d-flex flex-wrap ">
<li class="mr-3">© 2018 <span title="0.20048s from unicorn-85cc65849d-h9fbn">GitHub</span>, Inc.</li>
<li class="mr-3"><a data-ga-click="Footer, go to terms, text:terms" href="https://github.com/site/terms">Terms</a></li>
<li class="mr-3"><a data-ga-click="Footer, go to privacy, text:privacy" href="https://github.com/site/privacy">Privacy</a></li>
<li class="mr-3"><a href="https://help.github.com/articles/github-security/" data-ga-click="Footer, go to security, text:security">Security</a></li>
<li class="mr-3"><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>
<li><a data-ga-click="Footer, go to help, text:help" href="https://help.github.com">Help</a></li>
</ul>
<a aria-label="Homepage" title="GitHub" class="footer-octicon mr-lg-4" href="https://github.com">
<svg height="24" class="octicon octicon-mark-github" viewBox="0 0 16 16" version="1.1" width="24" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
</a>
<ul class="list-style-none d-flex flex-wrap ">
<li class="mr-3"><a data-ga-click="Footer, go to contact, text:contact" href="https://github.com/contact">Contact GitHub</a></li>
<li class="mr-3"><a href="https://github.com/pricing" data-ga-click="Footer, go to Pricing, text:Pricing">Pricing</a></li>
<li class="mr-3"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>
<li class="mr-3"><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>
<li class="mr-3"><a href="https://blog.github.com" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>
<li><a data-ga-click="Footer, go to about, text:about" href="https://github.com/about">About</a></li>
</ul>
</div>
<div class="d-flex flex-justify-center pb-6">
<span class="f6 text-gray-light"></span>
</div>
</div>
<div id="ajax-error-message" class="ajax-error-message flash flash-error">
<svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg>
<button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
<svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg>
</button>
You can’t perform that action at this time.
</div>
<script crossorigin="anonymous" integrity="sha512-mal0oz3cFcr4OqIE2eo7Pmax6HtpOKvQfO4vqg9JuCb+iaf4H3KUP9Aryp4oP5mSMgEYUOwgBOAL6MTFaeCZ3w==" type="application/javascript" src="https://assets-cdn.github.com/assets/compat-3c69a4d015c4208bce7a9d5e4e15a914.js"></script>
<script crossorigin="anonymous" integrity="sha512-MvNlmXbTAwL0N0zMxw8W6vtjWLf0QFvwVzvN8rZIJNdzFy9OJp2d4LQD9WA2rDNcHewz0PB9x/0G0Z9FOuUWgw==" type="application/javascript" src="https://assets-cdn.github.com/assets/frameworks-a2f69f341e3df821fdcb56e335ef9920.js"></script>
<script crossorigin="anonymous" async="async" integrity="sha512-ixxvBZF3eRHUBFtQhqjNyIJRouOkAqo1Glgy607wMwbpAT1Gu/1tGo5impwGiQi9DBWBeaXnVFEXmNTyPZjT3g==" type="application/javascript" src="https://assets-cdn.github.com/assets/github-1f0ca6fc0ad418e21430c85ad0f2544d.js"></script>
<script crossorigin="anonymous" async="async" integrity="sha512-pDH1ZzO4cV08egBZ18KFQ589QjcqrWIe2pM6xAABlDIgd2t0HXka9z0HdY6zcUJ3Ke7AO0+c7zhw1cUWesO2Nw==" type="application/javascript" src="https://assets-cdn.github.com/assets/gist-ba2ec4a0592f8faa0e81337df057841e.js"></script>
<div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none">
<svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg>
<span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>
<span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>
</div>
<div class="facebox" id="facebox" style="display:none;">
<div class="facebox-popup">
<div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">
</div>
<button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">
<svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg>
</button>
</div>
</div>
<template id="site-details-dialog">
<details class="details-reset details-overlay details-overlay-dark lh-default text-gray-dark" open>
<summary aria-haspopup="dialog" aria-label="Close dialog"></summary>
<details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast">
<button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog>
<svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg>
</button>
<div class="octocat-spinner my-6 js-details-dialog-spinner"></div>
</details-dialog>
</details>
</template>
<div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;" tabindex="0">
<div class="Popover-message Popover-message--bottom-left Popover-message--large Box box-shadow-large" style="width:360px;">
</div>
</div>
<div id="hovercard-aria-description" class="sr-only">
Press h to open a hovercard with more details.
</div>
</body>
</html>
Now if you reboot your machine, your nginx server should automatically start up.
Just a couple weeks ago, EFF came out with a nice update to its Let’s Encrypt client called “certbot” that has simple instructions to create certs for your website. For completion’s sake I will include the steps I followed, but I would highly recommend checking out the site if you need more info.
The first step here is to add backports to our apt-get sources list. If you’re running a Pi 3 on Jessie, you can do this via:
sudo nano /etc/apt/sources.list
# Add
deb http://ftp.debian.org/debian jessie-backports main
Then run an update and install the client:
sudo apt-get update
sudo apt-get install letsencrypt -t jessie-backports
Finally, you can run the client by calling:
letsencrypt certonly
and following the instructions on the screen (I’m running a standalone server which is option 2 from the initial list). When it’s done, you should see a message specifying the path to your keys. Take note of those as we’ll need them in a bit. In the meantime, you should add a cron job to update your keys, as they expire after 90 days. The EFF suggests twice daily updating on “random” minutes, so we can do something like:
crontab -e
# Add this. x is the minute of renewal, while y and z are the hours.
# You can (should) move the command into a script and run that.
x y,z * * * sudo service nginx stop && letsencrypt renew --quiet && sudo service nginx start
Now go back to your nginx configuration (/etc/nginx/sites-enabled/default) and make your requests go over SSL/TLS. Be sure to replace “example.com” with your site:
server {
listen 80;
server_name example.com; # Your site
rewrite ^ https://$host$request_uri permanent;
}
server {
listen 443 default_server ssl;
server_name example.com; # Your site
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # The key location from earlier
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # The key location from earlier
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
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_cache shared:SSL:1m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
location / {
auth_basic "Home Assistant";
auth_basic_user_file /etc/nginx/.htpasswd; # Your .htpasswd file
proxy_pass http://127.0.0.1:8123/; # The server you want to redirect to
proxy_set_header Host $host;
}
}
Restart the nginx service with sudo service nginx restart and try to hit your site again. If everything went well, then any requests to (for instance) ”http://example.com” should be redirected to ”https://example.com”, prompted with a login, and finally redirect to your Home Assistant server. Now you have a secure server to monitor your home automation site any time you want!
Igor Shults
Automatically download and setup OS-specific Webdriver executables.
A guide to set up a Raspberry Pi 3 with Home Assistant
Google has been updating their APIs to require OAuth 2.0. One of our clients makes considerable use of the Google Webmaster Tools APIs instrumented for 14,629 individual websites (and growing). I recently had the opportunity to help this client…
Igor is a self-driven developer with a desire to apply and expand his current skill set. He has experience working with companies of all sizes on the whole application stack, from the database to the front-end. He enjoys working in collaborative environments involving discussion and planning around data modeling and product development.