{
  "version": "https://jsonfeed.org/version/1",
  "title": "Tim Gaudette (iamtjg)",
  "home_page_url": "https://iamtjg.name/",
  "feed_url": "https://iamtjg.name/feed/feed.json",
  "description": "web developer | cynical idealist",
  "author": {
    "name": "Tim Gaudette",
    "url": "https://iamtjg.name/about/"
  },
  "items": [{
      "id": "https://iamtjg.name/posts/acronyms-suck/",
      "url": "https://iamtjg.name/posts/acronyms-suck/",
      "title": "Acronyms Suck",
      "content_html": "<p>Frustrated by acronyms and jargon all over documentation? Can't kick the habit of using them yourself? <strong>Well I certainly am.</strong> I constantly run into situations where the confusion and extra cognitive load caused by the use of acronyms far outweighs any of the positive effects it could have.</p>\n<p>So, I'm doing something about it.  I started on a script you can include on a page that will find all possible acronyms (possible being any words with 2 or more capital letters) and see if they are defined in a provided list of known acronyms and definitions.  It then inserts a widget on the screen that can be expanded to list all the acronyms on the page and their definitions.</p>\n<p>The default color of the widget is purple representing mystery. Once expanded, it turns blue representing truth.</p>\n<p>Ultimately, I plan/want/hopefully get around to making a service that this client script can send acronyms to and receive definitions back to give the option of not doing the matching client-side. People would also be able to manage and define acronyms in that service.</p>\n<p>Source: <a href=\"https://github.com/iamtjg/acronym-identifier\">https://github.com/iamtjg/acronym-identifier</a></p>\n",
      "date_published": "2016-11-16T00:00:00Z"
    },{
      "id": "https://iamtjg.name/posts/nexdock-raspberry-pi-3/",
      "url": "https://iamtjg.name/posts/nexdock-raspberry-pi-3/",
      "title": "NexDock and Raspberry Pi 3",
      "content_html": "<p>My <a href=\"http://nexdock.com/\">NexDock</a> arrived yesterday and I decided to start out by hooking it up to a Raspberry Pi 3.  Trouble is, the keyboard and touchpad (although I am not using GUI desktop) can only be connected over Bluetooth and the Pi (running latest version of Raspbian) is not setup to auto-connect to on boot.  After doing the initial pairing I setup a simple cron task:</p>\n<pre><code>@reboot echo &quot;connect MACADDRESSOFDEVICE&quot; | bluetoothctl\n</code></pre>\n<p>It is working great so far.  Mobile, battery powered Pi is a success!</p>\n<p>At some point I hope to obtain a phone with HDMI out or USB-C to put Linux on and try out using it as my 'single device.'</p>\n<p>Now to get some Velcro or something to stick the Pi to the back...</p>\n",
      "date_published": "2016-09-09T00:00:00Z"
    },{
      "id": "https://iamtjg.name/posts/when-webdav-attacks/",
      "url": "https://iamtjg.name/posts/when-webdav-attacks/",
      "title": "When WebDAV Attacks!!!",
      "content_html": "<blockquote>\n<p>It was a nice calm Thursday morning... or so we thought...</p>\n</blockquote>\n<h1 id=\"the-problem\">The Problem <a class=\"direct-link\" href=\"#the-problem\">#</a></h1>\n<p>We came in to reports of the production Apache web server being 'slow.'</p>\n<p>Sure enough the server was maxed out on total workers. But why?</p>\n<p>We discovered continuous <code>OPTIONS</code> requests via Microsoft Office Discovery Protocol coming from a single person's computer. Upon <s>interrogating</s> speaking with the individual we found they were doing absolutely nothing.</p>\n<p>Doing a deeper dive into the logs we discovered these types of requests were coming from many other computers as well.</p>\n<h1 id=\"attempts\">Attempts <a class=\"direct-link\" href=\"#attempts\">#</a></h1>\n<p>Turned off <code>mod_dav</code>. We had been experimenting with stuff a while back but did not need it anymore.</p>\n<p>Requests still kept coming.</p>\n<p>Denied all requests coming from the Office Discovery Protocol user agent.</p>\n<p>Requests still kept coming.</p>\n<h1 id=\"what-is-the-office-existence-discovery-protocol%3F\">What is the Office Existence Discovery Protocol? <a class=\"direct-link\" href=\"#what-is-the-office-existence-discovery-protocol%3F\">#</a></h1>\n<p>Let's take a moment to learn a little bit about the Office Discovery Protocol.</p>\n<p>When someone goes to download an Office document from a website in Internet Explorer it sends the URL for the document to the Office application rather than downloading it.  The application then checks to see if the web server supports WebDAV.  It is essentially checking to see if it is a SharePoint server can can utilize the collaborative features that would provide.  There is nothing wrong with this. You would definitely want to take advantage of those features if available.</p>\n<p>Now how this affects the specific problem at hand.</p>\n<p>The Office Discovery Protocol expects WebDAV details as part of the response it receives to determine if the server supports it.  Since <code>mod_dav</code> was turned off you would expect Office to stop making the requests when it did not get the information it needed.  But it did not.</p>\n<p>The server responds with a <code>200 OK</code> status as the request is a valid <code>HTTP OPTIONS</code> request.  The Office Discovery Protocol would continue to make requests so long as it received a <code>200 OK</code> regardless of WebDAV support information.<br>\n<strong>Note:</strong> This will <em>continuously</em> happen while the Office application is open.</p>\n<h1 id=\"solution\">Solution <a class=\"direct-link\" href=\"#solution\">#</a></h1>\n<p>Our solution was to rewrite all <code>OPTIONS</code> requests from the Office Discovery Protocol user agent to respond with a <code>405 Method Not Allowed</code> status.  After a few requests the client learns the server does not support WebDAV and stops making requests.</p>\n<pre><code>RewriteCond %{REQUEST_METHOD} ^OPTIONS\nRewriteCond %{HTTP_USER_AGENT} ^Microsoft\\ Office\\ Protocol\\ Discovery [OR]\nRewriteCond %{HTTP_USER_AGENT} ^Microsoft\\ Office\\ Existence\\ Discovery [OR]\nRewriteCond %{HTTP_USER_AGENT} ^Microsoft\\-WebDAV\\-MiniRedir.*$\nRewriteRule .* - [R=405,L]\n</code></pre>\n<p>Overtime clients in the environment learn and the requests diminish.</p>\n<p>This <a href=\"http://serverfault.com/questions/301955/stopping-microsoft-office-2010-from-integrating-with-subversion-server-as-if-it\">poster</a> had a similar situation however, they still had DAV enabled.</p>\n<h2 id=\"other-options\">Other Options <a class=\"direct-link\" href=\"#other-options\">#</a></h2>\n<p>If you do not have any servers that support this feature you <em>could</em> completely disable Office Collaboration Features in the client configuration. Assuming you have control over how the clients are configured.</p>\n<p>I believe you can also disable the feature in Internet Explorer that supports this.</p>\n<h1 id=\"when-webdav-returns\">When WebDAV RETURNS <a class=\"direct-link\" href=\"#when-webdav-returns\">#</a></h1>\n<p>The cache that stores which servers are supported will get cleared at some point. If a large number of clients have their cache cleared at once you could see a flood of requests again.</p>\n",
      "date_published": "2016-08-29T00:00:00Z"
    },{
      "id": "https://iamtjg.name/posts/soft-skills/",
      "url": "https://iamtjg.name/posts/soft-skills/",
      "title": "Soft Skills",
      "content_html": "<p>I recently discovered the <a href=\"https://softskills.audio/\">Soft Skills Engineering</a> podcast by <a href=\"https://twitter.com/djsmith42\">Dave Smith</a> and <a href=\"https://twitter.com/jergason\">Jamison Dance</a> where they talk about all the non-code things it takes to be a good developer.  These are things I often think about and it is nice to hear about their personal experiences on these topics.</p>\n<p>The show is both entertaining and down to earth, go check it out!</p>\n",
      "date_published": "2016-08-19T00:00:00Z"
    },{
      "id": "https://iamtjg.name/posts/github-twissues/",
      "url": "https://iamtjg.name/posts/github-twissues/",
      "title": "github-twissues",
      "content_html": "<p>Last week I saw some <a href=\"https://twitter.com/SaraSoueidan/status/738213211326009344\">chatter on Twitter</a> between Sara Soueidan, Greg Whitworth, and Lea Verou about reporting browser bugs through tweets.</p>\n<p>It seemed like a cool idea to me.  It would really lower the entrance barrier for users (non-programmer types) to report issues but how would you manage adding/tracking the issues?  Someone would have to watch the hashtag, you might miss some, etc.</p>\n<p>So I had the idea to create a bot that watches Twitter and automatically opens issues on a corresponding GitHub repo.</p>\n<p>Setup is pretty simple all you need is a Twitter and GitHub account. Set some variables and go!</p>\n<p>Published on npm for easy install: <a href=\"https://www.npmjs.com/package/github-twissues\">https://www.npmjs.com/package/github-twissues</a></p>\n<p>Source is on GitHub: <a href=\"https://github.com/iamtjg/github-twissues\">https://github.com/iamtjg/github-twissues</a></p>\n",
      "date_published": "2016-06-09T00:00:00Z"
    },{
      "id": "https://iamtjg.name/posts/hubot-remote-ark/",
      "url": "https://iamtjg.name/posts/hubot-remote-ark/",
      "title": "hubot-remote-ark",
      "content_html": "<p>A few weeks ago more of my friends started getting into the game ARK: Survival Evolved.  We run our own private server to avoid the known downfalls (not going to go into them here) that come with playing on a public server. Naturally, we do not feel like having the server running when no one is using it but we also do not want to give everyone shell access just to be able to start and stop the server.</p>\n<p>So I thought, &quot;what would give the flexibility we need but not be wayyyy overkill for this?&quot;</p>\n<p><strong>Enter the chatbot!</strong></p>\n<p>I did some digging around and settled on <a href=\"https://hubot.github.com/\">GitHub's Hubot</a>.  It already integrates with a number of chat platforms and is very easy to setup.</p>\n<p>From there I wrote a simple plugin for Hubot to connect to a server and execute the most basic commands for controlling your server.</p>\n<p>I published it to npm as <a href=\"https://www.npmjs.com/package/hubot-remote-ark\">hubot-remote-ark</a>.<br>\n<strong>Note:</strong> <em>The first couple versions don't do anything and were mostly me just playing with npm. First package I've published!</em></p>\n<p>I hope to expand it to be a complete tool for managing your server but for now it does what I need it to.</p>\n<ul>\n<li>npm: <a href=\"https://www.npmjs.com/package/hubot-remote-ark\">https://www.npmjs.com/package/hubot-remote-ark</a></li>\n<li>source &amp; issues: <a href=\"https://gitlab.com/iamtjg/hubot-remote-ark\">https://gitlab.com/iamtjg/hubot-remote-ark</a></li>\n</ul>\n",
      "date_published": "2016-05-30T00:00:00Z"
    },{
      "id": "https://iamtjg.name/posts/ssl-for-discourse-with-lets-encrypt/",
      "url": "https://iamtjg.name/posts/ssl-for-discourse-with-lets-encrypt/",
      "title": "SSL for Discourse with Let&#39;s Encrypt",
      "content_html": "<p>This all assumes you already have a running installation of Discourse on a Linux host.</p>\n<p>There is already a <a href=\"https://meta.discourse.org/t/allowing-ssl-https-for-your-discourse-docker-setup/13847\">great guide</a> on setting up Discourse with SSL but I wanted to share the setup process I used specifically for Let's Encrypt which deviates slightly.</p>\n<p>Head over to the <a href=\"http://letsencrypt.readthedocs.org/en/latest/using.html#installation\">Let's Encrypt docs</a> for the official Let's Encrypt documentation.</p>\n<h1>Stop your Discourse container if it is already running.</h1>\nLet's Encrypt will need port 80 available to perform the domain verification.</h1>\nFrom /var/discourse:\n<pre><code>./launcher stop [container name]</code></pre>\n<h1>Download the Let's Encrypt client</h2>\n<pre><code>git clone https://github.com/letsencrypt/letsencrypt\ncd letsencrypt</code></pre>\n<h1>Generate Certificates</h1>\nRun letsencrypt-auto in standalone mode. This is the best method to use (currently) since the nginx plugin isn't available yet and we will be using the certificate within a container once we get them.\n<p><code>./letsencrypt-auto certonly --standalone</code></p>\n<p>Follow the prompts from letsencrypt. As it tells you when it completes, your certificates will be stored in <code>/etc/letsencrypt/live/your-domain-name</code>.<br>\nIf you go there you will see four files:</p>\n<ul>\n  <li>cert.pem</li>\n  <li>chain.pem</li>\n  <li>fullchain.pem</li>\n  <li>privkey.pem</li>\n</ul>\nLater on we will be utilizing fullchain.pem and privkey.pem.  It is important to use fullchain.pem as nginx does not have a way of handling separate intermediary cert files.\n<h1>Create SSL Directory in Discourse</h1>\nCreate <code>/var/discourse/shared/standalone/ssl</code> if it does not already exist.\n<h1>Update Discourse Config</h1>\nOpen <code>/var/discourse/container/app.yml</code>\n<h2>Add SSL Template</h2>\nAdd <code>\"templates/web.ssl.template.yml\"</code> to your list of templates.\n<pre><code>templates:\n- \"templates/postgres.template.yml\"\n- \"templates/redis.template.yml\"\n- \"templates/sshd.template.yml\"\n- \"templates/web.template.yml\"\n- \"templates/web.ssl.template.yml\"</code></pre>\n<h2>Add listener for SSL</h2>\nAdd <code>\"443:443\"</code> to allow your container to listen on port 443.\n<pre><code>expose:\n- \"80:80\"\n- \"2222:22\"\n- \"443:443\"</code></pre>\n<h2>Add Mount to Let's Encrypt</h2>\nRather than copy your certificates into Discourse we will set up a mount point for the container.\nStill in app.yml, go down to the volumes section.\nIf you haven't made any other modifications you will see the following:\n<pre><code>volumes:\n  - volume:\n      host: /var/discourse/shared/standalone\n      guest: /shared\n  - volume:\n      host: /var/discourse/shared/standalone/log/var-log\n      guest: /var/log</code></pre>\n<p>Add an entry for Let's Encrypt:</p>\n<pre><code>volumes:\n  - volume:\n      host: /var/discourse/shared/standalone\n      guest: /shared\n  - volume:\n      host: /var/discourse/shared/standalone/log/var-log\n      guest: /var/log\n  - volume:\n      host: /etc/letsencrypt/\n      guest: /etc/letsencrypt/</code></pre>\n<h2>Update SSL Template</h2>\nBy default <code>/var/discourse/templates/template.web.ssl.yml</code> points to <code>/var/discourse/shared/standalone/ssl</code> for certificate information.\n<p>Update the template to point to your certificate and key located in the letsencrypt directory.</p>\n<p>Default:</p>\n<pre><code>ssl_certificate /shared/ssl/ssl.crt;\nssl_certificate_key /shared/ssl/ssl.key;</code></pre>\n<pre><code>ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;\nssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;</code></pre>\n<h1>Rebuild Your Container</h1>\nFrom <code>/var/discourse</code> run <code>./launcher rebuild [your container name].</code>  A full rebuild is necessary to incorporate all the changes.\n<p>Once the container is rebuilt and running navigate to your domain and enjoy your new encrypted connection!</p>\n",
      "date_published": "2015-12-12T00:00:00Z"
    }
  ]
}
