<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="http://wiredtron.com/feed.xml" rel="self" type="application/atom+xml" /><link href="http://wiredtron.com/" rel="alternate" type="text/html" /><updated>2023-11-28T16:15:19+00:00</updated><id>http://wiredtron.com/feed.xml</id><title type="html">WiredTron</title><subtitle>Just a blog tracking all of the technical issues I have run into which I couldn't find documented elsewhere.</subtitle><entry><title type="html">Setting up TP Link Kasa Devices without Smart Home app</title><link href="http://wiredtron.com/2023/11/28/setting-up-tp-link-kasa-devices-without-smart-home-app.html" rel="alternate" type="text/html" title="Setting up TP Link Kasa Devices without Smart Home app" /><published>2023-11-28T00:00:00+00:00</published><updated>2023-11-28T00:00:00+00:00</updated><id>http://wiredtron.com/2023/11/28/setting-up-tp-link-kasa-devices-without-smart-home-app</id><content type="html" xml:base="http://wiredtron.com/2023/11/28/setting-up-tp-link-kasa-devices-without-smart-home-app.html">&lt;p&gt;Kasa plugs and switches are some of the best smart home devices on the market and have been for many years. One of their most attractive attributes is the existence of a local LAN API that can be interacted with. Even though this use is not officially supported by Kasa, in recent years they have gone from actively &lt;a href=&quot;https://forum.universal-devices.com/topic/33115-kasa-will-no-longer-allow-local-access/&quot;&gt;blocking local access&lt;/a&gt; to more or less accepting it and even&lt;a href=&quot;https://community.tp-link.com/en/smart-home/forum/topic/638558&quot;&gt; fixing bugs &lt;/a&gt;that arise when users use their switches exclusively offline. For me one of the biggest annoyances was manually having to do setup and configuration through their app, so I did some digging to see if there was a better way, and luckily there is! In this post I will walk you through the steps to take a Kasa smart plug from out of the box to fully configured. This was tested using a HS103 running firmware 1.0.6 (which is what is came with from the faactory) but I have used these same commands against HS220 and other switches as well and they have all worked.&lt;/p&gt;

&lt;p&gt;A big thanks to softScheck for posting a full list of commands on &lt;a href=&quot;https://github.com/softScheck/tplink-smartplug/blob/master/tplink-smarthome-commands.txt&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;setup-the-tplink-cli&quot;&gt;Setup the TPLink CLI&lt;/h3&gt;

&lt;p&gt;In order to use these commands you will need a somewhat recent version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt;. Once you have node, you will need to install the &lt;a href=&quot;https://github.com/plasticrake/tplink-smarthome-api&quot;&gt;tplink-smarthome-api&lt;/a&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install -g tplink-smarthome-api&lt;/code&gt;. This API has a lot of commands available, all of which can be listed by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tplink-smarthome-api --help&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;connect-to-the-device&quot;&gt;Connect to the Device&lt;/h3&gt;

&lt;p&gt;When the device is plugged in it automatically creates a network containing the last 4 of it’s MAC address at the end. This network is unsecured so you can just connect to it with your computer. In my testing, the devices always come up with the IP &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.0.1&lt;/code&gt; but you can verify this information by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ifconfig&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ipconfig&lt;/code&gt; on Windows). Once you are on the devices network you can finalize setup.&lt;/p&gt;

&lt;h3 id=&quot;setup-the-device&quot;&gt;Setup the Device&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Use the TPLink smarthome CLI to query the device by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tplink-smarthome-api getInfo 192.168.0.1&lt;/code&gt;. This information includes the MAC address which I use to assign a static IP in my router.&lt;/li&gt;
  &lt;li&gt;(Optional) Before connecting it to your network you can give it a name by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tplink-smarthome-api setAlias 192.168.0.1 'Device Name'&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tplink-smarthome-api send 192.168.0.1 '{&quot;netif&quot;:{&quot;set_stainfo&quot;:{&quot;ssid&quot;:&quot;&amp;lt;ssid&amp;gt;&quot;,&quot;password&quot;:&quot;&amp;lt;password&amp;gt;&quot;,&quot;key_type&quot;:3}}}'&lt;/code&gt; to set your WIFI. This will cause the device to automatically disconnect and join the specified WIFI network.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From there you can jump back over to your WIFI network and send commands directly to the device at it’s IP address on your network. For example, to turn the device on/off run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tplink-smarthome-api setPowerState &amp;lt;new-ip&amp;gt; 1&lt;/code&gt; to turn the device on.&lt;/p&gt;

&lt;p&gt;And that’s it, enjoy managing your devices without an app!&lt;/p&gt;</content><author><name></name></author><summary type="html">Kasa plugs and switches are some of the best smart home devices on the market and have been for many years. One of their most attractive attributes is the existence of a local LAN API that can be interacted with. Even though this use is not officially supported by Kasa, in recent years they have gone from actively blocking local access to more or less accepting it and even fixing bugs that arise when users use their switches exclusively offline. For me one of the biggest annoyances was manually having to do setup and configuration through their app, so I did some digging to see if there was a better way, and luckily there is! In this post I will walk you through the steps to take a Kasa smart plug from out of the box to fully configured. This was tested using a HS103 running firmware 1.0.6 (which is what is came with from the faactory) but I have used these same commands against HS220 and other switches as well and they have all worked.</summary></entry><entry><title type="html">Setting up a ratgdo + Homebridge with MQTT</title><link href="http://wiredtron.com/2023/11/25/setting-up-a-ratgdo-homebridge-with-mqtt.html" rel="alternate" type="text/html" title="Setting up a ratgdo + Homebridge with MQTT" /><published>2023-11-25T00:00:00+00:00</published><updated>2023-11-25T00:00:00+00:00</updated><id>http://wiredtron.com/2023/11/25/setting-up-a-ratgdo-homebridge-with-mqtt</id><content type="html" xml:base="http://wiredtron.com/2023/11/25/setting-up-a-ratgdo-homebridge-with-mqtt.html">&lt;p&gt;With the &lt;a href=&quot;http://web.archive.org/web/20231113120033/https://chamberlaingroup.com/press/a-message-about-our-decision-to-prevent-unauthorized-usage-of-myq&quot;&gt;recent lockdown&lt;/a&gt; of the myQ APIs, I recently became very interested in alternative options. After having easy garage door control for a few months from my watch or phone, going back to not having this control didn’t seem like a very appealing option. For my specific garage door opener I found there were 2 options that were supported, &lt;a href=&quot;https://www.meross.com/en-gc/smart-garage-door-opener/garage-door-opener-remote-control/29&quot;&gt;Meross&lt;/a&gt; and &lt;a href=&quot;https://paulwieland.github.io/ratgdo/&quot;&gt;ratgdo&lt;/a&gt;. I ended up choosing the latter since it was able to natively interface with my garage door opener and didn’t require me to run any additional sensors and could read the current door state directly. Since the ratgdo does not yet have native Homekit support, I went ahead and utilized my Homebridge installation that I already have running for other devices in my home. As a note, this guide will no longer be relevant once &lt;a href=&quot;https://github.com/ratgdo/homekit-ratgdo&quot;&gt;homekit-ratgdo&lt;/a&gt; is more mature. With that out of the way, lets get started.&lt;/p&gt;

&lt;h3 id=&quot;step-0---homebridge&quot;&gt;Step 0 - Homebridge&lt;/h3&gt;
&lt;p&gt;This guide assumes you already have a Homebridge server running on your network. If you do not there is very good documentation on how to get that setup on https://homebridge.io/.&lt;/p&gt;

&lt;h3 id=&quot;step-1---setup-mosquitto-mqtt-server&quot;&gt;Step 1 - Setup Mosquitto MQTT Server&lt;/h3&gt;
&lt;p&gt;I was not very familiar with MQTT before this so at first I did not realize that it would be necessary for me to run a separate MQTT server, since ratgdo does not bundle it’s own. In order to overcome this I went ahead and installed &lt;a href=&quot;https://mosquitto.org/&quot;&gt;Mosquitto&lt;/a&gt; on my Raspberry Pi that also runs Homebridge. This was as simple as running&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt install mosquitto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can optionally also install the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mosquitto-clients&lt;/code&gt; package if you would like to be able to inspect the contents of the queues. Once this is complete you can check the service status by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl status mosquitto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ratgdo requires your MQTT server to have username and password authentication setup. In order to enable authentication I created a file at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/mosquitto/passwd&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;homebridge:YourUnencryptedPassword
garagedoor:YourUnencryptedPassword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Change the passwords above and make a note of their values, you’ll need them later.&lt;/p&gt;

&lt;p&gt;I then ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo mosquitto_passwd -U /etc/mosquitto/passwd&lt;/code&gt; to hash the password into the form that mosquitto expects.&lt;/p&gt;

&lt;p&gt;Next up I had to update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/mosquitto/mosquitto.conf&lt;/code&gt; and append the following 3 lines:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;password_file /etc/mosquitto/passwd
allow_anonymous false
listener 1883 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;password_file&lt;/code&gt; is the one we just created. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allow_anonymous&lt;/code&gt; setting disables anonymous access, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listener&lt;/code&gt; specifies that mosquitto is available on port 1883 to any machine on our local network.&lt;/p&gt;
&lt;h3 id=&quot;step-2---flash-the-ratgdo&quot;&gt;Step 2 - Flash the ratgdo&lt;/h3&gt;

&lt;p&gt;The next step was flashing the firmware to the ratgdo. This step took the longest for me only due to the fact that I could only find charging only micro USB cables. &lt;strong&gt;Make sure&lt;/strong&gt; the cable you are using is a data USB cable. The installation guide also mentions a driver that potentially needs to be installed but things seemed to work fine for me without the driver installed, so I believe the driver is bundled on Windows and Mac. Flashing happens completely through the browser and can be done &lt;a href=&quot;https://paulwieland.github.io/ratgdo/flash.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After flashing you will be prompted to setup your wifi network. I currently have this running on an isolated network without internet access and have added a firewall rule allowing access from the ratgdo to the MQTT server. You know your network better than I do so I won’t add much more here.&lt;/p&gt;

&lt;p&gt;Next up, configuring the ratgdo. Once the device is flashed you can navigate to the IP address of the ratgdo on your network and you will be greeted with a configuration screen. Below is a screenshot of my current configuration.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2023/Screenshot%202023-11-25%20at%201.59.09%E2%80%AFPM.png&quot; alt=&quot;Ratgdo configuration&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that the IP is my Homebridge/MQTT IP, and the username and password combination are the one from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/mosquitto/passwd&lt;/code&gt; file we setup above. I have my MQTT topic prefix set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/&lt;/code&gt; since ratgdo automatically adds the device name to the MQTT prefix. This means the resulting queue name in my case is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/garagedoor/status/availability&lt;/code&gt; for the availability queue.&lt;/p&gt;

&lt;p&gt;One final note, it seems that providing a bad MQTT configuration here can cause the ratgdo to hang causing it’s configuration webpage to become inaccessible. In my case this was fixed by adding a firewall rule allowing traffic between my 2 subnets.&lt;/p&gt;

&lt;h3 id=&quot;step-3---install-the-ratgdo&quot;&gt;Step 3 - Install the ratgdo&lt;/h3&gt;

&lt;p&gt;This one will vary a bit based on your setup however the instructions on how to do this can be found &lt;a href=&quot;https://paulwieland.github.io/ratgdo/03_wiring.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;step-3--setup-homebridge&quot;&gt;Step 3- Setup Homebridge&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A big thanks to &lt;a href=&quot;https://github.com/ozpaulb&quot;&gt;ozpaulb&lt;/a&gt; and specifically &lt;a href=&quot;https://github.com/PaulWieland/ratgdo/issues/228#issuecomment-1807241037&quot;&gt;this comment&lt;/a&gt; for providing basically everything I needed for this section.&lt;/p&gt;

&lt;p&gt;In order to connect Homebridge to MQTT, you will need the &lt;a href=&quot;https://github.com/arachnetech/homebridge-mqttthing#readme&quot;&gt;Homebridge MQTT-Thing&lt;/a&gt; plugin. I use the Homebridge UI so this was just a matter of searching for the plugin and clicking install. Once the plugin is installed you will need to add an accessory to your config file for your garage door. The accessory block in my homebridge config now looks as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;accessories&quot;: [
  {
    &quot;type&quot;: &quot;garageDoorOpener&quot;,
    &quot;name&quot;: &quot;Garage Door&quot;,
    &quot;url&quot;: &quot;mqtt://127.0.0.1:1883&quot;,
    &quot;username&quot;: &quot;homebridge&quot;,
    &quot;password&quot;: &quot;&amp;lt;your password&amp;gt;&quot;,
    &quot;logMqtt&quot;: true,
    &quot;topics&quot;: {
      &quot;getOnline&quot;: &quot;/home/garagedoor/status/availability&quot;,
      &quot;getCurrentDoorState&quot;: &quot;/home/garagedoor/status/door&quot;,
      &quot;getDoorMoving&quot;: &quot;/home/garagedoor/status/motion&quot;,
      &quot;getLockCurrentState&quot;: &quot;/home/garagedoor/status/lock&quot;,
      &quot;getLockTargetState&quot;: &quot;/home/garagedoor/status/lock&quot;,
      &quot;setLockTargetState&quot;: &quot;/home/garagedoor/command/lock&quot;,
      &quot;getObstructionDetected&quot;: &quot;/home/garagedoor/status/obstruction&quot;,
      &quot;setTargetDoorState&quot;: &quot;/home/garagedoor/command/door&quot;,
      &quot;getTargetDoorState&quot;: {
          &quot;topic&quot;: &quot;/home/garagedoor/status/door&quot;,
          &quot;apply&quot;: &quot;if(message == 'opening') message='open'; if(message == 'closing' || message=='closed') message='close'; return message;&quot;
      }
    },
    &quot;doorCurrentValues&quot;: [
      &quot;open&quot;,
      &quot;closed&quot;,
      &quot;opening&quot;,
      &quot;closing&quot;,
      &quot;stopped&quot;
    ],
    &quot;doorTargetValues&quot;: [
      &quot;open&quot;,
      &quot;close&quot;
    ],
    &quot;lockValues&quot;: [
      &quot;unlocked&quot;,
      &quot;locked&quot;
    ],
    &quot;doorValues&quot;: [
      &quot;open&quot;,
      &quot;closed&quot;,
      &quot;opening&quot;,
      &quot;closing&quot;,
      &quot;stopped&quot;
    ],
    &quot;accessory&quot;: &quot;mqttthing&quot;
  }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Go ahead and update the username and password to match what you set above in step 1 in mosquitto. In my case since my Homebridge server and MQTT server are running on the same host I was able to specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mqtt://127.0.0.1:1883&lt;/code&gt;, if you are hosting yours on different machines then you will need to update the IP accordingly.&lt;/p&gt;

&lt;p&gt;That should be it, enjoy taking control of your garage door once again!&lt;/p&gt;</content><author><name></name></author><summary type="html">With the recent lockdown of the myQ APIs, I recently became very interested in alternative options. After having easy garage door control for a few months from my watch or phone, going back to not having this control didn’t seem like a very appealing option. For my specific garage door opener I found there were 2 options that were supported, Meross and ratgdo. I ended up choosing the latter since it was able to natively interface with my garage door opener and didn’t require me to run any additional sensors and could read the current door state directly. Since the ratgdo does not yet have native Homekit support, I went ahead and utilized my Homebridge installation that I already have running for other devices in my home. As a note, this guide will no longer be relevant once homekit-ratgdo is more mature. With that out of the way, lets get started.</summary></entry><entry><title type="html">Using chrome debug tools to debug flaky Capybara system tests</title><link href="http://wiredtron.com/2022/11/15/using-chrome-debug-tools-to-debug-flaky-capybara-system-tests.html" rel="alternate" type="text/html" title="Using chrome debug tools to debug flaky Capybara system tests" /><published>2022-11-15T00:00:00+00:00</published><updated>2022-11-15T00:00:00+00:00</updated><id>http://wiredtron.com/2022/11/15/using-chrome-debug-tools-to-debug-flaky-capybara-system-tests</id><content type="html" xml:base="http://wiredtron.com/2022/11/15/using-chrome-debug-tools-to-debug-flaky-capybara-system-tests.html">&lt;p&gt;Chrome debug tools are super useful when trying to debug an issue while running Capybara system tests. In order to debug this failing test I really wanted the Chrome devtools Network tab open in order to see what requests were going between the server and browser. Unfortunately in my case the tests had to be run many times in order to reproduce the failure, and the Chrome network tab only begins logging requests after it is opened. This means unless the Network tab was opened right when the test began there was no way to see the traffic I was curious about. In order to achieve the desired result I ended up registering a new Capybara driver with the following config:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Capybara.register_driver :chrome_with_network_tab do |app|
  options = Selenium::WebDriver::Chrome::Options.new(args: %w[auto-open-devtools-for-tabs])
  options.add_preference(
    'devtools',
    'preferences' =&amp;gt; {
      'currentDockState' =&amp;gt; '&quot;bottom&quot;',
      'panel-selectedTab' =&amp;gt; '&quot;network&quot;',
    }
  )

  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    options: options,
  )
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I then ran my failing test in a loop until it failed:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;while true; do                                                                    
    bundle exec rspec ./spec/system/spec_that_fails_spec.rb:&amp;lt;line number of failing spec&amp;gt;
    if [ $? -ne 0 ]; then
        break
    fi
    sleep 1
done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point I was able to see all of the network requests and was able to narrow down the problem. If you prefer a different dock location or need a different active tab, feel free to change the setting to fit your needs.&lt;/p&gt;</content><author><name></name></author><summary type="html">Chrome debug tools are super useful when trying to debug an issue while running Capybara system tests. In order to debug this failing test I really wanted the Chrome devtools Network tab open in order to see what requests were going between the server and browser. Unfortunately in my case the tests had to be run many times in order to reproduce the failure, and the Chrome network tab only begins logging requests after it is opened. This means unless the Network tab was opened right when the test began there was no way to see the traffic I was curious about. In order to achieve the desired result I ended up registering a new Capybara driver with the following config:</summary></entry><entry><title type="html">Using twilio-video.js with esbuild</title><link href="http://wiredtron.com/2022/03/28/using-twilio-videojs-with-esbuild.html" rel="alternate" type="text/html" title="Using twilio-video.js with esbuild" /><published>2022-03-28T00:00:00+00:00</published><updated>2022-03-28T00:00:00+00:00</updated><id>http://wiredtron.com/2022/03/28/using-twilio-videojs-with-esbuild</id><content type="html" xml:base="http://wiredtron.com/2022/03/28/using-twilio-videojs-with-esbuild.html">&lt;p&gt;ESBuild is an extremely fast bundler for javascript. Unfortunately speed doesn’t matter if your app doesn’t work! While migrating from Webpacker to esbuild with a Rails 7 application I ran into an issue where esbuild would compile successfully, however the twilio-video.js library (and accompanying twilio-ruby gem) were not able to startup. The error was as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Uncaught ReferenceError: process is not defined
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This is happening due to a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require('twilio-video')&lt;/code&gt; which expects &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process.env&lt;/code&gt; to be available globally.  There is a good writeup on the cause of this in an &lt;a href=&quot;https://github.com/twilio/twilio-video.js/issues/1746&quot;&gt;issue on twilio-video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The trick to working around this issue with esbuild is to leverage the &lt;a href=&quot;https://www.npmjs.com/package/@esbuild-plugins/node-modules-polyfill&quot;&gt;@esbuild-plugins/node-modules-polyfill&lt;/a&gt; package. It provides a polyfill for built-in modules for the browser meaning things that would not normally be available inside a browser will still work. Below is how I included this using an esbuild configuration file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;esbuild.config.mjs:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import NodeModulesPolyfills from '@esbuild-plugins/node-modules-polyfill'
import esbuild from 'esbuild'

esbuild.build({
  entryPoints: ['app/javascript/application.js'],
  outdir: 'app/assets/builds',
  plugins: [NodeModulesPolyfills.default()]
}).catch(() =&amp;gt; process.exit(1))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From there, I was able to execute esbuild using the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node esbuild.config.mjs&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;twilio-video.js&lt;/code&gt; was once again working successfully..&lt;/p&gt;</content><author><name></name></author><summary type="html">ESBuild is an extremely fast bundler for javascript. Unfortunately speed doesn’t matter if your app doesn’t work! While migrating from Webpacker to esbuild with a Rails 7 application I ran into an issue where esbuild would compile successfully, however the twilio-video.js library (and accompanying twilio-ruby gem) were not able to startup. The error was as follows:</summary></entry><entry><title type="html">Setting up a Content Security Policy for Ruby on Rails Applications</title><link href="http://wiredtron.com/2021/02/19/setting-up-a-content-security-policy-for-rails-applications.html" rel="alternate" type="text/html" title="Setting up a Content Security Policy for Ruby on Rails Applications" /><published>2021-02-19T00:00:00+00:00</published><updated>2021-02-19T00:00:00+00:00</updated><id>http://wiredtron.com/2021/02/19/setting-up-a-content-security-policy-for-rails-applications</id><content type="html" xml:base="http://wiredtron.com/2021/02/19/setting-up-a-content-security-policy-for-rails-applications.html">&lt;p&gt;A Content Security Policy(CSP) is an important piece of mitigating multiple different types of attacks including XSS, Clickjacking, and other various types of code injections attacks. It does this by informing the end-users browser to not make requests or perform actions that don’t meet the CSP. Unfortunately, writing a generic CSP is not possible, and instead requires the developer to analyze their requirements and make appropriate exceptions before rolling out a CSP. In this article I will cover two sections: overall observations, and examples of Ruby on Rails specific gotcha’s I encountered along the way.&lt;/p&gt;

&lt;h1 id=&quot;overall-observations&quot;&gt;Overall Observations&lt;/h1&gt;

&lt;p&gt;My first step in writing a CSP was to enable the default one which Rails provides, and inspect what errors I received on the console. I was greeted with a few errors right away that looked very strange, which I quickly realized were not related to the application. They were caused by extensions which I had installed, specifically Vue Devtools and React Devtools. This lead me to my first takeaway: &lt;strong&gt;Use Private Browsing mode when testing your CSP&lt;/strong&gt; to ensure the errors you are seeing are relevant!&lt;/p&gt;

&lt;p&gt;Second, I noticed that the &lt;strong&gt;CSP messages in Firefox were not quite as helpful as the ones in Chrome&lt;/strong&gt;. I ended up having a lot more luck tracking down the root cause of CSP issues in Chrome than in Firefox.&lt;/p&gt;

&lt;h1 id=&quot;rails-specific-observations&quot;&gt;Rails-Specific Observations&lt;/h1&gt;

&lt;p&gt;There are 4 gems and 1 javascript code block I had to refactor as part of this exercise. I will include a link to my full set of changes at the end of the article since this was done on an open source project. Note that testing changes to your CSP in rails is slightly annoying since you need to reload the server after every change, since the CSP is saved in an initializer. If you feel like your changes aren’t taking effect, this is probably the reason.&lt;/p&gt;

&lt;h3 id=&quot;gems&quot;&gt;Gems&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#bootstrap-3&quot;&gt;Bootstrap 3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#jquery-rails&quot;&gt;jquery-rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#chartkick&quot;&gt;Chartkick&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#recaptcha&quot;&gt;reCAPTCHA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;code-refactoring&quot;&gt;Code Refactoring&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#rewriting-inline-scripts&quot;&gt;Rewriting Inline Scripts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;csp-settings&quot;&gt;CSP Settings&lt;/h2&gt;

&lt;p&gt;The default CSP in rails looks as follows (any items commented out were done by me):&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Be sure to restart your server when you modify this file.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Define an application-wide content security policy&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# For further information see the following documentation&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_security_policy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default_src&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;font_src&lt;/span&gt;    &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;img_src&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;object_src&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:none&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;script_src&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;style_src&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Specify URI for violation reports&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# policy.report_uri &quot;/csp-violation-report-endpoint&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# If you are using UJS then enable automatic nonce generation&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_security_policy_nonce_generator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SecureRandom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;base64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set the nonce only to specific directives&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_security_policy_nonce_directives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(script-src)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Report CSP violations to a specified URI&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# For further information see the following documentation:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Rails.application.config.content_security_policy_report_only = true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this application, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//= require jquery_ujs&lt;/code&gt; was included, so I went ahead and enabled the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;content_security_policy_nonce_generator&lt;/code&gt; feature. The only caveat was I also had to enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;content_security_policy_nonce_directives&lt;/code&gt; setting and limit it to only apply to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script-src&lt;/code&gt; since all of the Chartkick inline styles broke and there was no straightforward way to pass the nonce to stylesheets.&lt;/p&gt;

&lt;h2 id=&quot;nonce-helpers&quot;&gt;Nonce Helpers&lt;/h2&gt;

&lt;p&gt;First of all, what is a nonce? A nonce is a one-time-use code which is changed every time the page is refreshed.&lt;/p&gt;

&lt;p&gt;With the settings in the previous section enabled, it was necessary to modify the code in a few places to use the nonce. Specifically the following was the diff of the lines change in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;application.html.haml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gi&quot;&gt;+ = csp_meta_tag
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;- = javascript_include_tag &quot;application&quot;
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ = javascript_include_tag &quot;application&quot;, nonce: true
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;csp_meta_tag&lt;/code&gt; adds the a new tag to every page, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nonce: true&lt;/code&gt; adds that same nonce to the javascript assets tag, for example:&lt;/p&gt;
&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;csp-nonce&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Zp+yENSM5K9BKStdB22IbQ==&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/assets/application-1798ca4812645a78f896665e43c690d14f965504736ca9fe705e2d59cce6d622.js&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;nonce=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Zp+yENSM5K9BKStdB22IbQ==&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This same nonce is accessible through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;content_security_policy_nonce&lt;/code&gt; method and an example is used later on in the file.&lt;/p&gt;
&lt;h1 id=&quot;gems-1&quot;&gt;Gems&lt;/h1&gt;
&lt;h2 id=&quot;bootstrap-3&quot;&gt;Bootstrap 3&lt;/h2&gt;

&lt;p&gt;Bootstrap adds an inline style to navbar dropdowns. In my case the line:&lt;/p&gt;

&lt;div class=&quot;language-haml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;%button&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.navbar-toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;aria-controls&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;navbarSupportedContent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;aria-expanded&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;false&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;aria-label&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Toggle navigation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;data-target&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#navbarSupportedContent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;data-toggle&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;collapse&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;was throwing an error stating that the inline style&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;color: #fff
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;was not able to be applied. I was not applying a custom style to the navbar with an inline style, so this must be something that Bootstrap 3 adds on. Chartkick (below) also requires inline styles enabled, so I fixed this by ensuring the following was set in my CSP.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;style_src&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:unsafe_inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;jquery-rails&quot;&gt;jQuery Rails&lt;/h2&gt;

&lt;p&gt;This application was relying on an old version of jQuery without realizing it. In our application.js there was an include for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//= require jquery&lt;/code&gt;. This was causing an error inside jQuery itself on the following lines:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Support: IE&amp;lt;9 (lack submit/change bubble), Firefox (lack focus(in | out) events)
for ( i in { submit: true, change: true, focusin: true } ) {
  eventName = &quot;on&quot; + i;

  if ( !( support[ i ] = eventName in window ) ) {

    // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
    div.setAttribute( eventName, &quot;t&quot; );
    support[ i ] = div.attributes[ eventName ].expando === false;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It turns out the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jquery-rails&lt;/code&gt; gem includes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jQuery&lt;/code&gt; 1, 2, and 3. I found that switching to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//= require jquery2&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//= require jquery3&lt;/code&gt; fixed the issue.&lt;/p&gt;

&lt;h2 id=&quot;chartkick&quot;&gt;Chartkick&lt;/h2&gt;

&lt;p&gt;Chartkick has a really good writeup on what is required to make it work with CSP: &lt;a href=&quot;https://github.com/ankane/chartkick/blob/master/guides/Content-Security-Policy.md&quot;&gt;chartkick CSP guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my case, I already had to enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsafe_inline&lt;/code&gt; styles across the whole application due to Bootstrap 3, so this setting in conjunction with adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Chartkick.options[:nonce] = true&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config/initializers/chartkick.rb&lt;/code&gt; solved all of my Chartkick issues.&lt;/p&gt;

&lt;h2 id=&quot;recaptcha&quot;&gt;reCAPTCHA&lt;/h2&gt;

&lt;p&gt;The documentation for reCAPTCHA states that &lt;a href=&quot;https://developers.google.com/recaptcha/docs/faq#im-using-content-security-policy-csp-on-my-website.-how-can-i-configure-it-to-work-with-recaptcha&quot;&gt;whitelisting a few domains&lt;/a&gt; is required in order to allow reCAPTCHA to work with CSP enabled. This does not reflect what I experienced. I added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;invisible_recaptcha_tags nonce: content_security_policy_nonce&lt;/code&gt; (note that I am using the &lt;a href=&quot;https://github.com/ambethia/recaptcha&quot;&gt;ambethia/recaptcha&lt;/a&gt; gem and afterwards reCAPTCHA worked fine for me. The nonce used here pulls in the same nonce that is added as described in the nonce helpers section above.&lt;/p&gt;

&lt;h1 id=&quot;code-refactoring-1&quot;&gt;Code Refactoring&lt;/h1&gt;

&lt;h2 id=&quot;rewriting-inline-scripts&quot;&gt;Rewriting inline scripts&lt;/h2&gt;

&lt;p&gt;There was one instance of an inline script which used data from the controller to show the time remaining countdown. In order to still pass the data needed into Javascript, I had to add the data to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; attribute. The transformation can be seen from &lt;a href=&quot;https://github.com/mitre-cyber-academy/ctf-scoreboard/commit/b61f723cd1145b15b08101eab7c0fea2be5a572c#diff-23492f8696d5e59d70a27c592a1e7172efcb3e881e36436687456415bc857c88L5-R3&quot;&gt;here&lt;/a&gt; to &lt;a href=&quot;https://github.com/mitre-cyber-academy/ctf-scoreboard/commit/b61f723cd1145b15b08101eab7c0fea2be5a572c#diff-385d298b11967d2164b9b0889f3dd8b3c6eb7a11afacbf6b5ae2026ded30ff92R4-R33&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;resulting-csp&quot;&gt;Resulting CSP&lt;/h2&gt;

&lt;p&gt;With all of my investigation completed, I found the following CSP worked best for the application:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Be sure to restart your server when you modify this file.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Define an application-wide content security policy&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# For further information see the following documentation&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_security_policy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;default_src&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;font_src&lt;/span&gt;    &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;img_src&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:data&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;object_src&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:none&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;script_src&lt;/span&gt;  &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;style_src&lt;/span&gt;   &lt;span class=&quot;ss&quot;&gt;:unsafe_inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:https&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# If you are using UJS then enable automatic nonce generation&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_security_policy_nonce_generator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SecureRandom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;base64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set the nonce only to specific directives&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;content_security_policy_nonce_directives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%w(script-src)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Relevant commit: &lt;a href=&quot;https://github.com/mitre-cyber-academy/ctf-scoreboard/commit/b61f723cd1145b15b08101eab7c0fea2be5a572c&quot;&gt;mitre-cyber-academy/ctf-scoreboard&lt;/a&gt;&lt;/p&gt;</content><author><name>Robert</name></author><summary type="html">A Content Security Policy(CSP) is an important piece of mitigating multiple different types of attacks including XSS, Clickjacking, and other various types of code injections attacks. It does this by informing the end-users browser to not make requests or perform actions that don’t meet the CSP. Unfortunately, writing a generic CSP is not possible, and instead requires the developer to analyze their requirements and make appropriate exceptions before rolling out a CSP. In this article I will cover two sections: overall observations, and examples of Ruby on Rails specific gotcha’s I encountered along the way.</summary></entry><entry><title type="html">Expanding LVM Storage with Proxmox 5.2</title><link href="http://wiredtron.com/2018/07/07/extending-lvm-with-proxmox-52/" rel="alternate" type="text/html" title="Expanding LVM Storage with Proxmox 5.2" /><published>2018-07-28T05:00:00+00:00</published><updated>2018-07-28T05:00:00+00:00</updated><id>http://wiredtron.com/2018/07/07/extending-lvm-with-proxmox-52</id><content type="html" xml:base="http://wiredtron.com/2018/07/07/extending-lvm-with-proxmox-52/">&lt;p&gt;Proxmox is an Open Source virtualization solution that provides very easy installation at an irresistible price point. The biggest issue I have encountered so far after messing with it for 2 days is its lack of customization for installing across multiple drives. My initial goal was to have a setup that I have accomplished before with ESXi where I have a main drive and a secondary storage drive. In this setup, the main OS drive contains my OS and the secondary drive stores the VMs. Unfortunately, after the installation completed I found myself with both the root and data stores built on the main drives. This meant that I didn’t have enough space to store my ISOs or VMs. In order to fix this I needed to extend both the data and root volumes. Fortunately this is not my first go with LVM. The steps I used are as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open up fdisk for the secondary drive, in my case this was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdisk /dev/sdb&lt;/code&gt;. You will need to choose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; to delete any partitions on the disk and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w&lt;/code&gt; to write changes.&lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sgdisk -gN 1 /dev/sdb&lt;/code&gt; in order to convert this disk to GPT format. the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; option here even if If sgdisk finds a valid MBR or BSD disklabel but no GPT data.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pvcreate /dev/sdb1&lt;/code&gt; initializes Physical Volume for later use by the Logical Volume Manager.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vgextend pve /dev/sdb1&lt;/code&gt; extends the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pve&lt;/code&gt; volume group (which all 3 Proxmox volumes are a part of) to include the newly allocated Physical Volume.&lt;/li&gt;
  &lt;li&gt;This step can be adjusted as needed. For my use case I decided extending my root volume by 80g was sufficient, so I ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvresize -L +80g --resizefs /dev/pve/root&lt;/code&gt;. If you need more space, go ahead and change that 80g to something else.&lt;/li&gt;
  &lt;li&gt;I then allocated the rest of my space to the data volume for my VMs, using the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lvresize -l +100%FREE --resizefs /dev/pve/data&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;</content><author><name>Robert</name></author><category term="Linux" /><category term="Open Source Programs" /><summary type="html">Proxmox is an Open Source virtualization solution that provides very easy installation at an irresistible price point. The biggest issue I have encountered so far after messing with it for 2 days is its lack of customization for installing across multiple drives. My initial goal was to have a setup that I have accomplished before with ESXi where I have a main drive and a secondary storage drive. In this setup, the main OS drive contains my OS and the secondary drive stores the VMs. Unfortunately, after the installation completed I found myself with both the root and data stores built on the main drives. This meant that I didn’t have enough space to store my ISOs or VMs. In order to fix this I needed to extend both the data and root volumes. Fortunately this is not my first go with LVM. The steps I used are as follows:</summary></entry><entry><title type="html">Setting up Raspberry PI with Huawei E397u-53 dongle on Metro PCS</title><link href="http://wiredtron.com/2018/07/07/raspberry-pi-with-huawei-E397u-53-dongle-metro/" rel="alternate" type="text/html" title="Setting up Raspberry PI with Huawei E397u-53 dongle on Metro PCS" /><published>2018-07-07T05:00:00+00:00</published><updated>2018-07-07T05:00:00+00:00</updated><id>http://wiredtron.com/2018/07/07/raspberry-pi-with-huawei-E397u-53-dongle</id><content type="html" xml:base="http://wiredtron.com/2018/07/07/raspberry-pi-with-huawei-E397u-53-dongle-metro/">&lt;p&gt;The Huawei E397u-53 dongle is a low cost dongle which is available on Amazon for around $20. It is possible to get it working on startup on a Raspberry PI, and there is some very good documentation which I will mention in the credits of this post. Even with the documntation I was able to find, I still hit a decent number of roadblocks during setup.&lt;/p&gt;

&lt;p&gt;First up, I am going to summarize the actual steps I used, which are mostly the same as the one from the first blog post. I opted to use the NDISDUP method since WvDial is slower and harder to reliably bring up on startup.&lt;/p&gt;

&lt;p&gt;Also as a note, most blog posts mention needing to mess with usb_modeswitch. As of the time of this posting, with Raspbian 9 (Stretch) on a Raspberry PI 3 Model B version 1.2 this was not necessary since the device already showed up on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/ttyUSB0&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install screen using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt-get install screen&lt;/code&gt; and then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;screen /dev/ttyUSB0&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;This will put you in a console that will look hung. If you type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AT&lt;/code&gt; and hit enter you should get a response of OK back.&lt;/li&gt;
  &lt;li&gt;In the new console, type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AT^NDISDUP=1,1,&quot;&amp;lt;APN&amp;gt;&quot;&lt;/code&gt; where &amp;lt;APN&amp;gt; is the APN for your carrier. In my case it was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fast.metropcs.com&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;You will now need to install libqmi-utils. Unfortunately this is where I ran into the biggest issue. The current version of libqmi-utils in Rasbian has a bug (see 2nd link in credits) where you will get an error stating:
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo APN=fast.metropcs.com /usr/bin/qmi-network /dev/cdc-wdm0 start
Loading profile at /etc/qmi-network.conf...
 APN: fast.metropcs.com
 APN user: unset
 APN password: unset
 qmi-proxy: no
Checking data format with 'qmicli -d /dev/cdc-wdm0 --wda-get-data-format '...
error: couldn't create client for the 'wda' service: QMI protocol error (31): 'InvalidServiceType'
Device link layer protocol not retrieved: WDA unsupported
Starting network with 'qmicli -d /dev/cdc-wdm0 --wds-start-network=apn='fast.metropcs.com'  --client-no-release-cid '...
error: couldn't start network: QMI protocol error (64): '(null)'
Saving state at /tmp/qmi-network-state-cdc-wdm0... (CID: 1)
error: network start failed, no packet data handle
Clearing state at /tmp/qmi-network-state-cdc-wdm0...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;In order to workaround this, I first removed the version of libqmi-utils I installed by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt remove libqmi-utils&lt;/code&gt; and then reinstalled it from source by running
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget http://www.freedesktop.org/software/libqmi/libqmi-1.16.0.tar.xz
tar -vxf libqmi-1.16.0.tar.xz
cd libqmi-1.16.0
sudo apt-get install glib-networking libmbim-glib-dev libgudev-1.0-dev
./configure --prefix=/usr --disable-static
make &amp;amp;&amp;amp; sudo make install
sudo qmi-network /dev/cdc-wdm0 start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Once I was able to verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo qmi-network /dev/cdc-wdm0 start&lt;/code&gt; worked, I went ahead and rebooted the machine. From there I then edited &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/network/interfaces.d/wwan0&lt;/code&gt;, replacing &amp;lt;APN&amp;gt; with my APN settings and added
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;allow-hotplug wwan0
iface wwan0 inet dhcp
  pre-up for _ in $(seq 1 10); do /usr/bin/test -c /dev/cdc-wdm0 &amp;amp;&amp;amp; break; /bin/sleep 1; done
  pre-up for _ in $(seq 1 10); do /usr/bin/qmicli -d /dev/cdc-wdm0 --nas-get-signal-strength &amp;amp;&amp;amp; break; /bin/sleep 1; done
  pre-up APN=&amp;lt;APN&amp;gt; /usr/bin/qmi-network /dev/cdc-wdm0 start
  post-down /usr/bin/qmi-network /dev/cdc-wdm0 stop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;I was then able to reboot the PI and the networking came up successfully.&lt;/li&gt;
  &lt;li&gt;At this point everything was working, however I did not have any DNS resolution. In order to fix this I had to edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/resolv.conf.head&lt;/code&gt; and add
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#OpenDns Servers
nameserver 1.1.1.1
nameserver 1.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Credits:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://robpol86.com/raspberry_pi_project_fi.html&quot;&gt;https://robpol86.com/raspberry_pi_project_fi.html&lt;/a&gt; This article got me about 90% there, the biggest issue being the current version of libqmi-utils being broken.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=845979&quot;&gt;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=845979&lt;/a&gt; This bug report tipped me off to roll the libqmi-utils version back to before 1.16.2.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/alvaro893/f5b8dd026eb98959e8c6c59a45b63cc2&quot;&gt;https://gist.github.com/alvaro893/f5b8dd026eb98959e8c6c59a45b63cc2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Robert</name></author><category term="Linux" /><category term="Open Source Programs" /><summary type="html">The Huawei E397u-53 dongle is a low cost dongle which is available on Amazon for around $20. It is possible to get it working on startup on a Raspberry PI, and there is some very good documentation which I will mention in the credits of this post. Even with the documntation I was able to find, I still hit a decent number of roadblocks during setup.</summary></entry><entry><title type="html">Using Packer vmware-iso builder on Ubuntu 16.04 server with Workstation Player 14</title><link href="http://wiredtron.com/2017/10/19/using-packer-vmware-iso-builder-on-ubuntu-16-04-server-with-workstation-player-14/" rel="alternate" type="text/html" title="Using Packer vmware-iso builder on Ubuntu 16.04 server with Workstation Player 14" /><published>2017-10-19T15:59:42+00:00</published><updated>2017-10-19T15:59:42+00:00</updated><id>http://wiredtron.com/2017/10/19/using-packer-vmware-iso-builder-on-ubuntu-16-04-server-with-workstation-player-14</id><content type="html" xml:base="http://wiredtron.com/2017/10/19/using-packer-vmware-iso-builder-on-ubuntu-16-04-server-with-workstation-player-14/">&lt;p&gt;Getting VMWare Workstation Player 14 (the free one) to work with Packer on Ubuntu 16.04 is possible and not very difficult, however it is very undocumented. In order to get it working you will need a few different packages, listed below&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.packer.io/downloads.html&quot;&gt;Packer&lt;/a&gt; (Download the Linux 64-bit version, at the time of this guide the latest version is 1.1.1)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://my.vmware.com/en/web/vmware/free#desktop_end_user_computing/vmware_workstation_player/14_0&quot;&gt;VMWare Workstation Player 14&lt;/a&gt; (I downloaded the version for Linux 64-bit from the previous link)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://my.vmware.com/en/web/vmware/free#desktop_end_user_computing/vmware_workstation_player/14_0%7CPLAYER-1400%7Cdrivers_tools&quot;&gt;VMWare Vix 1.17&lt;/a&gt; (I downloaded the version for Linux 64-bit from the previous link)&lt;/li&gt;
  &lt;li&gt;In order to build kernel modules you will need to &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;sudo apt install libxt6 libxtst6 libxcursor-dev libxinerama-dev build-essential&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Install additional dependencies by running &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;sudo apt install qemu-utils libxi6&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Install packer by downloading the zip and moving the packer executable into /usr/local/bin. Next, download the VMWare Workstation Player 14 bundle and install it by running &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;sudo sh VMWare-Player-14.bundle&lt;/code&gt; . Finally, download the VMWare Vix bundle and install it by running  &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;sudo sh VMWare-Vix.bundle&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Next you will need to run &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;sudo vmware-modconfig --console --install-all&lt;/code&gt; to install all of the required kernel modules.&lt;/p&gt;

&lt;p&gt;You should now be able to do packer builds using the vmware-iso builder on your headless machine running Ubuntu 16.04.&lt;/p&gt;

&lt;p&gt;If the execution fails here with an error such as “Error: The operation was canceled”, then run packer with the command &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;PACKER_LOG=1 packer build -debug &amp;lt;yourpackerfile&amp;gt;.json&lt;/code&gt; which will allow you to step through each step of the packer build and pause before cleanup to inspect the logs written to your output directory, which is normally &lt;code class=&quot;prettyprint lang-sh&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;output-&amp;lt;vmname&amp;gt;&lt;/code&gt;. Inside that folder will be a vmware log file which should give you some hints towards what is going wrong.&lt;/p&gt;

&lt;p&gt;Credits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt; https://kradalby.no/setup-vmware-player-headless-on-debian.html got me the final undocumented step required to setup vmware-modconfig kernel modules.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Robert</name></author><category term="Linux" /><category term="Open Source Programs" /><summary type="html">Getting VMWare Workstation Player 14 (the free one) to work with Packer on Ubuntu 16.04 is possible and not very difficult, however it is very undocumented. In order to get it working you will need a few different packages, listed below</summary></entry><entry><title type="html">Enabling Poltergeist inspector while using capybara accessible + cucumber rails</title><link href="http://wiredtron.com/2017/04/25/enabling-poltergeist-inspector-while-using-capybara-accessible-cucumber-rails/" rel="alternate" type="text/html" title="Enabling Poltergeist inspector while using capybara accessible + cucumber rails" /><published>2017-04-25T18:51:45+00:00</published><updated>2017-04-25T18:51:45+00:00</updated><id>http://wiredtron.com/2017/04/25/enabling-poltergeist-inspector-while-using-capybara-accessible-cucumber-rails</id><content type="html" xml:base="http://wiredtron.com/2017/04/25/enabling-poltergeist-inspector-while-using-capybara-accessible-cucumber-rails/">&lt;p&gt;I know this is a very specific toolset to be using and doesn’t affect many people, however it took me some time to get it working so it seems that it may be worth documenting. If you are working on a project that uses rails + cucumber + capybara accessible + poltergeist for automated in browser tests and want the ability to use the poltergeist &lt;a href=&quot;https://github.com/teampoltergeist/poltergeist#remote-debugging-experimental&quot;&gt;remote debugging feature&lt;/a&gt; then you are in luck. Add the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;features/support/env.rb&lt;/code&gt;&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;Capybara.register_driver :poltergeist_debug do |app|
  driver = Capybara::Poltergeist::Driver.new(app, inspector: true)
  adaptor = Capybara::Accessible::SeleniumDriverAdapter.new
  Capybara::Accessible.setup(driver, adaptor)
end&lt;/pre&gt;

&lt;p&gt;Next update your Capabara default_driver and javascript_driver to use your newly registered driver:&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot; data-start-line=&quot;1&quot; data-visibility=&quot;visible&quot; data-highlight=&quot;&quot; data-caption=&quot;&quot;&gt;Capybara.default_driver    = :poltergeist_debug
Capybara.javascript_driver = :poltergeist_debug&lt;/pre&gt;

&lt;p&gt;Once the above code is inserted you can then follow the instructions on the poltergeist wiki on how to attach to the remote debugger.&lt;/p&gt;</content><author><name>Robert</name></author><category term="Other" /><summary type="html">I know this is a very specific toolset to be using and doesn’t affect many people, however it took me some time to get it working so it seems that it may be worth documenting. If you are working on a project that uses rails + cucumber + capybara accessible + poltergeist for automated in browser tests and want the ability to use the poltergeist remote debugging feature then you are in luck. Add the following to your features/support/env.rb</summary></entry><entry><title type="html">Setting up MaaS + Juju on one Node on Ubuntu (using Virsh)</title><link href="http://wiredtron.com/2016/08/18/setting-up-maas-juju-on-one-node-on-ubuntu-using-virsh/" rel="alternate" type="text/html" title="Setting up MaaS + Juju on one Node on Ubuntu (using Virsh)" /><published>2016-08-18T12:17:30+00:00</published><updated>2016-08-18T12:17:30+00:00</updated><id>http://wiredtron.com/2016/08/18/setting-up-maas-juju-on-one-node-on-ubuntu-using-virsh</id><content type="html" xml:base="http://wiredtron.com/2016/08/18/setting-up-maas-juju-on-one-node-on-ubuntu-using-virsh/">&lt;p&gt;Using MaaS and Juju to deploy Openstack on Ubuntu is pretty easy to do, however often requires a large number of machine sitting around in order to host everything. Fortunately it is possible to run your Juju controller alongside your MaaS machine using virsh. For the purpose of this guide we will be using MaaS 2.0 and Juju 2.0.&lt;/p&gt;

&lt;p&gt;First you will need to install MaaS and get it working. In my case I have 2 interfaces, my private interface which is managed by MaaS and my public interface which is managed by my router. My initial config looked as follows:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;# The loopback network interface&lt;/p&gt;

  &lt;p&gt;auto lo&lt;/p&gt;

  &lt;p&gt;iface lo inet loopback&lt;/p&gt;

  &lt;p&gt;# MaaS network interface&lt;/p&gt;

  &lt;p&gt;auto eth0&lt;/p&gt;

  &lt;p&gt;iface eth0 inet static&lt;/p&gt;

  &lt;p&gt;address 172.16.0.1&lt;/p&gt;

  &lt;p&gt;netmask 255.255.0.0&lt;/p&gt;

  &lt;p&gt;# The primary network interface&lt;/p&gt;

  &lt;p&gt;auto eth1&lt;/p&gt;

  &lt;p&gt;iface eth1 inet dhcp&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This config worked fine for commissioning machines inside MaaS, however it failed when I went to create a virtual machine on my MaaS node to run Juju. In order to get virtual machines working I had to do the following:&lt;/p&gt;

&lt;p&gt;Install virsh and other required packages:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p class=&quot;p1&quot;&gt;
  &lt;span class=&quot;s1&quot;&gt;sudo apt-get -y &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; libvirt-bin &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;linux-image-extra-virtual &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;kvm virt-manager&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p class=&quot;p1&quot;&gt;
  Add the MaaS user to the libvirtd group:
&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p class=&quot;p1&quot;&gt;
  &lt;span class=&quot;s1&quot;&gt;sudo &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;usermod&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; -G libvirtd -a maas&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p class=&quot;p1&quot;&gt;
  Update my networking config to look as follows:
&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p class=&quot;p1&quot;&gt;
  &lt;span class=&quot;s1&quot;&gt;# The loopback network interface&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;auto lo&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;iface lo inet loopback&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;iface enp9s0f0 inet manual&lt;/span&gt;
&lt;/p&gt;

  &lt;p class=&quot;p1&quot;&gt;
  &lt;span class=&quot;s1&quot;&gt;# The primary network interface&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;auto enp9s0f1&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;iface enp9s0f1 inet dhcp&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;auto br0&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;iface br0 inet static&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;bridge_ports enp9s0f0&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;address 172.16.0.1&lt;br /&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;    &lt;/span&gt;netmask 255.255.0.0&lt;/span&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p class=&quot;p1&quot;&gt;
  After updating your config, &lt;strong&gt;reboot the MaaS machine!&lt;/strong&gt; This step is very important as networking will not work until this step is completed.
&lt;/p&gt;

&lt;p class=&quot;p1&quot;&gt;
  Finally, I was then able to spin up a virtual machine using the following command:
&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p class=&quot;p1&quot;&gt;
  virt-install \&lt;br /&gt; &amp;#8211;name Juju-Controller-Node \&lt;br /&gt; &amp;#8211;ram 8192 \&lt;br /&gt; &amp;#8211;disk path=/var/kvm/images/Juju-Controller-Node.img,size=150 \&lt;br /&gt; &amp;#8211;network=bridge:br0 \&lt;br /&gt; &amp;#8211;vcpus 4 \&lt;br /&gt; &amp;#8211;os-type linux \&lt;br /&gt; &amp;#8211;os-variant ubuntu16.04 \&lt;br /&gt; &amp;#8211;graphics none \&lt;br /&gt; &amp;#8211;pxe \&lt;br /&gt; &amp;#8211;accelerate \&lt;br /&gt; &amp;#8211;boot network
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p class=&quot;p1&quot;&gt;
  Success! The node then showed up in MaaS. I then configured the power settings on the newly added machine to look as follows:
&lt;/p&gt;

&lt;p class=&quot;p1&quot;&gt;
  &lt;a href=&quot;http://wiredtron.com/2016/08/18/setting-up-maas-juju-on-one-node-on-ubuntu-using-virsh/screen-shot-2016-08-18-at-12-15-06-pm/&quot; rel=&quot;attachment wp-att-544&quot;&gt;&lt;img class=&quot;size-medium wp-image-544 alignnone&quot; src=&quot;http://wiredtron.com/wp-content/uploads/2016/08/Screen-Shot-2016-08-18-at-12.15.06-PM-300x152.png&quot; alt=&quot;Screen Shot 2016-08-18 at 12.15.06 PM&quot; width=&quot;300&quot; height=&quot;152&quot; srcset=&quot;https://wiredtron.com/wp-content/uploads/2016/08/Screen-Shot-2016-08-18-at-12.15.06-PM-300x152.png 300w, https://wiredtron.com/wp-content/uploads/2016/08/Screen-Shot-2016-08-18-at-12.15.06-PM-768x388.png 768w, https://wiredtron.com/wp-content/uploads/2016/08/Screen-Shot-2016-08-18-at-12.15.06-PM-1024x518.png 1024w, https://wiredtron.com/wp-content/uploads/2016/08/Screen-Shot-2016-08-18-at-12.15.06-PM.png 1116w&quot; sizes=&quot;(max-width: 300px) 100vw, 300px&quot; /&gt;&lt;br /&gt; &lt;/a&gt;I was then able to commission and deploy the node successfully.
&lt;/p&gt;</content><author><name>Robert</name></author><category term="Uncategorized" /><summary type="html">Using MaaS and Juju to deploy Openstack on Ubuntu is pretty easy to do, however often requires a large number of machine sitting around in order to host everything. Fortunately it is possible to run your Juju controller alongside your MaaS machine using virsh. For the purpose of this guide we will be using MaaS 2.0 and Juju 2.0.</summary></entry></feed>