Jekyll2023-08-23T02:26:05+00:00https://blog.repulsor.net/feed.xmlTheCaseTheCaseblog@repulsor.netI made ChatGPT write a blog post about ChatGPT2023-01-09T18:40:11+00:002023-01-09T18:40:11+00:00https://blog.repulsor.net/ChatGPT<p>I asked the ChatGPT AI to write a blog post about ChatGPT</p>
<p>This is what we got:</p>
<blockquote>
<p>Introducing ChatGPT: A New Approach to Chatbots</p>
<p>Over the past few years, chatbots have become an increasingly popular way for businesses to interact with customers. These virtual assistants use artificial intelligence to understand and respond to user inputs, allowing them to handle a wide range of customer inquiries and requests.</p>
<p>While chatbots have proven to be a useful tool for companies, they have also faced criticism for their often robotic and repetitive responses. In an effort to improve the chatbot experience, OpenAI has developed ChatGPT, a new type of chatbot that uses a cutting-edge language model called GPT-3 (Generative Pre-training Transformer 3).</p>
<p>What sets ChatGPT apart from traditional chatbots is its ability to generate human-like responses to user inputs. Using GPT-3, ChatGPT is able to understand the context and tone of a conversation, allowing it to provide more accurate and personalized responses.</p>
<p>In addition to its advanced language capabilities, ChatGPT also has the ability to learn from past conversations. This means that as it interacts with more users, it becomes increasingly intelligent and able to handle a wider range of inquiries.</p>
<p>One of the key benefits of ChatGPT is its ability to improve the customer experience. By providing more accurate and personalized responses, ChatGPT is able to better assist users and address their needs. This can help to increase customer satisfaction and loyalty, leading to improved business outcomes.</p>
<p>Overall, ChatGPT represents a major step forward in chatbot technology. Its advanced language capabilities and ability to learn from past conversations make it a powerful tool for businesses looking to improve their customer interactions.</p>
</blockquote>
<p>Well said. The future has some scary stuff in store for us humans.</p>TheCaseblog@repulsor.netI asked the ChatGPT AI to write a blog post about ChatGPTRoland JU-06A EXT CLK IN Doesn’t Trigger Arpeggiator2022-05-15T12:24:11+00:002022-05-15T12:24:11+00:00https://blog.repulsor.net/Roland-JU-06A-ext-clk-appegiator<p>A major miss by Roland on the JU-06a Boutique - the external clock sync does not trigger held notes when the arpeggio function is enabled.
This unfortunate, as it is a feature that exists in many (all?) other Boutique stynth models.</p>
<p>I wrote Roland about it, and here is their response. TLDR: Don’t hold your breath expecting them to fix it.</p>
<blockquote>
<p>Roland Product Support (Roland Corporation)<br />
May 13, 2022, 5:21 PM PDT</p>
<p>Hello,</p>
<p>Thank you fr contacting Roland Support.</p>
<p>Unfortunately the JU-06A is not compatible with arpeggiating gate with the “EXT CLK IN” port.
This is a much requested feature - Please understand that Roland has been actively engaged in research and development in diversified scientific & business areas for many years. While we value and appreciate feedback from users, our role in customer support is limited to inquiries regarding product operation only.</p>
<p>Thank you for your understanding, have a wonderful day!</p>
<p>Best Regards<br />
Roland Customer Support</p>
</blockquote>
<h2 id="workaround">Workaround</h2>
<p>There is a workaround, however. Enter your desired notes into the sequencer and hold down Edit, hit the 5 button and adjust the sequence length to the number of notes in your sequence. Hit start on the JU-06a and then start the Host clock sequence triggers.</p>
<h3 id="shortcomings">Shortcomings</h3>
<ul>
<li>Limited to 16 notes.</li>
<li>no up/down pattern</li>
<li>no 2/3 octave range</li>
</ul>
<p>While this workaround is not perfect, you might be able to stumble up some unique patterns in combination with different step order types.</p>TheCaseblog@repulsor.netA major miss by Roland on the JU-06a Boutique - the external clock sync does not trigger held notes when the arpeggio function is enabled. This unfortunate, as it is a feature that exists in many (all?) other Boutique stynth models.Roland Boutique Firmware Summary Page2022-04-02T03:20:13+00:002022-04-02T03:20:13+00:00https://blog.repulsor.net/boutique-firmware<p>I got tired of having to click through several (slow loading) pages to check for Boutique firmware updates for several units. As such, I created a tool that checks daily and builds a single summary page (with links!) for the latest firmware updates for each model.</p>
<p><a href="https://boutique-firmware.repulsor.net">https://boutique-firmware.repulsor.net</a></p>
<p>Screenshot:
<img src="https://res.cloudinary.com/thecase/image/upload/q_auto:good/Screen-Shot-2022-04-01-at-9.18.10-PM.png" alt="screenshot" /></p>
<p>If you have any issues with the page or its content, please report them here: <a href="https://github.com/TheCase/boutique-firmware/issues">https://github.com/TheCase/boutique-firmware/issues</a></p>TheCaseblog@repulsor.netI got tired of having to click through several (slow loading) pages to check for Boutique firmware updates for several units. As such, I created a tool that checks daily and builds a single summary page (with links!) for the latest firmware updates for each model.RK-007 MIDI Commander - Improved2021-04-30T18:05:56+00:002021-04-30T18:05:56+00:00https://blog.repulsor.net/rk007-midi-commander<p><b>UPDATE!</b> I whipped up a new batch of these for sale -> Check my Reverb Shop <a href="https://reverb.com/shop/very-sound-gear">https://reverb.com/shop/very-sound-gear</a></p>
<p>I recently stumbled across this incredible little device:
<a href="https://www.retrokits.com/shop/rk007/">https://www.retrokits.com/shop/rk007/</a></p>
<p>I was trying to figure out how to get the USB MIDI transport messages from my <a href="https://amzn.to/2PFm8Uk">Roland GO:KEYS</a> keyboard to other devices on the MIDI chain. While it didn’t solve my original problem, I ended up discovering a powerful little MIDI tool. Its such a treat to have full control to send Sequence Start/Stop, Patch changes, Control changes or any Note (and Panic!) to any Channel with one little device! It will operate as both a USB-MIDI device as well as through a 1/8” TRS jack to standard DIN-5 MIDI jack.</p>
<p><img src="/assets/img/IMG_2574-5.jpg" alt="IMG_2574-5" /></p>
<p>Here’s a <a href="https://www.youtube.com/watch?v=v8QWg009FRE">video by Retro Kits demoing the features</a></p>
<p>I built an Arduino Pro Micro version of the device, but I found the instructions and part sourcing information to be quite light. Also, I felt the 3D-printed case could use some more beef, as 1mm thickness is a bit too flimsy for the walls of a device case.</p>
<p>Here is a <a href="https://github.com/TheCase/rk007-arduino-pro-case-modified">link to my modified case STL</a> with 3mm thickness sides.</p>
<p>You might be wondering what that random rectangle is in my redesign. It is a spacer to put between the Arduino and the KeyPad for proper spacing when soldering it into place. This will allow the proper clearance when plugging the USB Micro cable into the Arduino.</p>
<p>Here are some Amazon referral links to all the parts you will need. Some of the parts are only available in sets of 2 or more to land on a reasonable per-unit price. Use the extra parts to build one for a friend!</p>
<ul>
<li><a href="https://amzn.to/2PDxIiP">Arduino Pro Micro</a></li>
<li><a href="https://amzn.to/3xwfhxD">I2C SSD1306 OLED Display</a></li>
<li><a href="https://amzn.to/3e2Rw8C">4x4 Keypad</a></li>
<li><a href="https://amzn.to/3e6zFO3">1/8” TRS Jack</a></li>
<li><a href="https://amzn.to/3u9DS99">10k potentiometer</a></li>
<li><a href="https://amzn.to/2ReixwG">220 Ohm 1/4 watt resistors</a></li>
<li><a href="https://amzn.to/3vyuJHK">Dial Knobs</a></li>
</ul>
<h4 id="items-of-note">Items of note</h4>
<p>“TRS” stands for Tip, Ring, Sleeve. When shopping for a TRS->MIDI 5-DIN cable, you are looking for a “Type A” version. Type A has the following pinout:</p>
<ul>
<li>Tip -> DIN Pin 5 (Data Reference) - TXD from Arduino</li>
<li>Ring -> DIN Pin 4 (Voltage Reference) - VCC from Arduino</li>
<li>Sleeve -> DIN Pin 2 (Shield) - GND from Arduino</li>
</ul>
<p>There are many cables on Amazon that advertise themselves as TRS->MIDI cables. Yet, they are the “Type B” that has a pinout configuration that will not work with the RK-007. Here is a <a href="https://www.sweetwater.com/store/detail/0-COASTMidi--make-noise-0-coast-midi-cable-1-8-inch-trs-to-5-pin-midi">link to an inexpensive Type A from Sweetwater</a></p>
<h4 id="tools">Tools</h4>
<p>In case you were wondering about my favorite soldering iron, wonder no more: <a href="https://amzn.to/3u8x7og">Weller WSTA6 Pyropen Junior Self-Igniting Cordless Butane Soldering Iron</a>. Look ma! No cords!</p>
<h4 id="need-help">Need help?</h4>
<p>If you have any other questions about the contstruction or operation of the MIDI Commander, drop a line in the commments. Thanks for reading!</p>TheCaseblog@repulsor.netUPDATE! I whipped up a new batch of these for sale -> Check my Reverb Shop https://reverb.com/shop/very-sound-gearSynthesizer Patch Visualizer2021-03-08T02:44:00+00:002021-03-08T02:44:00+00:00https://blog.repulsor.net/synthesizer-patch-visualizer<p>So, I’m new to synthesizers.</p>
<p>At least as far as owning and using one. I have forever loved their use in movie soundtracks of the eighties - and beyond. I recently became the proud owner of a <a href="https://amzn.to/2OekyI6">Roland SE-02</a>. Its amazing! There are hundreds of patches built-in and its incredibly easy to create, change and save those changes. I’ve been happily learning, tweaking sounds (from great to terrible) and sequencing them.</p>
<p>But I had one small problem…</p>
<p>I wanted to be able to see the orignal settings of a patch. Any patch.</p>
<p>So I built this tool:</p>
<p>Website: <a href="https://spv.repulsor.net">Synthesizer Patch Visualizer</a></p>
<p><img src="/assets/img/deck.png" alt="deck" /></p>
<p class="figcaption">sample render from the spv tool</p>
<h3 id="what-does-it-do">What does it do?</h3>
<p>It takes patch program files from synthesizers and visualizes the dial and switch positions in a dynamically generated PNG image file and gives you a link to the generated image so that you can post on your site or share via social media.</p>
<h3 id="what-synthesizer-models-are-supported">What synthesizer models are supported?</h3>
<ul>
<li><a href="https://amzn.to/2OekyI6">Roland SE-02</a></li>
<li><a href="https://amzn.to/3kUVSR0">Roland SH-01A</a></li>
<li><a href="https://amzn.to/3cmPePI">Roland JU-06A</a></li>
</ul>
<p>I’d love to add more Boutique Syths to this tool, but I only have these three. If you’d like to work with me to build support for more, hit me up in the comments.</p>
<h3 id="how-does-it-work">How does it work?</h3>
<p>Either select from the factory patch list, or UPLOAD YOUR OWN! You need to use the Backup function to download the patch file (ie: <code class="language-plaintext highlighter-rouge">SE02_PATCH00.PRM</code>). Then you use the “Choose File” button to upload it to the server.</p>
<p>The server will do some work and present you with a fully rendered PNG image representing the dial/switch setting of your patch. You can download the image or copy the generated link and share with your friends and/or the community. The server does not store any of your patch data. Once the image is generated, it is up to you to decide how to share or distribute the image or link. All of the actual patch data is securely encoded in the image as well as the form information included in the image link.</p>
<h3 id="go-check-it-out">Go check it out</h3>
<p>Here’s the link: <a href="https://spv.repulsor.net">Synthesizer Patch Visualizer</a></p>
<p>I hope you find it as interesting and useful as I do :)</p>
<h3 id="update">UPDATE</h3>
<p>I just added support for the <a href="https://amzn.to/3vjWNzl">Roland SH-01A</a>!</p>
<h3 id="update-2">UPDATE 2</h3>
<p>And I just added support for the <a href="https://amzn.to/3cmPePI">Roland JU-06A</a>!</p>
<h3 id="future-updates">Future Updates</h3>
<p>I’d love to add more Boutique Synths to this tool, but I only have these three. If you’d like to work with me to build support for more, hit me up in the comments.</p>
<p class="faded">* this post contains affiliate links to Amazon products</p>TheCaseblog@repulsor.netSo, I’m new to synthesizers.Using Ansible to update Synology with Acme certificates from pfSense Certificate Manager2021-01-31T18:49:38+00:002021-01-31T18:49:38+00:00https://blog.repulsor.net/using-ansible-to-update-synology-with-acme-certificates-from-pfsense-certificate-manager<p>I love that my pfSense router can manage Acme certificates for my local domain. I use <a href="https://m.do.co/c/9c55dc5264ba">DigitalOcean</a> for hosting this blog, so I was able to configure pfSense manage my Acme certificate updates using a DNS Challenge controlled through <a href="https://m.do.co/c/9c55dc5264ba">DigitalOcean</a>’s API (with a key).</p>
<p>I got tired of having to manually download and upload the certificate files to my Synology NAS every few months. I’m already leveraging Ansible for other maintenance drudgery, so yesterday I decided to explore automating it.</p>
<p>Prerequisite: you need to enable the “Write Certificates” option in pfSense’s Acme Certificates module. It is a checkbox that can be found if you follow Services -> Acme Certificates -> General Settings:</p>
<p><img src="https://res.cloudinary.com/thecase/image/upload/q_auto:good/Screen-Shot-2021-01-31-at-11.36.18-AM.png" alt="Screen-Shot-2021-01-31-at-11.36.18-AM" /></p>
<p>I’ll just cut to the chase here, I have two Github Gists with the Ansible tasks. There are two:</p>
<p>1) Copy certificates from pfSense to your Ansible workspace:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># file: "get_pfsense_certificates.yaml"</span>
<span class="c1"># alternatively, set as a variable in your inventory</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">set domain_name</span>
<span class="na">set_fact</span><span class="pi">:</span>
<span class="na">domain_name</span><span class="pi">:</span> <span class="s">mydomain.org</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">get certs</span>
<span class="na">fetch</span><span class="pi">:</span>
<span class="na">src</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/conf/acme/{{</span><span class="nv"> </span><span class="s">item</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">dest</span><span class="pi">:</span> <span class="s">../.certs/</span>
<span class="na">flat</span><span class="pi">:</span> <span class="s">yes</span>
<span class="na">with_items</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.fullchain"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.ca"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.key"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.crt"</span>
</code></pre></div></div>
<p>2) Copy the certificates to Synology and restart the affected services:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># file: "update_synology_certificates.yaml"</span>
<span class="s">update_synology_certificates.yaml</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">set directories</span>
<span class="na">set_fact</span><span class="pi">:</span>
<span class="na">sys_dir</span><span class="pi">:</span> <span class="s">/usr/syno/etc/certificate</span>
<span class="na">pkg_dir</span><span class="pi">:</span> <span class="s">/usr/local/etc/certificate</span>
<span class="na">stg_dir</span><span class="pi">:</span> <span class="s">/tmp/certs</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">create cert staging directory</span>
<span class="na">file</span><span class="pi">:</span>
<span class="na">path</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">stg_dir</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">state</span><span class="pi">:</span> <span class="s">directory</span>
<span class="c1"># certs from previous task</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">stage certs</span>
<span class="na">copy</span><span class="pi">:</span>
<span class="na">src</span><span class="pi">:</span> <span class="s2">"</span><span class="s">../.certs/{{</span><span class="nv"> </span><span class="s">item.s</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">dest</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/tmp/certs/{{</span><span class="nv"> </span><span class="s">item.d</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">with_items</span><span class="pi">:</span>
<span class="pi">-</span> <span class="pi">{</span> <span class="nv">s</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.crt"</span><span class="pi">,</span>
<span class="nv">d</span><span class="pi">:</span> <span class="s2">"</span><span class="s">cert.pem"</span> <span class="pi">}</span>
<span class="pi">-</span> <span class="pi">{</span> <span class="nv">s</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.fullchain"</span><span class="pi">,</span>
<span class="nv">d</span><span class="pi">:</span> <span class="s2">"</span><span class="s">fullchain.pem"</span> <span class="pi">}</span>
<span class="pi">-</span> <span class="pi">{</span> <span class="nv">s</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">domain_name</span><span class="nv"> </span><span class="s">}}.key"</span><span class="pi">,</span>
<span class="nv">d</span><span class="pi">:</span> <span class="s2">"</span><span class="s">privkey.pem"</span> <span class="pi">}</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">read the certificate info</span>
<span class="na">shell</span><span class="pi">:</span>
<span class="na">cmd</span><span class="pi">:</span> <span class="s">jq -r 'to_entries' {{ sys_dir }}/_archive/INFO</span>
<span class="na">register</span><span class="pi">:</span> <span class="s">cat_info</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">set cert_info</span>
<span class="na">set_fact</span><span class="pi">:</span>
<span class="na">cert_info</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">cat_info.stdout</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">from_json</span><span class="nv"> </span><span class="s">}}"</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">copy staged certs to archives</span>
<span class="na">copy</span><span class="pi">:</span>
<span class="na">src</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">stg_dir</span><span class="nv"> </span><span class="s">}}/"</span>
<span class="na">dest</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">sys_dir</span><span class="nv"> </span><span class="s">}}/_archive/{{</span><span class="nv"> </span><span class="s">item.key</span><span class="nv"> </span><span class="s">}}/"</span>
<span class="na">remote_src</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">with_items</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">cert_info</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">flatten</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">register</span><span class="pi">:</span> <span class="s">certs</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">copy certs for packaged services</span>
<span class="na">copy</span><span class="pi">:</span>
<span class="na">src</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">sys_dir</span><span class="nv"> </span><span class="s">}}/_archive/{{</span><span class="nv"> </span><span class="s">item.0.key</span><span class="nv"> </span><span class="s">}}/"</span>
<span class="na">dest</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">pkg_dir</span><span class="nv"> </span><span class="s">}}/{{</span><span class="nv"> </span><span class="s">item.1.subscriber</span><span class="nv"> </span><span class="s">}}/{{</span><span class="nv"> </span><span class="s">item.1.service</span><span class="nv"> </span><span class="s">}}/"</span>
<span class="na">remote_src</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">loop</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">cert_info</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">subelements('value.services')</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">when</span><span class="pi">:</span> <span class="s">item.1.isPkg</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">copy certs for system services</span>
<span class="na">copy</span><span class="pi">:</span>
<span class="na">src</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">sys_dir</span><span class="nv"> </span><span class="s">}}/_archive/{{</span><span class="nv"> </span><span class="s">item.0.key</span><span class="nv"> </span><span class="s">}}/"</span>
<span class="na">dest</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">sys_dir</span><span class="nv"> </span><span class="s">}}/{{</span><span class="nv"> </span><span class="s">item.1.subscriber</span><span class="nv"> </span><span class="s">}}/{{</span><span class="nv"> </span><span class="s">item.1.service</span><span class="nv"> </span><span class="s">}}/"</span>
<span class="na">remote_src</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">loop</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">cert_info</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">subelements('value.services')</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">when</span><span class="pi">:</span> <span class="s">not item.1.isPkg</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">restart affected services</span>
<span class="na">shell</span><span class="pi">:</span>
<span class="na">cmd</span><span class="pi">:</span> <span class="s2">"</span><span class="s">/usr/syno/sbin/synoservicectl</span><span class="nv"> </span><span class="s">--reload</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">item</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">with_items</span><span class="pi">:</span>
<span class="c1"># different per server - no doubt you will need to add or </span>
<span class="c1"># remove services from this list</span>
<span class="pi">-</span> <span class="s">nginx</span> <span class="c1"># DSM</span>
<span class="pi">-</span> <span class="s">pkgctl-MailServer</span>
<span class="pi">-</span> <span class="s">pkgctl-SynologyDrive</span>
<span class="pi">-</span> <span class="s">ftpd</span>
<span class="pi">-</span> <span class="s">pkgctl-ReplicationService</span>
<span class="na">when</span><span class="pi">:</span> <span class="s">certs.changed</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">remove cert staging directory</span>
<span class="na">file</span><span class="pi">:</span>
<span class="na">path</span><span class="pi">:</span> <span class="s2">"</span><span class="s">{{</span><span class="nv"> </span><span class="s">stg_dir</span><span class="nv"> </span><span class="s">}}"</span>
<span class="na">state</span><span class="pi">:</span> <span class="s">absent</span>
</code></pre></div></div>
<p>Even if you are not using either pfSense or a Synology, I’m sure these Ansible Tasks could prove useful in your particular situation. Need help? Feel free to leave and comment!</p>
<p>Shoutout to [BIT]arantno and <a href="https://dokuwiki.bitaranto.ch/doku.php?id=synologyimportcertfrompfsense">the discection of the certificate layout on the Synology filesystem</a>. You saved me a lot of time!</p>TheCaseblog@repulsor.netI love that my pfSense router can manage Acme certificates for my local domain. I use DigitalOcean for hosting this blog, so I was able to configure pfSense manage my Acme certificate updates using a DNS Challenge controlled through DigitalOcean’s API (with a key).My Computer Lab2019-11-02T18:53:00+00:002019-11-02T18:53:00+00:00https://blog.repulsor.net/home-datacenter<p>or… how I stopped worrying and learned to love containers…</p>
<p>[UPDATE Nov 2019] I’ve recently moved from Nomad/Consul to Kubernetes for my Orchestration and Service Discovery.</p>
<p>So I have been meaning to write about my hobby “datacenter” for a couple years now. I finally have it running in a state I’m happy with, and I’m ready to back up the write up with some code. I’ll also go into the tools I chose and why I chose them. I did a lot of research and much trial/error to get to this point and I’d like to pay if forward to all the great open source software and documentation that’s gotten me this far. Thanks to everyone that has contributed to every piece of software I’ve used and love. I can only hope that some of my experience will help others that are heading down the same path I have chosen.</p>
<p>I’ve been through many iterations of my “at home” computing stacks since the late 1990’s: the gradual progression of tower PCs running Linux on bare metal, adding more storage, moving into virtual machines, purchasing a NAS and moving into managed switches, etc etc.</p>
<p>Here’s where I’m at today with my hardware:</p>
<table>
<thead>
<tr>
<th> </th>
<th> </th>
</tr>
</thead>
<tbody>
<tr>
<td>Router</td>
<td>1U SuperMicro, 4x Intel ethernet + IPMI - pfSense</td>
</tr>
<tr>
<td>Compute</td>
<td>3x 1U SuperMicros with 12 Core CPU, 24GB RAM</td>
</tr>
<tr>
<td>Storage</td>
<td>8 Bay Synology RS1219+</td>
</tr>
<tr>
<td>Network</td>
<td>Cisco SG300-24 Managed Switch</td>
</tr>
<tr>
<td>Form factor</td>
<td>19” Server rack with UPS</td>
</tr>
<tr>
<td>WiFi</td>
<td>3x Eero mesh</td>
</tr>
</tbody>
</table>
<p>Let’s get started</p>
<ul id="markdown-toc">
<li><a href="#virtualization-proxmox" id="markdown-toc-virtualization-proxmox">Virtualization: Proxmox</a></li>
<li><a href="#infrastructure-node-provisioning-ipxe-tftpboot-and-http" id="markdown-toc-infrastructure-node-provisioning-ipxe-tftpboot-and-http">Infrastructure Node Provisioning: iPXE, tftpboot and http</a></li>
<li><a href="#services-and-orchestration-kubernetes" id="markdown-toc-services-and-orchestration-kubernetes">Services and Orchestration: Kubernetes</a></li>
<li><a href="#service-discovery-keys-and-secrets-kubernetes" id="markdown-toc-service-discovery-keys-and-secrets-kubernetes">Service Discovery, keys and secrets: Kubernetes</a></li>
<li><a href="#metrics-monitoring-and-alerting-prometheus-grafana-and-slack" id="markdown-toc-metrics-monitoring-and-alerting-prometheus-grafana-and-slack">Metrics, Monitoring and Alerting: Prometheus, Grafana and Slack</a></li>
<li><a href="#the-nuts-and-bolts" id="markdown-toc-the-nuts-and-bolts">The nuts and bolts</a></li>
<li><a href="#conclusion" id="markdown-toc-conclusion">Conclusion</a></li>
</ul>
<h2 id="virtualization-proxmox">Virtualization: Proxmox</h2>
<p>I chose Proxmox as my virtualization solution on each of the three compute-dedicated Supermicros. I have toyed with the idea of PXE booting something like CoreOS to the bare metal, but I’m not ready to go there yet. We’ll get to that later.</p>
<p>I am so glad I found Proxmox. VMWare licensing got difficult for us cheapskates doing stupid small things at home… and I wanted to find a light management interface that didn’t consume 25% of my total resource footprint. Citrix Zen was close, but it still required Windows for a management client. Proxmox is light and clean, has great HA features. Basically a wonderful GUI wrapping around KVM on top of the Debian OS that we’re all familiar with… System and Service upgrades via apt?? #yespls!</p>
<h2 id="infrastructure-node-provisioning-ipxe-tftpboot-and-http">Infrastructure Node Provisioning: iPXE, tftpboot and http</h2>
<p>I set up PXE boot and tftpboot to run from my Synology NAS. So this part is a bit of a hack. There actually are a couple Terraform plugins out there for automating privisioning of VMs in Proxmox. I’ve tried them. I’m probably using them wrong, because they want to work off clones or templates and usually time out while that process is happening. In lieu of learning Go and working to change those plugins to meet my needs, I hacked together some shell scripts that work with the Proxmox API to provision VMs.</p>
<p>My hack: I apply my own (sequentially incrementing) MAC address pattern to newly provisioned Proxmox VMs with the ending suffix based on the next available VM ID. I have a range of DHCP addresses assigned to this MAC address block on my pfSense DHCP Server. With PXE/tftpboot you can <a href="https://docs.oracle.com/cd/E24628_01/em.121/e27046/appdx_pxeboot.htm#EMLCM12198">force certain IP addresses to use a particular boot image</a>. This allows me to set up a known block of (10-20) possible nodes that will be serving as possible application backends for purposes of configuring the HAProxy server on my pfSense router, as well as a common block for a SSH config with the public keys already set for this known set of hosts. I named mine “node” with the sequential interval of VM ID’s from Proxmox (ie. node101, node102, node103). This greatly simplifies SSH connections to nodes for troubleshooting issues.</p>
<p>I’m currently using CoreOS with a <code class="language-plaintext highlighter-rouge">cloud-config</code> from a web server (again, the Synology, with its internal web server hosting cloud-config.yml files).</p>
<p>As CoreOS is already taking care of the Docker side of things, I just need to cloud-config to set up the kubeadmin, kubectl and flannel networking packages.</p>
<h2 id="services-and-orchestration-kubernetes">Services and Orchestration: Kubernetes</h2>
<p>To repeating myself, read about my <a href="https://github.com/TheCase/kubernetes-coreos-on-proxmox">full Kubernetes implementation</a></p>
<h2 id="service-discovery-keys-and-secrets-kubernetes">Service Discovery, keys and secrets: Kubernetes</h2>
<p>Really straight forward here. Kubernetes handles Secrets and internal Service Discovery natively. External service availability is handled by MetalLB and the Kubernetes-pfSense Controller (for automatic DNS updates). Details on that follow later.</p>
<h2 id="metrics-monitoring-and-alerting-prometheus-grafana-and-slack">Metrics, Monitoring and Alerting: Prometheus, Grafana and Slack</h2>
<p>Once we have all of our stuff up and running, we want to make sure it stays that way. Right? …. Right? I’d rather do something else with my weekends like <del>play video games all day</del> going outside and enjoying nature. So instead of staring at a screen all day, I make robots check stuff and let me know when things go bad.</p>
<p>I use a combination of node-exporter and CAdvisor to expose node metrics that Prometheus will scrape. Grafana visualization are used with their alerting feature when certain metrics cross thresholds that I’d like to know about - it gets chirped to Slack. Kuberentes monitoring is report via <a href="https://github.com/wongnai/kube-slack">kube-slack</a>.</p>
<h1 id="the-nuts-and-bolts">The nuts and bolts</h1>
<p>Here’s where we get into the details of my lab stack, top to bottom. Two of the cornerstone components in my lab are my pfSense router and my Synology NAS. I treat my pfSense router as a source-of-truth-for-all-things-Networking and the Synology as the source-of-truth-for-all-things-Persistent-Storage. Therefore, through Synology’s Docker service, I run persistent data services like MySQL and the like.</p>
<p>pfSense handles the DHCP and DNS services for the entire network. DHCP directs netboot clients the Synology NAS for PXE/tftpboot because its the thing that stores the kernel and boot images. pfSense’s DNSResolver (Unbound) resolves all <em>service</em>.svc DNS lookups to the HAProxy virtual IP (ie. <code class="language-plaintext highlighter-rouge">http://nginx.svc</code>) with <a href="https://metallb.universe.tf/">MetalLB</a> and the <a href="https://github.com/travisghansen/kubernetes-pfsense-controller">Kubernetes pfSense Controller</a>. The wonderful <a href="https://traefik.io/">Traefik Ingress Controller</a> reads the service information from Kubernetes and automatically applies backend connections to the name-translated frontend.</p>
<p>Unless things have changed recently, Traefik only handles HTTP connections… so any TCP specific rules need their own custom front and backend rules on pfSense’s HAProxy service.</p>
<h1 id="conclusion">Conclusion</h1>
<p>I know that was a quick fly-by of what I’ve done to make my lab serve my needs. It certainly doesn’t fall into the realm of “best practice” with all the DevOps-ness going around these days. At the end of the day, its the perfect learning tool at a known one-time expense enabling a wide range of experimental iterations inhibited only by one’s available time. If there’s one thing I would change, I’d go with the newer Intel NUCs now that they have remote management. The SuperMicro fans to move air through the 1U cases are way too loud.</p>
<p>Oh yeah, if you made it this far… or if TLDR’d your way here… here’s the source code for <a href="https://github.com/TheCase/kubernetes-coreos-on-proxmox">my implementation of my little piece of the cloud</a>.</p>
<p>Hope it helps. If not, hit me up for questions in the comments. I’d love to help.</p>
<p>Keep on hackin’ on…</p>TheCaseblog@repulsor.netor… how I stopped worrying and learned to love containers…AdaFruit MiniPOV code generator2018-10-15T03:38:10+00:002018-10-15T03:38:10+00:00https://blog.repulsor.net/minipov<p>After I migrated blog engines, I failed to realize that I killed my old minipov code generator tool. I got it working again (in a new location):</p>
<p><a href="https://minipov.repulsor.net">https://minipov.repulsor.net</a></p>
<p>If you have questions or get stuck, please use the <a href="https://github.com/TheCase/minipov/issues">Issues tracker</a> in the GitHub project.</p>TheCaseblog@repulsor.netAfter I migrated blog engines, I failed to realize that I killed my old minipov code generator tool. I got it working again (in a new location):I made a G4 iLamp from a iMac G4!2017-12-27T21:19:22+00:002017-12-27T21:19:22+00:00https://blog.repulsor.net/i-made-a-g4-ilamp-from-a-imac-g4<p>I was making it to sell, but I think I’ll keep it. It’s splendid.</p>
<p>I did remove the arm spring, but kept the action. The lamp can bend down and swivels 180 degrees!</p>
<p>This is the lamp kit I used: <a href="http://amzn.to/2Dq3iop">B&P Lamp Nickel Plated Finish Table Lamp Wiring Kit With 6 Inch Harp, Push-Thru Socket</a>. Because I used a 6″ harp, I had to use a <a href="http://amzn.to/2CdYjKw">smaller A15 light bulb</a>. Its LED because I want to keep the 3D printed parts away from heat.</p>
<p>Let me know if you have questions, I’m happy to share the details of the process if anyone is interested.</p>
<p><a href="https://i2.wp.com/res.cloudinary.com/thecase/image/upload/v1514682863/IMG_0133_zbsfsy.jpg"><img src="https://i0.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682863/IMG_0133_zbsfsy.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/v1514682861/IMG_0134_d7shk5.jpg"><img src="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682861/IMG_0134_d7shk5.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/v1514682858/IMG_0135_d3q1hp.jpg"><img src="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682858/IMG_0135_d3q1hp.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i2.wp.com/res.cloudinary.com/thecase/image/upload/v1514682856/IMG_0136_serg2y.jpg"><img src="https://i2.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682856/IMG_0136_serg2y.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i2.wp.com/res.cloudinary.com/thecase/image/upload/v1514682853/IMG_0137_ccclyj.jpg"><img src="https://i2.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682853/IMG_0137_ccclyj.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i0.wp.com/res.cloudinary.com/thecase/image/upload/v1514682844/IMG_0142_zxzgmb.jpg"><img src="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682844/IMG_0142_zxzgmb.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i0.wp.com/res.cloudinary.com/thecase/image/upload/v1514682841/IMG_0143_qxks4q.jpg"><img src="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682841/IMG_0143_qxks4q.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i2.wp.com/res.cloudinary.com/thecase/image/upload/v1514682848/IMG_0139_etmxs7.jpg"><img src="https://i0.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682848/IMG_0139_etmxs7.jpg?resize=768%2C1024" alt="" /></a></p>
<p><a href="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/v1514682846/IMG_0140_ksviul.jpg"><img src="https://i1.wp.com/res.cloudinary.com/thecase/image/upload/h_1024,w_768/v1514682846/IMG_0140_ksviul.jpg?resize=768%2C1024" alt="" /></a></p>TheCaseblog@repulsor.netI was making it to sell, but I think I’ll keep it. It’s splendid.Adding headrests to the back seat of a 2000 Jeep Cherokee (XJ) – Part Two2017-12-19T13:50:06+00:002017-12-19T13:50:06+00:00https://blog.repulsor.net/adding-headrests-to-the-back-seat-of-a-2000-jeep-cherokee-xj-part-two<p>Ok, so I found a neighbor that was able to get the welding done for me.</p>
<p><img src="/assets/img/0FXSVsJHRW65hKUCKduvqA_dyxymx.jpg" alt="" /></p>
<p><img src="/assets/img/bP6oXaYgQl2scnp3o9NIQ_q1ohm9.jpg" alt="" /></p>
<p>You’ll see why later, but in retrospect I would have mounted the brackets about another 1/4″ higher than I did. Turns out the seat cover puckers in a bit more than I’d like and in turn made it harder to get the top clips to stay connected to the main post mount.</p>
<p>Now its time to trim the foam. I left about 1 3/4″ at the top and cut away a good portion of the already hollowed out section. I did some googling and discovered that the best way to cut this foam is to use an <a href="http://amzn.to/2BgJXJN">electric carving knife</a>. Good advice, as it cut through this stuff like butter.</p>
<p><img src="/assets/img/fullsizeoutput_434e_igvkob.jpg" alt="" /></p>
<p><img src="/assets/img/fullsizeoutput_4354_qikfpi.jpg" alt="" /></p>
<p>I took all the pieces I cut away and used them to fill the gaps left by the now-absent lever connector bar. I ran out of duct tape or I would have used more to secure the pieces in a better way.</p>
<p><img src="/assets/img/IMG_0059_hzad0x.jpg" alt="" /></p>
<p>Now here’s the part that kinda sucks. You’ll need to zip the cover back into place so that you can determine exactly where you need to cut holes in the fabric for the posts. Feel around for the plastic post mount centers and mark the center of the opening on the fabric. Take the cover back off, because you’ll need to do some work to remove some of the inside padding of the cover to allow the post mount tops to snap in.</p>
<p><img src="/assets/img/IMG_0060_tvteqp.jpg" alt="" /></p>
<p>Once you’ve gapped all four holes, you’ll want to loosely fit the cover again and snap in the tops of the plastic post mounts. Here is where you see the problem with how I mounted my brackets a little too low. I’m not entirely happy with the amount of puckering on the cover, but c’est la vie, I’ll have to live with it… no big deal as the headrests sit on top and mostly hide the problem. Regardless of fit and form, the functionally is still perfect.</p>
<p><img src="/assets/img/IMG_0062_slgysd.jpg" alt="" /></p>
<p>Once you’ve zipped everything up and hidden the zipper ends back under the cover, you’re ready to reinstall the seatback. Here are a couple pictures of the final result and I really could not be happier with the match. Other then the fact they are not the original blue leather, they still match well with the fuzzy fabric on the seat back. Most importantly my son now has whiplash protection in the case of a rear-end collision and we can finally ditch the old booster seat!</p>
<p><img src="/assets/img/IMG_0063_laedf3.jpg" alt="" /></p>
<p><img src="/assets/img/IMG_0064_tvpvsw.jpg" alt="" /></p>TheCaseblog@repulsor.netOk, so I found a neighbor that was able to get the welding done for me.