<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Dan C Williams</title>
    <link>https://dancwilliams.com/</link>
    <description>Recent content on Dan C Williams</description>
    <generator>Hugo -- 0.152.2</generator>
    <language>en</language>
    <copyright>Copyright © 2008–2025, Dan C Williams; all rights reserved.</copyright>
    <lastBuildDate>Sat, 20 Jan 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://dancwilliams.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Using Actionable Notifications in Home Assistant</title>
      <link>https://dancwilliams.com/using-actionable-notifications-in-home-assistant/</link>
      <pubDate>Sat, 20 Jan 2024 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/using-actionable-notifications-in-home-assistant/</guid>
      <description>&lt;p&gt;This post has been updated to use the latest and greatest from Home Assistant.  There are no more categories and things are MUCH more streamlined!&lt;/p&gt;
&lt;p&gt;In this post I will cover how I use &lt;a href=&#34;https://home-assistant.io/docs/ecosystem/ios/notifications/actions/&#34;&gt;actionable notifications&lt;/a&gt; within &lt;a href=&#34;https://home-assistant.io&#34;&gt;Home Assistant&lt;/a&gt;.  Using &lt;a href=&#34;https://home-assistant.io/docs/ecosystem/ios/notifications/&#34;&gt;push notifications&lt;/a&gt; with the &lt;a href=&#34;https://home-assistant.io/docs/ecosystem/ios/&#34;&gt;Home Assistant iOS App&lt;/a&gt; you can setup some really cool triggers within the system.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Below is a list of the technology used at the time of writing:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://home-assistant.io&#34;&gt;&lt;em&gt;Home Assistant&lt;/em&gt;&lt;/a&gt; &lt;em&gt;- Version 2024.1.4&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.apple.com/iphone/&#34;&gt;&lt;em&gt;Apple iPhone 13 Pro and iPhone 15 Pro&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Apple iOS 17.3&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have two actionable notifications that get used most often:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This post has been updated to use the latest and greatest from Home Assistant.  There are no more categories and things are MUCH more streamlined!</p>
<p>In this post I will cover how I use <a href="https://home-assistant.io/docs/ecosystem/ios/notifications/actions/">actionable notifications</a> within <a href="https://home-assistant.io">Home Assistant</a>.  Using <a href="https://home-assistant.io/docs/ecosystem/ios/notifications/">push notifications</a> with the <a href="https://home-assistant.io/docs/ecosystem/ios/">Home Assistant iOS App</a> you can setup some really cool triggers within the system.</p>
<p><em>Below is a list of the technology used at the time of writing:</em></p>
<ul>
<li><a href="https://home-assistant.io"><em>Home Assistant</em></a> <em>- Version 2024.1.4</em></li>
<li><a href="https://www.apple.com/iphone/"><em>Apple iPhone 13 Pro and iPhone 15 Pro</em></a></li>
<li><em>Apple iOS 17.3</em></li>
</ul>
<p>I have two actionable notifications that get used most often:</p>
<ol>
<li>
<p>At 6AM I receive a push notification that asks if I am working from home today.</p>
<ul>
<li><code>Yes</code> and <code>No</code> options are presented</li>
<li>If I answer <code>Yes</code>, it will turn on the AC in my office and set the proper temperature based on the temperature outside.</li>
</ul>
</li>
<li>
<p>On days when my wife and I go into our &ldquo;<em>real</em>&rdquo; offices we will receive a notification when we leave in the evening and the house is set to away.  This notification asks if you are headed home.</p>
<ul>
<li><code>Yes</code> and <code>No</code> options are presented</li>
<li>If <code>Yes</code> is selected, it will set the air conditioner to the home setting to cool/heat the house in advance.</li>
</ul>
</li>
</ol>
<p>We will use my &ldquo;Are you working from home today?&rdquo; notification as the example[^1].</p>
<h4 id="step-one">Step One:</h4>
<p>I have an automation configured to send me a message asking if I am working from home on <code>weekdays</code> at <code>6AM</code> if the house is in <code>sleep</code> mode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">alias</span>: <span style="color:#ae81ff">Ask if Dan is working from home in the morning - Weekday</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">condition</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">condition</span>: <span style="color:#ae81ff">and</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">conditions</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">condition</span>: <span style="color:#ae81ff">state</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_select.home_state</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">state</span>: <span style="color:#ae81ff">sleep</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">condition</span>: <span style="color:#ae81ff">time</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">weekday</span>:
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">mon</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">tue</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">wed</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">thu</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">fri</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">trigger</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">time</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">at</span>: <span style="color:#e6db74">&#39;06:00:00&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">action</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">service</span>: <span style="color:#ae81ff">notify.mobile_app_daniels_iphone</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">message</span>: <span style="color:#e6db74">&#34;Are you working from home today?&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">actions</span>:
</span></span><span style="display:flex;"><span>          - <span style="color:#f92672">action</span>: <span style="color:#ae81ff">‘WORKING_FROM_HOME_YES’</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">title</span>: <span style="color:#ae81ff">‘Yes’</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">destructive</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#f92672">identifier</span>: <span style="color:#ae81ff">‘WORKING_FROM_HOME_NO’</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">title</span>: <span style="color:#ae81ff">‘No’</span>
</span></span></code></pre></div><h4 id="step-two">Step Two:</h4>
<p>This is where the rubber meets the road!</p>
<p>In this case the <code>No</code> option does nothing.  The notification will close on the phone and that is all.  But, &lsquo;Yes&rsquo; will trigger an automation in Home Assistant.</p>
<p>Here is the automation that is triggered when <code>Yes</code> is selected:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">alias</span>: <span style="color:#ae81ff">iOS Action - Working From Home Yes</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">trigger</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">event</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">event_type</span>: <span style="color:#ae81ff">mobile_app_notification_action</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">event_data</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">action</span>: <span style="color:#ae81ff">WORKING_FROM_HOME_YES</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">action</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">input_select.select_option</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_select.office_ac_power</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">option</span>: <span style="color:#e6db74">&#39;on&#39;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">input_select.select_option</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data_template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_select.office_ac_mode</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">option</span>: &gt;<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          {% if (states(&#34;sensor.dark_sky_temperature&#34;) | int) &lt; 65 %}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          heat
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          {% else %}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          cool
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          {% endif %}</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">input_number.set_value</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_number.office_ac_temperature</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">value</span>: <span style="color:#ae81ff">72</span>
</span></span></code></pre></div><p>Under the trigger <code>event_data</code> you will see that the <code>action</code> corresponds to the <code>action</code> used in Step One.  When <code>Yes</code> was selected it kicked off the automation to turn on the AC in my office and set the mode based on the outside temperature.  It has worked great!</p>
<h2 id="important-notes">IMPORTANT NOTES!</h2>
<h3 id="interacting-with-push-notifications">Interacting with Push Notifications:</h3>
<p>When you receive a notification on you iPhone, <strong>do not just tap on it!</strong>  <mark>This will open the Home Assistant app and not present your options!</mark></p>
<p>You can, however, tap notifications on your Apple Watch.  See explanations below:</p>
<h4 id="on-iphone">On iPhone:</h4>
<ul>
<li>
<p><strong>While phone is locked</strong>:</p>
<ul>
<li>
<p>Your received notification will look like this:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant/images/notification_while_locked_hu_3efdf315e3664066.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant/images/notification_while_locked_hu_227b506f75061edd.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant/images/notification_while_locked.jpg" 
          
          >
</li>
<li>
<p>Long press the notification to bring up the selection options</p>
</li>
<li>
<p>You will then be presented with your options:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant/images/locked_notification_options_hu_ea070786d1a2e88e.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant/images/locked_notification_options_hu_a23406af68947f46.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant/images/locked_notification_options.jpg" 
          
          >
</li>
</ul>
</li>
<li>
<p><strong>While phone is unlocked</strong>:</p>
<ul>
<li>
<p>Your received notification will look like this:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant/images/notification_while_using_hu_5773e549ff04ec38.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant/images/notification_while_using_hu_56f881f56881be24.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant/images/notification_while_using.jpg" 
          
          >
</li>
<li>
<p>Swipe down on the notification and you will be presented with your options:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant/images/unlocked_notification_options_hu_5455adc0a1dd27a4.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant/images/unlocked_notification_options_hu_6aac1003b7c49fb3.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant/images/unlocked_notification_options.jpg" 
          
          >
</li>
</ul>
</li>
</ul>
<h4 id="on-apple-watch">On Apple Watch:</h4>
<ul>
<li>
<p>Your received notification will look like this:</p>

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  <img 
    sizes="(min-width: 35em) 1200px, 100vw"
    srcset='
    
    
    
    '
    
      src="/using-actionable-notifications-in-home-assistant/images/watch_notification.jpg" 
    
    >
</li>
<li>
<p>Tap the notification to receive your options:</p>

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  <img 
    sizes="(min-width: 35em) 1200px, 100vw"
    srcset='
    
    
    
    '
    
      src="/using-actionable-notifications-in-home-assistant/images/watch_tap.jpg" 
    
    >
</li>
</ul>
<h3 id="summary">Summary</h3>
<p>This is covered often in the <a href="https://community.home-assistant.io">Home Assistant Community</a> and I just wanted to get my configuration out in hopes that others will find it useful.  If you have any questions feel free to leave a comment.</p>
<p>Thanks for reading!</p>
]]></content:encoded>
    </item>
    <item>
      <title>HomePod Mini Stuck in Setting Up</title>
      <link>https://dancwilliams.com/homepod-mini-stuck-in-setting-up/</link>
      <pubDate>Sun, 05 Dec 2021 10:05:00 -0600</pubDate>
      <guid>https://dancwilliams.com/homepod-mini-stuck-in-setting-up/</guid>
      <description>&lt;p&gt;I recently purchased an Apple HomePod Mini off of eBay to add to the ever expanding setup at our home.  We already have 6 or so scattered around so adding another should not have been an issue.  But, as with all things tech, sometimes it doesn&amp;rsquo;t go as planned.  I plugged in the Mini and it powered up fine and my phone discovered it.  I began the setup process and then things went sideways.  I got to the &amp;ldquo;setting up&amp;quot;screen and it just stayed there for as long as I would leave it, even overnight!  I checked everything.  I made sure I had network connectivity, made sure it was getting a DHCP address, made sure no filtering was catching anything&amp;hellip;on and on with the typical troubleshooting for network issues.  Still, nothing seemed to solve the issue.  I performed multiple resets of the HomePod to no positive result.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I recently purchased an Apple HomePod Mini off of eBay to add to the ever expanding setup at our home.  We already have 6 or so scattered around so adding another should not have been an issue.  But, as with all things tech, sometimes it doesn&rsquo;t go as planned.  I plugged in the Mini and it powered up fine and my phone discovered it.  I began the setup process and then things went sideways.  I got to the &ldquo;setting up&quot;screen and it just stayed there for as long as I would leave it, even overnight!  I checked everything.  I made sure I had network connectivity, made sure it was getting a DHCP address, made sure no filtering was catching anything&hellip;on and on with the typical troubleshooting for network issues.  Still, nothing seemed to solve the issue.  I performed multiple resets of the HomePod to no positive result.</p>
<p>Googling brought littel feedback.  Then I got deep into some searches and ran across <a href="https://www.reddit.com/r/HomePod/comments/q3n806/homepod_mini_stuck_setting_up/">this Reddit article</a>.  Since Reddit always tries to force you to use the app when on mobile and doesn&rsquo;t let you completely read a post before blocking you out I wanted to post my steps here for future reference.  This should be better outlined in the Apple troubleshooting steps as it did fix things right up!  But, I am lucky to have a Mac to perform these steps.  If you are without a Mac I am not sure what the fix action would be.</p>
<h3 id="step-one---plug-the-homepod-mini-into-mac">Step One - Plug the HomePod Mini Into Mac</h3>
<p>I have an M1 MacBook Air and was able to plug the HomePod directly into a USB C port.  After the light on the HomePod turned orange I checked finder and say the HomePod connected.  Once I clicked ont he device I confirmed that the device had the version 14 OS whereas the rest of the house was on 15.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /homepod-mini-stuck-in-setting-up/images/1_hu_8f5abb463ae24a00.png 500w
  
  
    , /homepod-mini-stuck-in-setting-up/images/1_hu_c4c8fe94c191b258.png 800w
  
  
    , /homepod-mini-stuck-in-setting-up/images/1_hu_fa17cfa7d2546e27.png 1200w
  
  
    , /homepod-mini-stuck-in-setting-up/images/1_hu_6ff7503c97c21075.png 1500w 
  '
  
    src="/homepod-mini-stuck-in-setting-up/images/1.png" 
  
  alt='Mac Finder showing Mini with OS version 14.2'>
<h3 id="step-two---restore-and-update">Step Two - Restore and Update</h3>
<p>I then pressed the &ldquo;Restore HomePod&rdquo; button and kicekd of the Restore and Update process.  I acknowledge the popup to confirm the factory restore and update process:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /homepod-mini-stuck-in-setting-up/images/2_hu_557aa1d72d770a77.png 500w
  
  
  
  '
  
    src="/homepod-mini-stuck-in-setting-up/images/2.png" 
  
  alt='Pop up after hitting the restore HomePod button'>
<p>It then let me know that the HomePod Mini would be updated to OS 15.1.  Great!  Click Next!</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /homepod-mini-stuck-in-setting-up/images/3_hu_2c82caee655949d8.png 500w
  
  
    , /homepod-mini-stuck-in-setting-up/images/3_hu_5751b9af101a174b.png 800w
  
  
  '
  
    src="/homepod-mini-stuck-in-setting-up/images/3.png" 
  
  alt='Window confirming update will go to OS verion 15.1'>
<h3 id="step-three---update-completion-and-reboot">Step Three - Update Completion and Reboot</h3>
<p>After clicking next your Mac will download the new OS version and begin flashing the HomePod and restoring factory settings:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /homepod-mini-stuck-in-setting-up/images/4_hu_262d0144e5d4dc91.png 500w
  
  
    , /homepod-mini-stuck-in-setting-up/images/4_hu_1917d6982e939423.png 800w
  
  
    , /homepod-mini-stuck-in-setting-up/images/4_hu_44d11fbc2da8566b.png 1200w
  
  
    , /homepod-mini-stuck-in-setting-up/images/4_hu_d3928ce7e88e81cc.png 1500w 
  '
  
    src="/homepod-mini-stuck-in-setting-up/images/4.png" 
  
  alt='Mac downloads and flashed HomePod Mini'>
<p>After the process is complete you will receive the following popup:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /homepod-mini-stuck-in-setting-up/images/5_hu_f360de2f835d28c7.png 500w
  
  
  
  '
  
    src="/homepod-mini-stuck-in-setting-up/images/5.png" 
  
  alt='Confirmation popup that process is complete'>
<p>After acknowledging the popup you will see the same screen as at the beginning with the updated OS showing:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /homepod-mini-stuck-in-setting-up/images/6_hu_8186949c0d4033e.png 500w
  
  
    , /homepod-mini-stuck-in-setting-up/images/6_hu_6e1a7ef105037b36.png 800w
  
  
    , /homepod-mini-stuck-in-setting-up/images/6_hu_f0292498ca6df89e.png 1200w
  
  
    , /homepod-mini-stuck-in-setting-up/images/6_hu_2c92dc594fd55b3b.png 1500w 
  '
  
    src="/homepod-mini-stuck-in-setting-up/images/6.png" 
  
  alt='Mac Finder showing Mini with OS version 15.1.1'>
<h3 id="summary">Summary</h3>
<p>That is all!  Just eject the HomePod from your system and go through the typical setup process.  It worked like a charm for me.</p>
<p>If you happen upon how to perform this is you do not have a Mac I would love to know.  Please comment below and I will update the post.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Monitoring TeslaFi in Home Assistant</title>
      <link>https://dancwilliams.com/monitoring-teslafi-in-home-assistant/</link>
      <pubDate>Tue, 27 Jul 2021 10:32:00 -0500</pubDate>
      <guid>https://dancwilliams.com/monitoring-teslafi-in-home-assistant/</guid>
      <description>&lt;p&gt;When I had my Tesla Model Y I had it hooked up to &lt;a href=&#34;https://teslafi.com&#34;&gt;TeslaFi&lt;/a&gt;.  There were a lot of stats in there and I wanted to expose some of that data in Home Assistant for easy consumption.  I also wanted to utilize the TeslaFi API to allow me to turn on the climate controls in my Tesla using Home Assistant and any voice control devices that I may be utilizing (Siri in my case).  I wanted to capture my config in case it helps someone else.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>When I had my Tesla Model Y I had it hooked up to <a href="https://teslafi.com">TeslaFi</a>.  There were a lot of stats in there and I wanted to expose some of that data in Home Assistant for easy consumption.  I also wanted to utilize the TeslaFi API to allow me to turn on the climate controls in my Tesla using Home Assistant and any voice control devices that I may be utilizing (Siri in my case).  I wanted to capture my config in case it helps someone else.</p>
<h3 id="sensor-for-teslafi-api">Sensor for TeslaFi API</h3>
<p>This REST sensor will poll the TeslaFi API and expose all JSON items as attributes in Home Assistant:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#75715e"># TeslaFi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">rest</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">name</span>: <span style="color:#ae81ff">TeslaFi Report</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">resource</span>: <span style="color:#e6db74">&#34;https://www.teslafi.com/feed.php&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">scan_interval</span>: <span style="color:#ae81ff">60</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">params</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">token</span>: <span style="color:#ae81ff">YOUR TESLAFI API TOKEN HERE</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">command</span>: <span style="color:#ae81ff">lastGood</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">value_template</span>: <span style="color:#e6db74">&#34;{{ value_json.display_name }}&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">json_attributes</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">api_version</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">autopark_state</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">autopark_state_v2</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">autopark_style</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">battery_current</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">battery_heater</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">battery_heater_on</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">battery_level</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">battery_range</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">calendar_enabled</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">calendar_supported</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">car_type</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">car_version</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">carState</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">center_display_state</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_current_request</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_current_request_max</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_enable_request</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_energy_added</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_limit_soc</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_limit_soc_max</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_limit_soc_min</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_limit_soc_std</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_miles_added_ideal</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_miles_added_rated</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_port_cold_weather_mode</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_port_door_open</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_port_latch</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_port_led_color</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_rate</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charge_to_max_range</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">chargeNumber</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charger_actual_current</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charger_phases</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charger_pilot_current</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charger_power</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charger_voltage</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">charging_state</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">climate_keeper_mode</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">color</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">conn_charge_cable</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">currency</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">data_id</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">Date</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">defrost_mode</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">df</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">display_name</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">dr</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">driveNumber</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">driver_temp_setting</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">driver_temp_settingF</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">elevation</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">est_battery_range</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">eu_vehicle</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">exterior_color</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">fan_status</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">fast_charger_brand</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">fast_charger_present</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">fast_charger_type</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">fd_window</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">fp_window</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">ft</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">gps_as_of</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">gui_24_hour_time</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">gui_charge_rate_units</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">gui_distance_units</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">gui_range_display</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">gui_temperature_units</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">heading</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">homelink_nearby</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">id</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">id_s</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">ideal_battery_range</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">idleNumber</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">idleTime</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">in_service</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">inside_temp</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">inside_tempF</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">is_auto_conditioning_on</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">is_climate_on</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">is_front_defroster_on</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">is_preconditioning</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">is_rear_defroster_on</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">is_user_present</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">last_autopark_error</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">latitude</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">left_temp_direction</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">location</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">locked</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">longitude</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">managed_charging_active</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">managed_charging_start_time</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">managed_charging_user_canceled</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">max_avail_temp</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">max_range_charge_counter</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">maxRange</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">measure</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">min_avail_temp</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">motorized_charge_port</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">newVersion</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">newVersionStatus</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">not_enough_power_to_heat</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">Notes</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">notifications_enabled</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">notifications_supported</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">odometer</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">odometerF</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">option_codes</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">outside_temp</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">outside_tempF</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">parsed_calendar_supported</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">passenger_temp_setting</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">perf_config</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">pf</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">polling</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">power</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">pr</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">rangeDisplay</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">rd_window</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">rear_seat_heaters</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">remote_start</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">remote_start_enabled</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">remote_start_supported</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">rhd</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">right_temp_direction</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">roof_color</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">rp_window</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">rt</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">scheduled_charging_pending</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">scheduled_charging_start_time</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_left</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_rear_center</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_rear_left</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_rear_left_back</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_rear_right</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_rear_right_back</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_heater_right</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">seat_type</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">sentry_mode</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">shift_state</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">side_mirror_heaters</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">sleepNumber</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">smart_preconditioning</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">speed</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">spoiler_type</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">state</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">steering_wheel_heater</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">sun_roof_installed</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">sun_roof_percent_open</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">sun_roof_state</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">temperature</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">third_row_seats</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">time_to_full_charge</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">timestamp</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">trip_charging</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">usable_battery_level</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">user_charge_enable_request</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">valet_mode</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">valet_pin_needed</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">vehicle_id</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">vehicle_name</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">vin</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">wheel_type</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">wiper_blade_heater</span>
</span></span></code></pre></div><h3 id="template-sensors">Template Sensors</h3>
<p>I then created a few template sensors to expose data I would use later on or wanted to see/track more quickly.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">binary_sensor</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">unique_id</span>: <span style="color:#ae81ff">teslafi_terry_hvac_status</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;vehicle_name&#39;) + &#39; HVAC Status&#39; }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">state</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;is_climate_on&#39;) }}&#34;</span>
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">sensor</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">unique_id</span>: <span style="color:#ae81ff">teslafi_terry_date</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;vehicle_name&#39;) + &#39; Last Reading&#39; }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">state</span>: <span style="color:#e6db74">&#34;{{ as_datetime(state_attr(&#39;sensor.teslafi_report&#39;, &#39;Date&#39;)).isoformat() }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">device_class</span>: <span style="color:#ae81ff">timestamp</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">unique_id</span>: <span style="color:#ae81ff">teslafi_terry_odometer</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;vehicle_name&#39;) + &#39; Odometer&#39; }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">state</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;odometer&#39;) | round(1) }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">unit_of_measurement</span>: <span style="color:#e6db74">&#34;mi&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">icon</span>: <span style="color:#ae81ff">mdi:counter</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">unique_id</span>: <span style="color:#ae81ff">teslafi_terry_battery</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;vehicle_name&#39;) + &#39; Battery&#39; }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">state</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;battery_level&#39;) | int }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">unit_of_measurement</span>: <span style="color:#e6db74">&#34;%&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">icon</span>: <span style="color:#ae81ff">mdi:battery-80</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">unique_id</span>: <span style="color:#ae81ff">teslafi_terry_range</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;vehicle_name&#39;) + &#39; Battery Range&#39; }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">state</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;battery_range&#39;) | float }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">unit_of_measurement</span>: <span style="color:#e6db74">&#34;mi&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">icon</span>: <span style="color:#ae81ff">mdi:gauge</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">unique_id</span>: <span style="color:#ae81ff">teslafi_terry_car_state</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;vehicle_name&#39;) + &#39; Car State&#39; }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">state</span>: <span style="color:#e6db74">&#34;{{ state_attr(&#39;sensor.teslafi_report&#39;, &#39;carState&#39;) }}&#34;</span>
</span></span></code></pre></div><h3 id="switches">Switches</h3>
<p>I then created two switches to control the HVAC status of Terry the Tesla:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#75715e"># TeslaFi Switches</span>
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">command_line</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">switches</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">teslafi_terry_climate_cli</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">command_on</span>: <span style="color:#e6db74">&#39;/usr/bin/curl -X GET &#34;https://www.teslafi.com/feed.php?token=YOUR API TOKEN HERE&amp;command=auto_conditioning_start&amp;wake=40&#34;&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">command_off</span>: <span style="color:#e6db74">&#39;/usr/bin/curl -X GET &#34;https://www.teslafi.com/feed.php?token=YOUR API TOKEN HERE&amp;command=auto_conditioning_stop&#34;&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">friendly_name</span>: <span style="color:#ae81ff">Terry HVAC Command Line</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">template</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">switches</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">teslafi_terry_climate</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">friendly_name</span>: <span style="color:#ae81ff">Terry HVAC</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">value_template</span>: <span style="color:#e6db74">&#34;{{ is_state(&#39;binary_sensor.template_teslafi_terry_hvac_status&#39;, &#39;on&#39;) }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">turn_on</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">service</span>: <span style="color:#ae81ff">switch.turn_on</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">target</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">switch.teslafi_terry_climate_cli</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">turn_off</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">service</span>: <span style="color:#ae81ff">switch.turn_off</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">target</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">switch.teslafi_terry_climate_cli</span>
</span></span></code></pre></div><p>I hope this helps someone!  If you have any questions please ask in the comments.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Building a Wireguard Router...Easier Than I Thought!</title>
      <link>https://dancwilliams.com/building-a-wireguard-router/</link>
      <pubDate>Sat, 12 Oct 2019 15:51:00 -0500</pubDate>
      <guid>https://dancwilliams.com/building-a-wireguard-router/</guid>
      <description>&lt;p&gt;I have been seeing a lot of buzz about Wireguard.  I had considered setting up a server at home for external access just for fun, but all of the examples I saw used NAT behind the Wireguard box and I wanted to route entire subnets without NATing.  After I finally took some time and realized that Wireguard was just an interface and I would just be leveraging some &lt;code&gt;iptables&lt;/code&gt; it all came together rather quickly.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I have been seeing a lot of buzz about Wireguard.  I had considered setting up a server at home for external access just for fun, but all of the examples I saw used NAT behind the Wireguard box and I wanted to route entire subnets without NATing.  After I finally took some time and realized that Wireguard was just an interface and I would just be leveraging some <code>iptables</code> it all came together rather quickly.</p>
<p>First, I have to give some credit to all of the sites that helped me along the way:</p>
<ul>
<li><a href="https://wiki.archlinux.org/index.php/WireGuard">https://wiki.archlinux.org/index.php/WireGuard</a></li>
<li><a href="https://securityespresso.org/tutorials/2019/03/22/vpn-server-using-wireguard-on-ubuntu/">https://securityespresso.org/tutorials/2019/03/22/vpn-server-using-wireguard-on-ubuntu/</a></li>
<li><a href="https://emanuelduss.ch/2018/09/wireguard-vpn-road-warrior-setup/">https://emanuelduss.ch/2018/09/wireguard-vpn-road-warrior-setup/</a></li>
<li><a href="https://restoreprivacy.com/wireguard/">https://restoreprivacy.com/wireguard/</a></li>
<li><a href="https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/">https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/</a></li>
<li><a href="https://github.com/pirate/wireguard-docs">https://github.com/pirate/wireguard-docs</a></li>
</ul>
<p>Without these write ups I would have had a much longer journey.</p>
<p>In this post I will not be going into any theory.  This is just a run down of my setup and mostly notes to myself before I forget everything!</p>
<p>I am running this on a NUC that I use for <a href="https://www.home-assistant.io/hassio/">HASS.IO</a>.  It has a lot of horsepower and is already in my DMZ so I thought, why not.  This NUC is running Ubuntu 18.04 and was up to date when I started.  After making sure my box was up to date I performed the following steps:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo -s
</span></span><span style="display:flex;"><span>add-apt-repository ppa:wireguard/wireguard
</span></span><span style="display:flex;"><span>apt install qrencode
</span></span><span style="display:flex;"><span>apt install wireguard
</span></span><span style="display:flex;"><span>modprobe wireguard
</span></span><span style="display:flex;"><span>lsmod | grep wireguard <span style="color:#75715e"># This lets you know that the wireguard module is good to go.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt; EOF &gt;&gt; /etc/sysctl.conf  # These lines add forwarding capability to your server
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">net.ipv4.ip_forward=1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">net.ipv6.conf.all.forwarding=1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sysctl -p
</span></span></code></pre></div><p>This should get the system ready to go.  Now set the wireguard ser to start at bootup:</p>
<p><code>systemctl enable wg-quick@wg0</code></p>
<p>Now we move on to configuring the server.</p>
<p>Run the following commands to lay the groundwork:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd /etc/wireguard
</span></span><span style="display:flex;"><span>umask <span style="color:#ae81ff">077</span>
</span></span><span style="display:flex;"><span>wg genkey | sudo tee privatekey | wg pubkey | sudo tee publickey
</span></span></code></pre></div><p>Next use you favorite text editor to create the <code>wg0.conf</code> file.  Here is an example of mine:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>[<span style="color:#a6e22e">Interface</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Address</span> = <span style="color:#ae81ff">172</span>.<span style="color:#ae81ff">24</span>.<span style="color:#ae81ff">1</span>.<span style="color:#ae81ff">1</span>/<span style="color:#ae81ff">24</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">SaveConfig</span> = <span style="color:#a6e22e">true</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PostUp</span> = <span style="color:#a6e22e">iptables</span> -<span style="color:#a6e22e">A</span> <span style="color:#a6e22e">FORWARD</span> -<span style="color:#a6e22e">i</span> <span style="color:#a6e22e">wg0</span> -<span style="color:#a6e22e">j</span> <span style="color:#a6e22e">ACCEPT</span>; <span style="color:#a6e22e">iptables</span> -<span style="color:#a6e22e">A</span> <span style="color:#a6e22e">FORWARD</span> -<span style="color:#a6e22e">i</span> <span style="color:#a6e22e">eno1</span>.<span style="color:#ae81ff">11</span> -<span style="color:#a6e22e">j</span> <span style="color:#a6e22e">ACCEPT</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PostDown</span> = <span style="color:#a6e22e">iptables</span> -<span style="color:#a6e22e">D</span> <span style="color:#a6e22e">FORWARD</span> -<span style="color:#a6e22e">i</span> <span style="color:#a6e22e">wg0</span> -<span style="color:#a6e22e">j</span> <span style="color:#a6e22e">ACCEPT</span>; <span style="color:#a6e22e">iptables</span> -<span style="color:#a6e22e">D</span> <span style="color:#a6e22e">FORWARD</span> -<span style="color:#a6e22e">i</span> <span style="color:#a6e22e">eno1</span>.<span style="color:#ae81ff">11</span> -<span style="color:#a6e22e">j</span> <span style="color:#a6e22e">ACCEPT</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ListenPort</span> = <span style="color:#ae81ff">51820</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PrivateKey</span> = &lt; <span style="color:#a6e22e">use</span> <span style="color:#a6e22e">privatekey</span> <span style="color:#a6e22e">generated</span> <span style="color:#a6e22e">in</span> <span style="color:#a6e22e">previous</span> <span style="color:#a6e22e">step</span> &gt;
</span></span></code></pre></div><p><em>You will need to adjust the interface in the <code>iptables</code> statement to reflect your interface name.  I used <code>eno1.11</code> on my server.</em></p>
<p>I have been asked about locking down the server some more using <code>iptables</code>.  It is definitely possible!  <a href="https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/">Here is a good example post</a>.  I have my server behind pfSense which helps me keep it locked down and that is why I used the <code>iptables</code> config above.</p>
<p>In this setup you will not perform any NAT.  You will ahve to ensure routing is setup properly in your environment since this will route your VPN user IPs straight through.  I use <code>pfSense</code> and have static routing setup to allow the proper flow of traffic.  It also helps me lock down access.</p>
<p>Now you can run <code>wg-quick up wg0</code> to bring up your wireguard interface.  Too easy!</p>
<p>Now to configure a client.  I use the wireguard app on my iPad and iPhone, so I will go through an example of how I configure a client for that.</p>
<p>First, I create a directory for my device.  This is not required, I do it for my own sanity.  Since we are still in <code>/etc/wireguard</code> i run <code>mkdir dan_iphone</code> then switch into that directory.  Next things look familiar:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd dan_iphone/
</span></span><span style="display:flex;"><span>umask <span style="color:#ae81ff">077</span>
</span></span><span style="display:flex;"><span>wg genkey | sudo tee privatekey | wg pubkey | sudo tee publickey
</span></span></code></pre></div><p>Now I create a file named <code>dan_iphone.conf</code>.  See example below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>[<span style="color:#a6e22e">Interface</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Address</span> = <span style="color:#ae81ff">172</span>.<span style="color:#ae81ff">24</span>.<span style="color:#ae81ff">1</span>.<span style="color:#ae81ff">2</span>/<span style="color:#ae81ff">24</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PrivateKey</span> = &lt; <span style="color:#a6e22e">use</span> <span style="color:#a6e22e">privatekey</span> <span style="color:#a6e22e">generated</span> <span style="color:#a6e22e">in</span> <span style="color:#a6e22e">previous</span> <span style="color:#a6e22e">step</span> &gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Peer</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Endpoint</span> = &lt; <span style="color:#a6e22e">Your</span> <span style="color:#a6e22e">server</span> <span style="color:#a6e22e">name</span> <span style="color:#a6e22e">or</span> <span style="color:#a6e22e">IP</span> &gt;:<span style="color:#ae81ff">51820</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PublicKey</span> = &lt; <span style="color:#a6e22e">Your</span> <span style="color:#a6e22e">server</span>&#39;<span style="color:#a6e22e">s</span> <span style="color:#a6e22e">public</span> <span style="color:#a6e22e">key</span> &gt;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">AllowedIPs</span> = <span style="color:#ae81ff">172</span>.<span style="color:#ae81ff">24</span>.<span style="color:#ae81ff">1</span>.<span style="color:#ae81ff">1</span><span style="color:#e6db74">/32, 192.168.0.0/</span><span style="color:#ae81ff">24</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PersistentKeepalive</span> = <span style="color:#ae81ff">25</span>
</span></span></code></pre></div><p>For allowed IPs use whatever you need for access to your network or <code>0.0.0.0/0</code> for a full tunnel experience.</p>
<p>You will need to run the following command on the server to add this peer:</p>
<p><code>wg set wg0 peer &lt; peer public key &gt; allowed-ips 172.24.1.2/32</code></p>
<p>Now generate a QR code to configure the Wireguard App on your iPhone:</p>
<p><code>qrencode -t ansiutf8 &lt; dan_iphone.conf</code></p>
<p>You can also output this to a file if you need to ship it off for some reason:</p>
<p><code>qrencode -t ansiutf8 -o dan_iphone.jpg &lt; dan_iphone.conf</code></p>
<p>Once your phone is configured you will be good to go!</p>
<p>To delete a peer do the following (while the <code>wg0</code> interface is up):</p>
<p><code>wg set wg0 peer &lt;peer_pubkey&gt; remove</code></p>
<p>I also added the piece pointed out in the <a href="https://wiki.archlinux.org/index.php/WireGuard#Endpoint_with_changing_IP">Archlinux Wireguard Page</a> to deal with changing IPs.  Since I am using this on phones and mobile hotspots, this could be an issue.</p>
<p>Here are the two files I created:</p>
<p><code>/etc/systemd/system/wireguard_reresolve-dns.timer</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>[<span style="color:#a6e22e">Unit</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Description</span>=<span style="color:#a6e22e">Periodically</span> <span style="color:#a6e22e">reresolve</span> <span style="color:#a6e22e">DNS</span> <span style="color:#a6e22e">of</span> <span style="color:#a6e22e">all</span> <span style="color:#a6e22e">WireGuard</span> <span style="color:#a6e22e">endpoints</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Timer</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">OnCalendar</span>=*:*:<span style="color:#ae81ff">0</span>/<span style="color:#ae81ff">30</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Install</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">WantedBy</span>=<span style="color:#a6e22e">timers</span>.<span style="color:#a6e22e">target</span>
</span></span></code></pre></div><p><code>/etc/systemd/system/wireguard_reresolve-dns.service</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>[<span style="color:#a6e22e">Unit</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Description</span>=<span style="color:#a6e22e">Reresolve</span> <span style="color:#a6e22e">DNS</span> <span style="color:#a6e22e">of</span> <span style="color:#a6e22e">all</span> <span style="color:#a6e22e">WireGuard</span> <span style="color:#a6e22e">endpoints</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Wants</span>=<span style="color:#a6e22e">network</span>-<span style="color:#a6e22e">online</span>.<span style="color:#a6e22e">target</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">After</span>=<span style="color:#a6e22e">network</span>-<span style="color:#a6e22e">online</span>.<span style="color:#a6e22e">target</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">Service</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Type</span>=<span style="color:#a6e22e">oneshot</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ExecStart</span>=<span style="color:#e6db74">/bin/</span><span style="color:#a6e22e">sh</span> -<span style="color:#a6e22e">c</span> <span style="color:#e6db74">&#39;for i in /etc/wireguard/*.conf; do /usr/share/doc/wireguard-tools/examples/reresolve-dns/reresolve-dns.sh &#34;$i&#34;; done&#39;</span>
</span></span></code></pre></div><p>Then you setup the timer service to run:</p>
<p><code>systemctl enable --now wireguard_reresolve-dns.timer</code></p>
<p>Now you should be good to go!  If you have any questions leave a comment.  Thanks for reading!</p>
]]></content:encoded>
    </item>
    <item>
      <title>The road to my PMP</title>
      <link>https://dancwilliams.com/the-road-to-my-pmp/</link>
      <pubDate>Thu, 05 Sep 2019 16:13:37 -0500</pubDate>
      <guid>https://dancwilliams.com/the-road-to-my-pmp/</guid>
      <description>&lt;h1 id=&#34;the-method-to-my-madness&#34;&gt;&amp;hellip;the method to my madness!&lt;/h1&gt;
&lt;p&gt;As a life long technology practitioner I am often asked what training I did to gain my PMP in 2017.  While I &amp;ldquo;only studied for 3 weeks&amp;rdquo; before taking the exam, I had a lot of experience that really made that possible.   I thought I would write all of my notes here so I have an easy point of reference and maybe it will help someone on their journey.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="the-method-to-my-madness">&hellip;the method to my madness!</h1>
<p>As a life long technology practitioner I am often asked what training I did to gain my PMP in 2017.  While I &ldquo;only studied for 3 weeks&rdquo; before taking the exam, I had a lot of experience that really made that possible.   I thought I would write all of my notes here so I have an easy point of reference and maybe it will help someone on their journey.</p>
<p>First, I have been participating in and directing projects for almost 20 years.  And more than just technology projects!  I have worked on construction projects, research and development projects, automotive projects, all sorts of things.  Although I had no &ldquo;formal&rdquo; project management education during a majority of that time, a lot of the methods are natural and you just have to learn the language and official name for the thing you are already doing.</p>
<p>I am also a &ldquo;nontraditional&rdquo; university student.  I went back to the <a href="https://USM.edu">University of Southern Mississippi</a> and finished my BS in Applied Technology back in 2016.  During my undergraduate coursework I had a 400 level class on project management that was based on the PMBOK.  Then I started my graduate work at <a href="https://latech.edu">Louisiana Tech</a> in Engineering and Technology Management.  During my coursework there I have a 500 level class in project management which required a research piece on the entire Project lifecycle for a sample construction project.  This added to my recent formal project management education.</p>
<p>Once I got serious about getting my PMP I went through quite a few study materials before I found two that worked very well for me:</p>
<ul>
<li><a href="https://www.project-management-prepcast.com">The PM Prepcast</a></li>
<li><a href="https://www.pmtraining.com/pmp/practice-exams">PMTraining PMP Practice Exams</a></li>
</ul>
<p>The way I approached this was that I first listen to the intro episode for every area of the PMBOK in the PM Prepcast.  Then I started taking practice exams.  The PMTraining material has a great method of guiding you through varying levels of questions and showing you where you need to focus.  I took this feedback and dove into more focused areas of the Prepcast.  Boom, 3 solid weeks of this and I passed first shot.</p>
<p>Hope this helps and thanks for reading.  If you have any questions comment below.</p>
]]></content:encoded>
    </item>
    <item>
      <title>You can&#39;t beat a good smoked pork shoulder</title>
      <link>https://dancwilliams.com/you-cant-beat-a-good-smoked-pork-shoulder/</link>
      <pubDate>Sat, 31 Aug 2019 11:13:59 -0500</pubDate>
      <guid>https://dancwilliams.com/you-cant-beat-a-good-smoked-pork-shoulder/</guid>
      <description>&lt;h1 id=&#34;so-i-wanted-to-share-how-i-make-one&#34;&gt;&amp;hellip;so I wanted to share how I make one!&lt;/h1&gt;
&lt;p&gt;When it comes to picking out a pork shoulder, I am not too picky.  I just want something that is 8 to 9 lbs and has a good chunk of fat on the top.&lt;/p&gt;
&lt;p&gt;Once I have my pork shoulder I make up a brine consisting of the following ingredients.  I mix the dry part separately first and save about half to rub on the shoulder after brining.  I put the rest of the mixture in the apple cider vinegar:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="so-i-wanted-to-share-how-i-make-one">&hellip;so I wanted to share how I make one!</h1>
<p>When it comes to picking out a pork shoulder, I am not too picky.  I just want something that is 8 to 9 lbs and has a good chunk of fat on the top.</p>
<p>Once I have my pork shoulder I make up a brine consisting of the following ingredients.  I mix the dry part separately first and save about half to rub on the shoulder after brining.  I put the rest of the mixture in the apple cider vinegar:</p>
<table>
  <thead>
      <tr>
          <th>Ingredient</th>
          <th>Amount</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Apple Cider Vinegar</td>
          <td>2 Quarts</td>
      </tr>
      <tr>
          <td>White Sugar</td>
          <td>5 Tablespoons</td>
      </tr>
      <tr>
          <td>Brown Sugar</td>
          <td>5 Tablespoons</td>
      </tr>
      <tr>
          <td>Kosher Salt</td>
          <td>2 Tablespoons</td>
      </tr>
      <tr>
          <td>Paprika</td>
          <td>2 Tablespoons</td>
      </tr>
      <tr>
          <td>Onion powder</td>
          <td>1 Tablespoon</td>
      </tr>
      <tr>
          <td>Garlic powder</td>
          <td>1 Tablespoon</td>
      </tr>
      <tr>
          <td>Black pepper</td>
          <td>1 Tablespoon</td>
      </tr>
  </tbody>
</table>
<p>I put this in a container that will hold the brine and cover the entire pork shoulder.  Adjust as needed for your container.  I brine the pork shoulder for 12+ hours in the fridge.  <em>BOOM!</em></p>
<p>I have a <a href="https://greenmountaingrills.com/products/grills/daniel-boone-pellet-grill-non-wifi-blk/">Daniel Boone</a> from <a href="https://greenmountaingrills.com">Green Mountain Grills</a>.  For this pork shoulder I use <a href="https://www.amazon.com/gp/product/B07C32G157/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=9325&amp;creativeASIN=B07C32G157&amp;linkCode=as2&amp;tag=dancwilliams-20&amp;linkId=0e96afff9dba7086c5ed3b249ec4224a">Black Cherry Pellets that I get on Amazon</a>.  I heat the smoker to 250 and let it sit for 30 minutes or so to even out.</p>
<p>While the grill is warming I remove the shoulder from the brine.  I put it on a tray and start patting it down with the remainder of the dry mix.  Once I have it coated it is ready for the smoker.  I place it toward the firebox in the smoker and insert my temperature probe from the GMG into a thick part of the shoulder.  Preferably somewhere away from the bone.  Sometimes I place a little bowl of the brine inside the smoker to raise the humidity a bit.  Dealers choice&hellip;</p>
<p><em>Now we wait&hellip;</em></p>
<p>I set the temp on the smoker to alert when the shoulder reaches 165 degrees internal temp.  I also use my <a href="https://www.amazon.com/gp/product/B079DRC97N/ref=as_li_ss_tl?ie=UTF8&amp;psc=1&amp;linkCode=ll1&amp;tag=dancwilliams-20&amp;linkId=034508446b2f1ab7db273c46c210377f&amp;language=en_US">instant thermometer</a> to check different spots on the shoulder as needed.  Once the shoulder hits 165 I remove and wrap in foil. I know that wrapping is a long discussion, but I do it for my pork shoulder.  I like it and it makes me happy.  I then place it back in the smoker until it hits 190 degrees internal temp, again checking with the thermometer to verify in other spots.</p>
<p>And we are done.  This has worked well for me every time I have smoked a shoulder and I have yet to receive any complaints from the family.  I hope it helps you in developing your own recipe!</p>
<p>Thanks for reading!</p>
<p><em>Here are a few pictures for good measure.</em></p>
<p>Brine:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_brine_hu_a0e80d78f1fbc171.jpg 500w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_brine_hu_b1ee8963004ca363.jpg 800w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_brine_hu_33bdf3b3e783877d.jpg 1200w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_brine_hu_6ff013915d6211d8.jpg 1500w 
  '
  
    src="/you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_brine.jpg" 
  
  alt='Pork Shoulder in brine.'>
<p>After Brine</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_after_brine_hu_7d7c7fc62f4477b9.jpg 500w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_after_brine_hu_51684d7284493d92.jpg 800w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_after_brine_hu_13dc915129edbd7.jpg 1200w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_after_brine_hu_ba8d5adb24d65e7b.jpg 1500w 
  '
  
    src="/you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_after_brine.jpg" 
  
  alt='Pork shoulder after brine.'>
<p>Start:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_start_hu_33a921642c050713.jpg 500w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_start_hu_63e96307026fb514.jpg 800w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_start_hu_75433955511004a2.jpg 1200w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_start_hu_7c7febf3eb2d5d50.jpg 1500w 
  '
  
    src="/you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_start.jpg" 
  
  alt='Prepared pork shoulder placed into smoker.'>
<p>Finish:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_finished_hu_df76d1a0bb094107.jpg 500w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_finished_hu_d6fa735cda31539c.jpg 800w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_finished_hu_1ce95157ffde94e8.jpg 1200w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_finished_hu_32cfd413aafd21dc.jpg 1500w 
  '
  
    src="/you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_finished.jpg" 
  
  alt='Pork shoulder finished and the foil opened.'>
<p>Shredded:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_shredded_hu_f14f159bbb3bd5c3.jpg 500w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_shredded_hu_adf2435b874991f.jpg 800w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_shredded_hu_f31c6f8dc4fd9f01.jpg 1200w
  
  
    , /you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_shredded_hu_d6b2d5229a3b73eb.jpg 1500w 
  '
  
    src="/you-cant-beat-a-good-smoked-pork-shoulder/images/pork_shoulder_shredded.jpg" 
  
  alt='Pork shoulder shredded in pan.'>
]]></content:encoded>
    </item>
    <item>
      <title>Staticman...The Journey Continues</title>
      <link>https://dancwilliams.com/staticman-the-journey-continues/</link>
      <pubDate>Tue, 20 Aug 2019 11:39:00 -0500</pubDate>
      <guid>https://dancwilliams.com/staticman-the-journey-continues/</guid>
      <description>&lt;p&gt;&lt;em&gt;In this post I will do a quick dive on how I setup my own staticman instance in &lt;a href=&#34;https://dashboard.heroku.com/apps&#34;&gt;Heroku&lt;/a&gt; since the &lt;a href=&#34;https://api.staticman.net&#34;&gt;public API&lt;/a&gt; and &lt;a href=&#34;https://dev.staticman.net/&#34;&gt;Dev API&lt;/a&gt; are no longer responding.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;First, &lt;a href=&#34;https://yasoob.me/posts/running_staticman_on_static_hugo_blog_with_nested_comments/&#34;&gt;this site&lt;/a&gt; from &lt;a href=&#34;https://github.com/yasoob&#34;&gt;yasoob&lt;/a&gt; does a great job running down how to get this setup in Github and on Heroku.  I will just add af ew changes I made based on the content of &lt;a href=&#34;https://github.com/eduardoboucas/staticman/issues/299&#34;&gt;Issue #299&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As pointed out in yasoob&amp;rsquo;s post, and in a &lt;a href=&#34;https://github.com/eduardoboucas/staticman/issues&#34;&gt;ton of issues&lt;/a&gt; on the repo, there are a few things amiss with the master branch.  And some of the fixes mentioned in the post did not work for me, but here is what did&amp;hellip;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><em>In this post I will do a quick dive on how I setup my own staticman instance in <a href="https://dashboard.heroku.com/apps">Heroku</a> since the <a href="https://api.staticman.net">public API</a> and <a href="https://dev.staticman.net/">Dev API</a> are no longer responding.</em></p>
<p>First, <a href="https://yasoob.me/posts/running_staticman_on_static_hugo_blog_with_nested_comments/">this site</a> from <a href="https://github.com/yasoob">yasoob</a> does a great job running down how to get this setup in Github and on Heroku.  I will just add af ew changes I made based on the content of <a href="https://github.com/eduardoboucas/staticman/issues/299">Issue #299</a>.</p>
<p>As pointed out in yasoob&rsquo;s post, and in a <a href="https://github.com/eduardoboucas/staticman/issues">ton of issues</a> on the repo, there are a few things amiss with the master branch.  And some of the fixes mentioned in the post did not work for me, but here is what did&hellip;</p>
<p>As pointed out by the trusty <a href="https://github.com/VincentTam">VincentTam</a> in his <a href="https://github.com/eduardoboucas/staticman/issues/299#issuecomment-508029359">comment on Issue #299</a> he points out that in his deploy release he is uing <a href="https://github.com/eduardoboucas/staticman/commit/55d14306d851059a2a27d24b5eb4cb17c5009477"><code>55d1430</code></a>.  So, that is what I used as well.  And after some testing everything seems to work fine.  I am using <code>v3</code> on both of my sites and the <code>Mailgun</code> integration and all is working as expected.  I have not tested GitLab integration as I do not have a GitLab setup, but I may give it a shot in the future.</p>
<p>So, here is the quick and dirty on how I did it:</p>
<ol>
<li>Fork the <a href="https://github.com/eduardoboucas/staticman">Staticman Repo</a></li>
<li>Create a Heroku app as mentioned above</li>
<li>Run <code>git checkout -b workaround 55d1430</code> to create a branch named <code>workaround</code> from the commit mentioned above.</li>
<li>Push that branch to Heroku using <code>git push -f heroku workaround:master</code>.  <em>I add the -f because I felt like living dangerously</em></li>
</ol>
<p>If you configured all of your environment variables properly you should be good to go!  I am running this instance on both <a href="https://networkhobo.com">NetworkHobo</a> and <a href="https://dancwilliams.com">Dan C Williams</a> using the <code>v3</code> API without issue.</p>
<p>I know this is quick, but I needed to get it out of my head.  Please comment below if there are any questions.  Thanks!</p>
]]></content:encoded>
    </item>
    <item>
      <title>I do enjoy a good pound cake</title>
      <link>https://dancwilliams.com/i-do-enjoy-a-good-pound-cake/</link>
      <pubDate>Sat, 17 Aug 2019 09:07:00 -0500</pubDate>
      <guid>https://dancwilliams.com/i-do-enjoy-a-good-pound-cake/</guid>
      <description>&lt;h2 id=&#34;and-here-is-my-favorite-recipe&#34;&gt;&amp;hellip;and here is my favorite recipe!&lt;/h2&gt;
&lt;p&gt;I do enjoy baking a pound cake form time to time and here is my favorite recipe.  It is very basic, but gets the job done!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 cups of flour&lt;/li&gt;
&lt;li&gt;2 cups of sugar&lt;/li&gt;
&lt;li&gt;2 sticks of butter&lt;/li&gt;
&lt;li&gt;2 teaspoons of vanilla&lt;/li&gt;
&lt;li&gt;6 eggs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Boom!  Too easy, right?  The secret is to mix this&amp;hellip;&lt;em&gt;&lt;em&gt;FOREVER&lt;/em&gt;&lt;/em&gt;.  When you put this in the mixer for 5 minutes or so it will be yellow.  Just keep mixing until the batter turns white.  Another way to check is by doing a taste test and seeing if the sugar is still gritty in the batter. If there is still grit&amp;hellip;&lt;em&gt;don&amp;rsquo;t quit!&lt;/em&gt;. When it is smooth that is when it is ready.  Move that batter to a greased up Bundt pan and bake at 325F for 1 hour.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="and-here-is-my-favorite-recipe">&hellip;and here is my favorite recipe!</h2>
<p>I do enjoy baking a pound cake form time to time and here is my favorite recipe.  It is very basic, but gets the job done!</p>
<ul>
<li>2 cups of flour</li>
<li>2 cups of sugar</li>
<li>2 sticks of butter</li>
<li>2 teaspoons of vanilla</li>
<li>6 eggs</li>
</ul>
<p>Boom!  Too easy, right?  The secret is to mix this&hellip;<em><em>FOREVER</em></em>.  When you put this in the mixer for 5 minutes or so it will be yellow.  Just keep mixing until the batter turns white.  Another way to check is by doing a taste test and seeing if the sugar is still gritty in the batter. If there is still grit&hellip;<em>don&rsquo;t quit!</em>. When it is smooth that is when it is ready.  Move that batter to a greased up Bundt pan and bake at 325F for 1 hour.</p>
<p>Sometimes I even make a <a href="https://www.onceuponachef.com/recipes/berry-sauce.html">mixed berry sauce</a> if I&rsquo;m feeling fancy&hellip;</p>
<p>Thanks for reading and I hope you enjoy!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Notify the world</title>
      <link>https://dancwilliams.com/notify-the-world/</link>
      <pubDate>Tue, 16 Jul 2019 19:06:30 -0500</pubDate>
      <guid>https://dancwilliams.com/notify-the-world/</guid>
      <description>&lt;h2 id=&#34;but-leave-me-out-of-the-discussion&#34;&gt;But leave me out of the discussion&amp;hellip;&lt;/h2&gt;
&lt;p&gt;We all know the patron Saint of spreading your message to the world:&lt;/p&gt;



























&lt;img 
  sizes=&#34;(min-width: 35em) 1200px, 100vw&#34;
  srcset=&#39;
  
  
  
  &#39;
  
    src=&#34;https://dancwilliams.com/notify-the-world/images/Francis_of_a_CC.jpg&#34; 
  
  &gt;
&lt;p&gt;But, lets be cognizant of our surroundings.  Everyone wants to hear your announcement.  But, maybe, they do not want to be a part of the overall discussion.  More often these days folks are copying God and country on every e-mail that goes out.  Most of these e-mails are announcements that require little to no feedback.  Even though that is the case there is always someone who hits that beloved &lt;code&gt;reply all&lt;/code&gt; button to give a quick and polite &lt;code&gt;Thanks&lt;/code&gt; or &lt;code&gt;Gotcha&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="but-leave-me-out-of-the-discussion">But leave me out of the discussion&hellip;</h2>
<p>We all know the patron Saint of spreading your message to the world:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
  
  
  '
  
    src="/notify-the-world/images/Francis_of_a_CC.jpg" 
  
  >
<p>But, lets be cognizant of our surroundings.  Everyone wants to hear your announcement.  But, maybe, they do not want to be a part of the overall discussion.  More often these days folks are copying God and country on every e-mail that goes out.  Most of these e-mails are announcements that require little to no feedback.  Even though that is the case there is always someone who hits that beloved <code>reply all</code> button to give a quick and polite <code>Thanks</code> or <code>Gotcha</code>.</p>
<h3 id="you-have-now-created-a-storm">You have now created a storm&hellip;</h3>
<p>After a coupla helpful <code>Thank You</code>s someone is going to pipe up with a <code>Please remove me from this list</code>.  Now it is all downhill.  If you are <em>old school</em> and have on-site exchange you are now getting a drive-by asking why you are killing the queues.  If you are using O365 the NOC is getting notified of direct connect traffic spike dues to a rouge e-mail and some improper routing in the core (<em>trust me</em>).  Routing, you would think we would be over that stuff by now.  But we aren&rsquo;t.</p>
<p>(<em>If you are using Google for the business e-mails&hellip;I am not sure who would be yelling at you.  I am sure there is someone.  Don&rsquo;t feel left out.</em>)</p>
<h3 id="invoke-the-power-of-bcc">Invoke the power of BCC!</h3>
<p>Unless you just want feedback from everyone please, <em>please</em>, use BCC.  For those who are not read in, this is the Blind Carbon Copy.  It gets the message to all of the people you want to get it to, but if someone does a reply all, no one else gets the reply.  No storm&hellip;no craziness&hellip;no hate.  If you receive a reply that you feel the entire grou should know about, send it to everyone, and BCC them. Too easy.  Another thing I do is actually send that e-mail to myself with everyone BCC&rsquo;d.  That way all replies come right back to me.  If there is a reply it is my burden to shoulder.  I started this mess anyhow&hellip;</p>
<h2 id="summary">Summary</h2>
<p>I know you are tired of e-mail stuff.  But, I have a lot of folks to teach.  <em>I NEED AN OUTLET</em></p>
<p>Thanks for reading.  Comments are awesome.  Thanks.</p>
]]></content:encoded>
    </item>
    <item>
      <title>I like vacations</title>
      <link>https://dancwilliams.com/i-like-vacations/</link>
      <pubDate>Sun, 14 Jul 2019 12:09:14 -0500</pubDate>
      <guid>https://dancwilliams.com/i-like-vacations/</guid>
      <description>&lt;h2 id=&#34;and-you-can-let-me-know-about-yours--just-dont-blow-up-my-calendar&#34;&gt;&amp;hellip;and you can let me know about yours.  Just don&amp;rsquo;t blow up my calendar.&lt;/h2&gt;
&lt;p&gt;Even with all the super cool collaboration tools that are available today, a lot of management types still rely on the old faithful Outlook Calendar.  They ask that you send out an invite for your vacation so that all the key stakeholders are aware of the time you will be out of the office.  I will admit, I still do this today and I encourage my staff to do the same.  It was beat into me at &lt;code&gt;GE&lt;/code&gt; and I just cannot break the habit.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="and-you-can-let-me-know-about-yours--just-dont-blow-up-my-calendar">&hellip;and you can let me know about yours.  Just don&rsquo;t blow up my calendar.</h2>
<p>Even with all the super cool collaboration tools that are available today, a lot of management types still rely on the old faithful Outlook Calendar.  They ask that you send out an invite for your vacation so that all the key stakeholders are aware of the time you will be out of the office.  I will admit, I still do this today and I encourage my staff to do the same.  It was beat into me at <code>GE</code> and I just cannot break the habit.</p>
<p><em>But let us be thoughtful of other&rsquo;s calendars&hellip;</em></p>
<p>When sending an invite out to your team, be cognizant of what that invite will look like on their calendar.  If you send out an invite marked as <code>Out of Office</code> and they accept, it will show them as out of office as well.  This is not good since they will likely still need to attend meetings and have an open calendar while you are on leave.  Let&rsquo;s make sure we do not block them out.</p>
<p><em>Send it free and clear&hellip;</em></p>
<p>When you send out the big group invite for your vacation, mark it as free time.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /i-like-vacations/images/1_hu_55e68923998266e3.png 500w
  
  
    , /i-like-vacations/images/1_hu_a735cbc013d56237.png 800w
  
  
    , /i-like-vacations/images/1_hu_175ab05f2262fe7.png 1200w
  
  
    , /i-like-vacations/images/1_hu_b908b2a801dcfc74.png 1500w 
  '
  
    src="/i-like-vacations/images/1.png" 
  
  alt='Select Free Time on Invite'>
<p>Also, do not ask for a response.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /i-like-vacations/images/2_hu_6aa6854e7f1d8f6.png 500w
  
  
    , /i-like-vacations/images/2_hu_9fa8076818b1e3cc.png 800w
  
  
    , /i-like-vacations/images/2_hu_64b366c564367d1d.png 1200w
  
  
    , /i-like-vacations/images/2_hu_66948e2b82bfe203.png 1500w 
  '
  
    src="/i-like-vacations/images/2.png" 
  
  alt='Uncheck the request responses option'>
<p>Now that the invite has gone out announcing that you will be on vacation and it is shown as free time on everyone&rsquo;s calendars, you are a meeting invite hero!  But, you have to show that you are in fact Out of Office on your individual calendar.  Too easy&hellip;just set an appointment for yourself showing Out of Office.  Now you are covered.</p>
<h2 id="summary">Summary</h2>
<p>It may feel like a little double work, but at the end of the day it really makes you look like you are a considerate team member.  It will go a long way with helping the entire team communicate better.</p>
<p>I am always looking for other ideas.  I would love to hear how you handle this on your teams.  Thanks for reading!</p>
]]></content:encoded>
    </item>
    <item>
      <title>First Test with new Drafts and Shortcuts Automations</title>
      <link>https://dancwilliams.com/first-test-with-new-drafts-and-shortcuts-automations/</link>
      <pubDate>Fri, 31 May 2019 22:38:21 -0500</pubDate>
      <guid>https://dancwilliams.com/first-test-with-new-drafts-and-shortcuts-automations/</guid>
      <description>&lt;h2 id=&#34;lets-see-if-this-works&#34;&gt;&amp;hellip;Let&amp;rsquo;s See if This Works!&lt;/h2&gt;
&lt;p&gt;I just spent the last day putting together some Drafts actions and iOS Shortcuts.  This is just a short test to see if the process works.  Then I will document it all.&lt;/p&gt;
&lt;p&gt;Image test:&lt;/p&gt;
&lt;p&gt;


























&lt;img 
  sizes=&#34;(min-width: 35em) 1200px, 100vw&#34;
  srcset=&#39;
  
    /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_f291a5ff69245170.jpg 500w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_8d254fd54f0dd3b6.jpg 800w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_54428c58da9086c3.jpg 1200w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_4ee2ab9d30c9cf5.jpg 1500w 
  &#39;
  
    src=&#34;https://dancwilliams.com/first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1.jpg&#34; 
  
  &gt;



























&lt;img 
  sizes=&#34;(min-width: 35em) 1200px, 100vw&#34;
  srcset=&#39;
  
    /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_af9b02dddf5cdac5.jpg 500w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_6708fe8815d45d3c.jpg 800w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_19772e6abd7054e3.jpg 1200w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_fe93f5f69e35f5c0.jpg 1500w 
  &#39;
  
    src=&#34;https://dancwilliams.com/first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2.jpg&#34; 
  
  &gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="lets-see-if-this-works">&hellip;Let&rsquo;s See if This Works!</h2>
<p>I just spent the last day putting together some Drafts actions and iOS Shortcuts.  This is just a short test to see if the process works.  Then I will document it all.</p>
<p>Image test:</p>
<p>


























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_f291a5ff69245170.jpg 500w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_8d254fd54f0dd3b6.jpg 800w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_54428c58da9086c3.jpg 1200w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1_hu_4ee2ab9d30c9cf5.jpg 1500w 
  '
  
    src="/first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_1.jpg" 
  
  >



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_af9b02dddf5cdac5.jpg 500w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_6708fe8815d45d3c.jpg 800w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_19772e6abd7054e3.jpg 1200w
  
  
    , /first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2_hu_fe93f5f69e35f5c0.jpg 1500w 
  '
  
    src="/first-test-with-new-drafts-and-shortcuts-automations/images/Test_photo_2.jpg" 
  
  ></p>
]]></content:encoded>
    </item>
    <item>
      <title>Drafts</title>
      <link>https://dancwilliams.com/drafts-app-realization/</link>
      <pubDate>Mon, 04 Feb 2019 18:06:27 -0600</pubDate>
      <guid>https://dancwilliams.com/drafts-app-realization/</guid>
      <description>&lt;h2 id=&#34;how-i-have-been-missing-this-app&#34;&gt;&amp;hellip;how I have been missing this app?!&lt;/h2&gt;
&lt;p&gt;This will be short.  Months ago someone recommended the &lt;a href=&#34;https://getdrafts.com&#34;&gt;Drafts app&lt;/a&gt; to me so I installed it.  They had told me how awesome it would be and how helpful it would be with my growing use of &lt;a href=&#34;https://www.omnigroup.com/omnifocus/ios/&#34;&gt;OmniFocus&lt;/a&gt;.  Well, not so much&amp;hellip;until now!&lt;/p&gt;
&lt;p&gt;I recently picked up an iPad Pro for work and have been using it a ton.  I was watching some random YouTube videos on various tools for the iPad and stumbled upon a &lt;a href=&#34;https://www.youtube.com/playlist?list=PLJ_odbyIW_Rc-hvHnyvFg6k2Jy-6qW_iB&#34;&gt;video playlist around Drafts 5&lt;/a&gt;.  Now I understand.  The blank white display and minimal interface hid so much power from being clearly evident.  Also, I was really busy so I did not spend much time poking and prodding.  Now I have added some new actions, learned how to quickly create blog posts from templates that automatically fill out front matter, all that jazz.  I am a sucker for templating!&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="how-i-have-been-missing-this-app">&hellip;how I have been missing this app?!</h2>
<p>This will be short.  Months ago someone recommended the <a href="https://getdrafts.com">Drafts app</a> to me so I installed it.  They had told me how awesome it would be and how helpful it would be with my growing use of <a href="https://www.omnigroup.com/omnifocus/ios/">OmniFocus</a>.  Well, not so much&hellip;until now!</p>
<p>I recently picked up an iPad Pro for work and have been using it a ton.  I was watching some random YouTube videos on various tools for the iPad and stumbled upon a <a href="https://www.youtube.com/playlist?list=PLJ_odbyIW_Rc-hvHnyvFg6k2Jy-6qW_iB">video playlist around Drafts 5</a>.  Now I understand.  The blank white display and minimal interface hid so much power from being clearly evident.  Also, I was really busy so I did not spend much time poking and prodding.  Now I have added some new actions, learned how to quickly create blog posts from templates that automatically fill out front matter, all that jazz.  I am a sucker for templating!</p>
<p>I had been writing with <a href="https://ia.net/writer">IAWriter</a>, which I will still be using, but I can see the power of Drafts for really getting to work quickly.</p>
<p>Ok, off to dinner with the family.  It is Monday night, gotta get some of those red beans.</p>
<p>Thanks for reading!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Forwarding E-Mails</title>
      <link>https://dancwilliams.com/forwarding-emails/</link>
      <pubDate>Thu, 10 Jan 2019 20:49:02 -0600</pubDate>
      <guid>https://dancwilliams.com/forwarding-emails/</guid>
      <description>&lt;h2 id=&#34;or-learning-to-show-others-you-appreciate-their-time&#34;&gt;&amp;hellip;Or Learning to Show Others You Appreciate Their Time&amp;hellip;&lt;/h2&gt;
&lt;p&gt;I often find myself receiving forwarded e-mails with little to no context or prior conversation.  This baffles me.  How could someone feel ok forwarding me an e-mail chain of twenty or so messages and the only notes from the sender is their automated signature block?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I immediately trash these&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then comes the inevitable drive-by, “Hey, did you get that e-mail I forwarded you?”  Nope, never received it.  If someone needs an explanation to make them feel better I will say something like I may have seen it, but at a glance it looked like it was an accidental forward and I canned it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="or-learning-to-show-others-you-appreciate-their-time">&hellip;Or Learning to Show Others You Appreciate Their Time&hellip;</h2>
<p>I often find myself receiving forwarded e-mails with little to no context or prior conversation.  This baffles me.  How could someone feel ok forwarding me an e-mail chain of twenty or so messages and the only notes from the sender is their automated signature block?</p>
<p><em>I immediately trash these&hellip;</em></p>
<p>Then comes the inevitable drive-by, “Hey, did you get that e-mail I forwarded you?”  Nope, never received it.  If someone needs an explanation to make them feel better I will say something like I may have seen it, but at a glance it looked like it was an accidental forward and I canned it.</p>
<p><em>”Oops&hellip;what was it about anyway?</em></p>
<h3 id="note-do-not-make-the-mistake-above">Note: Do not make the mistake above&hellip;</h3>
<p>We have all done it.  If you say you haven’t you are only kidding yourself.  That is fine to do, as long as deep inside you are aware of it.</p>
<p>You have read this e-mail chain, you know the reason you feel it needs to be passed on, take the initiative and put a quick summary at the top.  Hit them up on the chat app of the day, or, and this is crazy, pick up the phone and talk to the person you are forwarding it to.  Hell, call them, forward the e-mail, and then discuss the content you find interesting.</p>
<p><strong>SO MANY OPTIONS!!!</strong></p>
<h3 id="never-blind-forward-an-e-mail-and-expect-people-to-care-about-the-contents-as-much-as-you-do">Never blind forward an e-mail and expect people to care about the contents as much as you do&hellip;</h3>
<p>You are wasting their time.  It is that simple.  Know your audience and respect their time as if it were your own.  Why force someone else to dig through an entire string of poorly edited text just because you found a bit of info you found interesting.  Sum it up.  Heck, call it an executive summary if you want to sound fancy and your boss is one of the receiving parties.  Folks <strong>LOVE</strong> the feeling of receiving an executive summary.</p>
<h3 id="it-is-not-just-for-them-it-is-for-you-too">It is not just for them, it is for you too&hellip;</h3>
<p>When you summarize your thoughts it gives you a moment to analyze what you are thinking and be sure everything is clear.  It helps <em>you</em> gather <em>your</em> thoughts.  Because, if the e-mail content is as forwardworthy (TM) as you think it is, someone is eventually going to ask you to sum it up verbally in a meeting or huddle or scrum-whatever-the-folks-are-doing-these-days.  Now when asked to do this, usually on the spot, you already have your thoughts together.  <em>Too Easy!</em></p>
<h2 id="summary">Summary</h2>
<p>Ok, I am about to land so I need to wrap this up.  I have a many more thoughts on e-mail etiquette in a professional working environment, so I hope you don’t get too bored!</p>
<p>Thanks for reading&hellip;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Using Actionable Notifications in Home Assistant - Legacy</title>
      <link>https://dancwilliams.com/using-actionable-notifications-in-home-assistant-legacy/</link>
      <pubDate>Thu, 11 Jan 2018 19:02:48 -0600</pubDate>
      <guid>https://dancwilliams.com/using-actionable-notifications-in-home-assistant-legacy/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post uses legacy configuration.  I have updated this &lt;a href=&#34;https://dancwilliams.com/using-actionable-notifications-in-home-assistant&#34;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this post I will cover how I use &lt;a href=&#34;https://home-assistant.io/docs/ecosystem/ios/notifications/actions/&#34;&gt;actionable notifications&lt;/a&gt; within &lt;a href=&#34;https://home-assistant.io&#34;&gt;Home Assistant&lt;/a&gt;.  Using &lt;a href=&#34;https://home-assistant.io/docs/ecosystem/ios/notifications/&#34;&gt;push notifications&lt;/a&gt; with the &lt;a href=&#34;https://home-assistant.io/docs/ecosystem/ios/&#34;&gt;Home Assistant iOS App&lt;/a&gt; you can setup some really cool triggers within the system.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Below is a list of the technology used at the time of writing:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://home-assistant.io&#34;&gt;&lt;em&gt;Home Assistant&lt;/em&gt;&lt;/a&gt; &lt;em&gt;- Version 0.60.1&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.apple.com/iphone/&#34;&gt;&lt;em&gt;Apple iPhone X and iPhone 7&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://support.apple.com/en-us/HT208401&#34;&gt;&lt;em&gt;Apple iOS 11.2.2&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have two actionable notifications that get used most often:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><em>This post uses legacy configuration.  I have updated this <a href="https://dancwilliams.com/using-actionable-notifications-in-home-assistant">here</a></em></p>
<p>In this post I will cover how I use <a href="https://home-assistant.io/docs/ecosystem/ios/notifications/actions/">actionable notifications</a> within <a href="https://home-assistant.io">Home Assistant</a>.  Using <a href="https://home-assistant.io/docs/ecosystem/ios/notifications/">push notifications</a> with the <a href="https://home-assistant.io/docs/ecosystem/ios/">Home Assistant iOS App</a> you can setup some really cool triggers within the system.</p>
<p><em>Below is a list of the technology used at the time of writing:</em></p>
<ul>
<li><a href="https://home-assistant.io"><em>Home Assistant</em></a> <em>- Version 0.60.1</em></li>
<li><a href="https://www.apple.com/iphone/"><em>Apple iPhone X and iPhone 7</em></a></li>
<li><a href="https://support.apple.com/en-us/HT208401"><em>Apple iOS 11.2.2</em></a></li>
</ul>
<p>I have two actionable notifications that get used most often:</p>
<ol>
<li>
<p>At 6AM I receive a push notification that asks if I am working from home today.</p>
<ul>
<li><code>Yes</code> and <code>No</code> options are presented</li>
<li>If I answer <code>Yes</code>, it will turn on the AC in my office and set the proper temperature based on the temperature outside.</li>
</ul>
</li>
<li>
<p>On days when my wife and I go into our &ldquo;<em>real</em>&rdquo; offices we will receive a notification when we leave in the evening and the house is set to away.  This notification asks if you are headed home.</p>
<ul>
<li><code>Yes</code> and <code>No</code> options are presented</li>
<li>If <code>Yes</code> is selected, it will set the air conditioner to the home setting to cool/heat the house in advance.</li>
</ul>
</li>
</ol>
<p>We will use my &ldquo;Are you working from home today?&rdquo; notification as the example<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<h4 id="step-one">Step One:</h4>
<p>I have an automation configured to send me a message asking if I am working from home on <code>weekdays</code> at <code>6AM</code> if the house is in <code>sleep</code> mode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">alias</span>: <span style="color:#ae81ff">Ask if Dan is working from home in the morning - Weekday</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">id</span>: <span style="color:#ae81ff">ask_if_dan_is_working_from_home_in_morning_weekday</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">condition</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">condition</span>: <span style="color:#ae81ff">and</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">conditions</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">condition</span>: <span style="color:#ae81ff">state</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_select.home_state</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">state</span>: <span style="color:#ae81ff">sleep</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">condition</span>: <span style="color:#ae81ff">time</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">weekday</span>:
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">mon</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">tue</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">wed</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">thu</span>
</span></span><span style="display:flex;"><span>          - <span style="color:#ae81ff">fri</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">trigger</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">time</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">at</span>: <span style="color:#e6db74">&#39;06:00:00&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">action</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">service</span>: <span style="color:#ae81ff">notify.ios_dan_iphone</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">message</span>: <span style="color:#e6db74">&#34;Are you working from home today?&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">push</span>:
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">category</span>: <span style="color:#e6db74">&#34;working_from_home&#34;</span>
</span></span></code></pre></div><p>The thing to key on here is the <code>push category</code> used in the action.  This will be used later&hellip;</p>
<h4 id="step-two">Step Two:</h4>
<p>Now we need to configure the iOS push category that corresponds with the category used in the automation.</p>
<p>I keep my push categories in a separate file named <code>ios_push_categories.yaml</code>.  Here is the excerpt from my <code>configuration.yaml</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">ios</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">push</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">categories</span>: !<span style="color:#ae81ff">include ios_push_categories.yaml</span>
</span></span></code></pre></div><p>And here is the appropriate section fomr <code>ios_push_categories.yaml</code>:</p>
<p><strong>NOTE: The <code>identifier</code> must be lower-case!</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Working From Home</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">identifier</span>: <span style="color:#e6db74">&#39;working_from_home&#39;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">actions</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">identifier</span>: <span style="color:#e6db74">&#39;WORKING_FROM_HOME_YES&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">title</span>: <span style="color:#e6db74">&#39;Yes&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">activationMode</span>: <span style="color:#e6db74">&#39;background&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">authenticationRequired</span>: <span style="color:#66d9ef">no</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">destructive</span>: <span style="color:#66d9ef">yes</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">identifier</span>: <span style="color:#e6db74">&#39;WORKING_FROM_HOME_NO&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">title</span>: <span style="color:#e6db74">&#39;No&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">activationMode</span>: <span style="color:#e6db74">&#39;background&#39;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">authenticationRequired</span>: <span style="color:#66d9ef">no</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">destructive</span>: <span style="color:#66d9ef">no</span>
</span></span></code></pre></div><p>This will provide the options that are presented with the notification and tie those options with an <code>identifier</code>.  This will be used later&hellip;</p>
<h4 id="step-three">Step Three:</h4>
<p>This is where the rubber meets the road!</p>
<p>In this case the <code>No</code> option does nothing.  The notification will close on the phone and that is all.  But, &lsquo;Yes&rsquo; will trigger an automation in Home Assistant.</p>
<p>Here is the automation that is triggered when <code>Yes</code> is selected:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">alias</span>: <span style="color:#ae81ff">iOS Action - Working From Home Yes</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">id</span>: <span style="color:#ae81ff">ios_action_working_from_home_yes</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">trigger</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">platform</span>: <span style="color:#ae81ff">event</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">event_type</span>: <span style="color:#ae81ff">ios.notification_action_fired</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">event_data</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">actionName</span>: <span style="color:#ae81ff">WORKING_FROM_HOME_YES</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">action</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">input_select.select_option</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_select.office_ac_power</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">option</span>: <span style="color:#e6db74">&#39;on&#39;</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">input_select.select_option</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data_template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_select.office_ac_mode</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">option</span>: &gt;<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          {% if (states(&#34;sensor.dark_sky_temperature&#34;) | int) &lt; 65 %}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          heat
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          {% else %}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          cool
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          {% endif %}</span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">service</span>: <span style="color:#ae81ff">input_number.set_value</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">entity_id</span>: <span style="color:#ae81ff">input_number.office_ac_temperature</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">value</span>: <span style="color:#ae81ff">72</span>
</span></span></code></pre></div><p>Under the trigger <code>event_data</code> you will see that the <code>actionName</code> corresponds to the <code>identifier</code> used in Step Two.  When <code>Yes</code> was selected it kicked off the automation to turn on the AC in my office and set the mode based on the outside temperature.  It has worked great!</p>
<h2 id="important-notes">IMPORTANT NOTES!</h2>
<h3 id="creating-and-updating-ios-push-notifications">Creating and Updating iOS Push Notifications:</h3>
<p>Each time you create or update an iOS push notification within home assistant you must update oush settings within the iOS app.</p>
<p>To do this go into the settings (gear icon) within the iOS app and navigate to Notification Settings &gt; Update push notifications.</p>
<h3 id="interacting-with-push-notifications">Interacting with Push Notifications:</h3>
<p>When you receive a notification on you iPhone, <strong>do not just tap on it!</strong>  <mark>This will open the Home Assistant app and not present your options!</mark></p>
<p>You can, however, tap notifications on your Apple Watch.  See explanations below:</p>
<h4 id="on-iphone">On iPhone:</h4>
<ul>
<li>
<p><strong>While phone is locked</strong>:</p>
<ul>
<li>
<p>Your received notification will look like this:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant-legacy/images/notification_while_locked_hu_3efdf315e3664066.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant-legacy/images/notification_while_locked_hu_227b506f75061edd.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant-legacy/images/notification_while_locked.jpg" 
          
          >
</li>
<li>
<p>Swipe left on the notification and tap &ldquo;View&rdquo;:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant-legacy/images/notification_swipe_left_hu_31553d03c0dc408b.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant-legacy/images/notification_swipe_left_hu_4420cd71dc924cef.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant-legacy/images/notification_swipe_left.jpg" 
          
          >
</li>
<li>
<p>You will then be presented with your options:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant-legacy/images/locked_notification_options_hu_ea070786d1a2e88e.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant-legacy/images/locked_notification_options_hu_a23406af68947f46.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant-legacy/images/locked_notification_options.jpg" 
          
          >
</li>
</ul>
</li>
<li>
<p><strong>While phone is unlocked</strong>:</p>
<ul>
<li>
<p>Your received notification will look like this:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant-legacy/images/notification_while_using_hu_5773e549ff04ec38.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant-legacy/images/notification_while_using_hu_56f881f56881be24.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant-legacy/images/notification_while_using.jpg" 
          
          >
</li>
<li>
<p>Swipe down on the notification and you will be presented with your options:</p>

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        <img 
          sizes="(min-width: 35em) 1200px, 100vw"
          srcset='
          
            /using-actionable-notifications-in-home-assistant-legacy/images/unlocked_notification_options_hu_5455adc0a1dd27a4.jpg 500w
          
          
            , /using-actionable-notifications-in-home-assistant-legacy/images/unlocked_notification_options_hu_6aac1003b7c49fb3.jpg 800w
          
          
          '
          
            src="/using-actionable-notifications-in-home-assistant-legacy/images/unlocked_notification_options.jpg" 
          
          >
</li>
</ul>
</li>
</ul>
<h4 id="on-apple-watch">On Apple Watch:</h4>
<ul>
<li>
<p>Your received notification will look like this:</p>

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  <img 
    sizes="(min-width: 35em) 1200px, 100vw"
    srcset='
    
    
    
    '
    
      src="/using-actionable-notifications-in-home-assistant-legacy/images/watch_notification.jpg" 
    
    >
</li>
<li>
<p>Tap the notification to receive your options:</p>

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  <img 
    sizes="(min-width: 35em) 1200px, 100vw"
    srcset='
    
    
    
    '
    
      src="/using-actionable-notifications-in-home-assistant-legacy/images/watch_tap.jpg" 
    
    >
</li>
</ul>
<h3 id="summary">Summary</h3>
<p>This is covered often in the <a href="https://community.home-assistant.io">Home Assistant Community</a> and I just wanted to get my configuration out in hopes that others will find it useful.  If you have any questions feel free to leave a comment.</p>
<p>Thanks for reading!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><em>You can find all of my configuration on <a href="https://github.com/dancwilliams/networkhobo">GitHub</a> if you are curious about other actionable notification automations.</em>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>SecureCRT Auto Logging How-To</title>
      <link>https://dancwilliams.com/securecrt-auto-logging-how-to/</link>
      <pubDate>Wed, 10 Jan 2018 09:41:43 -0600</pubDate>
      <guid>https://dancwilliams.com/securecrt-auto-logging-how-to/</guid>
      <description>&lt;p&gt;This is a quick post to document the process I use to auto-log &lt;a href=&#34;https://www.vandyke.com/products/securecrt/&#34;&gt;SecureCRT&lt;/a&gt; sessions.&lt;/p&gt;
&lt;p&gt;I like to automatically log all sessions that I open, just so I have a record of all my keystrokes.  It also helps when doing discovery operations so that I do not have to repeat logins to collect information that I may not have felt was important previously.&lt;/p&gt;
&lt;p&gt;This post will lay out how to setup aut logging for all sessions globally.  This is also geared toward Windows, but the same logic can be used on any platform.  Only the folder structures will change.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This is a quick post to document the process I use to auto-log <a href="https://www.vandyke.com/products/securecrt/">SecureCRT</a> sessions.</p>
<p>I like to automatically log all sessions that I open, just so I have a record of all my keystrokes.  It also helps when doing discovery operations so that I do not have to repeat logins to collect information that I may not have felt was important previously.</p>
<p>This post will lay out how to setup aut logging for all sessions globally.  This is also geared toward Windows, but the same logic can be used on any platform.  Only the folder structures will change.</p>
<p><em>I am using SecureCRT Version 7.3.7 (build 1034).</em></p>
<p>Open <strong>SecureCRT</strong> &gt; <strong>Options</strong> &gt; <strong>Global Options</strong> &gt; <strong>General</strong> &gt; ****Default Session &gt; Select the <strong>Edit Default Settings</strong> button:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /securecrt-auto-logging-how-to/images/secure-crt-screecap_hu_e2cbff060e268c92.png 500w
  
  
  
  '
  
    src="/securecrt-auto-logging-how-to/images/secure-crt-screecap.png" 
  
  >
<p>Log File Name: <code>C:\Users\{{ YOUR USERNAME }}\{{ YOUR FOLDER LOCATION }}\%Y\%Y-%M\%Y-%M-%D\%S (%H) -- %Y-%M-%D_%h-%m.txt</code></p>
<p>Upon Connect: <code>Start recording %S (%H) - %Y/%M/%D %h:%m:%s</code></p>
<p>Upon Disconnect: <code>Stop recording %S (%H) - %Y/%M/%D %h:%m:%s</code></p>
<p>On each line: <code>%h:%m:%s.%s §</code></p>
]]></content:encoded>
    </item>
    <item>
      <title>Intel NUC Memory and BIOS Gotcha</title>
      <link>https://dancwilliams.com/intel-nuc-memory-and-bios-gotcha/</link>
      <pubDate>Wed, 10 Jan 2018 09:33:42 -0600</pubDate>
      <guid>https://dancwilliams.com/intel-nuc-memory-and-bios-gotcha/</guid>
      <description>&lt;p&gt;This is a quick post to cover a gotcha I ran into while preparing my &lt;em&gt;new to me&lt;/em&gt; &lt;a href=&#34;https://ark.intel.com/products/71275/Intel-NUC-Kit-DC3217IYE&#34;&gt;Intel NUC DC3217IYE&lt;/a&gt; to take over has my primary &lt;a href=&#34;https://home-assistant.io&#34;&gt;Home Assistant&lt;/a&gt; box.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This is a quick post to cover a gotcha I ran into while preparing my <em>new to me</em> <a href="https://ark.intel.com/products/71275/Intel-NUC-Kit-DC3217IYE">Intel NUC DC3217IYE</a> to take over has my primary <a href="https://home-assistant.io">Home Assistant</a> box.</p>
<p>The NUC I purchased had 4GB RAM, 64GB SSD, and wireless.  Before I began loading anyhting I wanted to make sure the NUC was updated with the latest and greatest BIOS version since I had heard of issues with previous versions.</p>
<p>When I logged into the machine I found it was running version 42.  The <a href="https://downloadcenter.intel.com/download/26602/NUCs-BIOS-Update-GKPPT10H-86A-?product=71275">Intel site</a> showed that the latest version for this platform is 62.  So, I followed the instructions to perform a <a href="https://www.intel.com/content/www/us/en/support/articles/000006030/mini-pcs.html">Power Button Menu Update</a>.  This method looked to be very straightforward, but then I hit an issue.</p>
<p>When I selected <code>F7</code> to load the new BIOS from the USB stick I went through the image selection and hit <code>ENTER</code> to install, the screen went black, then the power button flashed twice and the NUC rebooted.  I hit <code>F2</code> to bring up the BIOS menu and noticed it was still running version 42.  No change&hellip;</p>
<p>I reloaded the USB, tried other methods, everything!  But, the same outcome occured each time.</p>
<p>I started researching and finally found some random forum entry somewhere (no link) that mentioned to check the RAM speed.  I check the RAM that was installed in the NUC and it was 2 x 2GB 1066MHz sticks.  Then I started digging up the version 62 <a href="https://downloadmirror.intel.com/26602/eng/GK_0062_ReleaseNotes.pdf">release notes</a>.</p>
<p>There it was, 1066 MHz RAM was not supported by BIOS version 62:</p>
<p><strong>Note: The memory reference code in BIOS version 0046 was updated as a part of the changes made in the BIOS to meet Microsoft Windows 8.1 requirements. This new memory code no longer supports 1066 MHz memory modules.</strong></p>
<p>So, I went to the shop and found an old 4GB 1600MHz stick that I had and swapped out the RAM in the NUC.  I tried the Power Button Menu method again and it worked without issue!  Now I am up and running on the latest BIOS.</p>
<p>Hope this helps someone else that may run into this odd issue when the NUC provides very little feedback.</p>]]></content:encoded>
    </item>
    <item>
      <title>Hugo &#43; Staticman: Nested Replies and E-mail Notifications</title>
      <link>https://dancwilliams.com/hugo-staticman-nested-replies-and-email-notifications/</link>
      <pubDate>Sat, 30 Dec 2017 20:47:00 -0600</pubDate>
      <guid>https://dancwilliams.com/hugo-staticman-nested-replies-and-email-notifications/</guid>
      <description>&lt;p&gt;&lt;em&gt;Update 20190819: The public instance of the Staticman API is broken with no clear line-of-sight on when or if it will be repaired.  Reference issue &lt;a href=&#34;https://github.com/eduardoboucas/staticman/issues/307&#34;&gt;#307&lt;/a&gt;.  I am now running my own Staticman instance in Heroku using the suggestions from &lt;a href=&#34;https://github.com/VincentTam&#34;&gt;VincentTam&lt;/a&gt;.  I am using the &lt;a href=&#34;https://github.com/eduardoboucas/staticman&#34;&gt;master branch&lt;/a&gt; and integrating &lt;a href=&#34;https://github.com/eduardoboucas/staticman/pull/285&#34;&gt;PR #285&lt;/a&gt;.  VincentTam did a good write up on all of these things in a few places: &lt;a href=&#34;https://github.com/eduardoboucas/staticman/issues/296&#34;&gt;Issue #296&lt;/a&gt; &amp;amp; &lt;a href=&#34;https://vincenttam.gitlab.io/post/2018-09-16-staticman-powered-gitlab-pages/2/&#34;&gt;VincentTam&amp;rsquo;s blog on hosting your own instance of Staticman.&lt;/a&gt;.  This all takes some piecing together, so I may write an update post on how I am hosting my instance and &lt;a href=&#34;https://networkhobo.com/staticman-the-journey-continues&#34;&gt;link it here&lt;/a&gt;. If there are any questions feel free to hit me in the comments.&lt;/em&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><em>Update 20190819: The public instance of the Staticman API is broken with no clear line-of-sight on when or if it will be repaired.  Reference issue <a href="https://github.com/eduardoboucas/staticman/issues/307">#307</a>.  I am now running my own Staticman instance in Heroku using the suggestions from <a href="https://github.com/VincentTam">VincentTam</a>.  I am using the <a href="https://github.com/eduardoboucas/staticman">master branch</a> and integrating <a href="https://github.com/eduardoboucas/staticman/pull/285">PR #285</a>.  VincentTam did a good write up on all of these things in a few places: <a href="https://github.com/eduardoboucas/staticman/issues/296">Issue #296</a> &amp; <a href="https://vincenttam.gitlab.io/post/2018-09-16-staticman-powered-gitlab-pages/2/">VincentTam&rsquo;s blog on hosting your own instance of Staticman.</a>.  This all takes some piecing together, so I may write an update post on how I am hosting my instance and <a href="https://networkhobo.com/staticman-the-journey-continues">link it here</a>. If there are any questions feel free to hit me in the comments.</em></p>
<p>In this post I want to cover the steps I went through to get Staticman nested comments and e-mail notifications working in Hugo.</p>
<p><em>Disclaimer: I am new to Hugo, Go Templating, JavaScript, and all the bits and pieces used in this write-up.  I am sure there are more efficient methods to achieve these results.  Please provide any feedback in the comments or feel free to issue a pull request.  Thanks!</em></p>
<p><em>Below is a list of the technology I use for this blog:</em></p>
<ul>
<li><a href="https://gohugo.io"><em>Hugo</em></a> <em>- Version 0.31.1</em></li>
<li><a href="https://github.com/halogenica/beautifulhugo"><em>Beautiful Hugo Theme</em></a></li>
<li><a href="https://staticman.net"><em>Staticman</em></a></li>
<li><a href="https://www.netlify.com"><em>Netlify</em></a></li>
<li><a href="https://github.com/dancwilliams/networkhobo/"><em>Network Hobo GitHub Repo</em></a></li>
</ul>
<p><em>I do not go through all of the steps for basic Staticman setup and API registration.  This is covered in the great <a href="https://staticman.net/docs/">Staticman Documentation</a>.</em></p>
<h3 id="in-the-beginning">In the beginning&hellip;</h3>
<p>After years of hosting this blog on Wordpress I decided I wanted to make a move to a more flexible option.  I started looking at static site generation and all of the various options.  I finally decided to take a crack at Hugo.</p>
<p>I went in search of a clean template for my new Hugo site.  After much searching I decided to go with <a href="https://github.com/halogenica/beautifulhugo">Beautiful Hugo</a>.  At the time, I started using Beautiful Hugo it only supported <a href="https://disqus.com">Disqus</a> for commenting.  I knew I wanted to take this opportunity to gain control of all of my data, so I started adapting the Beautiful Hugo theme to use <a href="https://staticman.net">Staticman</a> for commenting.</p>
<ul>
<li><em>Note: As of November 21, 2017, the Beautiful Hugo theme now natively supports Staticman comments (<a href="https://github.com/halogenica/beautifulhugo/pull/99">PR#99</a>).  This is basic commenting without replies or e-mail notification.  I plan to work these features into the theme.  Just wanted to get my logic down here before I lose it :-).</em></li>
</ul>
<p>I started my work with Staticman by using the <a href="https://hugo.staticman.net">Hugo example site from Staticman themselves</a>.  <a href="https://github.com/eduardoboucas">Eduardo Bouças</a> (creator of Staticman) did a great job putting this small example site together. I used the <a href="https://github.com/eduardoboucas/hugo-plus-staticman/blob/master/themes/hugo-type-theme/layouts/partials/post-comments.html">post-comments.html</a> partial from this site as the base to begin exploring Staticman.  I broke this out into two partials, one for parsing the comments to show and one for the comment form itself.  I did this so that later I could add a feature to lock comments on a post if needed.</p>
<p>Now I need to investigate how to handle e-mail notifications.  That is when I stumbled upon <a href="https://mademistakes.com/articles/improving-jekyll-static-comments/">this gold mine of information</a> from <a href="https://github.com/mmistakes">Michael Rose</a>.  This article and Michael&rsquo;s <a href="https://github.com/mmistakes/made-mistakes-jekyll">GitHub repo</a> really helped me walk through the logic of e-mail replies as well as how he handled nesting replies.  What a <strong>GREAT</strong> source of information!</p>
<h3 id="putting-it-all-together">Putting it all together:</h3>
<p>The first thing I wanted to be sure of was that I did not statically configure anything.  I wanted Staticman to act just like another available comment module within the template.  Therefor I added the following pieces of information to the <code>Params</code> section of my <a href="https://github.com/dancwilliams/networkhobo/blob/master/config.toml"><code>config.toml</code></a> file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ae81ff">staticman_api = &#34;https://api.staticman.net/v2/entry/dancwilliams/networkhobo/master/comments&#34;</span> <span style="color:#75715e">#Add staticman API URL to enable staticman comments</span>
</span></span></code></pre></div><p>Then I added some logic to the <a href="https://github.com/dancwilliams/networkhobo/blob/master/layouts/_default/single.html"><code>layouts/_default/single.html</code></a> file to look for the staticman_api Site.Param, and if existed to add the <code>post-comments.html</code> partial:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>{{ if (.Params.comments) | or (and (or (not (isset .Params &#34;comments&#34;)) (eq .Params.comments nil)) (.Site.Params.comments)) }}
</span></span><span style="display:flex;"><span>  {{ if .Site.Config.Services.Disqus.Shortname }}
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;disqus-comments&#34;</span>&gt;
</span></span><span style="display:flex;"><span>      {{ template &#34;_internal/disqus.html&#34; . }}
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>  {{ end }}
</span></span><span style="display:flex;"><span>  {{ if (.Site.Params.staticman_api) }}
</span></span><span style="display:flex;"><span>    {{ partial &#34;post-comments&#34; . }}
</span></span><span style="display:flex;"><span>  {{ end }}
</span></span><span style="display:flex;"><span>{{ end }}
</span></span></code></pre></div><p>I then moved on to the creation of the <a href="https://github.com/dancwilliams/networkhobo/blob/master/layouts/partials/post-comments.html"><code>layouts/partials/post-comments.html</code></a> partial:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">section</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comments&#34;</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">h3</span>&gt;Comments&lt;/<span style="color:#f92672">h3</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  {{ $.Scratch.Add &#34;hasComments&#34; 0 }}
</span></span><span style="display:flex;"><span>  {{ $entryId := .File.BaseFileName }}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  {{ range $index, $comments := (index $.Site.Data.comments $entryId ) }}
</span></span><span style="display:flex;"><span>    {{ $.Scratch.Add &#34;hasComments&#34; 1 }}
</span></span><span style="display:flex;"><span>    {{ if not .reply_to }}
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-header&#34;</span>&gt;
</span></span><span style="display:flex;"><span>          &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-avatar&#34;</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.gravatar.com/avatar/{{ .email }}?s=100&#34;</span>&gt;
</span></span><span style="display:flex;"><span>          &lt;<span style="color:#f92672">p</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-info&#34;</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;{{ .name }}&lt;/<span style="color:#f92672">strong</span>&gt;&lt;<span style="color:#f92672">br</span>&gt;{{ dateFormat &#34;Monday, Jan 2, 2006&#34; .date }}&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>        {{ .body | markdownify }}
</span></span><span style="display:flex;"><span>      &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;comment__reply&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ ._id }}&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;btn-info&#34;</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;#comment-form&#34;</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;changeValue(&#39;fields[reply_to]&#39;, &#39;{{ ._id }}&#39;)&#34;</span>&gt;Reply to {{ .name }}&lt;/<span style="color:#f92672">a</span>&gt;
</span></span><span style="display:flex;"><span>          &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>      {{ partial &#34;comment-replies&#34; (dict &#34;entryId_parent&#34; $entryId &#34;SiteDataComments_parent&#34; $.Site.Data.comments &#34;parentId&#34; ._id &#34;parentName&#34; .name &#34;context&#34; .) }}
</span></span><span style="display:flex;"><span>    {{ end }}
</span></span><span style="display:flex;"><span>  {{ end }}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  {{ if eq ($.Scratch.Get &#34;hasComments&#34;) 0 }}
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">p</span>&gt;Nothing yet.&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  {{ end }}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  {{ partial &#34;comment_form&#34; . }}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">section</span>&gt;
</span></span></code></pre></div><p>You can see that most of this is pulled from the Staticman Hugo example.  I did remove some of the looping and dataset reading that I found to be excessive.  You will also see that I added some logic to only present comments that were not replies and to add a button for replies to those comments.</p>
<p>I had to add a piece of JavaScript to the reply button to set the value of the <code>fields[reply_to]</code> hidden input.  This field is set to the <code>._id</code> value of the current parent comment.  This allows for the fields to be properly populated by Staticman:</p>
<p>Located <a href="https://github.com/dancwilliams/networkhobo/blob/master/static/js/dan_custom.js">here</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#75715e">// Added function to change value onclick
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">changeValue</span>(<span style="color:#a6e22e">elementName</span>, <span style="color:#a6e22e">newValue</span>){
</span></span><span style="display:flex;"><span>  document.<span style="color:#a6e22e">getElementsByName</span>(<span style="color:#a6e22e">elementName</span>)[<span style="color:#ae81ff">0</span>].<span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#a6e22e">newValue</span>;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Here are examples of the two types of comment YAML files that are created:</p>
<h4 id="parent-comment">Parent Comment:</h4>
<p><em>In the parent comments you will see that the <code>reply_to</code> field is blank.</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">_id</span>: <span style="color:#ae81ff">74ea2730-ed18-11e7-96e3-b9aaffd0f2aa</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">_parent</span>: &gt;-<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  2013-12-23-cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">reply_to</span>: <span style="color:#e6db74">&#39;&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">Dan</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">email</span>: <span style="color:#ae81ff">9162d0c5aca33e7e4c8ec6fc3d44f541</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">body</span>: <span style="color:#ae81ff">Test comment 1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">date</span>: <span style="color:#e6db74">&#39;2017-12-30T04:18:15.955Z&#39;</span>
</span></span></code></pre></div><h4 id="child-comment">Child Comment:</h4>
<p><em>In the reply comments you will see that the <code>reply_to</code> field is populated with the <code>._id</code> value from the parent comment.</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">_id</span>: <span style="color:#ae81ff">f7be83c0-ed1a-11e7-96e3-b9aaffd0f2aa</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">_parent</span>: &gt;-<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  2013-12-23-cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">reply_to</span>: <span style="color:#ae81ff">74ea2730-ed18-11e7-96e3-b9aaffd0f2aa</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">Reply Tester</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">email</span>: <span style="color:#ae81ff">53d8e4904144b75f9ada3862b6ebafae</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">body</span>: <span style="color:#ae81ff">Testing a reply to Dan’s comment</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">date</span>: <span style="color:#e6db74">&#39;2017-12-30T04:36:14.421Z&#39;</span>
</span></span></code></pre></div><p>This <code>reply_to</code> field is what is used to differentiate parent and child comments.</p>
<p>After a &ldquo;parent&rdquo; comment is printed the <a href="https://github.com/dancwilliams/networkhobo/blob/master/layouts/partials/comment-replies.html"><code>layouts/partials/comment-replies.html</code></a> partial is called.  This partial looks much like the <code>post-comments</code> partial:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>{{ range $index, $comments := (index $.SiteDataComments_parent $.entryId_parent ) }}
</span></span><span style="display:flex;"><span>  {{ if eq .reply_to $.parentId }}
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-reply&#34;</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-header&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-avatar&#34;</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.gravatar.com/avatar/{{ .email }}?s=100&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">p</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-info&#34;</span>&gt;&lt;<span style="color:#f92672">strong</span>&gt;{{ .name }}&lt;/<span style="color:#f92672">strong</span>&gt;&lt;<span style="color:#f92672">br</span>&gt;&lt;<span style="color:#f92672">i</span>&gt;&lt;<span style="color:#f92672">small</span>&gt;In reply to {{ $.parentName }}&lt;/<span style="color:#f92672">i</span>&gt;&lt;/<span style="color:#f92672">small</span>&gt;&lt;<span style="color:#f92672">br</span>&gt;{{ dateFormat &#34;Monday, Jan 2, 2006&#34; .date }}&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>      {{ .body | markdownify }}
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>  {{ end }}
</span></span><span style="display:flex;"><span>{{ end }}
</span></span></code></pre></div><p>When this partial is called a dictionary of variables are passed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>{{ partial &#34;comment-replies&#34; (dict &#34;entryId_parent&#34; $entryId &#34;SiteDataComments_parent&#34; $.Site.Data.comments &#34;parentId&#34; ._id &#34;parentName&#34; .name &#34;context&#34; .) }}
</span></span></code></pre></div><p>These variables allow the replies partial to match the <code>reply_to</code> field against the parent comment <code>._id</code> field (variable <code>parentId</code>) within this partial.  Once a match it hit the same process is used for presenting the comment, with the slight addition of adding a text blurb to say this is a reply to the name of the parent comment author.</p>
<p>After all of the comments and replies for a particular post have been processed, the <a href="https://github.com/dancwilliams/networkhobo/blob/master/layouts/partials/comment_form.html"><code>layouts/partials/comment_form.html</code></a> partial is called:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">section</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;comment_form&#34;</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;comment-form&#34;</span>&gt;&lt;/<span style="color:#f92672">a</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">h3</span>&gt;Say something&lt;/<span style="color:#f92672">h3</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">form</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-new-comment&#34;</span> <span style="color:#a6e22e">method</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;POST&#34;</span> <span style="color:#a6e22e">action</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Site.Params.staticman_api }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[redirect]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Permalink }}#post-submitted&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[redirectError]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Permalink }}#post-error&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[entryId]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .File.BaseFileName }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[slug]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Permalink }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[origin]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Permalink }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[parent]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .File.BaseFileName }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;fields[reply_to]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[reCaptcha][siteKey]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Site.Params.recaptcha_siteKey }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;hidden&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[reCaptcha][secret]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Site.Params.recaptcha_secret }}&#34;</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;fields[name]&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-field&#34;</span> <span style="color:#a6e22e">placeholder</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Your name&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;fields[email]&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;email&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-field&#34;</span> <span style="color:#a6e22e">placeholder</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Your email address&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">textarea</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;fields[body]&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-field&#34;</span> <span style="color:#a6e22e">placeholder</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Your message. Feel free to use Markdown.&#34;</span> <span style="color:#a6e22e">rows</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;10&#34;</span>&gt;&lt;/<span style="color:#f92672">textarea</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;notify-me&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;checkbox&#34;</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;comment-form-reply&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[subscribe]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;email&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        Send me an email when someone comments on this post.
</span></span><span style="display:flex;"><span>      &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;g-recaptcha&#34;</span> <span style="color:#a6e22e">data-sitekey</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Site.Params.recaptcha_siteKey }}&#34;</span> <span style="color:#a6e22e">data-callback</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;enableBtn&#34;</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-comment-field btn&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Submit&#34;</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit_button&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;/<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">form</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">async</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#39;https://www.google.com/recaptcha/api.js&#39;</span> &gt;&lt;/<span style="color:#f92672">script</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text/javascript&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;submit_button&#34;</span>).<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">script</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text/javascript&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">enableBtn</span>(){
</span></span><span style="display:flex;"><span>       document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;submit_button&#34;</span>).<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">script</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-submitted&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;dialog&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">h3</span>&gt;Thank you&lt;/<span style="color:#f92672">h3</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">p</span>&gt;Your post has been submitted and will be published once it has been approved.&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>    {{ if (.Site.Params.githubPullURL) }}
</span></span><span style="display:flex;"><span>      &lt;<span style="color:#f92672">p</span>&gt;&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Site.Params.githubPullURL }}&#34;</span>&gt;Click here&lt;/<span style="color:#f92672">a</span>&gt; to see the pull request you generated.&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>    {{ end }}
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">p</span>&gt;&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;#&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;btn&#34;</span>&gt;OK&lt;/<span style="color:#f92672">a</span>&gt;&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-error&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;dialog&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">h3</span>&gt;OOPS!&lt;/<span style="color:#f92672">h3</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">p</span>&gt;Your post has not been submitted.  Please return to the page and try again.  Thank You!&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">p</span>&gt;&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;#&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;btn&#34;</span>&gt;OK&lt;/<span style="color:#f92672">a</span>&gt;&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">section</span>&gt;
</span></span></code></pre></div><p>This form was also taken from the Staticman Hugo example site and modified in a few ways.  Multiple hidden input fields were added to support replies as well as subscribing to comment e-mail notifications.</p>
<p>To support e-mail replies we had to add a checkbox to the comment form:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">fieldset</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;notify-me&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;checkbox&#34;</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;comment-form-reply&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;options[subscribe]&#34;</span> <span style="color:#a6e22e">value</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;email&#34;</span>&gt;
</span></span><span style="display:flex;"><span>        Send me an email when someone comments on this post.
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">fieldset</span>&gt;
</span></span></code></pre></div><p>When this checkbox is selected it sets the value of the input <code>options[subscribe]</code> to the given e-mail address.  This option is used by Staticman for creating and/or populating the mailing lists in <a href="https://www.mailgun.com">Mailgun</a>.</p>
<p>There is also logic to support <a href="https://www.google.com/recaptcha/">reCaptcha</a>.  The reCaptcha authorizationis used in two ways:</p>
<ul>
<li>It is used by the backend Staticman server (setting in <a href="https://github.com/dancwilliams/networkhobo/blob/master/staticman.yml"><code>staticman.yml</code></a>)</li>
<li>It is used by the submit button on the comment form.  The submit button remains disabled until the reCaptcha test is passed.</li>
</ul>
<p>Once the form is filled out and the comment is submitted one of two things could happen.  Within the <code>comment_form</code> partial there is a dialog for submission success and one for failure.</p>
<h4 id="success-dialog">Success Dialog:</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-submitted&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;dialog&#34;</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">h3</span>&gt;Thank you&lt;/<span style="color:#f92672">h3</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">p</span>&gt;Your post has been submitted and will be published once it has been approved.&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  {{ if (.Site.Params.githubPullURL) }}
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">p</span>&gt;&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;{{ .Site.Params.githubPullURL }}&#34;</span>&gt;Click here&lt;/<span style="color:#f92672">a</span>&gt; to see the pull request you generated.&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  {{ end }}
</span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">p</span>&gt;&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;#&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;btn&#34;</span>&gt;OK&lt;/<span style="color:#f92672">a</span>&gt;&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><p>If the Staticman API call comes back as successful, this dialog is presented.  If the configuration parameter <code>githubPullURL</code> is set, a link will be presented to view the pull request created by Staticman.  The OK button will take the user back to the beginning of the post.</p>
<h4 id="failure-dialog">Failure Dialog:</h4>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;post-error&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;dialog&#34;</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">h3</span>&gt;OOPS!&lt;/<span style="color:#f92672">h3</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">p</span>&gt;Your post has not been submitted.  Please return to the page and try again.  Thank You!&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">p</span>&gt;&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;#&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;btn&#34;</span>&gt;OK&lt;/<span style="color:#f92672">a</span>&gt;&lt;/<span style="color:#f92672">p</span>&gt;
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><p>If the Staticman API call reports a failure, this dialog is presented.  The OK button will take the user back to the beginning of the post.</p>
<h3 id="summary">Summary</h3>
<p>This has been a fun project that I have been working on for some time.  I have learned a lot about all of the components of Hugo and hope that some people will show me better/cleaner/more efficient ways of handling this.</p>
<p>In this post I tried to cover everything from my notes, but if I forgot something I will be sure to update.</p>
<p>Thanks for taking the time to read this and I hope you find it helpful.  Feel free to comment here and/or reach out to me on Twitter (<a href="https://twitter.com/dancwilliams">@dancwilliams</a>) if you would like to discuss any of this.</p>
<p><strong><em>Thanks again!</em></strong></p>
<h3 id="lagniappe">Lagniappe</h3>
<p>When I was migrating from Wordpress to Hugo + Staticman I wanted to be sure to migrate all of my existing comments.  There was a lot of good stuff in there and I didn&rsquo;t want to lose it.  Since Wordpress provides a full export of your site in an XML document, I wrote a little Python script to extract the comments and create the YAML files.  It even preserves the nesting. <a href="https://github.com/dancwilliams/wordpress_to_staticman_comments">Here is a link to the script in GitHub</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Intro to Ansible for Networkers</title>
      <link>https://dancwilliams.com/intro-to-ansible-for-networkers/</link>
      <pubDate>Thu, 14 Dec 2017 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/intro-to-ansible-for-networkers/</guid>
      <description>&lt;p&gt;I made this quick video as an &amp;ldquo;Ansible 101&amp;rdquo; type introduction for some networking friends that just wanted a high-level intro to playbook creation and logic.  So, I hope you enjoy it and get something useful from it.  Please feel free to comment with any questions you may have!&lt;/p&gt;
&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube-nocookie.com/embed/BlCjQAv6Ero?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;h3 id=&#34;github-repo&#34;&gt;GitHub Repo:&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/dancwilliams/ansible_101&#34;&gt;Intro to Ansible for Networkers - GitHub Repo&lt;/a&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I made this quick video as an &ldquo;Ansible 101&rdquo; type introduction for some networking friends that just wanted a high-level intro to playbook creation and logic.  So, I hope you enjoy it and get something useful from it.  Please feel free to comment with any questions you may have!</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/BlCjQAv6Ero?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<h3 id="github-repo">GitHub Repo:</h3>
<p><a href="https://github.com/dancwilliams/ansible_101">Intro to Ansible for Networkers - GitHub Repo</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco VIRL, pfSense, and Routed Management Networks</title>
      <link>https://dancwilliams.com/cisco-virl-pfsense-and-routed-management-networks/</link>
      <pubDate>Thu, 15 Jun 2017 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-virl-pfsense-and-routed-management-networks/</guid>
      <description>&lt;p&gt;In this post I hope to quickly cover how I use pfSense to provide easily reachable management networks for simulations within VIRL.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Below is a list of the technology I use in this lab environment:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.netgate.com/products/sg-1000.html&#34;&gt;&lt;em&gt;pfSense SG-1000&lt;/em&gt;&lt;/a&gt; &lt;em&gt;running 2.4 BETA&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://virl.cisco.com/&#34;&gt;&lt;em&gt;Cisco VIRL&lt;/em&gt;&lt;/a&gt;_ — Core 0.10.29.12_&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.vmware.com/&#34;&gt;&lt;em&gt;VMWare ESXi&lt;/em&gt;&lt;/a&gt; &lt;em&gt;5.5 Update 1&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Generic VLAN Aware Layer 2 Switching&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will not go through the entire installation of Cisco VIRL. I am just going to go through what I do in my personal environment to allow the FLAT &amp;amp; FLAT2 networks to be routable to the world. I have the SNAT network setup in a similar fashion, but I do not often use it so I will only mention SNAT this once.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this post I hope to quickly cover how I use pfSense to provide easily reachable management networks for simulations within VIRL.</p>
<p><em>Below is a list of the technology I use in this lab environment:</em></p>
<ul>
<li><a href="https://www.netgate.com/products/sg-1000.html"><em>pfSense SG-1000</em></a> <em>running 2.4 BETA</em></li>
<li><a href="http://virl.cisco.com/"><em>Cisco VIRL</em></a>_ — Core 0.10.29.12_</li>
<li><a href="https://www.vmware.com/"><em>VMWare ESXi</em></a> <em>5.5 Update 1</em></li>
<li><em>Generic VLAN Aware Layer 2 Switching</em></li>
</ul>
<p>I will not go through the entire installation of Cisco VIRL. I am just going to go through what I do in my personal environment to allow the FLAT &amp; FLAT2 networks to be routable to the world. I have the SNAT network setup in a similar fashion, but I do not often use it so I will only mention SNAT this once.</p>
<p>I will also not go through the process of adding VLANs and interfaces to the pfSense SG-1000. If this is something you would like me to cover in more detail just leave a comment or shoot me a tweet and I would be glad to help you out!</p>
<p>Instead of using the stock 172.16.1.0/24 &amp; 172.16.2.0/24 FLAT networks, I have updated the VIRL configuration for my local environment. This evolved changing the second octet from 16 to 23. Once that is completed I saved the changes in the VIRL admin portal and allowed it to go through the LENGTHY process of reconfiguration. This takes a while…grab a drink…</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-flat-config_hu_4f66681d83e22e5a.png 500w
  
  
    , /cisco-virl-pfsense-and-routed-management-networks/images/virl-flat-config_hu_24467b074d844374.png 800w
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-flat-config.png" 
  
  >
<p>After that I setup a VLAN (I used 200) and assigned it to an new interface on my pfSense SG-1000. I then give that interface the gateway IP of the FLAT network (172.23.1.0/24) and enable:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-flat-vlan-config_hu_6460abfec11469c9.png 500w
  
  
    , /cisco-virl-pfsense-and-routed-management-networks/images/virl-flat-vlan-config_hu_a536e3a8d6ce33fe.png 800w
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-flat-vlan-config.png" 
  
  >
<p>After everything is saved I added the FLAT2 gateway as a secondary virtual IP on the same interface:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/pfsense-virtual-ip_hu_81fd4ee248f4b0f2.png 500w
  
  
    , /cisco-virl-pfsense-and-routed-management-networks/images/pfsense-virtual-ip_hu_9ce6437ca785b701.png 800w
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/pfsense-virtual-ip.png" 
  
  >
<p>After this configuration is done all that is left is to add a rule to allow traffic to pass through the interface. The last rule in this list in the one that allows all traffic originating on the Interface to access the Internet. The top three rules are added by <a href="https://forum.pfsense.org/index.php?topic=86212.0">pfBlockerNG</a>, a package I highly recommend if you are a pfSense user!</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/pfsense-flat-rules_hu_61401c355e16dbbf.png 500w
  
  
    , /cisco-virl-pfsense-and-routed-management-networks/images/pfsense-flat-rules_hu_196481547181ed62.png 800w
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/pfsense-flat-rules.png" 
  
  >
<p><strong>Note…you DO NOT need to enable DHCP on your pfSense box! DHCP is handled by the VIRL system.</strong></p>
<p>Ok, now all the pfSense prep is complete! Take the time to trunk your new VLAN through your infrastructure and into your VMWare environment. Once the VLAN is in ESXi it is as easy as applying the VLAN to the FLAT and FLAT2 interfaces on your VIRL VM. In most cases this is Network adapters 2 &amp; 3:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/vmware-vlan-config_hu_408c6008a1c6e4c3.png 500w
  
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/vmware-vlan-config.png" 
  
  >
<p>Once this is complete you should be able to ping the gateway IPs from the FLAT (br1) and FLAT2 (br2) interfaces:</p>
<p>Great! Now…how do you use this in a simulation? I created a quick two nod simulation to show the usage. The main thing to pay attention to is the use of the “Shared flat network” setting in the Management Network dropdown while you are designing your sim. You get to this Properties screen by clicking the background in the simulation window:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-management_hu_dffdfff2c0e697b8.png 500w
  
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-management.png" 
  
  >
<p>Now save your sim and launch it. Once you launch the sim you will see that the nodes show “ACTIVE — UNREACHABLE”. Also, if you right click on the device and hover over “Telnet…” you will see that a 172.23.1.X IP has been assigned to the management port on the device:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-telnet_hu_759a2dfe90ca1fc8.png 500w
  
  
    , /cisco-virl-pfsense-and-routed-management-networks/images/virl-telnet_hu_14fbc90980a82de5.png 800w
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-telnet.png" 
  
  >
<p>While the IP is assigned to the device, it is not automatically configured on the device. If you log into the console of the device you will see that there are two interfaces, even though only one is shown on the sim. The first interface, Gi0/0 in this case, is connected to the imaginary back-end management network. You will need to configure this interface to use DHCP. It will pull the IP it has been assigned and you should be able to ping out to the gateway and beyond. I recommend using a mangement VRF just like you would in production. This way management will not interfere with your lab. See my config below:</p>
<p>As you see from the output above, DHCP hands out the IP VIRL has assigned. <strong>It must be noted this IP will change every time you launch the sim!</strong> So, how do you set a static IP? See the screen cap below. In the latest Alpha: While in the design pane you would click on the device, then scroll down to the bottom where it asks you to enter the Management address. If you enter an address that is not in the management scope, it will error when you try to launch the sim. In earlier versions of VIRL you will need to enter the static_ip extension manually. I have captured that in a screen shot as well.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-basic_hu_2bb3b1c4d51ba5bb.png 500w
  
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-basic.png" 
  
  >



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-basic-2_hu_eff045008392e3d7.png 500w
  
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-basic-2.png" 
  
  >
<p>Now when you launch the sim you will see that the telnet IP for node 1 is the static IP we assigned:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-virl-pfsense-and-routed-management-networks/images/virl-telnet-2_hu_57f67226ea7a2565.png 500w
  
  
    , /cisco-virl-pfsense-and-routed-management-networks/images/virl-telnet-2_hu_1aeaca8b377ccd77.png 800w
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-telnet-2.png" 
  
  >
<p>You will also notice that the device become reachable after you configure the management IP properly:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
  
  
  '
  
    src="/cisco-virl-pfsense-and-routed-management-networks/images/virl-reachable.png" 
  
  >
<p>Now you just need to configure your remote access method of choice (Telnet/SSH) and you are off to the races!</p>
<p>I hope this helps and if you have any questions, corrections, or additions please leave a comment or hit me up on twitter!</p>
]]></content:encoded>
    </item>
    <item>
      <title>PlaystationVUE, Amazon FireTV, pfSense, and Traffic Limiting</title>
      <link>https://dancwilliams.com/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/</link>
      <pubDate>Sat, 04 Mar 2017 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/</guid>
      <description>&lt;h3 id=&#34;quick-note&#34;&gt;Quick Note&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;All of the conclusions below were based off of my individual findings dealing with Vue and my cable provider. But, I used some parts of pfSense that a lot of people talk about and I thought it would be good to put it on paper for others to find.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For all of the pfSense examples below I am using pfSense 2.4.0-BETA on an &lt;a href=&#34;https://netgate.com/products/sg-1000.html&#34;&gt;Netgate SG-1000&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-issue&#34;&gt;The Issue&lt;/h2&gt;
&lt;p&gt;When the decision to cut the cord it was with much excitement about the upcoming experimenting with different content providers. Firs we tested hardware and ended up settling on the &lt;a href=&#34;https://www.amazon.com/Amazon-Fire-TV-Streaming-Media-Player/dp/B00U3FPN4U&#34;&gt;Amazon FireTV&lt;/a&gt;. Then we started a free trial of both &lt;a href=&#34;https://www.sling.com/&#34;&gt;Sling&lt;/a&gt; and &lt;a href=&#34;https://www.playstation.com/en-us/network/vue/&#34;&gt;Playstation Vue&lt;/a&gt;. While going back and forth between the two I started to notice an issue. Sling was streaming without issue while we kept getting queued up with Vue.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="quick-note">Quick Note</h3>
<p><em>All of the conclusions below were based off of my individual findings dealing with Vue and my cable provider. But, I used some parts of pfSense that a lot of people talk about and I thought it would be good to put it on paper for others to find.</em></p>
<p><em>For all of the pfSense examples below I am using pfSense 2.4.0-BETA on an <a href="https://netgate.com/products/sg-1000.html">Netgate SG-1000</a>.</em></p>
<h2 id="the-issue">The Issue</h2>
<p>When the decision to cut the cord it was with much excitement about the upcoming experimenting with different content providers. Firs we tested hardware and ended up settling on the <a href="https://www.amazon.com/Amazon-Fire-TV-Streaming-Media-Player/dp/B00U3FPN4U">Amazon FireTV</a>. Then we started a free trial of both <a href="https://www.sling.com/">Sling</a> and <a href="https://www.playstation.com/en-us/network/vue/">Playstation Vue</a>. While going back and forth between the two I started to notice an issue. Sling was streaming without issue while we kept getting queued up with Vue.</p>
<p>I began to investigate. At the time I was running the system wireless through a <a href="https://www.ubnt.com/unifi/unifi-ap/">Ubquiti UniFi</a> setup, through our <a href="https://pfsense.org/">pfSense firewall</a>, and out of our cable connection (70 down, 4 up). I noticed that while streaming Slack the data flow looked steady. But, when Vue was streaming, there were constant spikes in upload and download utilization. This really got me thinking&hellip;why would we be seeing spikes in both directions with a streaming service?</p>
<p>I started investigating. After digging and digging I finally found a post (which I can no longer find the link to&hellip;) that shed some light onto the subject. It was a description of the mechanism used by the Vue app to proactively monitor the bandwidth available to stream. It basically said that the due app was running a small bandwidth test periodically to test the available bandwidth for streaming.</p>
<p>This got me thinking about my cable internet provider. I had often run into issues with my link quality becoming garbage anytime I hit the limit on 70 down &amp; 4 up on our account. The policing the company used was vicious and would drop packets like mad.</p>
<h2 id="the-quick-test">The Quick Test</h2>
<p>I believed these periodic bandwidth tests were causing my providers aggressive policing to kick in and trash my link. To test my hypothesis I decided to put two limiter rules on my firewall. One was named upload and one was name download. I set the upload bandwidth to 2 meg and the download bandwidth to 5 meg (since this is the advertised Vue usage). I then put a rule on the LAN interface of my pfSense to catch traffic from my FireTV and apply the limiter.</p>
<p>After setting up this quick test I cleared my current firewall states so all the flows would be caught by the new rules. We fired up a show on Vue and I watched the limiters. Everything was working as it should on the firewall. Also, the stream was solid and I was not seeing the traffic spikes we were seeing earlier. I was seeing some drops on the limiters, but they did not seem to be affecting the quality of the stream.</p>
<p>I decided to put this into a more sustainable configuration so that I could maintain it moving forward, and make it scalable as we added FireTVs in other rooms of the home.</p>
<h2 id="the-long-term-solution">The Long Term Solution</h2>
<p>Since we were planning to add more FireTVs to the home I decided to:</p>
<ol>
<li>Create static DHCP reservations for the devices</li>
<li>Create a host alias group in pfSense that contains all of the devices</li>
<li>Create an upload and download limiter</li>
<li>Create a rule a firewall rule on my LAN interface to catch traffic and apply the limiter.</li>
</ol>
<h5 id="1-create-static-dhcp-reservations">1. Create Static DHCP Reservations</h5>
<p>To be sure I grabbed the proper devices each time, and to prevent myself from having to configure static IPs on my devices, I decided to use static DHCP reservations. Luckily static IP reservations are very easy in pfSense. I went to Status &gt; DHCP Leases and found my FireTV. I then select the white background plus sign:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
  
  
  '
  
    src="/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/dhcp_button.png" 
  
  >
<p>This will take you to the &ldquo;Static DHCP Mapping on LAN&rdquo; page. Here you will fill out all the information required for your environment. The only requirement is IP Address. The rest of the fields will accept the default settings from your DHCP configuration.</p>
<h5 id="2-create-a-host-alias-group-in-pfsense-that-contains-all-of-the-devices">2. Create a Host Alias Group in pfSense That Contains All of the Devices</h5>
<p>Once the static DHCP reservation is complete we move on to creating the alias group. For this I went to Firewall &gt; Aliases &gt; IP and clicked the &ldquo;+ Add&rdquo; button at the bottom of the list. Luckily for us the aliases setup within pfSense is very straightforward! Enter a desired name &amp; description. Then make sure &ldquo;Host(s)&rdquo; is selected in the &ldquo;Type&rdquo; dropdown. After this add your new static IP to the &ldquo;IP or FQDN&rdquo; field. If you have more devices to add to this group just click the &ldquo;+ Add Host&rdquo; button and add as many as you need!</p>
<h5 id="3-create-an-upload-and-download-limiter">3. Create an Upload and Download Limiter</h5>
<p>Now that we have our devices statically addressed and in an alias group we move on to configuring the limiters. We will need one limiter for the upload side and one for the download side. You will see why in the creation of the rule to catch traffic.</p>
<p>To configure a limiter is pfSense go to Firewall &gt; Traffic Shaper &gt; Limiters and select &ldquo;+ New Limiter&rdquo;. Below I have a screenshot of my AmazonTV_Download Limiter:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/download_limiter_hu_26623cacc61b56ac.png 500w
  
  
    , /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/download_limiter_hu_4d69fc04fd66200e.png 800w
  
  
  '
  
    src="/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/download_limiter.png" 
  
  >
<p>There are a lot of other fields available, but these are the basic ones that need to be filled out. I also created another limiter named AmazonTV_Upload. This one is set to 2 Mbit/s. I could probably lower that, since my FireTV shouldn&rsquo;t be uploading anything to the Internet&hellip;</p>
<p>Once these are created be sure to save and apply your changes!</p>
<h5 id="4-create-a-rule-a-firewall-rule-on-my-lan-interface-to-catch-traffic-and-apply-the-limiter">4. Create a Rule a Firewall Rule on My LAN Interface to Catch Traffic and Apply the Limiter.</h5>
<p>This is where the rubber hits the road! Once all of the other pieces are configured we are ready to create a firewall rule to apply the limiters to the traffic. To do this we go to Firewall &gt; Rules &gt; LAN (because all of my FireTV devices are on the LAN network).</p>
<p>Here we select the &ldquo;Add&rdquo; button with the arrow pointing up. This is chosen so that the new rule will catch the FireTV traffic before it hits any other rules on the LAN interface. Depending on your rule setup you may need this rule to be elsewhere. If you are using floating rules always be mindful of your order of operations within the firewall. Floating rules are processed first!</p>
<p>I have included a screenshot of my Amazon FireTV rule below. You will see that I am using the alias group as the source with any as the destination matching on any protocol. The limiter is configured under the advanced options, so you will need to click the &ldquo;Display Advanced&rdquo; button at the bottom of the rule. At the bottom of the Advanced section you will see &ldquo;In / Out Pipe&rdquo;. This is where we put our limiters to use!</p>
<p>I like to pretend I am standing on the firewall looking at the device. So, the &ldquo;In&rdquo; pipe is where you put your upload rule and the &ldquo;Out&rdquo; pipe is where you put your download rule. They have added some language to explain this in the section.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/firewall_rule_1_hu_4095294604524176.png 500w
  
  
    , /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/firewall_rule_1_hu_f37d8008edc5b3e6.png 800w
  
  
  '
  
    src="/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/firewall_rule_1.png" 
  
  >



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/firewall_rule_2_hu_70df65123d3b97f1.png 500w
  
  
    , /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/firewall_rule_2_hu_7d6e99ade1cdcbc2.png 800w
  
  
  '
  
    src="/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/firewall_rule_2.png" 
  
  >
<p>Once the rule is saved and applied all you need to do is power cycle your FireTV so it will pick up the new IP reservation and then everything should start working.</p>
<h2 id="monitoring">Monitoring</h2>
<p>To monitor your limiters go to Diagnostics &gt; Limiter Info. Here you will see the real time data pertaining to the usage of your configured limiters. I have included the output from mine below as an example:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/limiter_diagnostics_hu_be2f143cc443f31e.png 500w
  
  
  
  '
  
    src="/playstationvue-amazon-firetv-pfsense-and-traffic-limiting/images/limiter_diagnostics.png" 
  
  >
<h2 id="final-thoughts">Final Thoughts</h2>
<p>This is just one way I have used limiters. They are a VERY powerful tool in the pfSense arsenal!</p>
<p>If there are any questions/feedback/corrections please feel free to reach out in the comments below!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reset Toner Counter on Brother HL-3170CDW</title>
      <link>https://dancwilliams.com/reset-toner-counter-on-brother-hl-3170cdw/</link>
      <pubDate>Wed, 15 Apr 2015 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/reset-toner-counter-on-brother-hl-3170cdw/</guid>
      <description>&lt;h3 id=&#34;quick-note&#34;&gt;Quick Note&lt;/h3&gt;
&lt;p&gt;I thought I would make a quick post about how I reset the toner counters on my brother HL-3170CDW.  I find myself having to search for these steps every few months.&lt;/p&gt;
&lt;h2 id=&#34;the-request&#34;&gt;The Request:&lt;/h2&gt;
&lt;p&gt;I love my brother HL-3170CDW printer (&lt;a href=&#34;http://smile.amazon.com/Brother-HL-3170CDW-Digital-Wireless-Networking/dp/B00BQU141C/ref=sr_1_1?ie=UTF8&amp;amp;qid=1429131433&amp;amp;sr=8-1&amp;amp;keywords=HL-3170CDW&#34; title=&#34;Hl-3170CDW&#34;&gt;CLICK HERE&lt;/a&gt;).  It performs great and always works for us.  The one thing I do not like is buying toner cartridges&amp;hellip;and I have yet to do so!  I have owned this printer since August 13, 2013 and have yet to replace the toner even though I use it regularly.  My current page count is a total 1,432 pages with 1,009 being color and 423 being monochrome and I am still using the starter cartridges that came with the printer.  The brother spec sheet (&lt;a href=&#34;http://www.brother-usa.com/Printer/ModelDetail/1/HL3170CDW/spec#.VS7ZzPnF9fw&#34; title=&#34;HL-3170CDW Tech Specs&#34;&gt;CLICK HERE&lt;/a&gt;) states that the starter cartridges are good for 1,000 pages each, but I have been given the &amp;ldquo;Toner Low&amp;rdquo; error almost 3 times now.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="quick-note">Quick Note</h3>
<p>I thought I would make a quick post about how I reset the toner counters on my brother HL-3170CDW.  I find myself having to search for these steps every few months.</p>
<h2 id="the-request">The Request:</h2>
<p>I love my brother HL-3170CDW printer (<a href="http://smile.amazon.com/Brother-HL-3170CDW-Digital-Wireless-Networking/dp/B00BQU141C/ref=sr_1_1?ie=UTF8&amp;qid=1429131433&amp;sr=8-1&amp;keywords=HL-3170CDW" title="Hl-3170CDW">CLICK HERE</a>).  It performs great and always works for us.  The one thing I do not like is buying toner cartridges&hellip;and I have yet to do so!  I have owned this printer since August 13, 2013 and have yet to replace the toner even though I use it regularly.  My current page count is a total 1,432 pages with 1,009 being color and 423 being monochrome and I am still using the starter cartridges that came with the printer.  The brother spec sheet (<a href="http://www.brother-usa.com/Printer/ModelDetail/1/HL3170CDW/spec#.VS7ZzPnF9fw" title="HL-3170CDW Tech Specs">CLICK HERE</a>) states that the starter cartridges are good for 1,000 pages each, but I have been given the &ldquo;Toner Low&rdquo; error almost 3 times now.</p>
<h2 id="the-solution">The Solution:</h2>
<p>The secret behind the continual use of the toner cartridges is the ability to reset the counters so the printer thinks the cartridges are new again.  I will continue to do this until print quality decreases.  Below are the steps to reset the counters.  I always reset all cartridges&hellip;just to save myself time.</p>
<ol>
<li>Open the top lid of the printer and leave ajar.</li>
<li>Press and hold the &ldquo;Secure&rdquo; and &ldquo;X Cancel&rdquo; buttons.</li>
<li>Use the arrow keys to select the cartridge model you would like to reset and press &ldquo;OK&rdquo;.</li>
<li>Press the UP arrow to reset the cartridge.</li>
<li>Once reset is selected you will see &ldquo;ACCEPTED&rdquo; on the screen.</li>
</ol>
<p>After you perform the reset for the needed cartridges just close the printer lid and hit &ldquo;X Cancel&rdquo; to exit back to the main menu.  DONE! From time to time I also use the cartridge sliders to clean the wires and preventative maintenance to keep the printer running in good shape.</p>
<h2 id="thanks">Thanks!</h2>
<p>I would like to say thank you to the following resources:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=OsttkA329Bs">YouTube</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco DMVPN Phase 3</title>
      <link>https://dancwilliams.com/cisco-dmvpn-phase-3/</link>
      <pubDate>Sat, 21 Mar 2015 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-dmvpn-phase-3/</guid>
      <description>&lt;h3 id=&#34;the-request&#34;&gt;The Request&lt;/h3&gt;
&lt;p&gt;I have a client with a data center, a headquarters/DR site, and a lot of branches spread out all over the world with Internet connectivity.&lt;/p&gt;
&lt;p&gt;They are currently using static IPSEC Internet facing VPNs to connect to their data center and HQ environemts, but the company is hitting a growth spurt and they are quickly realizing this solution is becoming difficult to scale and manage with their limited in-house IT staff.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="the-request">The Request</h3>
<p>I have a client with a data center, a headquarters/DR site, and a lot of branches spread out all over the world with Internet connectivity.</p>
<p>They are currently using static IPSEC Internet facing VPNs to connect to their data center and HQ environemts, but the company is hitting a growth spurt and they are quickly realizing this solution is becoming difficult to scale and manage with their limited in-house IT staff.</p>
<p>The client wanted to stick with Internet based VPNs for connectivity. They also wanted a solution that would allow them to easily stand up a new remote site quickly with a template configuration and provide tunnel redundancy between the data center and HQ locations. They also wanted direct site-to-site communications when necessary.</p>
<h2 id="the-solution">The Solution:</h2>
<p><strong><em>The examples below are from my lab. They are working in production with different crypto algorithms.</em></strong></p>
<p>Since this client has an existing Cisco routing environment and plans to continue to use Cisco routers it was decided that a DMVPN setup would work best to met their needs. To provide the type of connectivity they desired a Phase 3 dual-hub setup would be the best bet.</p>
<p>The client also had an existing EIGRP setup that ran between the HQ and data center over an existing GRE tunnel. This GRE tunnel will be removed and replaced with the DMVPN as well. There is nothing special with the EIGRP configuration used on the routers when using this DMVPN setup besides the EIGRP aggregate statements we will place on the hub tunnel interfaces.</p>
<p>First lets look at the standard crypto config that goes on all routers, both hub and spoke:</p>
<pre><code>crypto isakmp policy 1
encr 3des
authentication pre-share
group 2
crypto isakmp key t3$tk3y address 0.0.0.0        
crypto isakmp keepalive 10
!
!
crypto ipsec transform-set TRANSSET ah-sha-hmac esp-aes 256 esp-sha-hmac 
 mode transport
!
crypto ipsec profile VPNPROF
 set transform-set TRANSSET
</code></pre>
<p>For the following tunnel interface examples we need to lay out an example IP scheme so everything makes sense:</p>
<ul>
<li>EIGRP AS: 1</li>
<li>Data Center
<ul>
<li>WAN IP: 1.1.1.1</li>
<li>Tunnel100: 10.100.0.1</li>
<li>LAN 1: 192.168.10.0/24</li>
<li>LAN 2: 192.168.11.0/24</li>
</ul>
</li>
<li>HQ
<ul>
<li>WAN IP: 2.2.2.2</li>
<li>Tunnel100: 10.100.0.10</li>
<li>LAN 1: 192.168.20.0/24</li>
<li>LAN 2: 192.168.21.0/24</li>
</ul>
</li>
<li>SPOKE 1
<ul>
<li>WAN IP: 3.3.3.3</li>
<li>Tunnel100: 10.100.0.20</li>
<li>LAN: 192.168.41.0/24</li>
</ul>
</li>
<li>SPOKE 2
<ul>
<li>WAN IP: 4.4.4.4</li>
<li>Tunnel100: 10.100.0.30</li>
<li>LAN: 192.168.51.0/24</li>
</ul>
</li>
</ul>
<p>Lets look at the configuration for our first hub…the Data Center:</p>
<pre><code>interface Tunnel100
ip address 10.100.0.1 255.255.255.0
no ip redirects
no ip split-horizon eigrp 1
ip pim dr-priority 100
ip pim sparse-dense-mode
ip nhrp authentication t3$tk3y
ip nhrp map multicast dynamic
ip nhrp map multicast 2.2.2.2
ip nhrp map 10.100.0.10 2.2.2.2
ip nhrp network-id 100
ip nhrp holdtime 360
ip nhrp nhs 10.100.0.10
ip nhrp shortcut
ip nhrp redirect
ip summary-address eigrp 1 192.168.0.0 255.255.0.0
ip summary-address eigrp 1 192.168.10.0 255.255.255.0
ip summary-address eigrp 1 192.168.11.0 255.255.255.0
ip tcp adjust-mss 1416
tunnel source Ethernet0/0
tunnel mode gre multipoint
tunnel key 100
tunnel protection ipsec profile VPNPROF
</code></pre>
<p>For this hub config you will see a few different things.</p>
<p>First you will see that in addition to the standard DMVPN dynamic statements you will also see a static config that is pointing to the second hub, in this case the HQ site.</p>
<p>You will also see the command <strong><em>ip nhrp shortcut</em></strong> and <strong><em>ip nhrp redirect</em></strong>. These commands enable the smooth creation of spoke-to-spoke tunnels and are additions in Phase 3.</p>
<p>Now for the summary addresses…</p>
<p>First we want to cover the entire private IP space that could be used inside the organization. Since this organization uses strictly 192.168.X.X space we place the 192.168.0.0/16 aggregate on the hub tunnel. But, since this is a dual-hub design, we also need to place the site specific aggregates on the tunnel as well. Since this sites design does not allow us to cleanly roll up the subnets each /24 was added as a separate statement.</p>
<p>The reason behind these aggregates is because the spoke will only see routes from the hub. In DMVPN Phase 3 the EIGRP relationship only exists between the spoke and hub. When a spoke tries to route to the IP space of another spoke the hub will pass the more specific route via an NHRP message and inject it into the spoke as an H designated route. The more specifics allow the traffic to flow directly to the hub that possesses that IP space. If the more specific aggregates were not configured both hubs would only advertise the /16 aggregate and this could lead to less than optimal routing.</p>
<p>Now lets look at the HQ tunnel remembering that HQ is the second hub:</p>
<pre><code>interface Tunnel100
ip address 10.100.0.10 255.255.255.0
no ip redirects
no ip split-horizon eigrp 1
ip pim dr-priority 95
ip pim sparse-dense-mode
ip nhrp authentication t3$tk3y
ip nhrp map multicast dynamic
ip nhrp map multicast 1.1.1.1
ip nhrp map 10.100.0.1 1.1.1.1
ip nhrp network-id 100
ip nhrp holdtime 360
ip nhrp nhs 10.100.0.1
ip nhrp shortcut
ip nhrp redirect
ip summary-address eigrp 1 192.168.0.0 255.255.0.0
ip summary-address eigrp 1 192.168.20.0 255.255.255.0
ip summary-address eigrp 1 192.168.21.0 255.255.255.0
ip tcp adjust-mss 1416
tunnel source Ethernet0/0
tunnel mode gre multipoint
tunnel key 100
tunnel protection ipsec profile VPNPROF
</code></pre>
<p>As you can see the configuration is close to identical except for the static NHRP configuration, the EIGRP aggregates, and the PIM DR priority.</p>
<p>Now that we have our hubs configured we can put together the configuration for our spokes. This tunnel config will be used over and over again as new spokes are rolled out. Since the HQ and Data Center IPs remain static the only thing that needs to be changed for each spoke would be the tunnel interface IP address and the source interface.</p>
<p>Remember…the spokes use the same crypto config as the hubs:</p>
<pre><code>interface Tunnel100
 ip address 10.100.0.20 255.255.255.0
 no ip redirects
 ip pim sparse-dense-mode
 ip nhrp authentication t3$tk3y
 ip nhrp map multicast 1.1.1.1
 ip nhrp map multicast 2.2.2.2
 ip nhrp map 10.100.0.1 1.1.1.1
 ip nhrp map 10.100.0.10 2.2.2.2
 ip nhrp network-id 100
 ip nhrp holdtime 360
 ip nhrp nhs 10.100.0.1
 ip nhrp nhs 10.100.0.10
 ip nhrp registration no-unique
 ip nhrp shortcut
 ip nhrp redirect
 ip tcp adjust-mss 1416
 ip ospf network point-to-multipoint
 tunnel source Ethernet0/0
 tunnel mode gre multipoint
 tunnel key 100
 tunnel protection ipsec profile VPNPROF
</code></pre>
<p>Pretty basic right? This config will create static DMVPN tunnels to both hubs. When you run a <strong><em>show dmvpn</em></strong> command you will see the following output on the spoke:</p>
<pre><code>SPOKE1#sh dmvpn
Legend: Attrb --&gt; S - Static, D - Dynamic, I - Incomplete
N - NATed, L - Local, X - No Socket
# Ent --&gt; Number of NHRP entries with same NBMA peer
NHS Status: E --&gt; Expecting Replies, R --&gt; Responding, W --&gt; Waiting
UpDn Time --&gt; Up or Down Time for a Tunnel
==========================================================================

Interface: Tunnel100, IPv4 NHRP Details 
Type:Spoke, NHRP Peers:2, 
# Ent  Peer NBMA Addr Peer Tunnel Add State  UpDn Tm Attrb
----- --------------- --------------- ----- -------- -----
    1  1.1.1.1         10.100.0.1       UP   01:20:18    S
    1  2.2.2.2         10.100.0.10      UP   01:20:08    S
</code></pre>
<p>Great! The spoke is now up and connect to the hubs! Lets take a look at the routing table: <strong><em>Routing table truncated to show relevant pieces</em></strong></p>
<pre><code>SPOKE1#sh ip route

 10.0.0.0/8 is variably subnetted, 10 subnets, 2 masks
C        10.100.0.0/24 is directly connected, Tunnel100
L        10.100.0.20/32 is directly connected, Tunnel100
D        10.254.254.1/32  [90/27008000] via 10.100.0.1, 01:23:00, Tunnel100
D        10.254.254.10/32 [90/27008000] via 10.100.0.10, 01:23:00, Tunnel100
D        10.254.254.30/32 [90/28288000] via 10.100.0.10, 01:23:00, Tunnel100
D     192.168.0.0/16 [90/27008000] via 10.100.0.10, 01:23:00, Tunnel100
                     [90/27008000] via 10.100.0.1, 01:23:00, Tunnel100
  192.168.41.0/24 is variably subnetted, 2 subnets, 2 masks
C        192.168.41.0/24 is directly connected, Loopback1
L        192.168.41.1/32 is directly connected, Loopback1
D     192.168.10.0/24 [90/27008000] via 10.100.0.1, 01:23:00, Tunnel100
D     192.168.11.0/24 [90/27008000] via 10.100.0.1, 01:23:00, Tunnel100
D     192.168.20.0/24 [90/27008000] via 10.100.0.10, 01:23:00, Tunnel100
D     192.168.21.0/24 [90/27008000] via 10.100.0.10, 01:23:09, Tunnel100
</code></pre>
<p>As you see we only have the aggregates in the spoke routing table. Now lets try to ping the LAN IP space on SPOKE 2. Lets look at the <strong><em>show dmvpn</em></strong> once again:</p>
<pre><code>SPOKE1#ping 192.168.30.1 source Lo1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.114.1, timeout is 2 seconds:
Packet sent with a source address of 192.168.30.1 
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 5/5/5 ms
SPOKE1#sh dmvpn                     
Legend: Attrb --&gt; S - Static, D - Dynamic, I - Incomplete
N - NATed, L - Local, X - No Socket
# Ent --&gt; Number of NHRP entries with same NBMA peer
NHS Status: E --&gt; Expecting Replies, R --&gt; Responding, W --&gt; Waiting
UpDn Time --&gt; Up or Down Time for a Tunnel
==========================================================================

Interface: Tunnel100, IPv4 NHRP Details 
Type:Spoke, NHRP Peers:3, 

 # Ent  Peer NBMA Addr Peer Tunnel Add State  UpDn Tm Attrb
 ----- --------------- --------------- ----- -------- -----
      1 1.1.1.1         10.100.0.1        UP 01:30:11     S
      1 2.2.2.2         10.100.0.10       UP 01:30:01     S
      2 4.4.4.4         10.100.0.30       UP 00:00:29     D
                        10.100.0.30       UP 00:00:29   DT1
</code></pre>
<p>Nice! The dynamic tunnel popped up without a problem. The following route was added to the routing table:</p>
<pre><code>H     192.168.30.0/24 [250/1] via 10.100.0.30, 00:04:38, Tunnel100
</code></pre>
<p>Just like we expected…NHRP has injected the more specific with the H designator. Now, if either of the hubs were to fail the other hub would continue to act as the NHRP server and the dynamic environment would continue to function.</p>
<h2 id="conclusion">Conclusion:</h2>
<p>DMVPN is a very useful tool in a Cisco routed environment. It can make rolling out new spokes very easy. There are also many ways to customize this environment. I see a lot of clients that will place the routers Internet interface and Internet default route into its own VRF and then have the tunnel passing routes into the global table. Then the hub will pass a default to the spoke and force all traffic through the hub. This allows for filtering and other security measures to be taken centrally.</p>
<h2 id="thanks">THANKS!</h2>
<p>Thanks for taking the time to read this. I hope you find it helpful! Please feel free to leave comments or contact me via twitter (<a href="https://twitter.com/dancwilliams">@dancwilliams</a>) if you have any questions or feedback.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco IOS SSL VPN with AD/RADIUS Authentication</title>
      <link>https://dancwilliams.com/cisco-ios-ssl-vpn-with-adradius-authentication/</link>
      <pubDate>Sat, 06 Dec 2014 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-ios-ssl-vpn-with-adradius-authentication/</guid>
      <description>&lt;h3 id=&#34;the-request&#34;&gt;The Request:&lt;/h3&gt;
&lt;p&gt;Now that Cisco has included SSL VPN licensing as part of the 15.3(3)M IOS I have had multiple clients ask about turning on the capability and reaching back into Active Directory for authentication.&lt;/p&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;The Solution:&lt;/h2&gt;
&lt;p&gt;The equipment I used to lab this solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cisco 881 w/ IOS 15.3(3)M3 (10.0.1.238)&lt;/li&gt;
&lt;li&gt;Windows Server 2008 R2 (10.0.1.231)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First we will go through the steps to configure the RADIUS server on Windows so we have access to Active Directory for authentication. You must first ensure the “Network Policy and Access Services” role is installed on the server. Once this role is installed we will go into NPS (Local) &amp;gt; RADIUS Clients and Servers &amp;gt; RADIUS Clients. Here will will configure our router as a RADIUS Client. Be sure to make note of the key you specify here as you will need it when configuring the RADIUS server on the router.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="the-request">The Request:</h3>
<p>Now that Cisco has included SSL VPN licensing as part of the 15.3(3)M IOS I have had multiple clients ask about turning on the capability and reaching back into Active Directory for authentication.</p>
<h2 id="the-solution">The Solution:</h2>
<p>The equipment I used to lab this solution:</p>
<ul>
<li>Cisco 881 w/ IOS 15.3(3)M3 (10.0.1.238)</li>
<li>Windows Server 2008 R2 (10.0.1.231)</li>
</ul>
<p>First we will go through the steps to configure the RADIUS server on Windows so we have access to Active Directory for authentication. You must first ensure the “Network Policy and Access Services” role is installed on the server. Once this role is installed we will go into NPS (Local) &gt; RADIUS Clients and Servers &gt; RADIUS Clients. Here will will configure our router as a RADIUS Client. Be sure to make note of the key you specify here as you will need it when configuring the RADIUS server on the router.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/add-radius-client-1_hu_bc1dcf6529e92610.png 500w
  
  
    , /cisco-ios-ssl-vpn-with-adradius-authentication/images/add-radius-client-1_hu_77b6501991e8286.png 800w
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/add-radius-client-1.png" 
  
  >
 <br>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-client-config-1.png" 
  
  >
<br>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-client-config-2.png" 
  
  >
<p>Once our RADIUS client is configured we will move on to configuring the Network Policies in NPS (Local) &gt; Policies &gt; Network Policies and clicking NEW under Actions.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-1_hu_e657036d640deebb.png 500w
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-1.png" 
  
  >
<p>Under the Conditions Tab you will want to add a Windows Group that contains your users that are allowed VPN access and a NAS IPv4 Address to specify the requesting router.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-2_hu_31dd418a7337cf1a.png 500w
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-2.png" 
  
  >
<p>Under the Constraints tab you will only select Unencrypted Authentication (PAP, SPAP).</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-3_hu_f5338ed2bc29fab2.png 500w
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-3.png" 
  
  >
<p>The Settings tab can be left at default. Make sure that you move your new policy to the top of the list!</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-4_hu_892c5bcf2a809ca6.png 500w
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/radius-policy-4.png" 
  
  >
<p>Now that we have the Windows Server piece configured we can move on to the configuration of the router. I have included the main configuration blocks below. Be sure to bind radius requests to the interface with the IP you specified in the Windows Server configuration or else requests may fail. Depending on the environment some people choose to use a loopback address for this.</p>
<p><strong>Note</strong>: <em>The only interface I have configured on this router is the Fa4 interface with the IP 10.0.1.238 which is plugged into my lab environment. Also, when you first issue the webvpn gateway NAME command and self-signed cert and trustpoint will be configured. I have included a reference doc at the bottom that goes through the SSL VPN config in more detail.</em></p>
<pre><code>aaa new-model
!
radius server RADIUS 
address ipv4 10.0.1.231 auth-port 1645 acct-port 1646 
key XXXXXXXXX
!
aaa group server radius TEST881
 server name RADIUS
!
ip radius source-interface FastEthernet4 
!
aaa authentication login SSL_VPN group TEST881 local
!
webvpn gateway SSLVPN_Gateway
    ip address 10.0.1.238 port 443  
    http-redirect port 80
    ssl trustpoint TP-self-signed-4045373729
    inservice
!
webvpn context SSLVPN_Context
    title &quot;Network Hobo VPN&quot;
    login-photo file flash:/Blog_LOGO.png
    logo file flash:/Blog_LOGO.png
    login-message &quot;Secure Access&quot;
    aaa authentication list SSL_VPN
    gateway SSLVPN_Gateway
    !
    ssl authenticate verify all
    !
    url-list &quot;Internal Sites&quot;
        heading &quot;LAB&quot;
        url-text &quot;CACTI&quot; url-value &quot;http://10.0.1.241&quot;
        url-text &quot;IOU-WEB&quot; url-value &quot;http://10.0.1.34&quot;
    inservice
    !
    policy group SSLVPN_DefaultPolicy
        url-list &quot;Internal Sites&quot;
    default-group-policy SSLVPN_DefaultPolicy
</code></pre>
<p>Once you have your RADIUS server and additional aaa config in place you can test RADIUS authentication using the following command:</p>
<pre><code>TEST_881#test aaa group radius dwilliams Test1Test1 legacy 
Attempting authentication test to server-group radius using radius
User was successfully authenticated.
</code></pre>
<p>Next you can navigate to your SSL VPN site and attempt to log in. Everthing should be good to go if you have followed the steps above.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/vpn-login_hu_19244f2b906e4af6.png 500w
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/vpn-login.png" 
  
  >
<br>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-ios-ssl-vpn-with-adradius-authentication/images/vpn-login-2_hu_a7473089ded0dd51.png 500w
  
  
  
  '
  
    src="/cisco-ios-ssl-vpn-with-adradius-authentication/images/vpn-login-2.png" 
  
  >
<h2 id="conclusion">Conclusion:</h2>
<p>The ability to implement the Cisco IOS SSL VPN and tie it back into AD without any additional cost or licensing is a big thing to many of my clients. This will give many existing organizations a new capability to lock down their edge and really enhance remote access capabilities with the investment of a little time and possibly some consulting dollars. While I mainly focused on authenticating through AD/RADIUS in this article there are many other capabilities of the SSL VPN that I did not cover. Maybe in a future write up…</p>
<h2 id="thanks">THANKS!</h2>
<p>I would like to say a quick thank you to the following references while I was working through this:</p>
<ul>
<li><a href="https://sites.google.com/site/amitsciscozone/home/security/clientless-ssl-vpn-on-cisco-ios-router-with-sdm">Clientless SSL VPN on Cisco IOS Router - Knowledge Base</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco 6807 VSS ISSU Upgrade</title>
      <link>https://dancwilliams.com/cisco-6807-vss-issu-upgrade/</link>
      <pubDate>Fri, 05 Dec 2014 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-6807-vss-issu-upgrade/</guid>
      <description>&lt;h3 id=&#34;the-request&#34;&gt;The Request:&lt;/h3&gt;
&lt;p&gt;I have a client with multiple 6807 VSS pairs that required an IOS upgrade. All of the pairs have a single SUP2-T in each chassis and were in the 15 code train. Although the ISSU process is very straight forward I wanted to put this quick process up as I had to search through multiple documents to gather all the pieces I needed to knock it out.&lt;/p&gt;
&lt;h3 id=&#34;the-solution&#34;&gt;The Solution:&lt;/h3&gt;
&lt;p&gt;Since these switches were in the proper code train to utilize ISSU I decided that was the best route to go. It also helps that everything was already dual-homed. This process is for VSS pairs with only one SUP per chassis! If you have another configuration you can reference the Cisco document provided at the bottom of the post. &lt;strong&gt;&lt;em&gt;Some example text was taken from the Cisco Document referenced below&lt;/em&gt;&lt;/strong&gt; One of the first things you want to verify is that there is a current boot variable configured on the VSS pair pointing to the version of code that is running currently. Some devices only have one version of code on the bootdisk so there is not a boot variable configured. For the ISSU to perform properly you MUST configure the boot variable:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="the-request">The Request:</h3>
<p>I have a client with multiple 6807 VSS pairs that required an IOS upgrade. All of the pairs have a single SUP2-T in each chassis and were in the 15 code train. Although the ISSU process is very straight forward I wanted to put this quick process up as I had to search through multiple documents to gather all the pieces I needed to knock it out.</p>
<h3 id="the-solution">The Solution:</h3>
<p>Since these switches were in the proper code train to utilize ISSU I decided that was the best route to go. It also helps that everything was already dual-homed. This process is for VSS pairs with only one SUP per chassis! If you have another configuration you can reference the Cisco document provided at the bottom of the post. <strong><em>Some example text was taken from the Cisco Document referenced below</em></strong> One of the first things you want to verify is that there is a current boot variable configured on the VSS pair pointing to the version of code that is running currently. Some devices only have one version of code on the bootdisk so there is not a boot variable configured. For the ISSU to perform properly you MUST configure the boot variable:</p>
<pre><code>Router(config)# boot system flash bootdisk:s72033-oldversion.v1
</code></pre>
<p>Next you will want to download the new image from your favorite file transfer spot to your bootdisk. I prefer to use FTP:</p>
<pre><code>Router# copy ftp: bootdisk:
Address or name of remote host []? test.ftp.local
Source filename []? s72033-newversion.v2
Destination filename [s72033-newversion.v2]?
Accessing ftp://test.ftp.local/s72033-newversion.v2...!!!!! Complete
</code></pre>
<p>Once the image is downloaded you will want to copy the image over to the slavebootdisk:</p>
<pre><code>Router# copy bootdisk: slavebootdisk:
Source filename []? s72033-newversion.v2
Destination filename [s72033-newversion.v2]?
Copy in progress...CCCCCCCCCCCCCCC Complete
</code></pre>
<p>After you have the images on both bootdisks you can begin the ISSU process. The first step is to verify the VSS pair is ready for the ISSU upgrade:</p>
<pre><code>Router# show issu state detail
Slot = 1/3
RP State = Active
ISSU State = Init
Boot Variable = bootdisk:s72033-oldversion.v1,12;
Operating Mode = sso
Primary Version = N/A
Secondary Version = N/A
Current Version = bootdisk:s72033-oldversion.v1
Variable Store = PrstVbl

Slot = 2/3
RP State = Standby
ISSU State = Init
Boot Variable = bootdisk:s72033-oldversion.v1,12;
Operating Mode = sso
Primary Version = N/A
Secondary Version = N/A
Current Version = bootdisk:s72033-oldversion.v1

Router# show redundancy states
my state = 13 -ACTIVE
peer state = 8 -STANDBY HOT
Mode = Duplex
Unit = Secondary
Unit ID = 18

Redundancy Mode (Operational) = sso
Redundancy Mode (Configured) = sso
Redundancy State = sso
Maintenance Mode = Disabled
Communications = Up

client count = 132
client_notification_TMR = 30000 milliseconds
keep_alive TMR = 9000 milliseconds
keep_alive count = 0
keep_alive threshold = 18
RF debug mask = 0x0
</code></pre>
<p>Once the pair is verified to be good to go you will want to load the new image onto the standby chassis. This will load the new code on the standby and reload the chassis. If you have <span style="text-decoration:underline;"><strong>EVERYTHING DUAL HOMED</strong></span> you will not see an interruption in traffic.</p>
<pre><code>Router# issu loadversion bootdisk:s72033-newversion.v2

000133: Aug 6 16:17:44.486 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet1/3/4, changed state to down
000134: Aug 6 16:17:43.507 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet2/3/4, changed state to down
000135: Aug 6 16:17:43.563 PST: %LINK-3-UPDOWN: Interface TenGigabitEthernet2/3/4, changed state to down
000136: Aug 6 16:17:44.919 PST: %LINK-3-UPDOWN: Interface TenGigabitEthernet1/3/4, changed state to down

(Deleted many interface and protocol down messages)

%issu loadversion executed successfully, Standby is being reloaded

(Deleted many interface and protocol down messages, then interface and protocol up messages)

0000148: Aug 6 16:27:54.154 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet1/3/5, changed state to up
000149: Aug 6 16:27:54.174 PST: %LINK-3-UPDOWN: Interface TenGigabitEthernet2/3/5, changed state to up
000150: Aug 6 16:27:54.186 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet2/3/5, changed state to up
000151: Aug 6 16:32:58.030 PST: %HA_CONFIG_SYNC-6-BULK_CFGSYNC_SUCCEED: Bulk Sync succeeded
</code></pre>
<p>During the process you will want to run the following command until you see that the <strong>ISSU</strong> <span style="text-decoration:underline;"><strong>Sub-State</strong></span> is <strong>Load Version Complete</strong>:</p>
<pre><code>Router# show issu state detail
Slot = 1/3
RP State = Active
ISSU State = Load Version
Boot Variable = bootdisk:s72033-oldversion.v1,12
Operating Mode = sso
Primary Version = bootdisk:s72033-oldversion.v1
Secondary Version = bootdisk:s72033-newversion.v2
Current Version = bootdisk:s72033-oldversion.v1
Variable Store = PrstVbl

Slot = 2/3
RP State = Standby
ISSU State = Load Version
Boot Variable = bootdisk:s72033-newversion.v2,12;bootdisk:s72033-oldversion.v1,12
Operating Mode = sso
Primary Version = bootdisk:s72033-oldversion.v1
Secondary Version = bootdisk:s72033-newversion.v2
Current Version = bootdisk:s72033-newversion.v2

Router# show redundancy status
my state = 13 -ACTIVE
peer state = 8 -STANDBY HOT
Mode = Duplex
Unit = Secondary
Unit ID = 18

Redundancy Mode (Operational) = sso
Redundancy Mode (Configured) = sso
Redundancy State = sso
Maintenance Mode = Disabled
Communications = Up

client count = 132
client_notification_TMR = 30000 milliseconds
keep_alive TMR = 9000 milliseconds
keep_alive count = 1
keep_alive threshold = 18
RF debug mask = 0x0
</code></pre>
<p>Once this state is reached you will want to go into the next step to force a switchover to the standby chassis that is running the new code and being upgrading the remaining chassis. Once you issue the runversion command it will start a rollback timer that is by default set to 45 minutes. <strong>If you do not commit the version (next step) before the timer runs out the upgrade will be rolled back!</strong></p>
<pre><code>Router# issu runversion
This command will reload the Active unit. Proceed ? [confirm]
(Deleted many lines)

Download Start
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(Deleted many lines)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Download Completed! Booting the image.
Self decompressing the image : ##########################################################################################
(Deleted many lines)
</code></pre>
<h6></h6>
<pre><code>running startup....

(Deleted many lines)

000147: Aug 6 16:53:43.199 PST: %HA_CONFIG_SYNC-6-BULK_CFGSYNC_SUCCEED: Bulk Sync succeeded
</code></pre>
<p>Once the chassis has rebooted we will once again want to verify the ISSU state and redundancy state:</p>
<pre><code>Router# show issu state detail
Slot = 2/3
RP State = Active
ISSU State = Run Version
Boot Variable = bootdisk:s72033-newversion.v2,12;bootdisk:s72033-oldversion.v1,12
Operating Mode = sso
Primary Version = bootdisk:s72033-newversion.v2
Secondary Version = bootdisk:s72033-oldversion.v1
Current Version = bootdisk:s72033-newversion.v2
Variable Store = PrstVbl

Slot = 1/3
RP State = Standby
ISSU State = Run Version
Boot Variable = bootdisk:s72033-oldversion.v1,12
Operating Mode = sso
Primary Version = bootdisk:s72033-newversion.v2
Secondary Version = bootdisk:s72033-oldversion.v1
Current Version = bootdisk:s72033-oldversion.v1

Router# show redundancy status
my state = 13 -ACTIVE
peer state = 8 -STANDBY HOT
Mode = Duplex
Unit = Primary
Unit ID = 39

Redundancy Mode (Operational) = sso
Redundancy Mode (Configured) = sso
Redundancy State = sso
Maintenance Mode = Disabled
Communications = Up

client count = 134
client_notification_TMR = 30000 milliseconds
keep_alive TMR = 9000 milliseconds
keep_alive count = 1
keep_alive threshold = 18
RF debug mask = 0x0
</code></pre>
<p>You will now want to commit the new version to reload the standby chassis and have it run the new image:</p>
<pre><code>Router# issu commitversion
Building configuration...
[OK]
000148: Aug 6 17:17:28.267 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet2/3/4, changed state to down
000149: Aug 6 17:17:28.287 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet1/3/4, changed state to down

(Deleted many interface and protocol down messages)

%issu commitversion executed successfully

(Deleted many interface and protocol down messages, then interface and protocol up messages)

000181: Aug 6 17:41:51.086 PST: %LINEPROTO-5-UPDOWN: Line protocol on Interface TenGigabitEthernet1/3/5, changed state to up
000182: Aug 6 17:42:52.290 PST: %HA_CONFIG_SYNC-6-BULK_CFGSYNC_SUCCEED: Bulk Sync succeeded
</code></pre>
<p>Once this has completed your entire VSS pair will be upgraded. You can verify the upgrade by once again checking the ISSU &amp; redundancy state:</p>
<pre><code>Router# show issu state detail
Slot = 2/3
RP State = Active
ISSU State = Init
Boot Variable = bootdisk:s72033-newversion.v2,12;bootdisk:s72033-oldversion.v1,12
Operating Mode = sso
Primary Version = N/A
Secondary Version = N/A
Current Version = bootdisk:s72033-newversion.v2
Variable Store = PrstVbl

Slot = 1/3
RP State = Standby
ISSU State = Init
Boot Variable = bootdisk:s72033-newversion.v2,12;bootdisk:s72033-oldversion.v1,12
Operating Mode = sso
Primary Version = N/A
Secondary Version = N/A
Current Version = bootdisk:s72033-newversion.v2

Router# show redundancy status
my state = 13 -ACTIVE
peer state = 8 -STANDBY HOT
Mode = Duplex
Unit = Primary
Unit ID = 39

Redundancy Mode (Operational) = sso
Redundancy Mode (Configured) = sso
Redundancy State = sso
Maintenance Mode = Disabled
Communications = Up

client count = 134
client_notification_TMR = 30000 milliseconds
keep_alive TMR = 9000 milliseconds
keep_alive count = 1
keep_alive threshold = 18
RF debug mask = 0x0
</code></pre>
<h3 id="conclusion">Conclusion:</h3>
<p>Once I found all of the information I needed this was a very easy process and actually did not take as long as I expected. The boot variable was one issue I ran into but once I figured out what it was asking for that was easy to fix. Another thing to be mindful of is that after the upgrade process your original active processor will be the standby processor.</p>
<h3 id="thanks">THANKS!</h3>
<p>I would like to say a quick thank you to the following references while I was working through this:</p>
<ul>
<li><a href="http://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst6500/ios/15-1SY/config_guide/sup2T/15_1_sy_swcg_2T/virtual_switching_systems.html#14718">Cisco Release 15.1SY Supervisor Engine 2T Software Configuration Guide</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>GoDaddy: Delegate Subdomain to Different Nameserver</title>
      <link>https://dancwilliams.com/godaddy-delegate-subdomain-to-different-nameserver/</link>
      <pubDate>Tue, 22 Jul 2014 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/godaddy-delegate-subdomain-to-different-nameserver/</guid>
      <description>&lt;ol&gt;
&lt;li&gt;Access your GoDaddy domain manager&lt;/li&gt;
&lt;li&gt;Select your domain&lt;/li&gt;
&lt;li&gt;Select the “DNS Zone File” Tab&lt;/li&gt;
&lt;li&gt;Select “Add Record”&lt;/li&gt;
&lt;li&gt;Create a new “Nameserver” entry. See capture below. The “host” will be the subdomain you want to point to the new server. Use the proper nameserver naming format or GoDaddy will kick an error.&lt;/li&gt;
&lt;/ol&gt;



























&lt;img 
  sizes=&#34;(min-width: 35em) 1200px, 100vw&#34;
  srcset=&#39;
  
    /godaddy-delegate-subdomain-to-different-nameserver/images/5_hu_ee6332dbf32e968b.png 500w
  
  
  
  &#39;
  
    src=&#34;https://dancwilliams.com/godaddy-delegate-subdomain-to-different-nameserver/images/5.png&#34; 
  
  alt=&#39;add fqdn initial pointer&#39;&gt;
&lt;ol start=&#34;6&#34;&gt;
&lt;li&gt;If you do not have a FQDN for your nameserver you will want to create an A record pointing to its IP:&lt;/li&gt;
&lt;/ol&gt;



























&lt;img 
  sizes=&#34;(min-width: 35em) 1200px, 100vw&#34;
  srcset=&#39;
  
    /godaddy-delegate-subdomain-to-different-nameserver/images/6_hu_e17a278c55818d13.png 500w
  
  
  
  &#39;
  
    src=&#34;https://dancwilliams.com/godaddy-delegate-subdomain-to-different-nameserver/images/6.png&#34; 
  
  alt=&#39;add pointer to dns server&#39;&gt;
&lt;h3 id=&#34;thanks&#34;&gt;THANKS!&lt;/h3&gt;
&lt;p&gt;I would like to that &lt;a href=&#34;https://twitter.com/ssl_boy&#34;&gt;Glen Kemp&lt;/a&gt; who began discussing this topic with me. I thought I should put this up even though GoDaddy clearly supports this procedure in their &lt;a href=&#34;http://support.godaddy.com/help/article/680/managing-dns-for-your-domain-names?pc_split_value=4&#34;&gt;Support Forums&lt;/a&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<ol>
<li>Access your GoDaddy domain manager</li>
<li>Select your domain</li>
<li>Select the “DNS Zone File” Tab</li>
<li>Select “Add Record”</li>
<li>Create a new “Nameserver” entry. See capture below. The “host” will be the subdomain you want to point to the new server. Use the proper nameserver naming format or GoDaddy will kick an error.</li>
</ol>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /godaddy-delegate-subdomain-to-different-nameserver/images/5_hu_ee6332dbf32e968b.png 500w
  
  
  
  '
  
    src="/godaddy-delegate-subdomain-to-different-nameserver/images/5.png" 
  
  alt='add fqdn initial pointer'>
<ol start="6">
<li>If you do not have a FQDN for your nameserver you will want to create an A record pointing to its IP:</li>
</ol>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /godaddy-delegate-subdomain-to-different-nameserver/images/6_hu_e17a278c55818d13.png 500w
  
  
  
  '
  
    src="/godaddy-delegate-subdomain-to-different-nameserver/images/6.png" 
  
  alt='add pointer to dns server'>
<h3 id="thanks">THANKS!</h3>
<p>I would like to that <a href="https://twitter.com/ssl_boy">Glen Kemp</a> who began discussing this topic with me. I thought I should put this up even though GoDaddy clearly supports this procedure in their <a href="http://support.godaddy.com/help/article/680/managing-dns-for-your-domain-names?pc_split_value=4">Support Forums</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Convert Audio Files for use with the Cisco Unified Communications Suite</title>
      <link>https://dancwilliams.com/convert-audio-files-for-use-with-the-cisco-unified-communications-suite/</link>
      <pubDate>Tue, 28 Jan 2014 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/convert-audio-files-for-use-with-the-cisco-unified-communications-suite/</guid>
      <description>&lt;h3 id=&#34;quick-note&#34;&gt;Quick Note:&lt;/h3&gt;
&lt;p&gt;I thought I would make a quick post around how I prepare audio files for deployment in Unity Connection, Communications Manager, Contact Center Express, and other Cisco UC&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; products. This post will be focused around Unity Connections but the same method can be used for all applications.&lt;/p&gt;
&lt;h3 id=&#34;the-request&#34;&gt;The Request:&lt;/h3&gt;
&lt;p&gt;Due to inclement weather conditions in the southeast I had multiple clients that needed emergency messages uploaded to their Unity Connection auto attendants. I have some clients that have call handler managers and record and configure their own messages on the systems.  But, I have quite a few that would much rather just record a message with whatever is handy (an iPhone more and more these days) and e-mail it to me for uploading and configuration.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="quick-note">Quick Note:</h3>
<p>I thought I would make a quick post around how I prepare audio files for deployment in Unity Connection, Communications Manager, Contact Center Express, and other Cisco UC<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> products. This post will be focused around Unity Connections but the same method can be used for all applications.</p>
<h3 id="the-request">The Request:</h3>
<p>Due to inclement weather conditions in the southeast I had multiple clients that needed emergency messages uploaded to their Unity Connection auto attendants. I have some clients that have call handler managers and record and configure their own messages on the systems.  But, I have quite a few that would much rather just record a message with whatever is handy (an iPhone more and more these days) and e-mail it to me for uploading and configuration.</p>
<h3 id="the-solution">The Solution:</h3>
<p>I like to use the <a href="http://www.nch.com.au/switch/index.html">Switch application by NCH Software</a> for this task. For the amount of time I spend performing this task I find the software to be extremely easy to use, accepting of every format I have thrown at it, and relatively inexpensive. I thought the best way to show how to do this would be by shooting a quick video:</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/liPCTVBRWT4?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>
<p>Also here is a quick screen shot of the settings for the WAV conversion so it will be in the format Cisco likes! I know we have all run into this especially with things like music on hold…</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /convert-audio-files-for-use-with-the-cisco-unified-communications-suite/images/audio_conversion_hu_407634ff3605ab0c.png 500w
  
  
    , /convert-audio-files-for-use-with-the-cisco-unified-communications-suite/images/audio_conversion_hu_b09cea9177983d62.png 800w
  
  
  '
  
    src="/convert-audio-files-for-use-with-the-cisco-unified-communications-suite/images/audio_conversion.png" 
  
  alt='audio conversion settings'>
<h3 id="conclusion">Conclusion:</h3>
<p>This is just a short post on a topic I am asked about often. I am sure there are MANY different ways to accomplish this task using many different tools and methods. I would love for you all to share your method in the comments so we can all learn!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Unified Communications&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Configure TACACS&#43; Access on Nexus 7K</title>
      <link>https://dancwilliams.com/configure-tacacs-access-on-nexus-7k/</link>
      <pubDate>Thu, 23 Jan 2014 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/configure-tacacs-access-on-nexus-7k/</guid>
      <description>&lt;h3 id=&#34;the-request&#34;&gt;The Request:&lt;/h3&gt;
&lt;p&gt;Two new Nexus 7Ks have been installed at one of my client’s data centers. Management connectivity was brought up to the data center core and verified. I was given console access and told to configure TACACS+&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; authentication and authorization on the F2 VDC&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h3 id=&#34;the-solution&#34;&gt;The Solution:&lt;/h3&gt;
&lt;p&gt;Configuring TACACS+ on the Nexus 7K is totally different than on IOS and even different than on the Nexus 5K equipment. It also requires a certain order of operations and there is one solid “gotcha” that most people run into. But, knowing these going in will make this a painless procedure. The first thing to remember is that you MUST enter the TACACS+ server key UNENCRYPTED. Most templates within many organizations I work with keep the TACACS+ key in its encrypted format within template documents. Entering it into a Nexus 7K in this format WILL NOT WORK. Been there…done that… First you will need to make sure the TACACS+ feature in enabled on the NEXUS 7K by entering the following command:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="the-request">The Request:</h3>
<p>Two new Nexus 7Ks have been installed at one of my client’s data centers. Management connectivity was brought up to the data center core and verified. I was given console access and told to configure TACACS+<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> authentication and authorization on the F2 VDC<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<h3 id="the-solution">The Solution:</h3>
<p>Configuring TACACS+ on the Nexus 7K is totally different than on IOS and even different than on the Nexus 5K equipment. It also requires a certain order of operations and there is one solid “gotcha” that most people run into. But, knowing these going in will make this a painless procedure. The first thing to remember is that you MUST enter the TACACS+ server key UNENCRYPTED. Most templates within many organizations I work with keep the TACACS+ key in its encrypted format within template documents. Entering it into a Nexus 7K in this format WILL NOT WORK. Been there…done that… First you will need to make sure the TACACS+ feature in enabled on the NEXUS 7K by entering the following command:</p>
<pre><code>config
feature tacacs+
</code></pre>
<p>Now you will need to decide how to configure your TACACS+ server keys. You can either configure a global key for all servers or on a per-server basis: Global Key:</p>
<pre><code>tacacs-server key 0 TESTKEY
</code></pre>
<p>Per-Server Key:</p>
<pre><code>tacacs-server host X.X.X.X key 0 TESTKEY
</code></pre>
<p>Now you will need to list all of your TACACS+ hosts. Previously I showed you how to enter a host with a per-server key. If you use a global key you will use this command:</p>
<pre><code>tacacs-server host X.X.X.X
</code></pre>
<p>Now we need to configure a TACACS+ group to use for authentication, authorization, accounting, etc. Here is an example:</p>
<pre><code>aaa group server tacacs+ TESTNAME
    server X.X.X.X
    server X.X.X.X
    server X.X.X.X
    use-vrf VRFNAME
</code></pre>
<p>The servers you enter into the group must first be defined as tacacs-server hosts as shown in the previous configuration . If you know this fact going in it is a huge time saver! It is also recommended that you configure the VRF that you would like to use for TACACS+ access. If you have no VRFs configured just use the following code to use the default VRF:</p>
<pre><code>use-vrf default
</code></pre>
<p>Now you want to tell the Nexus 7K where to source the request from. For example if you were to use VLAN 2 for the TACACS+ source interface you would use the following code:</p>
<pre><code>ip tacacs source-interface vlan 2
</code></pre>
<p>Some organizations also like to use directed requests to allow certain groups point their logins toward certain authentication servers outside of the standard group configuration. The command that allows this to happen is:</p>
<pre><code>tacacs-server directed-request
</code></pre>
<p>After all of this has been configured you are ready to add your authentication strings and test. I always recommend ensuring authentication works before configuring anything further, especially authorization as it can definitely slow down the process. The aaa string you need to enter is as follows:</p>
<pre><code>aaa authentication login default group TESTNAME
</code></pre>
<p>Now you can test using the following command:</p>
<pre><code>test aaa group TESTNAME username password
</code></pre>
<p>This will allow you to verify TACACS+ is working properly. Once this is confirmed you can move on to the authorization and accounting configuration:</p>
<pre><code>aaa authentication login console group TESTNAME
aaa authorization commands default group TESTNAME
aaa accounting default group TESTNAME
aaa authentication login error-enable
</code></pre>
<p>I have included the full config below. If commands are entered in this order you will be good to go!</p>
<pre><code>config
feature tacacs+
tacacs-server key 0 TESTKEY
tacacs-server host X.X.X.X
tacacs-server host X.X.X.X
tacacs-server host X.X.X.X
aaa group server tacacs+ TESTNAME
    server X.X.X.X
    server X.X.X.X
    server X.X.X.X
    use-vrf VRFNAME
ip tacacs source-interface vlan 2
tacacs-server directed-request
aaa authentication login default group TESTNAME
aaa authentication login console group TESTNAME
aaa authorization commands default group TESTNAME
aaa accounting default group TESTNAME
aaa authentication login error-enable
</code></pre>
<h3 id="conclusion">Conclusion:</h3>
<p>I had a selfish motive for writing this post…I was tired of join through it over and over again. If the order of operations is followed properly, and the gotchas are avoided, this can be a fun and painless procedure. I hope this helps everyone and if you have any questions or improvements just let me know!</p>
<h3 id="thanks">THANKS!</h3>
<p>I would like to say a quick thank you to the following references while I was working through this:</p>
<ul>
<li>Josh O’Brien (<a href="https://twitter.com/joshobrien77">@joshobrien77</a>) over at staticnat.com! You post on Nexus 7000 TACACS+ helped a TON. You can read it <a href="http://www.staticnat.com/2010/11/07/tacacs-on-nexus-7000/">here</a>.</li>
<li><a href="http://www.cisco.com/en/US/docs/switches/datacenter/sw/6_x/nx-os/security/configuration/guide/b_Cisco_Nexus_7000_NX-OS_Security_Configuration_Guide__Release_6.x_chapter_0110.html">Cisco Nexus 7K Security Design Guide</a></li>
<li><a href="https://supportforums.cisco.com/docs/DOC-16435">Cisco Nexus 7K TACACS+ Example</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Terminal Access Controller Access-Control System Plus&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Virtual Device Context&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco Unified Communications Manager &amp; Unity Connection SFTP Emergency Backup to Mac OS X over the Internet</title>
      <link>https://dancwilliams.com/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/</link>
      <pubDate>Mon, 23 Dec 2013 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/</guid>
      <description>&lt;h3 id=&#34;the-request&#34;&gt;The Request:&lt;/h3&gt;
&lt;p&gt;I was engaged by a long time client who was having an issue with their local SFTP&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; server. After some upgrades to their server infrastructure they noticed their phone/voicemail system had not been backed up in MONTHS! They asked if there was a way for me to perform an “emergency” backup to my system if they gave the voice VLAN access to the Internet temporarily while they fixed their SFTP issues.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="the-request">The Request:</h3>
<p>I was engaged by a long time client who was having an issue with their local SFTP<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> server. After some upgrades to their server infrastructure they noticed their phone/voicemail system had not been backed up in MONTHS! They asked if there was a way for me to perform an “emergency” backup to my system if they gave the voice VLAN access to the Internet temporarily while they fixed their SFTP issues.</p>
<h3 id="the-solution">The Solution:</h3>
<p>It just so happened that when the client called me I was out of the office and working from the family home for the holidays. Here is the equipment I had available to me:</p>
<ul>
<li>Apple Airport Express MC414LL/A (Internet Gateway)</li>
<li>MacBook Pro w/ OS X Mavericks 10.9.1</li>
</ul>
<p>The Cisco phone system consists of the following components:</p>
<ul>
<li>Cisco CUCM<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> 9.0</li>
<li>CUC<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> 9.0</li>
</ul>
<p>This process is the same on both the CUCM and CUC.  There are additional services to backup under CUC but the backup system is identical. The first thing I needed to do was access the phone system and verify Internet connectivity. I used RDP<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> to access the client’s management server. Once logged in I accessed the phone system to verify Internet connectivity. This is done by logging into Cisco Unified OS Administration web page then going to Services &gt; Ping and trying to ping an outside address (4.2.2.2 in this example):</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/CUCM_1_hu_8a699bde0725b473.png 500w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/CUCM_1_hu_70ec6ce41bdb5d55.png 800w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/CUCM_1_hu_653186c3b2d6f8fa.png 1200w
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/CUCM_1.png" 
  
  alt='Ensure CUCM can access the Internet.'>
<p>Once Internet connectivity from the phone system was verified I moved on to configuring my local system to accept the transfer. First I configured NAT on the Apple Airport Express to pass SSH (port 22) from the Internet to my laptop. Below are the screenshots: First we access the Airport Utility and click on the Internet access router.  Make note of the IP Address as you will need it later:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/Airport_1_hu_bee3c2023ab1110d.png 500w
  
  
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/Airport_1.png" 
  
  alt='Check airport for global IP.'>
<p>Next we click &ldquo;Edit&rdquo; and go to the &ldquo;Network&rdquo; tab.  Then click the &ldquo;+&rdquo; below the &ldquo;Port Settings&rdquo; field:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-44-35_hu_aba3f8e611d3d0fd.png 500w
  
  
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-44-35.png" 
  
  alt='Add port to NAT.'>
<p>Next use the drop down to select the &ldquo;Remote Login - SSH&rdquo; service and point it to the IP of your laptop.  Click &ldquo;Save&rdquo; and then apply the configuration to the Airport Express:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-44-53_hu_4a1ffb2d76de53c9.png 500w
  
  
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-44-53.png" 
  
  alt='forward port 22 to laptop'>
<p>Once this was configured I moved on to configuring my laptop to accept SSH connections.  This process is pretty straight forward and I have included screenshots below:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-41-10_hu_582037ec8bb8bf13.png 500w
  
  
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-41-10.png" 
  
  alt='enable remote login on laptop'>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-41-39_hu_c60ffe2c65a9c249.png 500w
  
  
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-41-39.png" 
  
  alt='add users to remote access'>
<p>Once SSH was configured on the laptop it was time to configure a backup device on the phone system and perform a manual backup. Below are the screenshots: First I accessed the Disaster Recovery System &gt; Backup &gt; Backup Device and configured a new device.  You would replace the X.X.X.X with you Internet/Public IP address that you got off of your Airport Express.  Point the path to where you would like the backup files to be saved (I created a folder on my desktop to collect the files).  Then use your laptop username and password.  When you save the backup device it will test connectivity before declaring a successful save.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-49-13_hu_34373034a7fae769.png 500w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-49-13_hu_3a3fcf9b7a14c742.png 800w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-49-13_hu_c54841c0bff5b002.png 1200w
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-08-49-13.png" 
  
  alt='configure remote backup in CUMC'>
<p>Next you will go into Backup &gt; Manual and start a manual backup of all available services.  You will select the services by checking the box beside each one.  In Unity Connection you may receive popups concerning dependencies.  This will be ok since you will be selecting all services to back up.</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-11_hu_e6b627fb93dd43c4.png 500w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-11_hu_5c296a4cba19ffb9.png 800w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-11_hu_42285f0fd50d837c.png 1200w
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-11.png" 
  
  alt='setup backup job'>
<p>Once I verified the backups (Backup &gt; History) were successful I loaded them to Dropbox and shared them out to my client. Too easy!</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-32_hu_b732c58bac51dd0d.png 500w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-32_hu_97872b000f4f7dda.png 800w
  
  
    , /cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-32_hu_b373b7df9183f3f0.png 1200w
  
  '
  
    src="/cisco-unified-communications-manager-unity-connection-sftp-emergency-backup-to-mac-os-x-over-the-internet/images/screenshot-2013-12-23-09-33-32.png" 
  
  alt='backup success message'>
<h3 id="conclusion">Conclusion:</h3>
<p>This is a short post but the process definitely came through in a pinch so I wanted to get it documented. Luckily I was at a location with high enough bandwidth that the entire procedure was not TOO painful. I was able to help the client in their time of need and provide the level of service they are accustomed to receiving. That being said I will be setting up a full time SFTP server in the DMZ<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> at the office to handle these issues in the future. If you have any questions or suggestions feel free to comment below!  Thanks!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Secure File Transfer Protocol <a href="1" title="return to article"> ↩</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Cisco Unified Communications System <a href="2" title="return to article"> ↩</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Cisco Unity Connection <a href="3" title="return to article"> ↩</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Remote Desktop Protocol <a href="4" title="return to article"> ↩</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Demilitarized Zone <a href="5" title="return to article"> ↩</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco Translation Rules, CDRs, and Unity Connection</title>
      <link>https://dancwilliams.com/cisco-translation-rules-cdrs-and-unity-connection/</link>
      <pubDate>Thu, 19 Dec 2013 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-translation-rules-cdrs-and-unity-connection/</guid>
      <description>&lt;h3 id=&#34;the-request&#34;&gt;The Request:&lt;/h3&gt;
&lt;p&gt;I had a new client contact me requesting that I investigate a call that came in over the weekend where an external customer was able to leave a voicemail on an internal users extension, using the corporate IVR, instead of being routed to the weekend service. This behavior was unacceptable and caused much concern throughout the leadership. The client provided me the internal extension where the voicemail was left and a timeframe. Since I was relatively new to the system I was excited to get my hands dirty and really investigate the routing. As all voice engineers know, coming into a system someone else built can always be an adventure…&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h3 id="the-request">The Request:</h3>
<p>I had a new client contact me requesting that I investigate a call that came in over the weekend where an external customer was able to leave a voicemail on an internal users extension, using the corporate IVR, instead of being routed to the weekend service. This behavior was unacceptable and caused much concern throughout the leadership. The client provided me the internal extension where the voicemail was left and a timeframe. Since I was relatively new to the system I was excited to get my hands dirty and really investigate the routing. As all voice engineers know, coming into a system someone else built can always be an adventure…</p>
<h3 id="the-investigation">The Investigation:</h3>
<p>The system in question is a Cisco CUCM<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and CUC<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> 9.0 with SCCP<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> trunking. Since this client is closed on the weekends I thought the best place to start would be by looking at the weekend CDRs<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> from the time frame provided to see if anything stood out. I pulled the records and noticed that some calls were being translated directly to a certain extension although the client only had a small set of DIDs mapped to internal extensions. I stepped into the translation patterns and found that there were many DIDs being translated to the single extension I had noticed in the CDRs. I found this extension was a CTI<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> Route Point and was forwarded to voicemail. Upon accessing the voicemail system I first went into forwarded routing rules and located the CTI Route Point extension I had collected from the CDRs. It was forwarded to a company standard IVR call handler with no schedule! This definitely looked like our culprit. I compiled a list of the DIDs using this extension and forwarded the list to my client. The client replied saying these extensions were from their pre-Cisco “legacy” days and were used for all hour access to the system but were not published to the public. Apparently someone on the outside of the organization had found or been giving one of these numbers. The question was…which one?</p>
<h3 id="translation-patterns-cdr-analysis-and-the-solution">Translation Patterns, CDR Analysis, and The Solution:</h3>
<p>To cut to the chase…translation patterns do not show up in CDR records. It is sad but true. You will see the Calling No. field as the external caller’s phone number and the Called No. as the called number AFTER translation. So, since all of these legacy DIDs were translating to a single internal extension I was unable to say with certainty exactly which DID was being used. To solve this problem I changed the translation patterns for these DIDs into CTI Route Points. CTI Route Points do produce CDRs unlike the translation patterns. I then forwarded these CTI Route Patterns to voicemail. I created a new <a href="http://www.cisco.com/en/US/docs/voice_ip_comm/cucm/admin/7_1_2/ccmcfg/b05vmprf.html">voicemail profile</a> for masking these numbers with some arbitrary mask (<code>99999XXXXXXXXXX</code> for example) so I can setup a forwarded routing rule within Unity Connection to catch this mask and hand the call off to the call handler. This way we will see the DID used in all of the CDRs from now on. The solutions was tested and the CDRs were checked and everything looks great! Has anyone else done this a different way or recommend a different approach?</p>
<h3 id="thanks">THANKS!</h3>
<p>First I would like to thank <a href="http://protocol41.wordpress.com/about/">David</a> over at <a href="http://protocol41.wordpress.com/2013/04/23/call-routing-rules/">protocol41</a>. His entry had a quick blurb concerning Unity Connection order of operations that I needed to verify to make sure I was thinking straight! A few other links I used were <a href="http://www.cisco.com/en/US/tech/tk652/tk653/technologies_tech_note09186a00801c43f6.shtml">DID configuration from Cisco</a>. I was just investigating the Cisco “best practice” for DID configuration. I also used the <a href="http://www.cisco.com/en/US/docs/voice_ip_comm/connection/9x/administration/guide/9xcucsag090.pdf">Unity Connection Administration Guide</a> which is always a ton of info.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Cisco Unified Communications System <a href="1" title="return to article"> ↩</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Cisco Unity Connection <a href="2" title="return to article"> ↩</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Skinny Call Control Protocol <a href="3" title="return to article"> ↩</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Call Detail Records <a href="4" title="return to article"> ↩</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Computer Telephony Integration <a href="5" title="return to article"> ↩</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Cisco VRF/MP-BGP Router on a Stick with NAT</title>
      <link>https://dancwilliams.com/cisco-vrfmp-bgp-router-on-a-stick-with-nat/</link>
      <pubDate>Wed, 18 Dec 2013 00:00:00 +0000</pubDate>
      <guid>https://dancwilliams.com/cisco-vrfmp-bgp-router-on-a-stick-with-nat/</guid>
      <description>&lt;h1 id=&#34;the-request&#34;&gt;The Request:&lt;/h1&gt;
&lt;p&gt;I was approached by a client who wanted me to build their multi tenant network for a small office building. During the initial meeting it came out that they already had equipment and would like to use this equipment without purchasing much more. This is what I had to work with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 x Cisco X8XX Series ISR&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;6 x Cisco 2960X Switches&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The client also has an existing Cisco Unified Communications System that they will be configuring to provide voice services to all of the tenants. There will be no LAN-to-LAN communications between the tenants. There will be a reasonable amount of commercial grade Internet access and the tenants will be allowed to host some services locally (e-mail, collaboration software, etc.).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="the-request">The Request:</h1>
<p>I was approached by a client who wanted me to build their multi tenant network for a small office building. During the initial meeting it came out that they already had equipment and would like to use this equipment without purchasing much more. This is what I had to work with:</p>
<ul>
<li>1 x Cisco X8XX Series ISR<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li>
<li>6 x Cisco 2960X Switches</li>
</ul>
<p>The client also has an existing Cisco Unified Communications System that they will be configuring to provide voice services to all of the tenants. There will be no LAN-to-LAN communications between the tenants. There will be a reasonable amount of commercial grade Internet access and the tenants will be allowed to host some services locally (e-mail, collaboration software, etc.).</p>
<h2 id="my-proposed-solution">My Proposed Solution:</h2>
<p>Since the switches are strictly layer two devices and there will be zero tenant-to-tenant communications at the LAN level I proposed a VRF<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> solution utilizing the ISR as a router-on-a-stick. There will be a VRF for each tenant, a VRF for the voice service, a VRF for the WAN/Internet circuit. This will allow for strict separation of tenants while still allowing the sharing of voice and Internet services. Each VRF will reside in a VLAN that will be trounced to the stack of switches via a port-channel. I will leave the management VLAN in the global routing table.</p>
<h2 id="the-proof-of-concept">The Proof of Concept:</h2>
<h3 id="diagrams">Diagrams:</h3>
<p>Here is a small, basic, diagram of what we will be building:</p>



























<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
  
  
  '
  
    src="/cisco-vrfmp-bgp-router-on-a-stick-with-nat/images/VRF_MPBGP_DIAGRAM.png" 
  
  alt='MPBGP Diagram'>
<p>Here is how we broke down the VLANs/VRFs for the PoC<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> lab:</p>
<h3 id="vrfvlan-breakdown">VRF/VLAN Breakdown:</h3>
<table>
  <thead>
      <tr>
          <th>VRF Name</th>
          <th>Route Distinguisher</th>
          <th>VLAN ID</th>
          <th>IP Address</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>WAN</td>
          <td>99</td>
          <td>N/A</td>
          <td><code>10.20.30.253/24</code></td>
          <td>Internet Access</td>
      </tr>
      <tr>
          <td>red</td>
          <td>1</td>
          <td>1</td>
          <td><code>192.168.1.1/24</code></td>
          <td>Tenant 1</td>
      </tr>
      <tr>
          <td>blue</td>
          <td>2</td>
          <td>2</td>
          <td><code>192.168.2.1/24</code></td>
          <td>Tenant 2</td>
      </tr>
      <tr>
          <td>green</td>
          <td>3</td>
          <td>3</td>
          <td><code>192.168.1.1/24</code></td>
          <td>Tenant 3 - Dup Red IP</td>
      </tr>
      <tr>
          <td>voice</td>
          <td>111</td>
          <td>111</td>
          <td><code>10.1.1.1/24</code></td>
          <td>Shared Voice</td>
      </tr>
      <tr>
          <td>N/A</td>
          <td>N/A</td>
          <td>999</td>
          <td><code>10.9.9.1/24</code></td>
          <td>Management</td>
      </tr>
  </tbody>
</table>
<p>Remember: VRFs are case sensitive!</p>
<h3 id="switch-configuration-overview">Switch Configuration Overview:</h3>
<p>We will begin with the switches since they are the most basic. The switches will be stacked and the VLANs will be configured for each tenant, voice, and management. Since the switches are strictly layer 2 they will not be concerned with any of the VRF specific information.</p>
<h3 id="router-configuration-overview">Router Configuration Overview:</h3>
<p>The router is where the real work takes place. The router we are using in the lab is a Cisco 2821 running IOS 15.1.4M7 Advanced Enterprise Services.</p>
<h3 id="vrf-configuration">VRF Configuration</h3>
<p>The first thing we did was configure the VRFs individually:</p>
<pre><code>ip vrf WAN
 rd 65000:99
!
ip vrf red
 rd 65000:1
!
ip vrf blue
 rd 65000:2
!
ip vrf green
 rd 65000:3
!
ip vrf voice
 rd 65000:111
</code></pre>
<p>I like to match the RD <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> to the BGP ASN <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> and VLAN number whenever possible. As we begin importing an exporting routing to/from MP-BGP<sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> it will definitely help you keep things straight! In this scenario we are using an private ASN since we are not performing any external peering.</p>
<h3 id="mp-bgp-configuration">MP-BGP Configuration</h3>
<p>Now that we have our VRFs setup I like to go ahead and configure MP-BGP. This can also be done after you configure all of your VLANs. MP-BGP is used in the scenario only for leaking routes between VRFs. Since each VRF is its own virtual router you have to have a mechanism to allow them to share, or “leak”, routes between virtual routers. MP-BGP is that mechanism and is MUCH easier than it sounds! See configuration below:</p>
<pre><code>router bgp 65000
 bgp log-neighbor-changes
 !
 address-family ipv4 vrf WAN
  redistribute connected
 exit-address-family
!
 address-family ipv4 vrf red
  redistribute connected
 exit-address-family
 !
 address-family ipv4 vrf blue
  redistribute connected
 exit-address-family
 !
 address-family ipv4 vrf green
  redistribute connected
 exit-address-family
!
 address-family ipv4 vrf voice
  redistribute connected
 exit-address-family
</code></pre>
<p>Now that we have MP-BGP configured we will set the export and import statements within the VRFs. When thinking of import and export statements I always like to imagine I am standing on top of the VRF looking at MP-BGP. When I export from my VRF I am sending it to MP-BGP and when I import into my VRF I am importing from MP-BGP. Below is the configuration from the lab:</p>
<pre><code>ip vrf WAN
 rd 65000:99
 route-target export 65000:99
 route-target import 65000:1
 route-target import 65000:2
 route-target import 65000:3
!
ip vrf blue
 rd 65000:1
 route-target export 65000:1
 route-target import 65000:99
 route-target import 65000:111
!
ip vrf red
 rd 65000:2
 route-target export 65000:2
 route-target import 65000:99
 route-target import 65000:111
!
ip vrf green
 rd 65000:3
 route-target export 65000:3
 route-target import 65000:99
 route-target import 65000:111
!
ip vrf voice
 rd 65000:111
 route-target export 65000:111
 route-target import 65000:1
 route-target import 65000:2
 route-target import 65000:3
</code></pre>
<p>Lets take a look at the WAN VRF import/export statements more closely:</p>
<pre><code>ip vrf WAN
 rd 65000:99
 route-target export 65000:99
 route-target import 65000:1
 route-target import 65000:2
 route-target import 65000:3
</code></pre>
<p>In this statement you will see that I am exporting 65000:99 to MP-BGP and am importing 65000:1, 65000:2, and 65000:3 from MP-BGP. Those imports are the routes for VRF red, blue, and green respectively. You will also see that under each of those VRFs they are importing 65000:99. That gives them access to the routes in the WAN VRF. You will also notice that we are not importing the voice VRF (65000:111) into the WAN VRF nor are we importing the WAN VRF routes into the voice VRF. This will isolate the voice network from the Internet while still allowing the vice VLAN to be accessed by the tenants.</p>
<h3 id="port-channel-configuartion">Port-Channel Configuartion:</h3>
<p>Next we will configure the port-channel from the Cisco 2800 to the switch stack. Since we are using a 2821 in the lab we only have access to two ethernet ports. We are using G0/0 for WAN connectivity and we will use G0/1 as one half of the port-channel. This will work fine for a PoC. Below you will find the configuration from the lab:</p>
<pre><code>interface GigabitEthernet0/1
 no ip address
 duplex auto
 speed auto
 no keepalive
 channel-group 1
!
interface Port-channel1
 no ip address
!
interface Port-channel1.1
 encapsulation dot1Q 1 native
 ip vrf forwarding red
 ip address 192.168.1.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
!
interface Port-channel1.2
 encapsulation dot1Q 2
 ip vrf forwarding blue
 ip address 192.168.2.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
!
interface Port-channel1.3
 encapsulation dot1Q 3
 ip vrf forwarding green
 ip address 192.168.1.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
!
interface Port-channel1.111
 encapsulation dot1Q 111
 ip vrf forwarding voice
 ip address 10.1.1.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
!
interface Port-channel1.999
 encapsulation dot1Q 999
 ip address 10.9.9.1 255.255.255.0
 ip virtual-reassembly in
</code></pre>
<p>Remember: Configure the VRF information under the interface FIRST! It will erase all layer 3 information on the interface when configured. This is a very basic setup. First interface G0/1 is added to channel-group 1. Then interface port-channel 1 on configured with no IP address. This is because we are utilizing this router as a router-on-a-stick. That means we must configure the VLANs as sub interfaces of the port-channel. Each of these sub interfaces will be assigned to their respective VRF and dot1q VLAN. These are also configured as “ip nat inside” interfaces as they will be NAT’d through the WAN VRF.</p>
<h3 id="wan-interface-configuration">WAN Interface Configuration:</h3>
<pre><code>interface GigabitEthernet0/0
 description INTERNET INTERFACE - DO NOT TOUCH!!!
 ip vrf forwarding WAN
 ip address 10.20.30.253 255.255.255.0
 ip nat outside
 ip virtual-reassembly in
 duplex auto
 speed auto
</code></pre>
<p>The WAN interface configuration is quite straight forward. First we place interface G0/0 into the WAN VRF and then add the IP information.</p>
<h3 id="default-route-and-nat-configuration">Default Route and NAT Configuration</h3>
<p>Now that all of the interface, VLANs, VRFs, and MP-BGP are configured we are ready to give these tenants access to the Internet. Below is the configuration from the lab:</p>
<pre><code>ip route vrf WAN 0.0.0.0 0.0.0.0 10.20.30.1
ip route vrf blue 0.0.0.0 0.0.0.0 10.20.30.1
ip route vrf green 0.0.0.0 0.0.0.0 10.20.30.1
ip route vrf red 0.0.0.0 0.0.0.0 10.20.30.1
!
ip access-list extended BLUENAT
 permit ip 192.168.2.0 0.0.0.255 any
ip access-list extended GREENNAT
 permit ip 192.168.1.0 0.0.0.255 any
ip access-list extended REDNAT
 permit ip 192.168.1.0 0.0.0.255 any
ip access-list extended WAN
 permit ip any any log
!
ip nat inside source list BLUENAT interface GigabitEthernet0/0 vrf blue overload
ip nat inside source list GREENNAT interface GigabitEthernet0/0 vrf green overload
ip nat inside source list REDNAT interface GigabitEthernet0/0 vrf red overload
</code></pre>
<p>First you will see the default routes for each VRF. This is a straightforward configuration that tells each VLAN how to leave the network. The voice VLAN is not given a default route as it is not allowed access outside and does not know about the WAN VRF. Next we configured extended access lists for each VRF and called out the IP address space. Afterward we configured the NAT overload statements for each VRF. This configuration is pretty standard if you are familiar with traditional NAT configuration.</p>
<h3 id="static-nat-for-outside-access">Static NAT for Outside Access</h3>
<p>We also had to configure static NAT to allow people on the Internet the ability to access services internal to each tenant. Below is the configuration from the lab:</p>
<pre><code>ip nat inside source static tcp 192.168.1.1 443 10.20.30.253 80 vrf green extendable
ip nat inside source static tcp 192.168.1.1 443 10.20.30.253 443 vrf red extendable
</code></pre>
<p>We used these static NAT statements to show that the system is capable of NAT’ing to the same IP in different VRFs. As you will see in the output below this works without issue:</p>
<pre><code>2821#sh ip nat translations  verbose 
Pro Inside global      Inside local       Outside local      Outside global
tcp 10.20.30.253:80    192.168.1.1:443    10.20.30.102:62834 10.20.30.102:62834
    create 00:00:34, use 00:00:33 timeout:86400000, left 00:00:26, 
    flags: 
extended, timing-out, use_count: 0, VRF : green, entry-id: 10, lc_entries: 0
tcp 10.20.30.253:80    192.168.1.1:443    10.20.30.102:62835 10.20.30.102:62835
    create 00:00:33, use 00:00:32 timeout:86400000, left 00:00:27, 
    flags: 
extended, timing-out, use_count: 0, VRF : green, entry-id: 11, lc_entries: 0
tcp 10.20.30.253:80    192.168.1.1:443    ---                ---
    create 00:00:42, use 00:00:33 timeout:0, 
    flags: 
static, extended, extendable, use_count: 2, VRF : green, entry-id: 7, lc_entries: 0
tcp 10.20.30.253:443   192.168.1.1:443    10.20.30.102:62826 10.20.30.102:62826
    create 00:00:38, use 00:00:37 timeout:86400000, left 00:00:22, 
    flags: 
extended, timing-out, use_count: 0, VRF : red, entry-id: 8, lc_entries: 0
tcp 10.20.30.253:443   192.168.1.1:443    10.20.30.102:62827 10.20.30.102:62827
    create 00:00:38, use 00:00:37 timeout:86400000, left 00:00:22, 
    flags: 
extended, timing-out, use_count: 0, VRF : red, entry-id: 9, lc_entries: 0
tcp 10.20.30.253:443   192.168.1.1:443    ---                ---
    create 00:02:42, use 00:00:38 timeout:0, 
Pro Inside global      Inside local       Outside local      Outside global
    flags: 
static, extended, extendable, use_count: 2, VRF : red, entry-id: 4, lc_entries: 0
</code></pre>
<p>One issue I did run into, and I am still investing, is that remote access to the WAN interface though both SSH and Telnet stopped working once we configured the static NAT statements. We removed the statements and instantly things began working again. To work around this we configured a loopback interface and NAT’d port 22. This allowed external access once again. Below is the configuration form the lab:</p>
<pre><code>interface Loopback0
 ip vrf forwarding WAN
 ip address 10.255.255.255 255.255.255.255
!
ip nat inside source static tcp 10.255.255.255 22 10.20.30.253 22 vrf WAN extendable
</code></pre>
<p>We placed the loopback in the WAN VRF to isolate it as a WAN service.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Although I ran into a few roadblocks along the way I was able to get all of the services the client requested working on the equipment they provided. IF anyone sees any issue with the above configurations or would like more information feel free to comment below.</p>
<h3 id="thanks">THANKS!</h3>
<p>First I would like to that <a href="http://bit.ly/1cc02gt">Greg Ferro</a> whose book <a href="http://bit.ly/J6645g">Arse First Method of Technical Blogging</a> really got me motivated to start writing. I had been keeping lists of ideas for quite some time but his book really helped me put a plan together to get started! I would also like to thank <a href="http://bit.ly/1dP2qqA">Paul Stewart</a> for his great blog at <a href="http://bit.ly/18XoDTl">PacketU</a>, <a href="http://bit.ly/19dgjld">Marko Milivojevic</a> for his great VRF Route Leaking explanation at <a href="http://bit.ly/1cRFwQC">IPExpert</a> and <a href="http://bit.ly/19yKAsx">Jeremy Stretch</a> for his excellent VRF blogs over at <a href="http://packetlife.net/blog/2010/mar/29/inter-vrf-routing-vrf-lite/">PacketLife</a>.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>ISR: Integrated Services Router&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>VRF: Virtual Routing &amp; Forwarding&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>PoC: Proof of Concept&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>RD: Route Distinguisher&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>BGP ASN: Border Gateway Protocol Autonomous System Number&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>MP-BGP: Mutliprotocol Border Gateway Protocol&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
