<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feed_style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
        <tabi:base_url>&#x2F;</tabi:base_url>
        <tabi:separator>
            •
        </tabi:separator>
        <tabi:about_feeds>This is a web feed, also known as an Atom feed. Subscribe by copying the URL from the address bar into your newsreader. Visit About Feeds to learn more and get started. It&#x27;s free.</tabi:about_feeds>
        <tabi:visit_the_site>Visit website</tabi:visit_the_site>
        <tabi:recent_posts>Recent posts</tabi:recent_posts>
        <tabi:last_updated_on>Updated on $DATE</tabi:last_updated_on>
        <tabi:default_theme></tabi:default_theme>
        <tabi:post_listing_date>date</tabi:post_listing_date>
        <tabi:current_section>Andrew Wippler&#x27;s Sketchpad</tabi:current_section>
    </tabi:metadata><link rel="extra-stylesheet" href="/skins/indigo_ingot.css?h=d429472afbb246441b1a" /><title>Andrew Wippler's Sketchpad</title>
        <subtitle>Ideas, blog, etc. </subtitle>
    <link href="/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="" rel="alternate" type="text/html"/>
    <generator uri="https://www.getzola.org/">Zola</generator><updated>2025-09-25T08:39:46.009249+00:00</updated><id>/atom.xml</id><entry xml:lang="en">
        <title>Helper Scripts</title>
        <published>2025-09-25T08:39:46.009249+00:00</published>
        <updated>2025-09-25T08:39:46.009249+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-25-helper-scripts/" type="text/html"/>
        <id>/2025-09-25-helper-scripts/</id>
        
            <content type="html">&lt;p&gt;I replaced OnlyOffice with Collabora in my lab. I was able to extend their WOPI example to produce a &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;Waffle-WOPI&quot;&gt;Minimum Viable Product&lt;&#x2F;a&gt;. As it stands now, the software is feature complete for my use case. From there, I mount my data to my NFS storage and sync that folder with Dropbox. This lets me use a filebrowser for my currently in work documents. I can then access those contents from my &lt;a href=&quot;&#x2F;2021-04-02-remarkable-2-review.md&quot;&gt;reMarkable&lt;&#x2F;a&gt; using the Dropbox integration. Unfortunately, the reMarkable reads PDFs and not docx. To combat this problem, I have created a nightly script to convert the files to PDF. This is easily packaged into a container and run as a kubernetes cronjob. Since my NFS storage is also a persistent volume claim, I can reuse the same ReadWriteMany mount for both my Waffle WOPI server and the wrapper script to libreoffice.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-script&quot;&gt;The Script&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-set z-shell&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; -euo pipefail&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Defaults: mounted &#x2F;data directory&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;input_dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;:-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&#x2F;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;output_dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;:-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;input_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Ensure output directory exists&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;output_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Converting DOCX files from: &lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;input_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Saving PDFs to: &lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;output_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-begin z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt; Convert all .docx → .pdf&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-shell&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-shopt z-shell&quot;&gt;shopt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; -s nullglob&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-assignment z-shell&quot;&gt;files&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-shell&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-shell&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;input_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-keyword z-operator z-regexp z-quantifier z-shell&quot;&gt;*&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-section z-parens z-end z-shell&quot;&gt;)&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-if z-shell&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-function z-test z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-arithmetic z-shell&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;files&lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-array z-shell&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt;-&lt;&#x2F;span&gt;eq&lt;&#x2F;span&gt; 0 &lt;span class=&quot;z-support z-function z-test z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-continue z-shell&quot;&gt;;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-then z-shell&quot;&gt;then&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;No .docx files found in &lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;input_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-exit z-shell&quot;&gt;exit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; 0&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-end z-shell&quot;&gt;fi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;soffice&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;headless&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;convert-to&lt;&#x2F;span&gt; pdf:writer_pdf_Export&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;outdir&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;output_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-variable z-shell&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-shell&quot;&gt;files&lt;span class=&quot;z-punctuation z-section z-braces z-begin z-shell&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-array z-shell&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-braces z-end z-shell&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-parameter z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-parameter z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-support z-function z-echo z-shell&quot;&gt;echo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Conversion complete.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;the-dockerfile&quot;&gt;The Dockerfile&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;Dockerfile&quot; class=&quot;language-Dockerfile z-code&quot;&gt;&lt;code class=&quot;language-Dockerfile&quot; data-lang=&quot;Dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; debian:&lt;span class=&quot;z-entity z-name z-enum z-tag-digest&quot;&gt;bullseye-slim&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Install LibreOffice (soffice)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y libreoffice &amp;amp;&amp;amp; rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;*
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Working directory for mounted data
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&#x2F;data
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Copy script
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; convert.sh &#x2F;usr&#x2F;local&#x2F;bin&#x2F;convert.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;chmod +x &#x2F;usr&#x2F;local&#x2F;bin&#x2F;convert.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Default entrypoint
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-dockerfile&quot;&gt;ENTRYPOINT &lt;&#x2F;span&gt;[&lt;span class=&quot;z-string z-quoted z-double z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;convert.sh&lt;span class=&quot;z-punctuation z-definition z-string z-end z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;the-cronjob&quot;&gt;The Cronjob&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;batch&#x2F;v1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;CronJob&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;remarkable-dropbox-helper&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;collabora&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;spec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;concurrencyPolicy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Forbid&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;failedJobsHistoryLimit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;jobTemplate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;remarkable-dropbox-helper&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;spec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;spec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;docker-domain&#x2F;remarkable-dropbox-helper:latest&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-flow-sequence z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-sequence z-begin z-yaml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;convert.sh&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-sequence z-yaml&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;data&#x2F;editable&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-sequence z-end z-yaml&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;imagePullPolicy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Always&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;remarkable-dropbox-helper&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&#x2F;data&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;remarkable-dropbox-helper-pvc&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;dnsPolicy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;ClusterFirst&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;imagePullSecrets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;regsecret&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;restartPolicy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;OnFailure&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;terminationGracePeriodSeconds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;30&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;remarkable-dropbox-helper-pvc&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;persistentVolumeClaim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;claimName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;middleware-files-pvc&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;schedule&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;@daily&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;timeZone&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Europe&#x2F;Helsinki&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;successfulJobsHistoryLimit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;suspend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-yaml&quot;&gt;false&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Thoroughly convinced</title>
        <published>2025-09-23T19:33:51.550596+00:00</published>
        <updated>2025-09-23T19:33:51.550596+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-23-thoroughly-convinced/" type="text/html"/>
        <id>/2025-09-23-thoroughly-convinced/</id>
        
            <content type="html">&lt;p&gt;I am thoroughly convinced that God still desires to pour out His Spirit into His chosen vessels as recorded in Acts 2:17–18, with the ultimate end being the salvation of souls (Acts 2:21). God’s purposes have not changed; He can empower His people so that He receives the glory through the lives that are transformed. While ministry today does not look exactly as it did in the first century, God remains more than capable of working through those who willingly submit to His plan (John 7:38–39). The same Spirit who filled the upper room is still available to fill surrendered hearts.&lt;&#x2F;p&gt;
&lt;p&gt;However, at times, we as His ambassadors are not truly positioned to receive this outpouring. We are easily distracted, can have divided loyalties, or are plagued by spiritual instability through inconsistency. This inadequacy can transform us to be like a cup in the unsteady hand of a child. When our Heavenly Father tries to pour His Spirit into our cups our shifting nature spills the liquid and is unable to fully contain what God wants for us. The issue is never with the abundance of God’s supply, but with the steadiness of our vessel.&lt;&#x2F;p&gt;
&lt;p&gt;It is in these very moments that God allows trials to enter our lives – not so that we crumble beneath the weight of the pressures, but to steady us to fully receive what He wants to give us. Through testing, He refines our faith and teaches us to wait patiently for Him. Trials teach us to throw out the anchor of our soul and fasten it firmly to the Solid Rock. As we lift our eyes from circumstances and fix them on Christ alone, stability begins to take root.&lt;&#x2F;p&gt;
&lt;p&gt;As we continue on this patient path with hearts resting in Him, we experience the truth David proclaimed in Psalm 23: our cup runneth over. The oversupply of God is not an accident. It is the intended state for the believer. We are not filled with His supply just so that we might be benefactors. We overflow and are splling over so that others may see Christ.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>feeling super productive</title>
        <published>2025-09-12T15:55:56.778969+00:00</published>
        <updated>2025-09-12T15:55:56.778969+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-12-feeling-super-productive/" type="text/html"/>
        <id>/2025-09-12-feeling-super-productive/</id>
        
            <content type="html">&lt;p&gt;Since August, I have been updating my digital life, which began with organizing my digital collection of books. I had never truly looked too indepth at Calibre before August 2025, but I am clearly blown away at its capabilities. I feel a bit awkward keeping the library on my desktop computer, but I have a script to periodically backup my home folder to my NAS. Today I finished organizing them in Calibre. I have discovered that I have 458 digital books - I have read 131, and have 135 on my reading list. The remainder are my wife&#x27;s digital collection and reference material.&lt;&#x2F;p&gt;
&lt;p&gt;I read books for information. Sometimes the information is good, so I highlight it for later consumption. I have build &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;SpeakerWindows&quot;&gt;SpeakerWindows&lt;&#x2F;a&gt; as a means to organize those highlights and other thoughts for later use. This past month, I created two importers - readwise and play books. Readwise gathered my highlights from the Amazon&#x27;s kindle, while Google Play Books sync their highlights in Google Drive. The end result was over 5,000 highlights that needed to be sorted.&lt;&#x2F;p&gt;
&lt;p&gt;At first, I updated 5 a day through a prompts to ChatGPT, but that process was slow. So, I built a script that asked a local LLM to categorize the content of my notes and thoughts. It took about 2 hours to churn through those notes and create relavant tags for all of them. In the end, I am very happy with the results.&lt;&#x2F;p&gt;
&lt;p&gt;I am now motivated to read books as fast as I can in Google Play Books, export them to Google Drive, and import them to SpeakerWindows.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Additional insight into collaborative editors</title>
        <published>2025-09-10T06:13:21.365082+00:00</published>
        <updated>2025-09-10T06:13:21.365082+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-10-additional-insight-into-collaborative-editors/" type="text/html"/>
        <id>/2025-09-10-additional-insight-into-collaborative-editors/</id>
        
            <content type="html">&lt;p&gt;I think I had it all wrong when I accused OnlyOffice of sending data to the Russian goverment. This architectural design is called WOPI and was created for web applications that want to integrate with Microsoft Office. That means the architecture was really designed for the CIA to intercept a target&#x27;s documents saved to Office 365.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; I think good targets would asummably be those &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ndr.de&#x2F;fernsehen&#x2F;sendungen&#x2F;panorama&#x2F;aktuell&#x2F;NSA-targets-the-privacy-conscious,nsa230.html&quot;&gt;people who were subscribed to or read&lt;&#x2F;a&gt; &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linuxjournal.com&#x2F;content&#x2F;nsa-linux-journal-extremist-forum-and-its-readers-get-flagged-extra-surveillance&quot;&gt;a certain magazine in the early 2010&#x27;s&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As a software design spec, WOPI appears to be robost for online collaborations, but when configured incorrectly, it can become an easy target for interception. I do not have that warm, fuzzy feeling that Russia does not have a backdoor to OnlyOffice, China does not have a backdoor to WPS Office, and the US government does not have a backdoor to Office 365 - so I think I will stay away from those implementations.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Although, as a US Citizen, I know that there is a due process of law before any sort of surveillance can occur. A judge has to be convinced that there is ample evidence of wrongdoing before any sort of warrant will be granted for surveillance. The other two countries do not seem to afford that legal roadblock.&lt;&#x2F;p&gt;
&lt;p&gt;A fourth option of the WOPI protocol is Collabora, which is the original web implementation of LibreOffice. This appeals to me as an alternative to my current OnlyOffice setup. Collabora has &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sdk.collaboraonline.com&#x2F;docs&#x2F;How_to_integrate.html&quot;&gt;great docs&lt;&#x2F;a&gt; and even an example &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;CollaboraOnline&#x2F;collabora-online-sdk-examples&#x2F;&#x2F;tree&#x2F;master&#x2F;webapp&#x2F;nodejs&quot;&gt;low-footprint WOPI server&lt;&#x2F;a&gt;. This will be better than my &lt;a href=&quot;&#x2F;2025-09-08-Only-Office-for-personal-use&quot;&gt;Vibe coded OnlyOffice middleware server&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;This is a totally sarcastic statement, but has a vague realism to it. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;I stay away from Mircrosoft products for other reasons too. Mainly, they are jumbled pieces of software designed for their largest US consumers, &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=BKorP55Aqvg&quot;&gt;who have no idea what they want in a product&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Recompiling AbiWord</title>
        <published>2025-09-08T09:03:20.706302+00:00</published>
        <updated>2025-09-08T09:03:20.706302+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-08-recompiling-abiword/" type="text/html"/>
        <id>/2025-09-08-recompiling-abiword/</id>
        
            <content type="html">&lt;p&gt;In my quest to replace Google Docs, I came across AbiWord, Gnome&#x27;s editor. It looks newer than LibreOffice, appears feature complete, and has footnote support. The only problem is that it does not have keyboard shortcuts for footnotes. This is how I compiled AbiWord from the git source:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;install-the-dependencies&quot;&gt;Install the dependencies&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; dnf install gcc gcc-c++ make autoconf automake libtool intltool m4 pkgconfig gtk3-devel libgsf-devel libxml2-devel glib2-devel libX11-devel libXext-devel libXpm-devel libXft-devel gperf bison flex libjpeg-turbo-devel libtiff-devel libpng-devel poppler-glib-devel cairo-devel pango-devel atk-devel gdk-pixbuf2-devel desktop-file-utils docbook2X docbook-dtds libxslt-devel libICE-devel libSM-devel libuuid-devel libIDL-devel boost-devel&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;build&quot;&gt;Build&lt;&#x2F;h2&gt;
&lt;p&gt;To build, one has to do &quot;the normal Unix installation method&quot;: &lt;code&gt;.&#x2F;autogen.sh&lt;&#x2F;code&gt;, &lt;code&gt;.&#x2F;configure --prefix=$HOME&#x2F;abi-install&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, &lt;code&gt;make -j$(nproc)&lt;&#x2F;code&gt;, and &lt;code&gt;make install&lt;&#x2F;code&gt;. However, on my Fedora 42 install, I received the error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;.&#x2F;autogen.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; putting auxiliary files in &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;.&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; copying file &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;.&#x2F;ltmain.sh&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; putting macros in AC_CONFIG_MACRO_DIRS, &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;m4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; copying file &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;m4&#x2F;libtool.m4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; copying file &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;m4&#x2F;ltoptions.m4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; copying file &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;m4&#x2F;ltsugar.m4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; copying file &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;m4&#x2F;ltversion.m4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;libtoolize:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; copying file &lt;span class=&quot;z-string z-quoted z-single z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;m4&#x2F;lt~obsolete.m4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;configure.ac:58:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; error: possibly undefined macro: AC_MSG_ERROR If this token and others are legitimate, please use m4_pattern_allow. See the Autoconf documentation.&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;autoreconf:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; error: &#x2F;usr&#x2F;bin&#x2F;autoconf failed with exit status: 1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;Running&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; .&#x2F;configure&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;enable-maintainer-mode&lt;&#x2F;span&gt; ...&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;configure:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; error: cannot find required auxiliary files: compile missing install-sh config.guess config.sub&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That meant I needed an additional package:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; dnf install autoconf-archive&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After recompiling, I found out that my added shortcuts did not integrate properly. I filed an issue against the repo and am awaiting a response.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;the prefix is to have a second, butchered version available to test. I can continue using distro version of AbiWord if this doesn&#x27;t work out. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Only Office for personal use</title>
        <published>2025-09-08T07:18:03.408003+00:00</published>
        <updated>2025-09-08T07:18:03.408003+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-08-only-office-for-personal-use/" type="text/html"/>
        <id>/2025-09-08-only-office-for-personal-use/</id>
        
            <content type="html">&lt;p&gt;Vibe coding is supposedly going to replace actual programmers. I can’t wait for it to go away. Robots have a terrible way of doing things, and they are not very good at writing code. That, however, has not kept me from regularly dabbling with ChatGPT and code generation.&lt;&#x2F;p&gt;
&lt;p&gt;Programming is my hobby - not my livelihood. So when it comes to solving an personal issue with code, ChatGPT appeals to me. I am too busy in life to spend hours catching myself up from recent advancements in technology in order to find the right framework, read the docs, and use that knowledge to write good, secure code.&lt;&#x2F;p&gt;
&lt;p&gt;I am still not convinced that ChatGPT is smart enough to replace anything of value. In my haste of finding an alternative to Google Docs, I asked ChatGPT to help me code a simple middleware to load OnlyOffice behind authentication.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; OnlyOffice required a JSON Web Token, but their docs were very vague - a vice of all companies that want free fixes from Open Source Software enthusiasts, yet also want money.&lt;&#x2F;p&gt;
&lt;p&gt;What was supposed to be a simple task ended up to be a conversaion where ChatGPT said, &quot;Ah, OnlyOffice does x,y,z, but I wrote a,b,c instead. Here, let me fix that for you.&quot; When that did not work, ChatGPT would say, &quot;Ah, let&#x27;s try this instead.&quot; To save others from having to spend hours repeating the conversation I had with a robot to generate boilerplate code, let me provide you with the end result.&lt;&#x2F;p&gt;
&lt;p&gt;To host and OnlyOffice locally, you need middleware that signs a JSON Web Token, and passes it to OnlyOffice&#x27;s Document Server for identification. This Document server stores your text and sends it to &lt;del&gt;Vladimir Putin and the Kremlin&lt;&#x2F;del&gt; your storage server after you close your browser window. If anyone wants &lt;del&gt;to send their important documents to dubious destinations&lt;&#x2F;del&gt; to self host OnlyOffice, you may find help with this generated code:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;middleware-server&quot;&gt;Middleware Server&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;javascript&quot; class=&quot;language-javascript z-code&quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;dotenv&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;express&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;express&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;axios&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;axios&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;jwt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;jsonwebtoken&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;qs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;querystring&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;fs&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;path&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;express-session&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;officegen&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;require&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;officegen&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;express&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-variable z-object z-process z-ts&quot;&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-process z-ts&quot;&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-property z-ts&quot;&gt;PORT&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;3000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-binding-pattern z-object z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_SECRET&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;JWT_SECRET&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DOCUMENTSERVER_URL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;MIDDLEWARE_SERVER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;NODE_ENV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-binding-pattern z-object z-ts&quot;&gt;}&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-variable z-object z-process z-ts&quot;&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-process z-ts&quot;&gt;env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_ID&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_SECRET&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;JWT_SECRET&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DOCUMENTSERVER_URL&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;MIDDLEWARE_SERVER&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Missing required env vars. Please set DEX_ISSUER, CLIENT_ID, CLIENT_SECRET, JWT_SECRET, DOCUMENTSERVER_URL, MIDDLEWARE_SERVER&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-variable z-object z-process z-ts&quot;&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-process z-ts&quot;&gt;exit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;NODE_ENV&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-ts&quot;&gt;===&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;production&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;set&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;trust proxy&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Body parsers&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;express&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;express&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;urlencoded&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;extended&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Session&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;JWT_SECRET&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;resave&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-false z-ts&quot;&gt;false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;saveUninitialized&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-false z-ts&quot;&gt;false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;cookie&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;secure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;NODE_ENV&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-ts&quot;&gt;===&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;production&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;httpOnly&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;sameSite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;lax&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Files directory&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-object z-node z-ts&quot;&gt;__dirname&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;files&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;existsSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;mkdirSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;recursive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-boolean z-true z-ts&quot;&gt;true&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Utility: create empty docx&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;createEmptyDocx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-new z-ts&quot;&gt;new&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-name z-type z-ts&quot;&gt;Promise&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;reject&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;docx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;officegen&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;out&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;createWriteStream&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;error&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;err&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;reject&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;docx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;error&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;err&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;reject&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;close&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;docx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;generate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;out&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-new z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Middleware: login required&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;requireLogin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;next&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;redirectAfterLogin&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;originalUrl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;login&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;next&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;*&lt;&#x2F;span&gt; ---------------- Routes ---------------- &lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Root&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Dashboard&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;requireLogin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;readdirSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;filter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;f&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;endsWith&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;fileLinks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;files&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-ts&quot;&gt;length&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;?&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;files&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;map&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;f&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;&#x2F;edit&#x2F;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;encodeURIComponent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;quot;&amp;gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;a&amp;gt;&amp;lt;&#x2F;li&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;lt;li&amp;gt;No documents yet&amp;lt;&#x2F;li&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;!DOCTYPE html&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;head&amp;gt;&amp;lt;title&amp;gt;Dashboard&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;style&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    body {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      font-family: &amp;quot;Segoe UI&amp;quot;, Tahoma, Geneva, Verdana, sans-serif;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      margin: 0;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      padding: 20px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      background: #f7f8fa;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      color: #333;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    h1, h2 {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      color: #222;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    ul {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      list-style-type: none;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      padding-left: 0;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    li {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      margin-bottom: 8px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    a {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      text-decoration: none;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      color: #0078d4;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    a:hover {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      text-decoration: underline;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    form {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      margin-bottom: 20px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      background: #fff;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      padding: 15px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      border-radius: 8px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      box-shadow: 0 2px 6px rgba(0,0,0,0.1);
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    input[type=&amp;quot;text&amp;quot;] {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      padding: 6px 10px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      width: 250px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      border-radius: 4px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      border: 1px solid #ccc;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    button {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      padding: 6px 12px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      background-color: #0078d4;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      color: #fff;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      border: none;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      border-radius: 4px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      cursor: pointer;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    button:hover {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      background-color: #005a9e;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    .topbar {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      margin-bottom: 20px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      font-size: 0.9rem;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    .topbar a {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      margin-left: 10px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  &amp;lt;&#x2F;style&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;h1&amp;gt;Welcome, &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;h1&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;h2&amp;gt;Your Documents&amp;lt;&#x2F;h2&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;ul&amp;gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileLinks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;ul&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;h2&amp;gt;Create New Document&amp;lt;&#x2F;h2&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;form action=&amp;quot;&#x2F;create&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;filename&amp;quot; placeholder=&amp;quot;Document name&amp;quot; required&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Create&amp;lt;&#x2F;button&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;&#x2F;form&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;h2&amp;gt;Rename Document&amp;lt;&#x2F;h2&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;form action=&amp;quot;&#x2F;rename&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        &amp;lt;select name=&amp;quot;oldName&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;          &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;files&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;map&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;f&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&amp;lt;option value=&amp;quot;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;quot;&amp;gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;option&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        &amp;lt;&#x2F;select&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;newName&amp;quot; placeholder=&amp;quot;New name&amp;quot; required&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Rename&amp;lt;&#x2F;button&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;&#x2F;form&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;&#x2F;logout&amp;quot;&amp;gt;Logout&amp;lt;&#x2F;a&amp;gt;&amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;&#x2F;html&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Create new document&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;create&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;requireLogin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-async z-ts&quot;&gt;async&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-binding-pattern z-object z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-binding-pattern z-object z-ts&quot;&gt;}&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filename&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-character-class z-set z-regexp&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-backslash z-regexp&quot;&gt;\&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-backslash z-regexp&quot;&gt;\\&lt;&#x2F;span&gt;?%*:|&amp;quot;&amp;lt;&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-character-class z-set z-regexp&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;[&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;-&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;existsSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;File exists. &amp;lt;a href=&amp;#39;&#x2F;&amp;#39;&amp;gt;Back&amp;lt;&#x2F;a&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;try&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;await&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;createEmptyDocx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&#x2F;edit&#x2F;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;encodeURIComponent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;catch&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Error creating file. &amp;lt;a href=&amp;#39;&#x2F;&amp;#39;&amp;gt;Back&amp;lt;&#x2F;a&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Rename document&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;rename&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;requireLogin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;let&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object-binding-pattern-variable z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-binding-pattern z-object z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;oldName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;newName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-binding-pattern z-object z-ts&quot;&gt;}&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;newName&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;newName&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-character-class z-set z-regexp&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-backslash z-regexp&quot;&gt;\&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape z-backslash z-regexp&quot;&gt;\\&lt;&#x2F;span&gt;?%*:|&amp;quot;&amp;lt;&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-character-class z-set z-regexp&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;[&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-character-class z-regexp&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-single z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;-&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;oldPath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;oldName&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;newPath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;newName&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;existsSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;oldPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Original file not found. &amp;lt;a href=&amp;#39;&#x2F;&amp;#39;&amp;gt;Back&amp;lt;&#x2F;a&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;existsSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;newPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Target filename exists. &amp;lt;a href=&amp;#39;&#x2F;&amp;#39;&amp;gt;Back&amp;lt;&#x2F;a&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;renameSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;oldPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;newPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Dex login&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;login&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;redirect_uri&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;MIDDLEWARE_SERVER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;callback&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;authUrl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;auth?client_id=&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;encodeURIComponent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_ID&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;amp;redirect_uri=&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;encodeURIComponent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;redirect_uri&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;amp;response_type=code&amp;amp;scope=openid%20email%20profile&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;authUrl&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Dex callback&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;callback&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-async z-ts&quot;&gt;async&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;try&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;code&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;400&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Missing code&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;tokenResp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;await&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;axios&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;      &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;token&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;qs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;grant_type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;authorization_code&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;redirect_uri&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;MIDDLEWARE_SERVER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;callback&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;client_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;        &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;client_secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;CLIENT_SECRET&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;      &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;headers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Content-Type&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;application&#x2F;x-www-form-urlencoded&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;idToken&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;tokenResp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;id_token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;idToken&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;500&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;No id_token received&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;jwt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;decode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;idToken&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;sub&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;500&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Invalid id_token&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;user&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt; &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;sub&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;email&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;email&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;name&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;preferred_username&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;userInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;email&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Unnamed User&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;redirectAfterLogin&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;redirectUrl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;redirectAfterLogin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-keyword z-operator z-expression z-delete z-ts&quot;&gt;delete&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;redirectAfterLogin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;redirectUrl&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;catch&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Callback error:&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-optional z-ts&quot;&gt;?.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;data&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;500&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Authentication failed&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Logout&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;logout&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;destroy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;err&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;logoutUrl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;?&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-object z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;endsWith&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;?&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;logout&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;logout&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-ternary z-ts&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; New document without login&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;new&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-async z-ts&quot;&gt;async&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;try&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;new-&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-builtin z-ts&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;newFilePath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;await&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;createEmptyDocx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;newFilePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;redirect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&#x2F;edit&#x2F;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;encodeURIComponent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;catch&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Error creating new file:&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;500&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Failed to create new document&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Serve files&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;use&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;files&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;express&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;static&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setHeaders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setHeader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Cache-Control&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;no-cache, no-store, must-revalidate&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setHeader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Pragma&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;no-cache&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;setHeader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Expires&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Edit OnlyOffice document&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;edit&#x2F;:filename&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;requireLogin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;params&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;existsSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filePath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;404&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;File not found&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;documentUrl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;MIDDLEWARE_SERVER&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;files&#x2F;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;encodeURIComponent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;?v=&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-builtin z-ts&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;documentKey&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;-&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-builtin z-ts&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;session&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;dsPayload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;document&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;fileType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;documentKey&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;url&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;documentUrl&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;editorConfig&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;edit&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;name&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;callbackUrl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;${MIDDLEWARE_SERVER}&#x2F;onlyoffice-callback&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;iat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-math z-ts&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-math z-ts&quot;&gt;floor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-builtin z-ts&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;    &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;exp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-math z-ts&quot;&gt;Math&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-math z-ts&quot;&gt;floor&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-builtin z-ts&quot;&gt;Date&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;3600&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;dsToken&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;jwt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;sign&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;dsPayload&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;JWT_SECRET&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;algorithm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;HS256&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;!DOCTYPE html&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;title&amp;gt;Editing &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;fileId&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;style&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  html, body { height: 100%; margin: 0; background: #f7f8fa; font-family: &amp;quot;Segoe UI&amp;quot;, Tahoma, Geneva, Verdana, sans-serif; }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  #placeholder { width: 100%; height: 100%; }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  .topbar {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    position: absolute;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    top: 8px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    right: 12px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    z-index: 10;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    font-family: &amp;quot;Segoe UI&amp;quot;, Tahoma, Geneva, Verdana, sans-serif;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    background: rgba(255,255,255,0.9);
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    padding: 6px 10px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    border-radius: 6px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    box-shadow: 0 2px 6px rgba(0,0,0,0.1);
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  .topbar a {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    margin-left: 8px;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    color: #0078d4;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    text-decoration: none;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  .topbar a:hover {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    text-decoration: underline;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&amp;lt;&#x2F;style&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;div id=&amp;quot;placeholder&amp;quot;&amp;gt;&amp;lt;&#x2F;div&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;div class=&amp;quot;topbar&amp;quot;&amp;gt;Logged in as &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;escapeHtml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; | &amp;lt;a href=&amp;quot;&#x2F;logout&amp;quot;&amp;gt;Logout&amp;lt;&#x2F;a&amp;gt;&amp;lt;&#x2F;div&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;script src=&amp;quot;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;DOCUMENTSERVER_URL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;web-apps&#x2F;apps&#x2F;api&#x2F;documents&#x2F;api.js&amp;quot;&amp;gt;&amp;lt;&#x2F;script&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;script&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        const config = {
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;          document: &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-json z-ts&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-json z-ts&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;dsPayload&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;document&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;          documentType: &amp;quot;word&amp;quot;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;          editorConfig: &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-json z-ts&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-json z-ts&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;dsPayload&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;editorConfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;,
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;          token: &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-constant z-json z-ts&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-json z-ts&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;dsToken&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        };
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;        const docEditor = new DocsAPI.DocEditor(&amp;quot;placeholder&amp;quot;, config);
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;      &amp;lt;&#x2F;script&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;    &amp;lt;&#x2F;html&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; ONLYOFFICE callback&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;post&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;onlyoffice-callback&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-async z-ts&quot;&gt;async&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;body&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;ONLYOFFICE callback:&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;includes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;try&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;originalFilename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;split&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-array z-literal z-ts&quot;&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-square z-ts&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-ts&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;.docx&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;originalFilename&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;await&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;axios&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;responseType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;arraybuffer&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;writeFileSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;Saved document: &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-trycatch z-ts&quot;&gt;catch&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;      &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Error saving document:&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-optional z-ts&quot;&gt;?.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;data&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-ts&quot;&gt;||&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-property z-ts&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;    &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-objectliteral z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-object z-member z-ts&quot;&gt;&lt;span class=&quot;z-meta z-object-literal z-key z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-ts&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;0&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; Serve individual files&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-dom z-ts&quot;&gt;get&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;files&#x2F;:filename&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-parameter z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;req&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-object z-property z-ts&quot;&gt;params&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-variable z-property z-dom z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-meta z-var z-expr z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-ts&quot;&gt;const&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-var-single-variable z-expr z-ts&quot;&gt;&lt;span class=&quot;z-meta z-definition z-variable z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-ts&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant z-ts&quot;&gt;FILES_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;existsSync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;sendFile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-conditional z-ts&quot;&gt;else&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;status&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-decimal z-ts&quot;&gt;404&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;send&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;File not found&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-ts&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-double-slash z-ts&quot;&gt; XSS helper&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-ts&quot;&gt;function&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-definition z-function z-ts&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;escapeHtml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-ts&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;  &lt;span class=&quot;z-keyword z-control z-flow z-ts&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-builtin z-ts&quot;&gt;String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&amp;amp;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;amp;amp;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&amp;lt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;amp;lt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;amp;gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&amp;quot;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;amp;quot;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-ts&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&amp;#39;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-ts&quot;&gt;g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&amp;amp;#039;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-ts&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function z-ts&quot;&gt;&lt;span class=&quot;z-meta z-block z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-block z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-ts&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-object z-ts&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function z-ts&quot;&gt;listen&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;port&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-comma z-ts&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt; &lt;span class=&quot;z-meta z-parameters z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-begin z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-parameters z-end z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-arrow z-ts&quot;&gt;&lt;span class=&quot;z-storage z-type z-function z-arrow z-ts&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-ts&quot;&gt;&lt;span class=&quot;z-support z-class z-console z-ts&quot;&gt;console&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-ts&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function z-console z-ts&quot;&gt;log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-template z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-begin z-ts&quot;&gt;`&lt;&#x2F;span&gt;OnlyOffice middleware listening on port &lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-begin z-ts&quot;&gt;${&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-template z-expression z-ts&quot;&gt;&lt;span class=&quot;z-meta z-embedded z-line z-ts&quot;&gt;&lt;span class=&quot;z-variable z-other z-readwrite z-ts&quot;&gt;port&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-template-expression z-end z-ts&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-template z-end z-ts&quot;&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round z-ts&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-statement z-ts&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;package-json&quot;&gt;Package.json&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;json&quot; class=&quot;language-json z-code&quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;name&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;onlyoffice-middleware&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;version&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;1.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;main&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;index.js&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;dependencies&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-begin z-json&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;express&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;^4.18.2&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;jsonwebtoken&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;^9.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;axios&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;^1.6.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;dotenv&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;^16.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;express-session&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;^1.17.3&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-pair z-json&quot;&gt;,&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;    &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-key z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;officegen&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-separator z-mapping z-key-value z-json&quot;&gt;:&lt;&#x2F;span&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;^0.6.4&lt;span class=&quot;z-punctuation z-definition z-string z-end z-json&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;  &lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;&lt;span class=&quot;z-meta z-mapping z-value z-json&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-mapping z-end z-json&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-json&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;dockerfile&quot;&gt;Dockerfile&lt;&#x2F;h2&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;FROM node:20-alpine
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;WORKDIR &#x2F;app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;COPY package*.json .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;RUN npm install --production
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;COPY . .
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EXPOSE 3000
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;CMD [&amp;quot;node&amp;quot;, &amp;quot;index.js&amp;quot;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;environment-variables&quot;&gt;Environment Variables&lt;&#x2F;h2&gt;
&lt;p&gt;The needed Environment variables are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;DEX_ISSUER: The domain name to your OAuth2 server&lt;&#x2F;li&gt;
&lt;li&gt;CLIENT_ID: OAuth2 client ID&lt;&#x2F;li&gt;
&lt;li&gt;CLIENT_SECRET: OAuth2 client secret&lt;&#x2F;li&gt;
&lt;li&gt;JWT_SECRET: What you set in OnlyOffice Document Server as the JWT Secret&lt;&#x2F;li&gt;
&lt;li&gt;DOCUMENTSERVER_URL: The DocumentServer doman name&lt;&#x2F;li&gt;
&lt;li&gt;MIDDLEWARE_SERVER: the domain name serving this application&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;kubernetes-deployment-example&quot;&gt;Kubernetes deployment example&lt;&#x2F;h2&gt;
&lt;p&gt;I host this application in my kubernetes cluster.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; with the following deployment manifest:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Deployment&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;onlyoffice-middleware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;onlyoffice&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;spec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;1&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;selector&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;onlyoffice-middleware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;template&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;labels&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;onlyoffice-middleware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;spec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;imagePullSecrets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;regsecret&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;middleware&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;d.domain.tld&#x2F;onlyoffice-middleware:latest&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;imagePullPolicy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Always&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;ports&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;3000&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;resources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;requests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;100m&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;128Mi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;limits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;500m&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;512Mi&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;env&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;DEX_ISSUER&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;dex.domain.tld&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;CLIENT_ID&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;onlyoffice-middleware-domain.tld&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;DOCUMENTSERVER_URL&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-yaml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;https:&#x2F;&#x2F;office.domain.tld&lt;span class=&quot;z-punctuation z-definition z-string z-end z-yaml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;CLIENT_SECRET&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;valueFrom&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;                &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;secretKeyRef&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;                  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;onlyoffice-secrets&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;                  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;MIDDLEWARE_SECRET&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;JWT_SECRET&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;valueFrom&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;                &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;secretKeyRef&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;                  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;onlyoffice-secrets&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;                  &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;JWT_SECRET&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;files-storage&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;              &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&#x2F;app&#x2F;files&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;files-storage&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;          &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;persistentVolumeClaim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;            &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;claimName&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;middleware-files-pvc&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The middleware has a simple gui for creating new documents and editing existing ones. There is a delay when you save in the web app and see the changes in the actual file. For my use case, these documents will be short lived. &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=43503467&quot;&gt;According to one hackernews post&lt;&#x2F;a&gt;, OnlyOffice has Russian ties. While I like free software, I do not support Russia&#x27;s agression in Ukraine.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; The free world has imposed sanctions on Russia, and I participate in those by not using Russian-based software. So, if you know of a good lightweight editor that is not markdown based, let me know.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;I have Dex which is connected to my local LDAP server. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;At least until I find a better lightweight word processor that has easy footnote support. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;I have even gone as far as removing nginx from my kubernetes cluster. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Word processor to replace Google Docs</title>
        <published>2025-09-06T16:22:14.660761+00:00</published>
        <updated>2025-09-06T16:22:14.660761+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-06-word-processor-to-replace-google-docs/" type="text/html"/>
        <id>/2025-09-06-word-processor-to-replace-google-docs/</id>
        
            <content type="html">&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2025-09-06-An-open-letter-to-Google&quot;&gt;I have a few frustrations with Google Docs&lt;&#x2F;a&gt;. It has gotten slow over the years. There is now a sudden push to migrate to Google Workspaces, which is something I do not want to do. There a few routes I can go in an endeavor to switch away from Google Docs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;web-options&quot;&gt;Web Options&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Office 365&lt;&#x2F;li&gt;
&lt;li&gt;Etherpad-lite&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hedgedoc.org&#x2F;&quot;&gt;Hedgedoc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;OnlyOffice&lt;&#x2F;li&gt;
&lt;li&gt;Other various options that do not support footnotes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;desktop-options&quot;&gt;Desktop Options&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;LibreOffice&lt;&#x2F;li&gt;
&lt;li&gt;VSCode&lt;&#x2F;li&gt;
&lt;li&gt;Geany&lt;&#x2F;li&gt;
&lt;li&gt;Other options not as good as the ones listed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-direction&quot;&gt;The Direction&lt;&#x2F;h2&gt;
&lt;p&gt;I really only need a word processor. I do not need a full blown office replacement. LibreOffice is nice, but I would like something that looks more modern. Hedgedoc is a great option, but footnotes are a bit clunky.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Etherpad-lite says it will do what I need, but all of the plugins that I would want to use do not work with the latest version. VSCode and Geany do not support footnotes as I would need them. That left me with only one option to try OnlyOffice.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;onlyoffice&quot;&gt;OnlyOffice&lt;&#x2F;h2&gt;
&lt;p&gt;OnlyOffice is bundled with well known third-party solutions, such as CryptPad, NextCloud, and OwnCloud. Those options offer more than a document processor, and I am only looking to add a word processor. This meant I had to custom supply my own OnlyOffice solution.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; In a followup post, I will post how I accomplished to vibe code middleware to handle the Document server oddities behind an OAuth2 authentication flow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I thought there would be more free wordprocessing options available in 2025, but it appears everyone stopped developing new things once Google created their free Google Docs product. It appears others paid OnlyOffice to write competitive software in 2015. I am just thankful there is an AGPL v3.0 license .... even if the Documentation is difficult to understand.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;I would have to manually type the references. While this is what I do on this blog, when I write, I want fast footnote insertion. If Hedgedoc had a button I could press, it would have switched to it in a heartbeat. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Worst case scenario, I could code my own option, but this is not ideal. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;This is more difficult than it seems. The Docs were lacking in this area. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        </entry><entry xml:lang="en">
        <title>An open letter to Google</title>
        <published>2025-09-06T16:17:10.887031+00:00</published>
        <updated>2025-09-06T16:17:10.887031+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-06-an-open-letter-to-google/" type="text/html"/>
        <id>/2025-09-06-an-open-letter-to-google/</id>
        
            <content type="html">&lt;p&gt;Dear Google,&lt;&#x2F;p&gt;
&lt;p&gt;I want a functioning product that is fast. That means I do not want to participate in your “simulate slowness experiments.”
I use your product because I think it is good. You do not have to annoy me about trying your new Google workspace. If I want to try it, I will try it.&lt;&#x2F;p&gt;
&lt;p&gt;When I dismiss your notifications, it means I have acknowledged your banner, read the contents, and do not want to try this new offering. It does not mean you need to prompt me about Google Workspace at every opportunity. This behavior has become very annoying to me and has now caused me to seek other options for word processing.&lt;&#x2F;p&gt;
&lt;p&gt;I wish I could stay with your Google Doc application, but my writing time needs to be without interruption. Even the little change (such as nesting page numbers in a sub menu, which adds another click) can be tolerated for a time, but this 90px banner is just too much for me.&lt;&#x2F;p&gt;
&lt;p&gt;Sincerely,
Andrew&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Goodbye Wordpress</title>
        <published>2025-09-03T07:53:48.094453+00:00</published>
        <updated>2025-09-03T07:53:48.094453+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2025-09-03-goodbye-wordpress/" type="text/html"/>
        <id>/2025-09-03-goodbye-wordpress/</id>
        
            <content type="html">&lt;p&gt;I have delayed switching away from Wordpress on my personal blog to something different for quite some time. I liked the new idea of a flat-file static html concept, but Jekyll did not appeal to me. Then, Hugo appeared on the scene and appeared to take the rightful place as the cool kid on the block. Hugo has a simple concept and drew my interest from being written in Go, but from my delay in switching, I have been able to discover a potential flaw in my workflow. Occasional bloggers like me are fighting with updates just to add a new post.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In my opinion, markdown has its own challenges. It seems very clunky and difficult to memorize the correct ordering of braces&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-markdown-1&quot;&gt;&lt;a href=&quot;#fn-markdown&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; compared to the old-stlye BB code or regular html. Switching to a new blogging platform that adds more complexity &lt;em&gt;AND&lt;&#x2F;em&gt; forces me to move to markdown is not appealing. However, I came across &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;, which I heard updates &quot;once every other glacial age.&quot;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; That explanation that enough to pique my interest and switch this blog over.&lt;&#x2F;p&gt;
&lt;p&gt;Wordpress has served me well over the years, and I still have one application running a Wordpress frontend. I have another with Wordpress as a Headless CMS. I will continue to use Wordpress whenever I need an easy admin interface that a simpleton like myself can use when half asleep.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-wordpress-1&quot;&gt;&lt;a href=&quot;#fn-wordpress&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; However, I like the idea of removing another MySql&#x2F;MariaDB database as I slowly port over to PostgreSQL.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-postgre-1&quot;&gt;&lt;a href=&quot;#fn-postgre&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It took several hobby hours on my day off to make the change, but I have a fairly good workflow now. I asked ChatGPT to create a script for new post generation, and it gave me this python&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python z-code&quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-python&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-from z-python&quot;&gt;from&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-meta z-import-source z-python&quot;&gt; &lt;span class=&quot;z-meta z-import-path z-python&quot;&gt;&lt;span class=&quot;z-meta z-import-name z-python&quot;&gt;datetime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-import z-python&quot;&gt;import&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-import z-python&quot;&gt; &lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;datetime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-python&quot;&gt;#&lt;&#x2F;span&gt; Step 1: Get the current date and timestamp
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;datetime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;date_str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;strftime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-constant z-other z-placeholder z-python&quot;&gt;%Y&lt;&#x2F;span&gt;-&lt;span class=&quot;z-constant z-other z-placeholder z-python&quot;&gt;%m&lt;&#x2F;span&gt;-&lt;span class=&quot;z-constant z-other z-placeholder z-python&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;now&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;isoformat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-python&quot;&gt;#&lt;&#x2F;span&gt; Step 2: Prompt user for title and tags
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;Enter title: &lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;strip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tags_input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;Enter comma-separated tags: &lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;strip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tags&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-sequence z-list z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;strip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-expression z-generator z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-for z-generator z-python&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tag&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-for z-in z-python&quot;&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tags_input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;split&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;,&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-conditional z-if z-python&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;strip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-python&quot;&gt;#&lt;&#x2F;span&gt; Step 3: Prepare directory and file path
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;safe_title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt; &lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;-&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;replace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;-&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;  &lt;span class=&quot;z-comment z-line z-number-sign z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-python&quot;&gt;#&lt;&#x2F;span&gt; sanitize title
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-string z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;date_str&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;safe_title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;.md&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;content_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;getcwd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;content&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;content_dir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;filename&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-python&quot;&gt;#&lt;&#x2F;span&gt; Step 4: Write content
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-string z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;+++
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;title = &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;date = &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;[taxonomies]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;tags = [&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-python&quot;&gt;, &lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;join&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-sequence z-list z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-begin z-python&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-single z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-single z-python&quot;&gt;&amp;quot;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-expression z-generator z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-loop z-for z-generator z-python&quot;&gt;for&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tag&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-loop z-for z-in z-python&quot;&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;tags&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-sequence z-end z-python&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;+++
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-block z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-statement z-with z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-flow z-with z-python&quot;&gt;with&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;open&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;w&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-arguments z-python&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-parameter z-python&quot;&gt;encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-python&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;utf-8&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-statement z-with z-python&quot;&gt;&lt;span class=&quot;z-keyword z-control z-flow z-with z-as z-python&quot;&gt;as&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-statement z-with z-python&quot;&gt; &lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-block z-with z-python&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;    &lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-python&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;write&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-python&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-variable z-function z-python&quot;&gt;&lt;span class=&quot;z-support z-function z-builtin z-python&quot;&gt;print&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-begin z-python&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-string z-python&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-string z-interpolated z-python&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;File created: &lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-begin z-python&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python z-embedded&quot;&gt;&lt;span class=&quot;z-meta z-qualified-name z-python&quot;&gt;&lt;span class=&quot;z-meta z-generic-name z-python&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-interpolation z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-interpolation z-end z-python&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-python&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-python&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-arguments z-end z-python&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-python&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have added a few of my edits to the script it output. For instace, I removed the line creating the directory because I know it already exists and I added a few new lines to the content so I do not have to add them in when I open the file.&lt;&#x2F;p&gt;
&lt;p&gt;My future workflow of creating a blog post is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;python new-post.py
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;edit file&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.&#x2F;build-container.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.&#x2F;update-container.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;python announce-to-socials.py
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This seems like a lot of steps for one post. I have not even created the script to update or announce to socials yet. I will probably create the announcement cod in golang - so I can include it in the update-container script.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h2&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commaok.xyz&#x2F;post&#x2F;on_hugo&#x2F;&quot;&gt;https:&#x2F;&#x2F;commaok.xyz&#x2F;post&#x2F;on_hugo&#x2F;&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-markdown&quot;&gt;
&lt;p&gt;I think I will have to visit &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pulldown-cmark&#x2F;pulldown-cmark&#x2F;blob&#x2F;f4a326d225e79412b5ecabd1c241c851e8160815&#x2F;guide&#x2F;src&#x2F;cheat-sheet.md&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;pulldown-cmark&#x2F;pulldown-cmark&#x2F;blob&#x2F;f4a326d225e79412b5ecabd1c241c851e8160815&#x2F;guide&#x2F;src&#x2F;cheat-sheet.md&lt;&#x2F;a&gt; regularly &lt;a href=&quot;#fr-markdown-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mamot.fr&#x2F;@thibaultamartin&#x2F;115123535906012521&quot;&gt;https:&#x2F;&#x2F;mamot.fr&#x2F;@thibaultamartin&#x2F;115123535906012521&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-wordpress&quot;&gt;
&lt;p&gt;This is the true test of application robustness. &lt;a href=&quot;#fr-wordpress-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-postgre&quot;&gt;
&lt;p&gt;I like that PostgreSQL has an easy admin interface with PgAdmin, better integration with Prometheus, and had easier options to load the data into RAM for faster queries. &lt;a href=&quot;#fr-postgre-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;Python is another one of those languages that I try to stay away from. I prefer more elegant looking code like TypeScript, Ruby, or Go. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        </entry><entry xml:lang="en">
        <title>GnuCash mysql backend on Fedora</title>
        <published>2024-12-16T19:37:30+00:00</published>
        <updated>2024-12-16T19:37:30+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2024-12-16-gnucash-mysql-backend-on-fedora/" type="text/html"/>
        <id>/2024-12-16-gnucash-mysql-backend-on-fedora/</id>
        
            <content type="html">&lt;p&gt;I have been using GnuCash for personal finance since 2014. Two years ago, I switched over to a mysql backend because it was available in the flatpak. I never understood why the regular package on Fedora did not allow for opening a mysql database until today.&lt;&#x2F;p&gt;
&lt;p&gt;On Fedora, GnuCash is bundled with weak dependencies. GnuCash does not need mysql support to run properly. It does not make sense to require mysql support for everyone, but if you want mysql support, here is how to enable it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Find out what GnuCash depends upon:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dnf repoquery --depends gnucash
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Updating and loading repositories:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Repositories loaded.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;perl
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dconf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;gnome-icon-theme
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;gnucash-docs &amp;gt;= 5.9
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libaqbanking.so.44()(64bit)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libboost_filesystem.so.1.83.0()(64bit)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libboost_locale.so.1.83.0()(64bit)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libboost_program_options.so.1.83.0()(64bit)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libc.so.6(GLIBC_2.38)(64bit)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libcairo.so.2()(64bit)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libdbi-dbd-mysql
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libdbi-dbd-pgsql
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;libdbi-dbd-sqlite
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# These three packages enable support for their respective DB
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Install the option you want&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ sudo dnf install -y libdbi-dbd-mysql
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Enjoy using the native GnuCash package to save to mysql.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>My heartfelt apologies to Oulunkylä</title>
        <published>2024-05-16T09:52:56+00:00</published>
        <updated>2024-05-16T09:52:56+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2024-05-16-my-heartfelt-apologies-to-oulunkyla/" type="text/html"/>
        <id>/2024-05-16-my-heartfelt-apologies-to-oulunkyla/</id>
        
            <content type="html">&lt;p&gt;ChatGPT4 has emotion now, and I asked it to write a song about everything being just OK in Oulunkylä (A neighborhood of Helsinki). I have visited there and one of the dentist&#x27;s office signs declared itself to be an &quot;OK Dentist,&quot; which prompted this massively incorrect song about the neighborhood.&lt;&#x2F;p&gt;
&lt;p&gt;(Verse 1)
Oh, the streets of Oulunkylä are so serene,
Where the potholes are just a massage machine,
The traffic lights play a game of red and green,
But don&#x27;t worry, everything is just pristine.&lt;&#x2F;p&gt;
&lt;p&gt;(Chorus)
Oh, everything is OK in Oulunkylä,
Where the chaos is just part of the allure-a,
The sidewalks are cracked, but don&#x27;t you fret,
It&#x27;s a quirky charm you won&#x27;t forget.&lt;&#x2F;p&gt;
&lt;p&gt;(Verse 2)
The buses run like clockwork, that&#x27;s a fact,
If by &quot;clockwork&quot; you mean they&#x27;re always packed,
But hey, who needs space when you&#x27;ve got tact?
In Oulunkylä, we&#x27;re always on the right track.&lt;&#x2F;p&gt;
&lt;p&gt;(Chorus)
Oh, everything is OK in Oulunkylä,
Where the delays are just part of the culture-a,
The public transport&#x27;s a cozy squeeze,
Just enjoy the ride and feel the breeze.&lt;&#x2F;p&gt;
&lt;p&gt;(Bridge)
The winters here are mild, if you&#x27;re a polar bear,
And summer&#x27;s heatwave? It’s a sauna in the air,
The parks are pristine, if you squint and stare,
Oulunkylä, life&#x27;s without a care.&lt;&#x2F;p&gt;
&lt;p&gt;(Verse 3)
The neighbors&#x27; parties are a silent delight,
Except for the bass that rocks you at night,
And the construction? A lullaby in daylight,
In Oulunkylä, everything is just right.&lt;&#x2F;p&gt;
&lt;p&gt;(Chorus)
Oh, everything is OK in Oulunkylä,
Where the noise is our symphony aura,
The peace and quiet might be a myth,
But it&#x27;s a lovely place to take a fifth.&lt;&#x2F;p&gt;
&lt;p&gt;(Outro)
So come on down to Oulunkylä town,
Where nothing ever brings you down,
It&#x27;s a utopia of slight despair,
But hey, it&#x27;s Oulunkylä, and we don&#x27;t care!&lt;&#x2F;p&gt;
&lt;p&gt;(Verse 1)
Oi, Oulunkylän kadut ovat niin rauhalliset,
Missä kuopat ovat vain hierontakoneet,
Liikennevalot pelaavat punaista ja vihreää,
Mutta älä huoli, kaikki on ihan priimaa.&lt;&#x2F;p&gt;
&lt;p&gt;(Chorus)
Oi, kaikki on just OK Oulunkylässä,
Missä kaaos on osa vetovoimaa,
Jalkakäytävät halkeilee, mutta älä pelkää,
Se on outo viehätys, jonka muistat.&lt;&#x2F;p&gt;
&lt;p&gt;(Verse 2)
Bussit kulkevat kuin kellokoneisto, se on fakta,
Jos &quot;kellokoneistolla&quot; tarkoitat aina täynnä,
Mutta hei, kuka tarvitsee tilaa, kun on taitoa?
Oulunkylässä olemme aina oikealla radalla.&lt;&#x2F;p&gt;
&lt;p&gt;(Chorus)
Oi, kaikki on just OK Oulunkylässä,
Missä viivästykset ovat osa kulttuuria,
Julkinen liikenne on tiivis kokemus,
Nauti matkasta ja tunne tuuli.&lt;&#x2F;p&gt;
&lt;p&gt;(Bridge)
Talvet täällä ovat leutoja, jos olet jääkarhu,
Ja kesän helle? Se on sauna ilmassa,
Puistot ovat puhtaita, jos siristät silmiä,
Oulunkylä, elämä ilman huolia.&lt;&#x2F;p&gt;
&lt;p&gt;(Verse 3)
Naapureiden juhlat ovat hiljainen ilo,
Paitsi basso, joka rokkaa yöllä,
Ja rakennustyö? Kehtolaulu päivällä,
Oulunkylässä kaikki on juuri oikein.&lt;&#x2F;p&gt;
&lt;p&gt;(Chorus)
Oi, kaikki on just OK Oulunkylässä,
Missä melu on meidän sinfonia,
Rauha ja hiljaisuus saattavat olla myytti,
Mutta se on ihana paikka ottaa viides.&lt;&#x2F;p&gt;
&lt;p&gt;(Outro)
Joten tule Oulunkylän kylään,
Missä mikään ei koskaan masenna,
Se on utopiaa pienellä epätoivolla,
Mutta hei, se on Oulunkylä, eikä meitä haittaa!&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>New Glasses</title>
        <published>2024-04-19T05:40:54+00:00</published>
        <updated>2024-04-19T05:40:54+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2024-04-19-new-glasses/" type="text/html"/>
        <id>/2024-04-19-new-glasses/</id>
        
            <content type="html">&lt;p&gt;For most of my life I had to visit the optometrist yearly as my vision changed frequently, but as I got older, my eyes stopped degrading. For the last 5 years, I was on the same prescription, which is worth celebrating. However, I noticed a slight blur at a distance, and for the last 3 months, I just sort of lived with that new reality. At first, I was able to shrug it off and think that it was just my imagination. I could still clearly read items that were within a 1 kilometer range. Then, my son started to squint a bit more (a clear sign that his eyes were changing). Considering he needed the checkup, I made one for myself on the same day. The result was that both of us needed new prescriptions. Whereas my strength did not need correction, the astigmatism (focus) changed.&lt;&#x2F;p&gt;
&lt;p&gt;As I wear my new glasses now, I can see the sharp edges of characters in text and contrasts are more vibrant. I am able to enjoy knowing that my vision is correct and that I have a functional tool at my disposal. Oh, how foolish I was for delaying that check-up! Things are better now than before.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>New Year Reading Plan</title>
        <published>2023-12-22T07:23:29+00:00</published>
        <updated>2023-12-22T07:23:29+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-12-22-new-year-reading-plan/" type="text/html"/>
        <id>/2023-12-22-new-year-reading-plan/</id>
        
            <content type="html">&lt;p&gt;Next year I want to encourage my children to read the Bible through at least once. However, I found that most yearly Bible reading plans repeat reading the books of Psalms or Proverbs. Sure, that feature may make normal daily reading more enjoyable for adults, but extra reading is too much for children who have never read the Bible before. I wanted a plan for my children that would get them through the complete Bible and not repeat any verses. Unfortunately, most reading plans I found for children were not the complete Bible. This meant if I wanted them to read the Bible through once without repeated reading, I had to make my own plan for them.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily for my children, their dad is a computer nerd. I loaded up my database with data from &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scrollmapper&#x2F;bible_databases&quot;&gt;scrollmapper&lt;&#x2F;a&gt; to get the book, chapter, and verse bindings. Then I proceeded to calculate the total number of verse in the 66 books of the canon of Scripture - 31,102. To make it as easy as possible, the plan would have to have an equal amount of verses for each day. (Sadly, 31,102 does not reduce into 365 or 366 rounded segments.) I was able to get all the verses into a yearly plan by having the first 77 days with 86 verses and the remainder of the year at 85 verses a day (77*86)+(288*85)=31,102.&lt;&#x2F;p&gt;
&lt;p&gt;Even with the reduced number, it seemed 86 or 85 verses a day might be too much for a 7 year old to read in one sitting. Therefore, I split the reading into two sections - morning and evening portions. The morning will have 43 verses and the evening will have the remainder. Thus, if a child cannot read all 86 verses in one sitting, they have opportunity to break it up in the day. Based upon my youngest&#x27;s reading speed, it will take him approximately 45 minutes a day to complete this reading plan.&lt;&#x2F;p&gt;
&lt;p&gt;Because this will appear to be a very difficult task for my children - to read the Bible from cover to cover in a year, we are offering them 10 € per month of completed reading. Hopefully this will help them conquer bigger tasks in the future.&lt;&#x2F;p&gt;
&lt;p&gt;The generated plans and code (for leap and non-leap years) are available at &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;andrewwippler&#x2F;b0977ef9d8c8c79483ef9110f3cb53ae&quot;&gt;https:&#x2F;&#x2F;gist.github.com&#x2F;andrewwippler&#x2F;b0977ef9d8c8c79483ef9110f3cb53ae&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>From nginx to traefik (and solving X-Forwarded-For)</title>
        <published>2023-07-18T11:23:43+00:00</published>
        <updated>2023-07-18T11:23:43+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-07-18-from-nginx-to-traefik-and-solving-x-forwarded-for/" type="text/html"/>
        <id>/2023-07-18-from-nginx-to-traefik-and-solving-x-forwarded-for/</id>
        
            <content type="html">&lt;p&gt;I recently switched my home setup from &lt;em&gt;nginx&lt;&#x2F;em&gt; to &lt;em&gt;traefik&lt;&#x2F;em&gt;. I had to get used to the new configuration styles and weird doc style of &lt;em&gt;traefik&lt;&#x2F;em&gt;, but suffice to say, I am happy at the end results.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Traefik&lt;&#x2F;em&gt; ships with SNI, allowing me to snoop the connection and prevent unauthorized access to my file server. (One must have the correct &lt;em&gt;hostname&lt;&#x2F;em&gt; to see my shared photos.) My first action was to replace my edge &lt;em&gt;nginx&lt;&#x2F;em&gt; reverse proxy with &lt;em&gt;traefik&lt;&#x2F;em&gt;. If this was a success, then I would move onto replacing &lt;em&gt;nginx&lt;&#x2F;em&gt; in my k8s cluster. I was surprized that after zero OS tuning changes, &lt;em&gt;traefik&lt;&#x2F;em&gt; was able to serve pages faster for my k8s cluster. I initially thought that &lt;em&gt;traefik&lt;&#x2F;em&gt; would perform marginally slower than &lt;em&gt;nginx&lt;&#x2F;em&gt; due to additional &lt;em&gt;HostSNI&lt;&#x2F;em&gt; checks, but that was totally disproved by the first page load.&lt;&#x2F;p&gt;
&lt;p&gt;After switching to &lt;em&gt;traefik&lt;&#x2F;em&gt; inside my k8s cluster, performance improved even more. However, a new problem emerged: I was getting the IPs of my internal traffic logged instead of the real origin IP. While I would not normally care, malicious bots were attempting to brute force my WordPress installations, and I need to block their IPs.&lt;&#x2F;p&gt;
&lt;p&gt;I was able to get the &lt;em&gt;X-Forwarded-For&lt;&#x2F;em&gt; header populated with the true ip by enabling the Proxy Protocol on my edge &lt;em&gt;traefik&lt;&#x2F;em&gt;, setting externalTrafficPolicy: Local on my &lt;em&gt;traefik&lt;&#x2F;em&gt; k8s service, and finally telling &lt;em&gt;traefik&lt;&#x2F;em&gt; to accept the &lt;em&gt;proxyProtocol&lt;&#x2F;em&gt; information from the edge server.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Edge Router providers.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tcp:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  routers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    to-web:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      service: web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      rule: HostSNIRegexp(`www.andrewwippler.com`, `andrewwippler.com`, ...)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      entryPoints:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    to-websecure:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      service: websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      rule: HostSNIRegexp(`www.andrewwippler.com`, `andrewwippler.com`, ...)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      entryPoints:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      tls:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        passthrough: true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;services:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    web:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      loadBalancer:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        proxyProtocol:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          version: 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        servers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    websecure:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      loadBalancer:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        proxyProtocol:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          version: 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        servers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# traefik k8s deployment and service
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# missing service account definition and CRDs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: apps&#x2F;v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: Deployment
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  replicas: 3 #&amp;lt;-- one for each of my nodes, for failover
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  strategy: #&amp;lt;-- forces k8s to update pods on configuration change
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    rollingUpdate:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      maxSurge: 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      maxUnavailable: 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    type: RollingUpdate
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  selector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    matchLabels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      app: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  template:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        app: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      affinity: #&amp;lt;-- one replica per node
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        podAntiAffinity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          requiredDuringSchedulingIgnoredDuringExecution:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          - labelSelector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              matchExpressions:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              - key: app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                operator: In
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                values:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                - traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            topologyKey: &amp;quot;kubernetes.io&#x2F;hostname&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      serviceAccountName: traefik-ingress-controller
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      containers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - name: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          image: traefik:v2.10.3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          args:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.web.address=:80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.websecure.address=:443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.websecure.http.tls
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.websecure.http3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --experimental.http3=true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --providers.kubernetesingress
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --providers.kubernetescrd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --log.level=DEBUG
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.web.http.redirections.entrypoint.scheme=https
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entrypoints.web.http.redirections.entrypoint.to=websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            # - --accesslog
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entryPoints.web.proxyProtocol.trustedIPs=127.0.0.1&#x2F;32,10.0.0.0&#x2F;8,172.16.0.0&#x2F;12,192.168.0.0&#x2F;16 #&amp;lt;-- local CIDRs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - --entryPoints.websecure.proxyProtocol.trustedIPs=127.0.0.1&#x2F;32,10.0.0.0&#x2F;8,172.16.0.0&#x2F;12,192.168.0.0&#x2F;16 #&amp;lt;-- local CIDRs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;          ports:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - name: web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              containerPort: 80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            - name: websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              containerPort: 443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: Service
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  type: NodePort
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  selector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: traefik
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ports:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - protocol: TCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      port: 80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      name: web
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      targetPort: 80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - protocol: TCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      port: 443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      name: websecure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      targetPort: 443
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  externalTrafficPolicy: Local # &amp;lt;--- changed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>How do you repent from sin?</title>
        <published>2023-06-27T13:05:09+00:00</published>
        <updated>2023-06-27T13:05:09+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-06-27-how-do-you-repent-from-sin/" type="text/html"/>
        <id>/2023-06-27-how-do-you-repent-from-sin/</id>
        
            <content type="html">&lt;p&gt;How do you repent from sin? How does one get all of their sins forgiven? These questions often fill the minds of those who have sin. Perform a search query on a popular web indexing service and you will find many interpretations of these questions.&lt;&#x2F;p&gt;
&lt;p&gt;I was surprised at the results from the Church of Jesus Christ (LDS, Mormonism) and popular writings concerning Allah. They both came to the same conclusions that one must be performers of an action in order to know for certain they have been forgiven. For the mormon, &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.churchofjesuschrist.org&#x2F;study&#x2F;manual&#x2F;gospel-principles&#x2F;chapter-19-repentance?lang=eng&quot;&gt;one must keep the commandments of God&lt;&#x2F;a&gt;, and for the Islamic worshipper of Allah, &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;yaqeeninstitute.org&#x2F;roohi-tahir&#x2F;how-do-i-ask-allah-for-forgiveness&quot;&gt;one must follow the four R&#x27;s&lt;&#x2F;a&gt;. A logical flaw is present in both of these conclusions - humans are not able to repeatedly reproduce perfect outcomes.&lt;&#x2F;p&gt;
&lt;p&gt;For example, If I were to present a list of 10 questions and to a person for 1 minute. Then if I were to request that same person to fill in the answers on a new paper with only the questions, the person might get it correct on the first try. Now, if I were to repeat this process to the same person - showing 10 new questions and answers - eventually, the person will miss a question. It may not be immediate. It may take days before the person gets a question wrong. However, that person will get a question wrong - not because the person is uneducated or lacks memorizing ability, but because he is a human.&lt;&#x2F;p&gt;
&lt;p&gt;One of my favorite hobbies is computer science. I read a lot of technical papers and designs. Still, with all the advancements that have been made, computer bugs find a way to exist. Even with the best error correction mechanisms in place, humans find a way to create flawed computer code that does not work. It is not because they lack intelligence in organizing words and characters into computer instructions, but because humans lack the ability of perfection.&lt;&#x2F;p&gt;
&lt;p&gt;All humans are flawed humans. At the risk of losing credibility, I must also admit that I have the capacity to be wrong. I am flawed. In Bible terms, this is called being a sinner. As a sinner, I have sin and this sin causes me to be imperfect. At one point in my life, I asked the right question - how do you repent from sin? - to the right person. The answer I was given was to place my trust in Jesus - to believe that Jesus is real, that He died on a cross for my sin, and that Jesus rose again on the third day. The Bible supports this fact: those who put their trust in Jesus are given forgiveness of past, present, and future sin.&lt;&#x2F;p&gt;
&lt;p&gt;It has now been over 20 years since I placed my trust in Jesus. Each day, I live in the reality of grace, with absolute knowledge that my sins have been forgiven.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>TIL: Zoom has captions</title>
        <published>2023-06-09T09:06:28+00:00</published>
        <updated>2023-06-09T09:06:28+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-06-09-til-zoom-has-captions/" type="text/html"/>
        <id>/2023-06-09-til-zoom-has-captions/</id>
        
            <content type="html">&lt;p&gt;The Zoom application has built in AI captions for various languages. It is great for those hard of hearing to read the words that are spoken.&lt;&#x2F;p&gt;
&lt;p&gt;In other news, you can select the spoken language to be in Finnish, speak in English, and get wonderfully funny sentences in Finnish.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>A few pictures on my phone</title>
        <published>2023-05-31T07:44:33+00:00</published>
        <updated>2023-05-31T07:44:33+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-05-31-a-few-pictures-on-my-phone/" type="text/html"/>
        <id>/2023-05-31-a-few-pictures-on-my-phone/</id>
        
            <content type="html">&lt;div&gt;

    &lt;a class=&quot;gallery-image&quot; href=&quot;&#x2F;2023-05-31-a-few-pictures-on-my-phone&#x2F;wp_story1685519071518_2884776088272888422.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;&amp;#x2F;processed_images&amp;#x2F;wp_story1685519071518_2884776088272888422.fdebd650e5045d95.jpg&quot; alt=&quot;Gallery image&quot; loading=&quot;lazy&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    &lt;a class=&quot;gallery-image&quot; href=&quot;&#x2F;2023-05-31-a-few-pictures-on-my-phone&#x2F;wp_story1685519071519_15560477310965744105.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;&amp;#x2F;processed_images&amp;#x2F;wp_story1685519071519_15560477310965744105.4a42b44ebf7c6b07.jpg&quot; alt=&quot;Gallery image&quot; loading=&quot;lazy&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    &lt;a class=&quot;gallery-image&quot; href=&quot;&#x2F;2023-05-31-a-few-pictures-on-my-phone&#x2F;wp_story1685519072052_55849421647301837682.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;&amp;#x2F;processed_images&amp;#x2F;wp_story1685519072052_55849421647301837682.f7c92e2c432e4284.jpg&quot; alt=&quot;Gallery image&quot; loading=&quot;lazy&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    &lt;a class=&quot;gallery-image&quot; href=&quot;&#x2F;2023-05-31-a-few-pictures-on-my-phone&#x2F;wp_story1685519072232_06890778882110170040.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;&amp;#x2F;processed_images&amp;#x2F;wp_story1685519072232_06890778882110170040.dce6b293f6db8f22.jpg&quot; alt=&quot;Gallery image&quot; loading=&quot;lazy&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    &lt;a class=&quot;gallery-image&quot; href=&quot;&#x2F;2023-05-31-a-few-pictures-on-my-phone&#x2F;wp_story1685519072422_43809962456477229500.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;&amp;#x2F;processed_images&amp;#x2F;wp_story1685519072422_43809962456477229500.092bc9dc404a35dd.jpg&quot; alt=&quot;Gallery image&quot; loading=&quot;lazy&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
    &lt;a class=&quot;gallery-image&quot; href=&quot;&#x2F;2023-05-31-a-few-pictures-on-my-phone&#x2F;wp_story1685519731795_35627313678291969325.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;&amp;#x2F;processed_images&amp;#x2F;wp_story1685519731795_35627313678291969325.02e647c478a512fe.jpg&quot; alt=&quot;Gallery image&quot; loading=&quot;lazy&quot; &#x2F;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;</content>
        </entry><entry xml:lang="en">
        <title>Who is the author in AI-generated content?</title>
        <published>2023-05-16T11:02:55+00:00</published>
        <updated>2023-05-16T11:02:55+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-05-16-who-is-the-author-in-ai-generated-content/" type="text/html"/>
        <id>/2023-05-16-who-is-the-author-in-ai-generated-content/</id>
        
            <content type="html">&lt;p&gt;As AI tools are becoming more frequent, many have found interesting use cases. Some are using AI tools to publish children&#x27;s books or other creative works primarily done by humans. However, when one publishes a work that was generated by AI, who is the author of the work? Should a notice be included or a sub author be added to the work that was derived from an AI tool? If two publish a paragraph of the same text at the same time from the same AI tool, who gets to declare that they were the original work?&lt;&#x2F;p&gt;
&lt;p&gt;These questions are difficult to answer through legal matters. Consider the following paragraph:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Sheep: The Domesticated Mammal
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep have been domesticated by humans since Creation. They have been bred for their wool, milk, and meat. Specialized breeds Despite their seemingly simple appearance, sheep have a lot of interesting physical characteristics, a unique relationship with humans, and a crucial role in agriculture that make them an important part of human life and civilization.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;## Physical Characteristics of Sheep
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep are mammals that belong to the Bovidae family, which includes cows, goats, and antelopes. They are herbivores and have four-chambered stomachs that allow them to digest tough plant material efficiently. Sheep have thick woolly coats that can be white, brown, black, or gray. The wool serves as insulation and protects them from the elements. Sheep are social animals and prefer to live in groups called flocks. They have excellent hearing and can detect sounds up to 10 times better than humans. This heightened sense of hearing helps them stay alert to potential predators.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;## Sheep and Humans
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep have played an important role in human civilization for thousands of years. They were one of the first animals to be domesticated, and their wool, meat, and milk have been used for various purposes. Sheep have also been used for their skin, which can be made into leather. The wool from sheep has been used for clothing, blankets, and carpets. In some cultures, sheep are also used for religious ceremonies.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The relationship between sheep and humans is unique. Farmers have developed a deep understanding of their sheep&amp;#39;s behavior and needs, and shepherds have been known to develop close bonds with their flocks. Sheep are also used in therapy programs to provide comfort and companionship to people in need. Their gentle nature and calming presence have been shown to have a positive effect on mental health.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;## Sheep in Agriculture
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep are an important part of agriculture. They are raised for their wool, meat, and milk. Sheep farming is a major industry in many countries, and the demand for sheep products continues to grow. Sheep are also used for grazing and can help control weeds and keep the grass short. They are often used to maintain grasslands and prevent soil erosion. Additionally, sheep are known for their ability to convert low-quality forage into high-quality meat and wool, making them a valuable resource for farmers and communities.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;## Conclusion
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;In conclusion, sheep are fascinating creatures that have played an integral role in human life and civilization. Their physical characteristics, unique relationship with humans, and crucial role in agriculture make them an important part of our world. As we continue to rely on sheep for their wool, meat, and milk, it&amp;#39;s important that we treat them with the respect and care that they deserve. By doing so, we can ensure that these gentle creatures continue to thrive and contribute to our society for years to come.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This article was solely developed through the Notion AI engine. (At first, I did not like the generated paragraph about sheep. I requested the engine to make it longer, which is the version posted above.)&lt;&#x2F;p&gt;
&lt;p&gt;Now consider this different paragraph about sheep:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep have been domesticated by humans since the Fall of Man, with Abel offering a lamb of his fold to God in Genesis 4. Specialized breeds, such as the California Variegated Mutant or Finnish Landrace, display mutant-like qualities or produce more young than average. Nevertheless, all sheep today are primarily raised for their wool, milk, and meat. Despite looking seemingly simple, sheep have a lot of interesting physical characteristics, a unique relationship with humans, and a crucial role in agriculture which makes them an important part of human life and civilization.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep are mammals that belong to the same animal family as cows, goats, and antelopes. Sheep are plant eaters and have four-chambered stomachs. Sheep are social animals and live in flocks, which sometimes makes them an easy target for predators. However, sheep have excellent hearing which helps them stay alert to potential predators. Sheep come in a variety of colors, such as white, brown, black, or gray. The thick, woolly coat serves the sheep by insulating it from the elements, which is why humans have used it for various purposes.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Over time, farmers have developed a deep understanding of their sheep&amp;#39;s behavior and needs, which has bonded shepherds with their flocks. Scripture records that David, as a young shepherd boy, fought both a lion and a bear to rescue his sheep. Some have begun using sheep in therapy programs because their gentle nature and calming presence have been proven to have a positive effect on mental health.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The demand for sheep products continues to grow, including their physical presence in a field. Sheep have an immense desire to eat, which helps control weeds and keep grass short. Sheep are  rented out to maintain grasslands in some areas. Additionally, sheep are known for their ability to convert low-quality forage into high-quality meat and wool, making them a valuable resource for farmers and communities.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sheep share an important part of our world. When we treat them with care, we can ensure that these gentle creatures continue to thrive and contribute to our society for years to come.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I produced this second article using a summarization technique after reading the first one. These words were formed from using a combination of editing the underlying text and inserting my narrative. Could that mean I co-authored the text with AI? I am certain that I could fool people into thinking the second article is my original content; however, I would be in a difficult spot if I were to be asked to produce sources of the claims. (Although, I did do &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.raisingsheep.net&#x2F;cvm-sheep&quot;&gt;a little research which uncovered mutant sheep&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;Who is the author of a published work that is generated by AI? It is an AI program. Proper attribution to the rightful author should be mandated everywhere. Until that time comes, one can spot AI generated content through its lack of sources cited and repeated textual patterns.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Personal Tech Debt</title>
        <published>2023-05-10T08:18:29+00:00</published>
        <updated>2023-05-10T08:18:29+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-05-10-personal-tech-debt/" type="text/html"/>
        <id>/2023-05-10-personal-tech-debt/</id>
        
            <content type="html">&lt;p&gt;This past week I have been able to traverse down the rabbit hole of personal tech debt. After a week&#x27;s work, I think I was able to get to the bottom and give everything an updated timestamp! All kidding aside, here were some of the projects I was able to revisit:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kubernetes-cluster&quot;&gt;Kubernetes Cluster&lt;&#x2F;h2&gt;
&lt;p&gt;My k8s cluster hosts websites, internal applications, and personal projects. While many choose to host their services on cloud services, I find it easier (and cheaper) to run it in a controlled home cluster. This week I was able to troubleshoot why some services were sluggish and crashing. After deploying prometheus and grafana a month ago, I was able to determine that my cluster was maxed out. I added another node to the cluster and performance improved. On a side note, I do not understand why people want to purchase barebone Intel NUCs when one can get everything included in a Dell Optiplex 5050 micro form factor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;website-redesign&quot;&gt;Website redesign&lt;&#x2F;h2&gt;
&lt;p&gt;My theme from 2015 was based on bootstrap 4 and had a few Admin UI bugs. The errors were only visible to me, so I have been putting it off for quite a while. This took me a morning to clean up with TailwindCSS. There are still a few UI features missing on the frontend due to a problem with my build and deployment process. I hope this new tech debt does not stay on the list for very long.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;personal-finances&quot;&gt;Personal Finances&lt;&#x2F;h2&gt;
&lt;p&gt;I have been using GnuCash since 2014, and I have found that it is a perfect program for dual-entry accounting. However, it requires that I use a computer and the program to add or remove purchases. The reporting features are also lacking functionality; however, the program has been working flawlessly. It has been on my list to revisit how I do finances to see if a web-based solution would be better. Considering I now have multiple currencies, I need a program that could do both USD and Euro. GnuCash already has this feature and I found the new Alpha Vantage API to be quite buggy.&lt;&#x2F;p&gt;
&lt;p&gt;Considering I have been a longtime user of GnuCash, my file had some corrupted entries. GnuCash did not have any friendly warnings that would hint at the solution. I could not save the file in SQLite or in MySQL to use the Python library piecash.&lt;&#x2F;p&gt;
&lt;p&gt;I looked at Firefly-iii and considered migrating to that - it had multi-currency support as well. The rules feature meant I could create a webhook that updates transactions from USD to Euro against the public trading exchange rate for that day. At first, this program looked promising.&lt;&#x2F;p&gt;
&lt;p&gt;I was able to export my files to simple CSVs and attempt to import and map them to appropriate fields. However, account splits did not export very well. I had to spend 4 hours manually importing my splits into Firefly-iii. Then I tried importing new CSVs from my bank into Firefly-iii and I found that I would have to spend several minutes creating rules in Firefly-iii. At this point, I realized that these rules were already programmed into GnuCash. If Firefly-iii existed in 2014, I think I would have begun my personal finance with it, but the work required now to migrate to this solution is, in my opinion, not worth it for me.&lt;&#x2F;p&gt;
&lt;p&gt;In GnuCash, I can import CSV, QFX, and QIF. I can map the transactions quickly and easily. Since 2014, GnuCash has been training on my data to give me a personalized experience, which has kept me on this program. It has served my financial banking needs, but now I realized I had to figure out the corruption problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gnucash-corruption-problem&quot;&gt;GnuCash Corruption problem&lt;&#x2F;h2&gt;
&lt;p&gt;Tech dept often snowballs into bigger problems. I was facing the largest snowball in existence. How am I supposed to find this transaction_id that the GnuCash error was telling me? I cannot save the file as SQLite to use the piecash python library to find it. It seemed hopeless.&lt;&#x2F;p&gt;
&lt;p&gt;Then I realized I am a forgetful nerd.&lt;&#x2F;p&gt;
&lt;p&gt;In my attempt to create a clean, XML export to CSV of GnuCash, I came across a &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cebe&#x2F;gnucash-php&quot;&gt;PHP GnuCash XML library&lt;&#x2F;a&gt;. I then created a script which outputted all of the information I needed for &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;firefly_import&quot;&gt;exporting GnuCash XML to CSV&lt;&#x2F;a&gt;. The odd transactions, which had errors, were searchable in the CSV my script created. I was able to find and fix my GnuCash transactions. Then, I was able to successfully save my GnuCash file in SQLite.&lt;&#x2F;p&gt;
&lt;p&gt;I still laugh at the GnuCash error: Transaction description cannot be null. My faulty transactions had the string &quot;null&quot; in them. Once I removed the string, saving worked.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;new-tech-debt&quot;&gt;New tech debt&lt;&#x2F;h2&gt;
&lt;p&gt;The processing of my personal tech debt is down to two items: 1.) Fixing the CSS bugs in my new website theme. 2.) Creating scripts to extend GnuCash functionality through the SQL backend. I think I can work on some of these next month :)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Speaker Windows</title>
        <published>2023-04-22T06:40:25+00:00</published>
        <updated>2023-04-22T06:40:25+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-04-22-speaker-windows/" type="text/html"/>
        <id>/2023-04-22-speaker-windows/</id>
        
            <content type="html">&lt;p&gt;I have been working on a personal project to organize my preaching illustrations. Whereas one could use a tool such as Notion, Evernote, or Obsidian, I have had a desire to keep my data in an easy to use interface. I should not have to spend 10 minutes to find that illustration I need. Plus, those services might charge me more than $3&#x2F;month to access advanced features I may become dependent upon.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2023&#x2F;04&#x2F;speakerwindows.png&quot;&gt;&lt;img src=&quot;&#x2F;2023&#x2F;04&#x2F;speakerwindows.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Over the years, I have collected over a thousand notes and jots from various sources, which I have been storing in &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;speaker-illustrations&quot;&gt;Speaker Illustrations&lt;&#x2F;a&gt;. However, the time has come to add features (such as attaching images or videos) and I am not very proficient in Rails to make such a change. I have re-written Speaker Illustrations in JavaScript using React and Nextjs, with an API provided by AdonisJS. I have called it &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;SpeakerWindows&quot;&gt;Speaker Windows&lt;&#x2F;a&gt; because an illustration is just a window for people to look through to understand your meaning.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2023&#x2F;04&#x2F;ability.png&quot;&gt;&lt;img src=&quot;&#x2F;2023&#x2F;04&#x2F;ability.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Anyone can host their own copy of &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;SpeakerWindows&quot;&gt;Speaker Windows&lt;&#x2F;a&gt;, but I know how most who would benefit from this service are inept to install software on a server. Therefore, I have designed the application with multi-user auth. Anyone can register for an account on my &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sw.wplr.rocks&#x2F;&quot;&gt;publicly hosted instance&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2023&#x2F;04&#x2F;speakerwindows2.png&quot;&gt;&lt;img src=&quot;&#x2F;2023&#x2F;04&#x2F;speakerwindows2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The new features have yet to be added, but the project is now at the same functionality as my old implementation. Currently, I am satisfied with the rewrite and am happy with using NextJS and AdonisJS in future personal projects, such as a shopping list app to replace our use of Google Keep. (There are rumors Google Keep is being axed.)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>What will cause you to change?</title>
        <published>2023-03-29T07:32:49+00:00</published>
        <updated>2023-03-29T07:32:49+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-03-29-what-will-cause-you-to-change/" type="text/html"/>
        <id>/2023-03-29-what-will-cause-you-to-change/</id>
        
            <content type="html">&lt;p&gt;&quot;I am right. Therefore, you must change.&quot; This is a common sentiment among anyone who holds an opinion. Major convincing arguments are then given as to reasons why others must change to your point of view.&lt;&#x2F;p&gt;
&lt;p&gt;It is proud to assume that you have all of the right answers to everything. To make such a claim is to decree that you are like God: all-knowing and perfect in every way. However, any human cannot make such a claim. Humans are notorious for failure.&lt;&#x2F;p&gt;
&lt;p&gt;Did Edison invent the lightbulb on the first try?
Did all the Apollo missions succeed without incident?
How many attempts did it take Spacex engineers to land a rocket? Was it 1?
How many answers did you get wrong on all of the tests you took in school? Was it 0?&lt;&#x2F;p&gt;
&lt;p&gt;As a human, I understand my faults. Compared to a Holy God, I can never be perfect. Thankfully, this God offers forgiveness of sin through placing one&#x27;s trust in His substitutionary death on the cross. Oh, what freedom I experienced when I trusted Christ!&lt;&#x2F;p&gt;
&lt;p&gt;Now, as I have been a Christian for over two decades, it disturbs me at the audacity of some who claim the inability to change their opinions. Our sacred text shows a few examples of the opposite. Job had an idea of God, but when he saw Him, Job&#x27;s lifestyle changed (Job 42:5-6). Paul admonished the reduction of one&#x27;s liberty to maintain the edification of one another (Romans 14:19-21). Even the early church demonstrated the necessity of change to minister to the needs of those who were experiencing poverty from becoming a Christian (Acts 4:32-35).&lt;&#x2F;p&gt;
&lt;p&gt;Christianity is not a list of stubborn rules which are unmovable. Instead, it is a journey leading one &quot;to be conformed to the image of his Son&quot; (Romans 8:29), and it is built upon continual scrutiny of one&#x27;s decisions (Romans 12:2). Change (or demonstration of critical thinking as to why one is not changing) is an indicator of one&#x27;s belief in God. &quot;We have always done it this way&quot; is not acceptable thinking in Christianity. Change must be performed when necessitated.&lt;&#x2F;p&gt;
&lt;p&gt;What will cause you to change from your position? What evidence is required for you to stay with your current thinking? Defining these should be a requirement for any individual desiring to hold a position of ministry.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Three goals in Bible Reading</title>
        <published>2023-02-13T08:05:48+00:00</published>
        <updated>2023-02-13T08:05:48+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-02-13-three-goals-in-bible-reading/" type="text/html"/>
        <id>/2023-02-13-three-goals-in-bible-reading/</id>
        
            <content type="html">&lt;p&gt;Recently, I evaluated why I take time out of my day to read the Bible. I have heard that the Bible has one singular meaning. If that is true, then reading the Bible through once is sufficient. However, those that promote singular meaning also advocate for daily Bible reading. This seems like a logical fallacy, which should be addressed; nevertheless, I attempt to achieve at least one of these three goals every time I open my Bible to read it.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Personal Growth
I need to learn God&#x27;s view of man&#x27;s relations. I need to adapt my lifestyle to fit.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Time with God
Sometimes the only result I get is adding minutes to our relationship. When I was dating my wife, it did not matter if all we did was sit and watch an old movie. We were adding minutes of being together. The same is true for any relationship - time spent together matters.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Finding a truth to teach others
Pet peeves are often taught as truth; however, one must follow the logical, linguistic chain to find the truth that Scripture teaches. One must pull out the application rather than inject the thought into the text. One must be fully equipped in the truth to be able to teach others the same truth.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Link sharing in the blog era</title>
        <published>2023-02-07T10:09:58+00:00</published>
        <updated>2023-02-07T10:09:58+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-02-07-link-sharing-in-the-blog-era/" type="text/html"/>
        <id>/2023-02-07-link-sharing-in-the-blog-era/</id>
        
            <content type="html">&lt;p&gt;I just remembered how painful it was to share content through a blog to friends. Social media, such as Twitter, solved that issue. I do not want to attempt trying to remember my Digg.it password (Does the site even exist anymore?)&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, I said all of that to say this: I know where both of these locations are:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;yle.fi&#x2F;a&#x2F;74-20016727?origin=rss&quot;&gt;https:&#x2F;&#x2F;yle.fi&#x2F;a&#x2F;74-20016727&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I can be excited for both the US and Finnish teams.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Extension to make Twitter more usable</title>
        <published>2023-01-25T04:32:17+00:00</published>
        <updated>2023-01-25T04:32:17+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-01-25-extension-to-make-twitter-more-usable/" type="text/html"/>
        <id>/2023-01-25-extension-to-make-twitter-more-usable/</id>
        
            <content type="html">&lt;p&gt;After setting up an RSS reader and a bridge to pull in tweets, I no longer access Twitter. If there is interesting content, I click the link on my RSS reader and comment directly without visiting the Twitter homepage.&lt;&#x2F;p&gt;
&lt;p&gt;If I were a more regular user of Twitter, I think I would use this extension: &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;insin&#x2F;tweak-new-twitter&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;insin&#x2F;tweak-new-twitter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I might even install it for the few times a month I click on a Twitter link.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Depression and Anxiety</title>
        <published>2023-01-19T08:50:38+00:00</published>
        <updated>2023-01-19T08:50:38+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-01-19-depression-and-anxiety/" type="text/html"/>
        <id>/2023-01-19-depression-and-anxiety/</id>
        
            <content type="html">&lt;p&gt;This morning I read from one of the people I follow a short, concise list of comparing Depression and Anxiety. &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;JoeShakour&#x2F;status&#x2F;1615766430535778333?s=20&quot;&gt;It is quite good to read over&lt;&#x2F;a&gt;, but I think it is quite lacking in its explanation. Primarily limited from the 280 character posts on Twitter.&lt;&#x2F;p&gt;
&lt;p&gt;I feel like I have authority to speak on this subject because I am the son of a medically-diagnosed bi-polar manic depressive and my other parent is anxious about living in the perfect climate known as San Diego, California. To say that I know what depression and anxiety look like would be an understatement. Not only have I observed it in my parents, but I have had seasons where the struggle between the two extremes was real in my own life. Now, as a parent, I view some of the struggles that I have seen in my parents and my own life beginning to surface in my children.&lt;&#x2F;p&gt;
&lt;p&gt;How does one overcome anxiety or depression? Here are some solutions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find an anchor.&lt;&#x2F;strong&gt; An anchor is one that does not change over time. Some like to put their anchor in a schedule, in a relationship, in a religious set of beliefs, or in a church; however, those are false anchors.&lt;&#x2F;p&gt;
&lt;p&gt;The only true anchor is God.&lt;&#x2F;p&gt;
&lt;p&gt;David wrote, &quot;Truly my soul waiteth upon God: from him cometh my salvation. He only is my rock and my salvation; he is my defence; I shall not be greatly moved.&quot; (Psalm 62:1-2).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Belong to a church that develops your connection to the anchor.&lt;&#x2F;strong&gt; Some like to evaluate this position to mean that the church has a ton of programs going on. However, the way to evaluate this section is if the pastor gives a sermon (or brings in men to preach on his behalf), that equip you to become better attached to the anchor. This is amplified through opportunities to use this attachment.&lt;&#x2F;p&gt;
&lt;p&gt;Sadly, it is increasingly common to find a church in America that preaches republicanism where Trump is god or wokeism where everything must be accepted. If you increasingly feel better equipped to attack the other side rather than develop the peace which is in God (John 14:27), it is time for you to find a different church.&lt;&#x2F;p&gt;
&lt;p&gt;Paul wrote, &quot;For the kingdom of God is not meat and drink; but righteousness, and peace, and joy in the Holy Ghost. For he that in these things serveth Christ is acceptable to God, and approved of men. Let us therefore follow after the things which make for peace, and things wherewith one may edify another.&quot; (Romans 14:17-19)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Understand: depression and anxiety are temporary seasons (Ecc 3:1).&lt;&#x2F;strong&gt; If you are finding that they linger longer than expected, you might have to seek medical help. Medicine is the use of God&#x27;s created resources to aid in the sustainability of His creation.&lt;&#x2F;p&gt;
&lt;p&gt;Anxiety is relieved when that particular worry is completely let go to be cared for by God (1 Peter 5:7). It is a difficult practice to learn, but God&#x27;s outcomes are better than mine.&lt;&#x2F;p&gt;
&lt;p&gt;Depression has many causes and it is complex to even identify the reason for the depression. The worst thing you can do to yourself is to hide this depression from others. Seek help when necessary from your pastor or a Nuethetic Counselor he recommends.&lt;&#x2F;p&gt;
&lt;p&gt;What makes me get into a depressive mood is when I am overwhelmed with tasks. I feel like I am drowning and there appears to be no deliverer. This is often caused by my own doing; therefore, it is solvable by me without the help of others. I have to remove tasks from my workload through completing them or not taking as many on as I would like. In recent days, I have discovered a new thing that contributes to my depression - a lack of sunlight. Whereas this only affects those who live in the earth&#x27;s extremities, the solution is easily known - take Vitamin D.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to depression, one should not seek to self-diagnose or fix by one&#x27;s self. Depression is exaggerated when there is no one to help you. However, to this seemingly impossible season, the Bible is the source giver of hope:&lt;&#x2F;p&gt;
&lt;p&gt;&quot;There hath no temptation taken you but such as is common to man: but God is faithful, who will not suffer you to be tempted above that ye are able; but will with the temptation also make a way to escape, that ye may be able to bear it.&quot; (1 Cor 10:13 - memorize it if you have not already done so!)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If you are not currently going through a season of depression or anxiety, help someone who is.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&quot;And the Lord said,
Simon,
Simon,
behold,
Satan hath desired to have you,
that he may sift you as wheat:&lt;&#x2F;p&gt;
&lt;p&gt;But I have prayed for thee,
that thy faith fail not:
and when thou art converted,
strengthen thy brethren.&quot;
(Luke 22:31-32)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Ironic</title>
        <published>2023-01-18T07:07:40+00:00</published>
        <updated>2023-01-18T07:07:40+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2023-01-18-ironic/" type="text/html"/>
        <id>/2023-01-18-ironic/</id>
        
            <content type="html">&lt;p&gt;It is very ironic - to me at least - that when I visit drive.google.com on a Chromebook, I am presented with a notification to install Google drive.&lt;&#x2F;p&gt;
&lt;p&gt;This is a Chromebook.&lt;&#x2F;p&gt;
&lt;p&gt;Google apps are loaded by default.&lt;&#x2F;p&gt;
&lt;p&gt;This includes Google drive.&lt;&#x2F;p&gt;
&lt;p&gt;I just prefer the web experience over the native file explorer.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>2023 - Return to the Syndicated Stone age (RSSa)</title>
        <published>2022-12-28T08:53:04+00:00</published>
        <updated>2022-12-28T08:53:04+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2022-12-28-2023-return-to-the-syndicated-stone-age-rssa/" type="text/html"/>
        <id>/2022-12-28-2023-return-to-the-syndicated-stone-age-rssa/</id>
        
            <content type="html">&lt;p&gt;The new year has already been dubbed by some in the tech world as the year of RSS, meaning people will ditch social media for the consumption-style RSS feed. It is the same concept of switching from a smartphone to a mobile phone. You might be thinking, &quot;Why would anyone go backwards in technology?&quot; Everyone may have their own reasons for doing so, but mine is simply because of the social media trap.&lt;&#x2F;p&gt;
&lt;p&gt;The past few months I have noticed a personal, increased social media presence. I would have my app open 7 or 8 times a day, and because of the algorithms to keep me in the app longer, this would equate to 4 or 5 hours a day. I was managing to keep my studies, work, and family life balanced so I do not feel as if I have somehow lost that time or that I am wrong for spending that spare time on social media. It is just that 4 or 5 hours can be a bit excessive for a single particular hobby.&lt;&#x2F;p&gt;
&lt;p&gt;One of the items I have learned through osmosis is that having regularly scheduled checkpoints to evaluate my personal life is important. Just like the feedback loop in software engineering presents a better product, a feedback loop in daily life is just as important. Software engineering says the feedback loop should be the shortest possible to completion; however, my feedback loop is every 3 months. This gives me enough time to cycle through and evaluate how I am doing without changing too rapidly. This last iteration, ending in September, allowed me to gather the data to know I was spending about 24 hours a week on social media.&lt;&#x2F;p&gt;
&lt;p&gt;This current iteration was filled with thoughts of, &quot;I know I need to do something, but what!?&quot; However, when Elon Musk bought Twitter, everyone scrambled off of it to their own respective platforms. It was then I remembered that a solution exists in the form of RSS. The content I want to view and consume is retrieved without the help of a company&#x27;s algorithm of keeping me on their platform.&lt;&#x2F;p&gt;
&lt;p&gt;I settled for &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nkanaev&#x2F;yarr&quot;&gt;Yarr&lt;&#x2F;a&gt; as my feed reader and &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RSS-Bridge&#x2F;rss-bridge&quot;&gt;RSS-Bridge&lt;&#x2F;a&gt; for middleware when RSS feeds were not available. I am hosting these apps in my Kubernetes homelab and am using Github OAuth for authentication. While I have only tested this option for several weeks now, it seems to have kept me out of the algorithm octopus. Preliminary observations have shown 3-5 more hours for other hobbies - such as sleep, books, video games, blog posts, and other silly stuff that is interesting to me alone.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>I think I will keep LastPass</title>
        <published>2022-12-24T15:22:18+00:00</published>
        <updated>2022-12-24T15:22:18+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2022-12-24-i-think-i-will-keep-lastpass/" type="text/html"/>
        <id>/2022-12-24-i-think-i-will-keep-lastpass/</id>
        
            <content type="html">&lt;p&gt;LastPass was recently hacked and the hacker was able to steal keys from a developer which had access to the company&#x27;s backup files. In the backup files, the hacker could use the decryption keys he stole from the developer to create something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;somesite.com,&amp;lt;plaintext_username&amp;gt;,&amp;lt;hashed_password&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I can assume my data has been leaked. I am a LastPass user; however, I do not think this is good reason for my departure from LastPass.&lt;&#x2F;p&gt;
&lt;p&gt;This is not the first time a hacker was able to get this sort of information from LastPass. I was also a LastPass user during that time and my passwords were never compromised after than hack. The Zero-knowledge password storing employed by LastPass seems to have worked in the past, and I anticipate it being sufficient again.&lt;&#x2F;p&gt;
&lt;p&gt;As a safety precaution, I went ahead and changed my financial passwords, but other than that step, is there anything else that needs to be done? Perhaps I will change my Master password once more. If LastPass gets hacked again, at least all my SHAs will be different.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Incarnation Haiku</title>
        <published>2022-12-17T09:37:18+00:00</published>
        <updated>2022-12-17T09:37:18+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2022-12-17-incarnation-haiku/" type="text/html"/>
        <id>/2022-12-17-incarnation-haiku/</id>
        
            <content type="html">&lt;p&gt;God became a man.
He experienced life.
A life without sin.&lt;&#x2F;p&gt;
&lt;p&gt;He, unworthily,
Received punishment for sin.
God the Son had died.&lt;&#x2F;p&gt;
&lt;p&gt;Three days have now passed.
And Jesus did not stay dead
He came back to life.&lt;&#x2F;p&gt;
&lt;p&gt;It was His power.
Without the help of others.
Life came back to Him.&lt;&#x2F;p&gt;
&lt;p&gt;By resurrection,
Jesus says, “Place trust in me.”
“I make all things new.”&lt;&#x2F;p&gt;
&lt;p&gt;This event declares
And even more loudly proclaims
Flawless victory.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Impossible to define</title>
        <published>2022-12-07T09:36:03+00:00</published>
        <updated>2022-12-07T09:36:03+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2022-12-07-impossible-to-define/" type="text/html"/>
        <id>/2022-12-07-impossible-to-define/</id>
        
            <content type="html">&lt;p&gt;It is impossible to define a complex thought with one sentence. Even the previous sentence demands further information. What kind of thoughts do I mean? What is the reasoning for saying such a thing? Context adds further information to the reasoning behind such a statement. It also sets the stage for the real reason for the statement or provokes further thought.&lt;&#x2F;p&gt;
&lt;p&gt;If one considers the previous paragraph to be accurate in its message, then one should not settle for a single verse to explain a complex doctrine, such as salvation.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Asking ChatGPT to define love</title>
        <published>2022-12-06T11:25:44+00:00</published>
        <updated>2022-12-06T11:25:44+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2022-12-06-asking-chatgpt-to-define-love/" type="text/html"/>
        <id>/2022-12-06-asking-chatgpt-to-define-love/</id>
        
            <content type="html">&lt;p&gt;As programmers develop new text generation methods, what can come as a result is interesting. Recently, ChatGPT responses have been propagating to Twitter, with many asking the AI text generator for common paradigms with known human solutions. Some posts have been insightful about how the chatbot was instructed to learn and associate words. However, to those who have programmed AI models, the shortcomings are apparent, and there is no immediate threat of a robot uprising. Currently, many perceived issues are corrected by inputting the correct wording to the chatbot, indicating the idiom, garbage in - garbage out, is still valid.&lt;&#x2F;p&gt;
&lt;p&gt;I was interested in asking the ChatGPT to clarify the love quality found in John 3:16.&lt;&#x2F;p&gt;
&lt;p&gt;Love is an emotion that is, in Christian circles, attributed to different levels or types of love. One can have a love for a sports team, a love for a spouse, and a love for chocolate. However, these types of love vary based on each object and the love holder.&lt;&#x2F;p&gt;
&lt;p&gt;In English, we would use the same word for love to describe the varying emotion, but in other languages, the varying degrees are expressed in different word choices. It is common for Bible preachers to equate Greek word choices with varying forms of love, such as in the dialog between Peter and Jesus in John 21. (Although Carson has made good dialog into overthrowing this perceived relation.&lt;sup&gt;1&lt;&#x2F;sup&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;My recent study of the Greek text in John 3:16 revealed a language barrier between what is written in Greek and what is translated into English. When written, love was given a form without English verb equivalency. It is translated in the English past tense, which offers a sense of something performed in previous times, but does not apply to today. However, as John wrote in Greek, the phrasal action exists in an eternal state.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps ChatGPT could describe this immeasurable amount of love:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2022&#x2F;12&#x2F;gnome-shell-screenshot-6xv4gg.png&quot;&gt;&lt;img src=&quot;&#x2F;2022&#x2F;12&#x2F;gnome-shell-screenshot-6xv4gg.png&quot; alt=&quot;ChatGPT trying to express love by stating: Ultimately, the best way to express an immeasurable amount of love is to show it through your actions, and to make the other person feel loved and valued.&quot; title=&quot;ChatGPT question&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The response is what you would expect of popular psychology, being there for a person regardless of the circumstance. The fallacy of this thought is easily identified in a situation where the one you love has escaped from prison. In that instance, supporting them would require you to harbor a known fugitive - an act punishable by US law. It is also impossible to be supportive of everyone&#x27;s actions at all times. Can immeasurable love be shown to groups that have contrary opinions? However, this type of love is expressed in John 3:16.&lt;&#x2F;p&gt;
&lt;p&gt;God&#x27;s love is an immeasurable amount of love, which has lasting effects that continually build up. The potency by which God shows His love is presented through its conceptualization and increasing exponential power, which began in eternity past. In essence, God&#x27;s love will continually build upon the foundation until the recipient has no more room to receive it. At this point, God&#x27;s love is exponentially more.&lt;&#x2F;p&gt;
&lt;p&gt;The very nature of God’s love felt for the world is signified by this thought: God expressed it in giving the most prized possession He had - His only begotten Son. The power and intensity by which God loves are based on the virtue of Jesus Christ.&lt;&#x2F;p&gt;
&lt;p&gt;God so loved; therefore, He gave.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;sup&gt;1 &lt;&#x2F;sup&gt;D. A. Carson, &lt;em&gt;Exegetical Fallacies&lt;&#x2F;em&gt;, 2nd ed. (Grand Rapids, MI: Baker Books, 2013). 51-53.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Back to the blogs</title>
        <published>2022-11-22T10:36:04+00:00</published>
        <updated>2022-11-22T10:36:04+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2022-11-22-back-to-the-blogs/" type="text/html"/>
        <id>/2022-11-22-back-to-the-blogs/</id>
        
            <content type="html">&lt;p&gt;The painfully slow death of social media is pushing the masses back into our blog-o-spheres. In 2 years, the only people doing social media will be those who are not technical enough to click a one-button wordpress&#x2F;ghost install and pay $5&#x2F;month from a hosting provider.
Of course, there will be the faithful few who still insist that Markdown is the way to go.&lt;&#x2F;p&gt;
&lt;p&gt;For now, I want to experiment and see how a &quot;status&quot; post format works.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>ReMarkable 2 Review</title>
        <published>2021-04-02T22:22:45+00:00</published>
        <updated>2021-04-02T22:22:45+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2021-04-02-remarkable-2-review/" type="text/html"/>
        <id>/2021-04-02-remarkable-2-review/</id>
        
            <content type="html">&lt;p&gt;At first glance, the reMarkable seemed expensive for a one show pony. Replacing a pad of paper for notes was its only selling point and truly main focus. Could it really fit my use case and deliver an experience I needed?&lt;&#x2F;p&gt;
&lt;p&gt;As one who regularly types notes and prints them for use in public speaking, I sought out a replacement for physical paper. I had multiple copies of notes, printed quite regularly, and often would get copies confused. In my flow, I numbered the pages as to not get them confused which order they were to be referred. I reprinted each time a correction to the notes or if the paper withered due to use. This seemed like a huge waste of paper. (At $.05 estimated per sheet of paper, 10 pages of notes would cost approximately $2 by the time I was finished.)&lt;&#x2F;p&gt;
&lt;p&gt;I first started using my Kindle Paperwhite as a replacement to printing. I could easily send myself a PDF and have it appear on my Kindle. Over time I realized the screen was perfect for the lighting environments where I routinely looked at my notes - a pulpit. It was like having my notes printed, but without the glare of an LED from a tablet. One flaw of the Kindle stood out: while it was the perfect size for reading a book, it was too small for reading full sized PDF documents at a distance. I learned that I had to type &quot;convert&quot; in the subject line of each PDF email sent to my Kindle. This allowed better font viewing, but my formatting would not appear the way I needed it to.&lt;&#x2F;p&gt;
&lt;p&gt;When I first saw the reMarkable, it looked like it would alleviate my two concerns. Once I received my remarkable (thank you, stimulus money), I was able to import a few PDFs and view them as full-sized on the glare-free e-ink display. The formatting was also exactly as I set it in my word processor. Everything seemed as if it was going to be perfect; however, the reMarkable had one flaw - it does not have a typing program. Yes, it does have an on-screen keyboard for filling out items such as filenames, emails, and others, but if you want to word process, you have to manually write out the letters. While this is good for hand-written note takers, this threw a wrench in my workflow. I could not use the reMarkable as an all-inclusive document processor to where I would no longer need to type on a computer. (To reMarkable&#x27;s credit, they did not market the device as such, but I was erroneously thinking there would be some sort of typing application included.)&lt;&#x2F;p&gt;
&lt;p&gt;After some reviewing my workflow of typing my document in GSuite, saving it as PDF, and uploading it to the reMarkable, I figured this required too much effort to get something on the reMarkable. There had to be an easier way - considering I would update my typed document quite frequently. Looking for options, I was able to find the &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bsdz&#x2F;google-drive-remarkable-sync&quot;&gt;google-drive-sync&lt;&#x2F;a&gt; script and &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bsdz&#x2F;google-drive-remarkable-sync&#x2F;pull&#x2F;11&quot;&gt;extend it to include Documents and convert them to PDFs.&lt;&#x2F;a&gt; My workflow now is as follows:&lt;&#x2F;p&gt;
&lt;p&gt;I. I type a document into GSuite
2. It syncs to remarkable cloud and my device
3. I copy the file to a local folder, make annotations in the process of reviewing
4. I update the file on GSuite
5. Repeat from step 2&lt;&#x2F;p&gt;
&lt;p&gt;I still have a few flaws to work out with the sync, but it works for now.&lt;&#x2F;p&gt;
&lt;p&gt;As for the other aspect of the reMarkable - note taking and eBook reading, I have to say, that I quite enjoy the experience. Jotting down a to-do list, quickly putting thoughts down (instead of waiting for a note app to boot on a phone or computer), and notating on top of eBooks have been a breeze. The experience is just like using paper, and for one who can detect lag from a stylus, I cannot tell that I am using one.&lt;&#x2F;p&gt;
&lt;p&gt;For a device that is marketed as replacing paper notes, it does quite well. My use case is also satisfied with some modifications that I have made. Overall, I am satisfied in the purchase and 2 year break-even point.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Use the same Dockerfile - please</title>
        <published>2019-08-21T16:20:23+00:00</published>
        <updated>2019-08-21T16:20:23+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2019-08-21-use-the-same-dockerfile-please/" type="text/html"/>
        <id>/2019-08-21-use-the-same-dockerfile-please/</id>
        
            <content type="html">&lt;p&gt;As Containers have progressed, Docker has stood out as the defacto standard. As many of the laggards are coming up to speed, Dockerfiles can be seen in many open source repositories. With the addition to that, I have seen a few repos with a &lt;code&gt;Dockerfile-prod&lt;&#x2F;code&gt;, &lt;code&gt;Dockerfile-dev&lt;&#x2F;code&gt;, &lt;code&gt;Dockerfile-test&lt;&#x2F;code&gt;, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, you find an IF clause in the &lt;code&gt;CMD&lt;&#x2F;code&gt; statement such as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;CMD if [ &amp;quot;$REACT_NODE_ENV&amp;quot; = &amp;quot;development&amp;quot; ]; \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  then yarn dev;  \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  else yarn build &amp;amp;&amp;amp; yarn start --only=production; \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To those repositories, I have one daunting question:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;WHY?&lt;&#x2F;h2&gt;
&lt;p&gt;Container start commands can be overwritten at run time. Here is how to do it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Dockerfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;FROM alpine:3.6
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;CMD echo &amp;quot;production start command&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# docker-compose.yml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;version: &amp;#39;3&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;services:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  dev-server:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    build: .
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    command: echo &amp;#39;development start command&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# kubernetes-deployment.yml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: apps&#x2F;v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: Deployment
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: cool-app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: cool-app-testing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: cool-app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  replicas: 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  selector:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    matchLabels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      app: cool-app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  template:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        app: cool-app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      containers:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - name: cool-app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        image: alpine:3.6
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        command:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - echo
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        - &amp;#39;testing start command&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>WordPress Containerization Boilerplate</title>
        <published>2018-11-29T15:17:59+00:00</published>
        <updated>2018-11-29T15:17:59+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-11-29-wordpress-containerization-boilerplate/" type="text/html"/>
        <id>/2018-11-29-wordpress-containerization-boilerplate/</id>
        
            <content type="html">&lt;p&gt;As a step further to my previous post, I have created a boilerplate for future WordPress projects. It can be accessed at &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;WordPress-Containerization-Boilerplate&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;WordPress-Containerization-Boilerplate&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To quickly start a WordPress environment, simply run the following commands:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;git clone git@github.com:andrewwippler&#x2F;WordPress-Containerization-Boilerplate.git
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cd WordPress-Containerization-Boilerplate&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;docker-compose up
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and by visiting &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;localhost:8080&quot;&gt;http:&#x2F;&#x2F;localhost:8080&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;More instructions are in the repo README.&lt;&#x2F;p&gt;
&lt;p&gt;Happy Plugin&#x2F;Theme development.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Docker-izing WordPress for Kubernetes</title>
        <published>2018-11-27T20:16:55+00:00</published>
        <updated>2018-11-27T20:16:55+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-11-27-docker-izing-wordpress-for-kubernetes/" type="text/html"/>
        <id>/2018-11-27-docker-izing-wordpress-for-kubernetes/</id>
        
            <content type="html">&lt;p&gt;WordPress is amazingly popular considering how antiquated the file structure and code appears to be. Even still, it is the easiest CMS that I have used and the community has created plugins to make the copy-folder-for-a-new-theme&#x2F;plugin at least tolerable. A challenge comes when one wants to use the 1990&#x27;s method of serving web applications in a more modern way (such as running inside a container on top of Kubernetes).&lt;&#x2F;p&gt;
&lt;p&gt;Containers are meant to be immutable and treated as read-only. (No change to files in the container after they are built.) Containers are supposed to be a point-in-time release of software. As such, I can roll-back to a specific container version and have that specific code running. This causes a problem when one wants to use a file-dependent application such as WordPress. The best I could come up with for running WordPress in a container is a forward-only method of deploying code (basically, giving up the ability to use a previous version of code.) There &lt;strong&gt;is&lt;&#x2F;strong&gt; a way to keep that functionality, but it would mean storing everything (including uploads) inside an ever-growing container or using a central object store such as S3 for uploads. It would also require a re-build of the container every time a plugin is updated - which would presumably be every hour.&lt;&#x2F;p&gt;
&lt;p&gt;My deployments of WordPress are so little that I can hardly justify using S3 for uploads, keeping the plugins in sync, and going backwards in time.&lt;&#x2F;p&gt;
&lt;p&gt;When deploying to Kubernetes, one can scale the replicas to N copies. Keeping plugins, themes, and updates the same across all replicas will require a READ WRITE MANY (rwx) volume to be shared. This could be a GlusterFS volume or NFS, but it cannot be a AWS EBS volume or any other single-use block storage.&lt;&#x2F;p&gt;
&lt;p&gt;When looking at the available WordPress images, there are three that seem interesting. With the official image, I like that I can use php-fpm and alpine. The next top two implementations of WordPress have &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;r&#x2F;bitnami&#x2F;wordpress&#x2F;~&#x2F;dockerfile&#x2F;&quot;&gt;very&lt;&#x2F;a&gt; &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;r&#x2F;centurylink&#x2F;wordpress&#x2F;~&#x2F;dockerfile&#x2F;&quot;&gt;bloated&lt;&#x2F;a&gt; docker files. I have come to the conclusion that my WordPress container will have to be built from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.githubusercontent.com&#x2F;andrewwippler&#x2F;9b62322d3dff2ddd3b1890ae0a22a17c&#x2F;raw&#x2F;ee25ecc4abf5dd0f9a2170c8bca19a244fbf9a72&#x2F;Dockerfile&quot;&gt;Dockerfile&lt;&#x2F;a&gt; is very similar to the official WordPress container. It uses &lt;code&gt;php:7.2-fpm-alpine&lt;&#x2F;code&gt; as the base image, adds in nginx, and inserts a generic &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.githubusercontent.com&#x2F;andrewwippler&#x2F;9b62322d3dff2ddd3b1890ae0a22a17c&#x2F;raw&#x2F;ee25ecc4abf5dd0f9a2170c8bca19a244fbf9a72&#x2F;wp-config.php&quot;&gt;wp-config.php&lt;&#x2F;a&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;The folder structure for the container is as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;WordPress Container Folder
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;├── docker-entrypoint.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;├── Dockerfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;├── html
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;│   └── ... Contents of wordpress-X.Y.Z.zip
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;├── nginx.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;└── wp-config.php
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It can be built by running a command similar to &lt;code&gt;docker build -t andrewwippler&#x2F;wordpress:latest .&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.githubusercontent.com&#x2F;andrewwippler&#x2F;9b62322d3dff2ddd3b1890ae0a22a17c&#x2F;raw&#x2F;ee25ecc4abf5dd0f9a2170c8bca19a244fbf9a72&#x2F;nginx.conf&quot;&gt;nginx.conf&lt;&#x2F;a&gt; is a very basic configuration file with gzip and cache headers. The real neat things come in the &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.githubusercontent.com&#x2F;andrewwippler&#x2F;9b62322d3dff2ddd3b1890ae0a22a17c&#x2F;raw&#x2F;ee25ecc4abf5dd0f9a2170c8bca19a244fbf9a72&#x2F;docker-entrypoint.sh&quot;&gt;docker-entrypoint.sh&lt;&#x2F;a&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;I &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;docker-library&#x2F;wordpress&#x2F;blob&#x2F;443eb3028423485fdf3943250db5609f3f37afbe&#x2F;php7.0&#x2F;fpm-alpine&#x2F;docker-entrypoint.sh#L218-L257&quot;&gt;borrowed&lt;&#x2F;a&gt; the database creation script; however, since PHP was already installed in the container, I ran a few more checks in PHP rather than bash. For instance, the container places the local code in &lt;code&gt;&#x2F;var&#x2F;www&#x2F;html-original&lt;&#x2F;code&gt; and rsyncs it to &lt;code&gt;&#x2F;var&#x2F;www&#x2F;html&lt;&#x2F;code&gt; where the webserver sees it, but it only does this if the code in &lt;code&gt;html-original&lt;&#x2F;code&gt; is newer than &lt;code&gt;html&lt;&#x2F;code&gt;. This allows an operator to mount a storage volume at &lt;code&gt;&#x2F;var&#x2F;www&#x2F;html&lt;&#x2F;code&gt; which can be shared across Kubernetes Deployment replicas. The code for this is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; see if we need to copy files over
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include &amp;#39;&#x2F;var&#x2F;www&#x2F;html-original&#x2F;wp-includes&#x2F;version.php&amp;#39;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$dockerWPversion = $wp_version;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if (file_exists(&amp;#39;&#x2F;var&#x2F;www&#x2F;html&#x2F;wp-includes&#x2F;version.php&amp;#39;)) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    include &amp;#39;&#x2F;var&#x2F;www&#x2F;html&#x2F;wp-includes&#x2F;version.php&amp;#39;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    $installedWPversion = $wp_version;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;} else {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    $installedWPversion = &amp;#39;0.0.0&amp;#39;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fwrite($stderr, &amp;quot;dockerWPversion: $dockerWPversion - installedWPversion: $installedWPversion\n&amp;quot;);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if(version_compare($dockerWPversion, $installedWPversion, &amp;#39;&amp;gt;&amp;#39;)) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    fwrite($stderr, &amp;quot;Installing wordpress files\n&amp;quot;);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    exec(&amp;#39;rsync -au &#x2F;var&#x2F;www&#x2F;html-original&#x2F; &#x2F;var&#x2F;www&#x2F;html&amp;#39;);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have also included a theme-only check that will update the theme if it has changed. This is necessary to update the theme files when the version of WordPress has not changed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if (filemtime(&amp;#39;&#x2F;var&#x2F;www&#x2F;html-original&#x2F;wp-content&#x2F;themes&amp;#39;) &amp;gt; filemtime(&amp;#39;&#x2F;var&#x2F;www&#x2F;html&#x2F;wp-content&#x2F;themes&amp;#39;)) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    fwrite($stderr, &amp;quot;Updating theme files\n&amp;quot;);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    exec(&amp;#39;rsync -au --delete-after &#x2F;var&#x2F;www&#x2F;html-original&#x2F;wp-content&#x2F;themes&#x2F; &#x2F;var&#x2F;www&#x2F;html&#x2F;wp-content&#x2F;themes&amp;#39;);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All files I have referenced in this article are&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;andrewwippler&#x2F;9b62322d3dff2ddd3b1890ae0a22a17c&quot;&gt; located in a gist&lt;&#x2F;a&gt;. In addition to those files a local docker-compose.yml file might be helpful for your local development:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;version: &amp;#39;2&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;services:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  db:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    image: mariadb:10
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    volumes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - .&#x2F;tmp&#x2F;db:&#x2F;var&#x2F;lib&#x2F;mysql
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    environment:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - MYSQL_ROOT_PASSWORD=secretPASS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  wordpress:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    build: wordpress
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    volumes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - .&#x2F;html:&#x2F;var&#x2F;www&#x2F;html
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - .&#x2F;nginx.conf:&#x2F;etc&#x2F;nginx&#x2F;nginx.conf:ro
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    links:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - db
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    environment:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - WORDPRESS_DB_NAME=wordpress
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - WORDPRESS_DB_HOST=db
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - WORDPRESS_DB_USER=root
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - WORDPRESS_DB_PASSWORD=secretPASS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ports:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      - 8080:80
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Kubernetes: Heapster to Metrics Server</title>
        <published>2018-07-09T13:58:16+00:00</published>
        <updated>2018-07-09T13:58:16+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-07-09-kubernetes-heapster-to-metrics-server/" type="text/html"/>
        <id>/2018-07-09-kubernetes-heapster-to-metrics-server/</id>
        
            <content type="html">&lt;p&gt;I recently updated my kubernetes cluster from &lt;code&gt;1.10.2&lt;&#x2F;code&gt; to &lt;code&gt;1.11.0&lt;&#x2F;code&gt;. I noticed heapster was being deprecated and completely removed by version &lt;code&gt;1.13.0&lt;&#x2F;code&gt;. I thought this would be the perfect time to try out metrics-server. I had to download the git repo to apply the kubernetes yaml to my cluster. Since this is sometimes not as ideal as I would like, (I prefer &lt;code&gt;kubectl apply -f http:&#x2F;&#x2F;&lt;&#x2F;code&gt; when it comes from a trusted source) I am writing the below for easy access in the future:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;auth-delegator.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;auth-reader.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;metrics-apiservice.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;metrics-server-deployment.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;metrics-server-service.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kubectl apply -f https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;kubernetes-incubator&#x2F;metrics-server&#x2F;master&#x2F;deploy&#x2F;1.8%2B&#x2F;resource-reader.yaml
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: this is for clusters running v1.8.0 or greater.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Jenkins-x on home kubernetes cluster</title>
        <published>2018-06-06T12:15:42+00:00</published>
        <updated>2018-06-06T12:15:42+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-06-06-jenkins-x-on-home-kubernetes-cluster/" type="text/html"/>
        <id>/2018-06-06-jenkins-x-on-home-kubernetes-cluster/</id>
        
            <content type="html">&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jenkins-x.io&quot;&gt;Jenkins-x&lt;&#x2F;a&gt; appears to be the next big thing in CI&#x2F;CD workflows - especially if you develop applications on kubernetes. There were a few tweaks I needed to do to set it up:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I had to manually create Persistent Volumes (no big deal, below are what I have for my NFS share)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-chartmuseum
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-chartmuseum
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 100Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-chartmuseum&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-docker-registry
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-docker-registry
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-docker-registry&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-mongodb
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-mongodb
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-mongodb&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;---
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;apiVersion: v1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kind: PersistentVolume
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;metadata:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  name: jenkins-x-nexus
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  namespace: jx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  labels:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    app: jenkins-x-nexus
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spec:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  capacity:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    storage: 30Gi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  accessModes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    - ReadWriteOnce
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nfs:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server: 192.168.0.101
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path: &amp;quot;&#x2F;volume1&#x2F;k8s&#x2F;jenkins&#x2F;jenkins-x-nexus&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I had to modify the install line&lt;code&gt;jx install --ingress-namespace ingress-nginx --domain wplr.rocks --tls-acme true --skip-ingress&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I had to modify the &lt;code&gt;jenkins-x-mongodb&lt;&#x2F;code&gt; deployment to use image &lt;code&gt;mongo:3.6.5-jessie&lt;&#x2F;code&gt;. Still wonder why people use bitnami images.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I had to&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;securityContext:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  runAsUser: 1024
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;on the &lt;code&gt;jenkins-x-nexus&lt;&#x2F;code&gt; deployment. The container was trying to change permissions on my nfs mount. Not sure why my Synology NFS does not like permission changes.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Even after those changes, &lt;code&gt;jenkins-x-monocular-ui&lt;&#x2F;code&gt; still fails to start -_- ... I have run out of time for now. More debugging to come later (MUCH MUCH later)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>DHCP IP updater</title>
        <published>2018-04-04T16:17:19+00:00</published>
        <updated>2018-04-04T16:17:19+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-04-04-dhcp-ip-updater/" type="text/html"/>
        <id>/2018-04-04-dhcp-ip-updater/</id>
        
            <content type="html">&lt;p&gt;This is the script I use to change the DNS record of my home IP when it changes. I have it running once a week and have not noticed a lapse in coverage. If your ISP has DHCP configured correctly, you will receive the same IP address when you are due for a renew. Otherwise you need a script like the one below.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;ruby
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;require &amp;#39;aws-sdk&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;require &amp;#39;socket&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;def my_first_public_ipv4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  Socket.ip_address_list.detect{|intf| intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast? and !intf.ipv4_private?}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ip = my_first_public_ipv4.ip_address
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;unless ip.nil?
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;change = {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  :action =&amp;gt; &amp;#39;UPSERT&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  :resource_record_set =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    :name =&amp;gt; &amp;quot;home.andrewwippler.com&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    :type =&amp;gt; &amp;quot;A&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    :ttl =&amp;gt; 600,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    :resource_records =&amp;gt; [{:value =&amp;gt; ip}]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;route53 = Aws::Route53::Client.new(
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    region: &amp;#39;us-east-1&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;route53.change_resource_record_sets({
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  hosted_zone_id: &amp;#39;&#x2F;hostedzone&#x2F;XXXXXXXXXXXXXXX&amp;#39;, # required
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  change_batch: { # required
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    changes: [change],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  },
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;})
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;end
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Allowing outside access to Home Kubernetes Cluster</title>
        <published>2018-04-03T15:36:25+00:00</published>
        <updated>2018-04-03T15:36:25+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-04-03-allowing-outside-access-to-home-kubernetes-cluster/" type="text/html"/>
        <id>/2018-04-03-allowing-outside-access-to-home-kubernetes-cluster/</id>
        
            <content type="html">&lt;p&gt;After I created a home kubernetes cluster, I immediately wanted to allow external access to pods&#x2F;services&#x2F;ingresses hosted inside the cluster. One must be aware that in bare metal environments, there is no receiver of an api call to create a load balancer. Since there is not a scriptable environment available to kubernetes, kubernetes cannot request external IP addresses or provision resources that one has come to expect in cloud environments such as AWS. This is a huge bummer - especially since dynamically built environments are fun to have.&lt;&#x2F;p&gt;
&lt;p&gt;To route traffic to web services inside of kubernetes, you have to options available: &lt;code&gt;ingress&lt;&#x2F;code&gt; and &lt;code&gt;service&lt;&#x2F;code&gt;. Services can be exposed via &lt;code&gt;NodePort&lt;&#x2F;code&gt;, &lt;code&gt;LoadBalancer&lt;&#x2F;code&gt;, or &lt;code&gt;ClusterIP&lt;&#x2F;code&gt;. In bare metal, &lt;code&gt;LoadBalancer&lt;&#x2F;code&gt; would never work (unless you coded your own API call to configure a load balancer outside of kubernetes). &lt;code&gt;ClusterIP&lt;&#x2F;code&gt; might work if you want to manage a routing table somewhere inside your network, and &lt;code&gt;NodePort&lt;&#x2F;code&gt; will work if you want to manage a port forwarding table on your router. None of these options are fun for home labs on bare metal. An &lt;code&gt;Ingress&lt;&#x2F;code&gt; is like a layer 7 firewall in that it reads the hostname and path of the incoming HTTP request and can route to applicable services. This works great for a dynamic environment where I am going to host multiple http endpoints.&lt;&#x2F;p&gt;
&lt;p&gt;The overall view of this traffic is going to be: &lt;code&gt;Internet&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;Router&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;k8s Ingress&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;k8s Service&lt;&#x2F;code&gt; &amp;gt; &lt;code&gt;Pod(s)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To create an ingress in kubernetes, you have to make it a &lt;code&gt;Service&lt;&#x2F;code&gt;. In cloud environments, the &lt;code&gt;Ingress&lt;&#x2F;code&gt; is created as type &lt;code&gt;LoadBalancer&lt;&#x2F;code&gt; in home labs, we create this as type &lt;code&gt;NodePort&lt;&#x2F;code&gt; and port forward on the router to any node in the kubernetes cluster.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl get svc -n ingress-nginx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;default-http-backend   ClusterIP   10.102.173.184           80&#x2F;TCP                       3d
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ingress-nginx          NodePort    10.110.162.247           80:30746&#x2F;TCP,443:32641&#x2F;TCP   3d
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my home lab, I am port forwarding on my router &lt;code&gt;0.0.0.0:80 -&amp;gt; &amp;lt;any_node&amp;gt;:30746&lt;&#x2F;code&gt; and &lt;code&gt;0.0.0.0:443 -&amp;gt; &amp;lt;any_node&amp;gt;:32641&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Since I have a non-traditional home router (a Linux &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;2EeaCDu&quot;&gt;server with two nics&lt;&#x2F;a&gt;), I had to either enter these into &lt;code&gt;iptables&lt;&#x2F;code&gt; or I could improve upon that by setting up a load balancer such as &lt;code&gt;nginx&lt;&#x2F;code&gt;. &lt;code&gt;nginx&lt;&#x2F;code&gt; will allow me to port-forward load balance across all my nodes and have an easy config file to edit. Because I also want to use &lt;code&gt;cert-manager&lt;&#x2F;code&gt; with Let&#x27;s Encrypt free SSLs, I chose to use the TCP stream server of &lt;code&gt;nginx&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another hiccup (so to speak) in home based labs, is that ISPs give DHCP addresses. So when my internet IP changes, I need to update the DNS of all my http endpoints. Rather than doing that, I have all my home urls (&lt;code&gt;*.wplr.rocks&lt;&#x2F;code&gt;) CNAME to a single hostname which I update with a script with the correct IP.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Home Kubernetes cluster</title>
        <published>2018-04-02T15:26:52+00:00</published>
        <updated>2018-04-02T15:26:52+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-04-02-home-kubernetes-cluster/" type="text/html"/>
        <id>/2018-04-02-home-kubernetes-cluster/</id>
        
            <content type="html">&lt;p&gt;So I admit it - I am completely obsessed with Kubernetes. All of the web app&#x2F;api deployment challenges in the past 20 years have been somewhat solved with the Kubernetes orchestration and scheduling platform. Kubernetes brings fault-tolerance, and Highly available systems if set up correctly (i.e. use a Kubernetes cloud installer). I enjoy having the power to write yaml and apply it to infrastructure and it eventually becomes what I told it to be. No longer do I need to write the scripts to do it - it does it for me :)&lt;&#x2F;p&gt;
&lt;p&gt;In my first kubernetes home cluster, I re-used my home router and my old media center as a single node + master, but I was hit by a 2 year old Kubernetes bug. It appears my old PC was out in the open. Since my 2 year old son likes to press power buttons, he came over and constantly pressed the power button on my Kubernetes master. This caused me to find a small mini computer that I could place in my cabinet out of view. I finally settled on &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;2GsTRL3&quot;&gt;this as my computer of choice&lt;&#x2F;a&gt;. At $150&#x2F;each for 4 cores, 4GB RAM, and 32GB nve, I thought it was a good deal and ample to run a few containers per node with a nfs-backed storage array.&lt;&#x2F;p&gt;
&lt;p&gt;These little machines booted via UEFI pxe (after pressing DEL for bios and selecting the Realtek boot in the save&#x2F;exit page). I used this kickstart file which installed CentOS 7 minimal by passing in the &lt;code&gt;ks&lt;&#x2F;code&gt; argument to a CentOS initramfs:&lt;&#x2F;p&gt;
&lt;p&gt;After the servers installed, I ran this script:&lt;&#x2F;p&gt;
&lt;p&gt;Note: for one of the three machines I received, I had to put &lt;code&gt;modprobe br_netfilter&lt;&#x2F;code&gt; in &lt;code&gt;&#x2F;etc&#x2F;rc.local&lt;&#x2F;code&gt; before &lt;code&gt;&#x2F;etc&#x2F;sysctl.d&#x2F;k8s.conf&lt;&#x2F;code&gt; would apply.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Why Jesus and Easter Matters</title>
        <published>2018-03-31T08:00:31+00:00</published>
        <updated>2018-03-31T08:00:31+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-03-31-why-jesus-and-easter-matters/" type="text/html"/>
        <id>/2018-03-31-why-jesus-and-easter-matters/</id>
        
            <content type="html">&lt;p&gt;&lt;em&gt;There is a God and He loves you&lt;&#x2F;em&gt;. John 3:16 says, “For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life.”&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Everyone is a sinner&lt;&#x2F;em&gt; and our sin separates us from the love that God wants to express toward us “For all have sinned, and come short of the glory of God;” (Romans 3:23) “But your iniquities have separated between you and your God, and your sins have hid his face from you...” (Isaiah 59:2).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Jesus came to break down the barrier of sin.&lt;&#x2F;em&gt; “But God commendeth his love toward us, in that, while we were yet sinners, Christ died for us” (Romans 5:8).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The death of Jesus satisfied all the requirements&lt;&#x2F;em&gt;, but Jesus did not stay dead. Three days later - Easter morning, He arose from the grave by His own power. “He is not here: for he is risen, as he said.” (Matthew 28:6) “No man taketh it from me, but I lay it down of myself. I have power to lay it down, and I have power to take it again.”(John 10:18)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Having a relationship with God is not about being good or religious. It is claiming the work Jesus fulfilled on the cross.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Jesus said in John 6:47, “He that believeth on me hath everlasting life.”&lt;&#x2F;p&gt;
&lt;p&gt;Those who trust in Jesus are saved from the penalty and power of sin and will have eternal life in Heaven with God.&lt;&#x2F;p&gt;
&lt;p&gt;“For whosoever shall call upon the name of the Lord shall be saved” (Romans 10:13).&lt;&#x2F;p&gt;
&lt;p&gt;Place your trust in Jesus today.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Not posting as much</title>
        <published>2018-02-02T14:02:17+00:00</published>
        <updated>2018-02-02T14:02:17+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2018-02-02-not-posting-as-much/" type="text/html"/>
        <id>/2018-02-02-not-posting-as-much/</id>
        
            <content type="html">&lt;p&gt;I have not been posting as much tech stuff on my blog as I want to. The reason for this is I have been mulling about the idea of submitting my tutorials to a publication and get paid for my work. I still have not decided if this is the right course of action. Not that I have to explain myself with the readers of my blog - I just wanted something other than a Christmas post as my newest blog post :o&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Merry Christmas</title>
        <published>2017-12-25T15:00:49+00:00</published>
        <updated>2017-12-25T15:00:49+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-12-25-merry-christmas-2/" type="text/html"/>
        <id>/2017-12-25-merry-christmas-2/</id>
        
            <content type="html">&lt;p&gt;Merry Christmas from the Wippler family!&lt;&#x2F;p&gt;
&lt;p&gt;We pray that you are enjoying this season of celebration as we reflect upon our Saviour&#x27;s birth. Truly, for the Christian, Christ is the focal point of the season.&lt;&#x2F;p&gt;
&lt;p&gt;October was unusually mild and warm for Minnesota. Then on Friday, October 27, a snowstorm swept through our area dumping the highest one-day snowfall total ever recorded in Duluth since October 1933! Quite a rude awakening for this California family. However, we are loving the snow and are adjusting to the colder climate (although we&#x27;re told the worst is yet to come). Like today, when the high is going to be -10°F!&lt;&#x2F;p&gt;
&lt;p&gt;On the family side of things, it&#x27;s been a joy to watch the Lord work in Mollie&#x27;s life this past year--first with her salvation in June and then with her decision to be baptized 3 weeks ago. She has a tender heart, and we&#x27;re praying the Lord uses her greatly. On a humorous note, she decided yesterday she wanted to style her hair like &quot;mommy&#x27;s.&quot; While Nicole prepared lunch downstairs, Mollie was upstairs adjusting her hairstyle.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2017&#x2F;12&#x2F;IMG_20171222_135215883.jpg&quot;&gt;&lt;img src=&quot;&#x2F;2017&#x2F;12&#x2F;IMG_20171222_135215883.jpg&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, not too much damage was done, and the hairdresser informed us that having shorter layers in the front and longer in the back is the &quot;in&quot; look.&lt;&#x2F;p&gt;
&lt;p&gt;Meg turned 4 on November 7, while Clark celebrated his 3rd birthday on December 15! How time flies! Meg continues to astound us with her love of and ability to learn. She&#x27;s a thinker for sure: the other day during family devotions, Nicole asked her why Mary washed Jesus feet with her hair, hoping she&#x27;d say something along the lines of &quot;because she loved Jesus.&quot; Instead she responded with, &quot;because she didn&#x27;t have any towels.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Now that Jake&#x27;s gotten a little older, Clark and Jake have become car&#x2F;train playing buddies. It&#x27;s hilarious to watch them playing&#x2F;dragging their blankets together around the house. Both boys are becoming more articulate. After Clark fell on his face one day, Nicole teasingly said, &quot;Oh no! Your face has broken into 100 pieces. Let&#x27;s get some glue.&quot; With a panic stricken tone, Clark told Mollie, &quot;Get the glue, Mollie! Hurry! My face is broken!&quot; We&#x27;re truly blessed with 4 precious children!&lt;&#x2F;p&gt;
&lt;p&gt;Speaking of blessings, it&#x27;s been a tremendous blessing to see the Lord working in our church. At our annual Christmas dinner, we had many visitors with several making professions of salvation. The following Sunday morning we had our children&#x27;s Christmas program. The auditorium was filled, and several of our bus children had family in attendance. One little girl invited and saw her school mentor in attendance. We&#x27;re praying that many of these visitors will be saved, baptized, and then discipled in the upcoming months.&lt;&#x2F;p&gt;
&lt;p&gt;In closing, let us wish your family a Happy New Year! We truly appreciate your prayers as we seek to be faithful to the Lord and His calling upon our lives. You are in our thoughts and prayers as well.&lt;&#x2F;p&gt;
&lt;p&gt;Love,&lt;&#x2F;p&gt;
&lt;p&gt;Andrew and Nicole&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>kubernetes health check</title>
        <published>2017-12-08T15:00:22+00:00</published>
        <updated>2017-12-08T15:00:22+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-12-08-kubernetes-health-check/" type="text/html"/>
        <id>/2017-12-08-kubernetes-health-check/</id>
        
            <content type="html">&lt;p&gt;The day before thanksgiving, I was pondering an issue I was having. I was pinning a package to a specific version in my Docker container and the repository I grabbed it from stopped offering this specific version. This resulted in a container that Jenkins responded as being built correctly, but missing an integral package that allowed my application to function properly. This led me to believe I had to implement &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;puppet.com&#x2F;blog&#x2F;using-lumogon-inspect-your-containers&quot;&gt;Puppet&#x27;s Lumogon&lt;&#x2F;a&gt; in my Jenkins build process. Curious if anyone had something like this already developed, I headed over to github.com which eventually led me to compose this tweet:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Step 1: Have k8s technical problem
Step 2: Review &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;kelseyhightower?ref_src=twsrc%5Etfw&quot;&gt;@kelseyhightower&lt;&#x2F;a&gt;&#x27;s recent git pushes
Step 3: Find: &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;ato&#x2F;blob&#x2F;master&#x2F;deployments&#x2F;helloworld.yaml#L26-L29&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;ato&#x2F;blob&#x2F;master&#x2F;deployments&#x2F;helloworld.yaml#L26-L29&lt;&#x2F;a&gt;Step 4: Realize this is exactly something I needed to implement
Step 5: Implement feature
Step 6: Enjoy thanksgiving without worry
Step 7: Blog post&lt;&#x2F;p&gt;
&lt;p&gt;— Andrew J. Wippler (@AndrewWippler) &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;AndrewWippler&#x2F;status&#x2F;933413365837418498?ref_src=twsrc%5Etfw&quot;&gt;November 22, 2017&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; communicates with &lt;code&gt;kubeproxy&lt;&#x2F;code&gt; to either allow a pod to be in service or out of service. At first I thought the &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; was a once-and-done check, but I found out later this is not the case. When a pod gets launched, kubernetes waits until the container is in the ready state. We can define what consists of a ready container by the use of probes. Coupled with a kubernetes strategy, we can also define and ensure our application survives broken container updates.&lt;&#x2F;p&gt;
&lt;p&gt;Since the application I am supporting is already HTTP based, making an HTTP check to an endpoint that reports on connectivity to core services was the most trivial to implement. I created a script to verify connectivity to MariaDB, MongoDB, Memcached, Message Queue, and verified certain paths on the NFS share were present. All of these items are important to my application and most of them require certain configuration values in my containers to operate. Having kubernetes run this script every time there is a new pod verifies I will never an experience an outage due to a missing package again. As I mentioned before, I thought the &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; was a once-and-done, however, I found that after implementing it, my metrics indicated the script was running every 10 seconds per every replica... this quickly added up!&lt;&#x2F;p&gt;
&lt;p&gt;After some chatting in the #kubernetes-users slack, I was able to get more understanding of the &lt;code&gt;readinessProbe&lt;&#x2F;code&gt; and how it was designed to communicate with kubeproxy so that you could &quot;shut off&quot; a container by taking it out of rotation. This was not the behavior I wanted so it was suggested that I create a state file. This state file is created after the check and, if it is present, it skips all checks. Due to the ephemeral nature of container storage, it can be assumed this file will never exist on a pod where this check has not been performed.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Adding a user to k8s RBAC</title>
        <published>2017-12-01T15:00:36+00:00</published>
        <updated>2017-12-01T15:00:36+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-12-01-adding-a-user-to-k8s-rbac/" type="text/html"/>
        <id>/2017-12-01-adding-a-user-to-k8s-rbac/</id>
        
            <content type="html">&lt;p&gt;In order to add a user to a kubernetes cluster, we will need several things: kubectl, CA.crt and CA.key (found in your head node&#x27;s &lt;code&gt;&#x2F;etc&#x2F;kubernetes&#x2F;pki&lt;&#x2F;code&gt; folder), and openssl.&lt;&#x2F;p&gt;
&lt;p&gt;First, create a private key for the new user. In this example, we will name the file employee.key:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl genrsa -out employee.key 2048
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we will need to create a certificate sign request - employee.csr - using the private key we just created (employee.key in this example). Make sure to specify your username and group in the &lt;code&gt;-subj&lt;&#x2F;code&gt; section (CN is for the username and O for the group).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl req -new -key employee.key -out employee.csr -subj &amp;quot;&#x2F;CN=username&#x2F;O=developer&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Generate the final certificate employee.crt by approving the certificate sign request, employee.csr, you made earlier. In this example, the certificate will be valid for 90 days.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl x509 -req -in employee.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out employee.crt -days 90
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Give &lt;strong&gt;employee.crt&lt;&#x2F;strong&gt;, &lt;strong&gt;employee.key&lt;&#x2F;strong&gt;, and &lt;strong&gt;CA.crt&lt;&#x2F;strong&gt; to the new employee and have the employee follow the below steps.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set up the cluster
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl config set-cluster k8s.domain.tld --server https:&#x2F;&#x2F;api.k8s.domain.tld --certificate-authority &#x2F;path&#x2F;to&#x2F;CA.crt --embed-certs=true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set up the credentials (a.k.a login information)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl config set-credentials &amp;lt;name&amp;gt; --client-certificate=&#x2F;path&#x2F;to&#x2F;cert.crt --client-key=&#x2F;path&#x2F;to&#x2F;cert.key --embed-certs=true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# bind login to server
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$ kubectl config set-context k8s.domain.tld --cluster= k8s.domain.tld --user=&amp;lt;name&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Optional: append `--namespace=&amp;lt;namespace&amp;gt;` to the command to set a default namespace.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note&lt;&#x2F;em&gt;: You may move the certificates to a safe location since the commands included &lt;code&gt;--embed-certs=true&lt;&#x2F;code&gt;. This saved the certs in base64 format in the kubernetes config.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes I post to my blog so I remember how to do a particular thing. This is one of those times.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Reusable containers with confd</title>
        <published>2017-11-28T21:01:51+00:00</published>
        <updated>2017-11-28T21:01:51+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-11-28-reusable-containers-with-confd/" type="text/html"/>
        <id>/2017-11-28-reusable-containers-with-confd/</id>
        
            <content type="html">&lt;p&gt;I recently had the need to populate a file in a docker container based upon whether or not the container is in production or development. I eventually came across &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;confd&quot;&gt;confd&lt;&#x2F;a&gt; which let me populate data in files based upon particular environment variables. While confd excels with distributed key value stores, my needs (and infrastructure) is at a much simpler level.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;andrewwippler.com&#x2F;wp-content&#x2F;uploads&#x2F;2017&#x2F;11&#x2F;Screenshot-from-2017-11-28-14-07-15.png&quot;&gt;&lt;img src=&quot;&#x2F;2017&#x2F;11&#x2F;Screenshot-from-2017-11-28-14-07-15.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Confd requires a few folders to store a toml (&#x2F;etc&#x2F;confd&#x2F;conf.d&#x2F;) and a template file (&#x2F;etc&#x2F;confd&#x2F;templates&#x2F;). When confd runs, it will look at the contents of each toml file in the conf.d directory and process them according to their instructions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;blog-confd&quot;&gt;In my repository example&lt;&#x2F;a&gt;, I am wanting a container to say hello to me when it senses a NAME environment variable and print out the current datetime. If no environment variable is set, only the datetime is printed out. To do this, I must create the toml file &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;blog-confd&#x2F;blob&#x2F;master&#x2F;docker&#x2F;confd&#x2F;conf.d&#x2F;echo.toml&quot;&gt;to look like this&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[template]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;src = &amp;quot;echo.tmpl&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dest = &amp;quot;&#x2F;echo&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This file is instructing confd to generate the echo file, place it in the root (&#x2F;) and use &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;blog-confd&#x2F;blob&#x2F;master&#x2F;docker&#x2F;confd&#x2F;templates&#x2F;echo.tmpl&quot;&gt;&#x2F;etc&#x2F;confd&#x2F;templates&#x2F;echo.tmpl&lt;&#x2F;a&gt; as the contents.&lt;&#x2F;p&gt;
&lt;p&gt;When we are building the container, we must include these configuration files and ensure confd is ran to generate the destination file. My &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;blog-confd&#x2F;blob&#x2F;master&#x2F;Dockerfile&quot;&gt;example Dockerfile&lt;&#x2F;a&gt; is doing just that by including all of the files in the container and running the &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;blog-confd&#x2F;blob&#x2F;master&#x2F;docker&#x2F;docker-entrypoint.sh&quot;&gt;docker-entrypoint script&lt;&#x2F;a&gt; which is basically running confd and the newly generated file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; andrew@wipplerxps &amp;gt; ~&#x2F;git_repos&#x2F;confd $  docker build -t blog-confd .
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Sending build context to Docker daemon 57.34 kB
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 1&#x2F;9 : FROM centos:7.4.1708
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; 5076a7d1a386
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 2&#x2F;9 : LABEL maintainer &amp;quot;andrew.wippler@gmail.com&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; Using cache
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; d712b31f7449
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 3&#x2F;9 : RUN mkdir -p &#x2F;etc&#x2F;confd&#x2F;{conf.d,templates}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; Running in f340bdcdf973
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; 1f0faa9b962f
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container f340bdcdf973
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 4&#x2F;9 : COPY docker&#x2F;confd&#x2F; &#x2F;etc&#x2F;confd&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; fb16dffc63ac
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container 133128cb7fc1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 5&#x2F;9 : ADD https:&#x2F;&#x2F;github.com&#x2F;kelseyhightower&#x2F;confd&#x2F;releases&#x2F;download&#x2F;v0.14.0&#x2F;confd-0.14.0-linux-amd64 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Downloading 17.61 MB&#x2F;17.61 MB
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; a62b388274e6
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container 3f9ec343a5ab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 6&#x2F;9 : RUN chmod +x &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; Running in 1489dd02ea45
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; ab99a5fc5f95
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container 1489dd02ea45
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 7&#x2F;9 : COPY docker&#x2F;docker-entrypoint.sh &#x2F;var&#x2F;local&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; 16906971c8ef
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container 7a17a8e17e22
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 8&#x2F;9 : RUN chmod a+x &#x2F;var&#x2F;local&#x2F;docker-entrypoint.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; Running in 1562a6d06432
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; f963372159b1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container 1562a6d06432
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Step 9&#x2F;9 : ENTRYPOINT &#x2F;var&#x2F;local&#x2F;docker-entrypoint.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; Running in 1b7e12c38b4c
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ---&amp;gt; f7d260597e0a
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Removing intermediate container 1b7e12c38b4c
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Successfully built f7d260597e0a
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; andrew@wipplerxps &amp;gt; ~&#x2F;git_repos&#x2F;confd $  docker run blog-confd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:24Z 0931113b25f4 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Backend set to env
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:24Z 0931113b25f4 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Starting confd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:24Z 0931113b25f4 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Backend source(s) set to
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:24Z 0931113b25f4 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Target config &#x2F;echo out of sync
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:24Z 0931113b25f4 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Target config &#x2F;echo has been updated
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The current time is: Tue Nov 28 20:05:24 UTC 2017
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; andrew@wipplerxps &amp;gt; ~&#x2F;git_repos&#x2F;confd $  docker run -e NAME=&amp;quot;Andrew Wippler&amp;quot; blog-confd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:52Z 223f28e8d18f &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Backend set to env
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:52Z 223f28e8d18f &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Starting confd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:52Z 223f28e8d18f &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Backend source(s) set to
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:52Z 223f28e8d18f &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Target config &#x2F;echo out of sync
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;2017-11-28T20:05:52Z 223f28e8d18f &#x2F;usr&#x2F;local&#x2F;bin&#x2F;confd[7]: INFO Target config &#x2F;echo has been updated
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Hello Andrew Wippler
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The current time is: Tue Nov 28 20:05:34 UTC 2017
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; andrew@wipplerxps &amp;gt; ~&#x2F;git_repos&#x2F;confd $
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While it is fun to say hello to yourself once in a while, I am using confd to modify an nginx.conf. When I pass in the SSL environment variable, nginx will listen on port 443 with a self signed cert and forward all HTTP traffic to HTTPS. Obviously in production, I want to use a real SSL cert. Using confd allows me to have the same docker container in development and production - the only difference being a configuration change.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Old glory</title>
        <published>2017-10-12T14:14:56+00:00</published>
        <updated>2017-10-12T14:14:56+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-10-12-old-glory/" type="text/html"/>
        <id>/2017-10-12-old-glory/</id>
        
            <content type="html">&lt;p&gt;I was going through my articles I have collected over the years and found this little gem. The author is unknown.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;I AM THE FLAG OF THE
UNITED STATES OF AMERICA&lt;&#x2F;p&gt;
&lt;p&gt;I am the flag of the United States of America.
My name is Old Glory.
I fly atop the world&#x27;s tallest buildings.
I stand watch in America&#x27;s halls of justice.
I fly majestically over institutions of learning.
I stand guard with power in the world.
Look up and see me.&lt;&#x2F;p&gt;
&lt;p&gt;I stand for peace, honor, truth and justice.
I stand for freedom.
I am confident.
I am arrogant.
I am proud.&lt;&#x2F;p&gt;
&lt;p&gt;When I am flown with my fellow banners,
My head is a little higher,
My colors a little truer.&lt;&#x2F;p&gt;
&lt;p&gt;I bow to no one!
I am recognized all over the world.
I am worshipped - I am saluted.
I am loved - I am revered.
I am respected - and I am feared.&lt;&#x2F;p&gt;
&lt;p&gt;I have fought in every battle of every war
For more then 200 years.
I was flown at Valley Forge, Gettysburg,
Shiloh and Appomattox.
I was there at San Juan Hill,
The trenches of France,
In the Argonne Forest, Anzio, Rome
And the beaches of Normandy, Guam.
Okinawa, Korea and KheSan, Saigon, Vietnam&lt;&#x2F;p&gt;
&lt;p&gt;Know me,
I was there.
I led my troops,
I was dirty, battle worn and tired,
But my soldiers cheered me
And I was proud.
I have been burned, torn and trampled
On the streets of countries I have helped set free.
It does not hurt, for I am invincible.&lt;&#x2F;p&gt;
&lt;p&gt;I have been soiled upon, burned, torn
And trampled on the streets of my country.
And when it&#x27;s by those whom I&#x27;ve served in battle - it hurts.
But I shall overcome - for I am strong.&lt;&#x2F;p&gt;
&lt;p&gt;I have slipped the bonds of Earth
And stood watch over the uncharted frontiers of space
From my vantage point on the moon.
I have borne silent witness
To all of America&#x27;s finest hours.
But my finest hours are yet to come.&lt;&#x2F;p&gt;
&lt;p&gt;When I am torn into strips
And used as bandages
For my wounded comrades on the battlefield,
When I am flown at half-mast to honor my soldier,
Or when I lie in the trembling arms
Of a grieving parent
At the grave of their fallen son or daughter,
I am proud.&lt;&#x2F;p&gt;
&lt;p&gt;MY NAME IS OLD GLORY
LONG MAY I WAVE.
DEAR GOD IN HEAVEN
LONG MAY I WAVE.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Settling in</title>
        <published>2017-09-14T14:06:31+00:00</published>
        <updated>2017-09-14T14:06:31+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-09-14-settling-in/" type="text/html"/>
        <id>/2017-09-14-settling-in/</id>
        
            <content type="html">&lt;p&gt;It has been a month and a half since we moved, and we finally are on a set schedule. The girls have started school, all boxes are unpacked, our house in California closed escrow, and we have successfully adjusted to the CST time zone.&lt;&#x2F;p&gt;
&lt;p&gt;It always amazes me how much God has blessed my family. We are all in good health, we are debt free, we have a roof over our head, and we have food to eat. I can attribute this all to God as I have no control over my health, I am horrible when it comes to big financial matters (such as retirement savings, stock trading, etc.), and I am not the best at selecting the best food choices for myself. It is only through God&#x27;s providential guidance that I am in the state I am.&lt;&#x2F;p&gt;
&lt;p&gt;I have been able to go fishing twice since arriving. As a result, I caught 2 fish. Neither were big enough to keep, but it was a great experience to enjoy. It seems the best fishing out here is on a lake. As a result, one needs a boat to get to the middle of the lake. This has caused me to research fishing kayaks. It is doubtful I will get one for the 2017 season, but if I save enough money, I can definitely get one for the 2018 season :)&lt;&#x2F;p&gt;
&lt;p&gt;Being a bi-vocational Assistant Pastor is rather weird. It is a role I have not experienced for too long, but I am very excited for what God has in store. Since being here in Duluth, I have been able to share the gospel with several people and see one make a profession for Christ. It was neat to see the &quot;lightbulb&quot; appear when he understood that Jesus came to do all the work of salvation for us and that salvation is not dependent upon our good works or how we live. It is very sad that many people are trapped in the religion of Catholicism, Lutheranism, and Atheism that they fail to see who Jesus is, why he came, and how we can experience life through a relationship with Him.&lt;&#x2F;p&gt;
&lt;p&gt;I am very thankful I can have a second job which is remote work and allows me to be in the tech industry. I like working with bleeding edge software such as Docker, Kubernetes, Puppet, and the like. It also allows me to scratch the itch I have with the nerdy side of tech - coding. I have been able to maintain a legacy PHP app while develop some in NodeJS and Go. Mostly I have been sharing cool things about Github, build pipelines, and the philosophy of &quot;Let the robots do it.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;My coffee survival habit has been amplified by the purchase of a Ninja coffee maker last Amazon Prime day. I was not able to use it until we moved here and I am quite satisfied with how it makes iced coffee. It also gave me a recipe which I have been following for my daily iced coffee - it requires half and half with a few ounces of flavored syrup. I think this is the best approach for iced coffee.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Moving Adventures Part 2</title>
        <published>2017-08-01T20:46:34+00:00</published>
        <updated>2017-08-01T20:46:34+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-08-01-moving-adventures-part-2/" type="text/html"/>
        <id>/2017-08-01-moving-adventures-part-2/</id>
        
            <content type="html">&lt;p&gt;(Note: This guest post is from my wife, Nicole. These are the events that happened July 25th, 2017.)&lt;&#x2F;p&gt;
&lt;p&gt;After 6 hours of rest, we awakened rested (somewhat) and ready to resume our journey. Morning was fairly uneventful, and we were back on the road by 9. As we were fueling up, we realized that Clark&#x27;s cup (which he went to bed with) was accidentally left somewhere amid the sheets despite going through the room 2-3 times. No worries! Remembered that were had brought 2 extra sippy cups ?&lt;&#x2F;p&gt;
&lt;p&gt;As we merged on the I-76 we spotted what we believe to be our moving van. Too funny! The day before we&#x27;d seen the same truck as we left Barstow. At least we know our belongings should arrive by Friday, lol! An hour into our drive, all the kids except Mollie fell asleep.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, the next leg of our journey was fairly uneventful, and we were able to stop for lunch in Kearney by 2:45. Other then an icky diaper and ordering the wrong sandwich for Andrew, lunch was quite pleasant. In fact, Jake ate more than Clark or Meg! Thanks to everyone&#x27;s prayers, the children were very well behaved as we made our way to the next stop--Des Moine.&lt;&#x2F;p&gt;
&lt;p&gt;For the next 3.5 hours: played with toys, watched cartoons, and slept (praise the Lord!!). Seems whenever we&#x27;re close to our destination one of the younger three decides they&#x27;ve had it and begins to fuss. Thankfully, Clark perks up with food or cars, and Jake loves snacks and playing with random items (wipes bucket, water bottle, thermos, favorite afghan etc.). As a reward, hoping to get a little pool time at the hotel. So thankful we&#x27;re only driving 5 hours tomorrow and going to get a good 2 hour break at the Mall of America!&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Moving Adventures Part 1</title>
        <published>2017-07-31T20:46:03+00:00</published>
        <updated>2017-07-31T20:46:03+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-07-31-moving-adventures-part-1/" type="text/html"/>
        <id>/2017-07-31-moving-adventures-part-1/</id>
        
            <content type="html">&lt;p&gt;(Note: This guest post is from my wife, Nicole. These are the events that happened July 24th, 2017.)&lt;&#x2F;p&gt;
&lt;p&gt;Well, after 4 hours of sleep, we woke and were on the road by 5. Forgot one little detail... taking girls to the restroom before we left. When we reached Adelanto, Mollie said she had to go the bathroom. Pulled in to the first gas station we saw and wouldn&#x27;t you know it, the restrooms were both out of order ? Bought a potty seat for emergencies such as this.&lt;&#x2F;p&gt;
&lt;p&gt;In the mean time, Meg decided she wanted to get dressed. Dressed the girls and was handing out the snack when Jake gagged himself and threw up the banana I just fed him! Cleaned him up, scrounged around to find the clothes I&#x27;d stuffed in our overloaded van. A 10 minute stop took 30 minutes ?&lt;&#x2F;p&gt;
&lt;p&gt;Back on the road! Fortunately, despite a quick run through McDonald&#x27;s, we reached St. George, Utah by noon. As we unloaded the car, we spent 10 minutes in 107° weather looking for Mollie&#x27;s shoe and 3 elusive crayons. Finally decided to look when we returned from lunch and have Mollie ride in the shopping cart with one shoe.&lt;&#x2F;p&gt;
&lt;p&gt;Took Jake out of the car only to discover he&#x27;d blown out his diaper! He didn&#x27;t want to be changed because his poor rear is so irritated. Think the ladies in the Costco restroom thought I was crazy as I held down a squirmy, stinky baby. Once he was changed, I took the girls to the restroom and heard someone commenting on the smell in the bathroom! Way to go baby boy!!&lt;&#x2F;p&gt;
&lt;p&gt;Returned to the van and spent another 10 minutes finding the lost flip flop and crayons. Between the puke and diaper blowout, we&#x27;d nearly used our stash of wipes. So had to run to Walmart of course! Back to the road!&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully the kids played quietly with their aqua doodle pads, and the girls fell asleep ? Just as Jake was starting to fuss, we passed through a rainstorm, and the boys stared out the window awestruck. Rain is discovered (by the way, the storm cleaned our windshield better than the Lancaster Cruz Thru)!&lt;&#x2F;p&gt;
&lt;p&gt;Things went fairly well for the next few hours. Kids napped and ate dinner at Wendy&#x27;s. About 20 minutes into the home stretch, I heard a noise any mother learns to dread--Clark was about to spew. Managed to get most of his dinner in the plastic bag I&#x27;d brought for such emergencies. After a quick clean up job, we were back in business. Five minutes later though, we had to stop again because we suspected Jake had dirtied his diaper. False alarm!&lt;&#x2F;p&gt;
&lt;p&gt;Why is it the last 100 miles of any trip seems the longest. After hitting a few construction spots, we finally pulled into Denver at midnight. Sadly, kids who are awakened at midnight are not exactly pleasant. Mollie did okay, but Meg is a bear whenever her sleep&#x27;s interrupted. Clark perked up a bit as we trekked across the parking lot. Once we reached the unfamiliar hotel room, however, he started crying that he wanted out of the room! Andrew left me with the three younger ones while he and Mollie retrieved our luggage. In the mean time, Jake&#x27;s full diaper leaked out onto my shirt. Andrew hadn&#x27;t returned so I quickly stripped Jake down and threw him into the tub. At which point Jake joined the crying chorus ? I half expected the manager to come throw us out any minute with all the ruckus we were causing.&lt;&#x2F;p&gt;
&lt;p&gt;Andrew finally came with the luggage (except for the toiletries bag but that&#x27;s another story). Prepared for bed and let the kids watch a little episode of Daniel Tiger&#x27;s Neighborhood before settling in for a few hours of much needed rest!&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Leaving California</title>
        <published>2017-07-24T15:00:00+00:00</published>
        <updated>2017-07-24T15:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-07-24-leaving-california/" type="text/html"/>
        <id>/2017-07-24-leaving-california/</id>
        
            <content type="html">&lt;p&gt;Today marks the first day in over 29 years where I am no longer a resident of the great state of California. No longer will iscaliforniaonfire.com be relevant to me or my family! With all changes to life there are some good things and bad things with every major life decision.&lt;&#x2F;p&gt;
&lt;p&gt;From the move, I will miss the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In-n-Out burgers&lt;&#x2F;li&gt;
&lt;li&gt;Nearby family members&lt;&#x2F;li&gt;
&lt;li&gt;Lancaster Baptist Church&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;However, I will not miss the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;100 degree weather&lt;&#x2F;li&gt;
&lt;li&gt;California driving&lt;&#x2F;li&gt;
&lt;li&gt;Smog&lt;&#x2F;li&gt;
&lt;li&gt;Time Warner Cable&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I am also super pumped about these:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;More fishing opportunities&lt;&#x2F;li&gt;
&lt;li&gt;Snow&lt;&#x2F;li&gt;
&lt;li&gt;A new ISP&lt;&#x2F;li&gt;
&lt;li&gt;Dunkin donuts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Autosign Puppet certificates on AWS</title>
        <published>2017-06-30T16:06:26+00:00</published>
        <updated>2017-06-30T16:06:26+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-06-30-autosign-puppet-certificates-on-aws/" type="text/html"/>
        <id>/2017-06-30-autosign-puppet-certificates-on-aws/</id>
        
            <content type="html">&lt;p&gt;Let&#x27;s face it, Puppet&#x27;s method of certificates is a pain and huge administration overkill if done manually. Thankfully, puppet has designed several methods of auto-signing certificates. One of which is via crafting a special certificate signing request and verifying the certificate signing request is genuine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-the-puppet-master&quot;&gt;On the puppet master&lt;&#x2F;h2&gt;
&lt;p&gt;Apply the following code on your puppet master. This will set up the autosign script which will verify your custom certificate signing request. If the CSR is genuine, the puppet master will sign the certificate.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  service { &amp;#39;puppetserver&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure =&amp;gt; running,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    enable =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The file must have execute permissions
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The master will trigger this as `&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;autosign.sh FQDN`
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  file { &amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;autosign.sh&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure  =&amp;gt; file,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    mode    =&amp;gt; &amp;#39;0750&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    owner   =&amp;gt; &amp;#39;puppet&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    group   =&amp;gt; &amp;#39;puppet&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    content =&amp;gt; &amp;#39;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;HOST=$1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;openssl req -noout -text -in &amp;quot;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;ssl&#x2F;ca&#x2F;requests&#x2F;$HOST.pem&amp;quot; | grep pi0jzq9qmabtnTa8KfkBs2z5rQZ3vZsa&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# This sets up the required ini setting and restarts the puppet master service
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ini_setting {&amp;#39;autosign nodes&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure  =&amp;gt; present,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    path    =&amp;gt; &amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;puppet.conf&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    section =&amp;gt; &amp;#39;master&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    setting =&amp;gt; &amp;#39;autosign&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    value   =&amp;gt; &amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;autosign.sh&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    notify  =&amp;gt; Service[&amp;#39;puppetserver&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    require =&amp;gt; File[&amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;autosign.sh&amp;#39;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;on-the-agents&quot;&gt;On the agents&lt;&#x2F;h2&gt;
&lt;p&gt;With our puppet master ready to go, we need to set up our agents to generate the custom certificate request. This can be done by editing &lt;code&gt;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;csr_attributes.yaml&lt;&#x2F;code&gt; before running puppet with the following content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;custom_attributes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    1.2.840.113549.1.9.7: pi0jzq9qmabtnTa8KfkBs2z5rQZ3vZsa
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;extension_requests:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    pp_instance_id: $(curl -s http:&#x2F;&#x2F;169.254.169.254&#x2F;latest&#x2F;meta-data&#x2F;instance-id)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    pp_image_name:  $(curl -s http:&#x2F;&#x2F;169.254.169.254&#x2F;latest&#x2F;meta-data&#x2F;ami-id)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: The &lt;code&gt;1.2.840.113549.1.9.7&lt;&#x2F;code&gt; value must match the item you are grepping for in the autosigning request. This specific value in the certificate is reserved for purposes such as this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;execution&quot;&gt;Execution&lt;&#x2F;h2&gt;
&lt;p&gt;With everything in place, the way to execute this successfully is to pass in the below as the userdata script when creating an EC2 instance:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if [ ! -d &#x2F;etc&#x2F;puppetlabs&#x2F;puppet ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;   mkdir &#x2F;etc&#x2F;puppetlabs&#x2F;puppet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;gt; &#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;csr_attributes.yaml &amp;lt;&amp;lt; YAML
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;custom_attributes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    1.2.840.113549.1.9.7: pi0jzq9qmabtnTa8KfkBs2z5rQZ3vZsa
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;extension_requests:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    pp_instance_id: $(curl -s http:&#x2F;&#x2F;169.254.169.254&#x2F;latest&#x2F;meta-data&#x2F;instance-id)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    pp_image_name:  $(curl -s http:&#x2F;&#x2F;169.254.169.254&#x2F;latest&#x2F;meta-data&#x2F;ami-id)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;YAML
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An alternative method is to create a custom AMI (especially for auto-scaling groups). I use the below puppet code to create my golden AMI.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  cron { &amp;#39;run aws_cert at reboot&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    command =&amp;gt; &amp;#39;&#x2F;aws_cert.sh&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    user    =&amp;gt; &amp;#39;root&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    special =&amp;gt; &amp;#39;reboot&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    require =&amp;gt; File[&amp;#39;&#x2F;aws_cert.sh&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  file { &amp;#39;&#x2F;aws_cert.sh&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure  =&amp;gt; file,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    mode    =&amp;gt; &amp;#39;0755&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    content =&amp;gt; &amp;#39;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if [ ! -d &#x2F;etc&#x2F;puppetlabs&#x2F;puppet ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;   mkdir &#x2F;etc&#x2F;puppetlabs&#x2F;puppet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;gt; &#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;csr_attributes.yaml &amp;lt;&amp;lt; YAML
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;custom_attributes:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  1.2.840.113549.1.9.7: pi0jzq9qmabtnTa8KfkBs2z5rQZ3vZsa
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;extension_requests:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  pp_instance_id: $(curl -s http:&#x2F;&#x2F;169.254.169.254&#x2F;latest&#x2F;meta-data&#x2F;instance-id)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  pp_image_name: $(curl -s http:&#x2F;&#x2F;169.254.169.254&#x2F;latest&#x2F;meta-data&#x2F;ami-id)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;YAML
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;export CERTNAME=&amp;quot;aws-node_name-`date +%s`&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;opt&#x2F;puppetlabs&#x2F;bin&#x2F;puppet apply -e &amp;quot;ini_setting {\&amp;quot;certname\&amp;quot;: \ ensure =&amp;gt; present, \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  path =&amp;gt; \&amp;quot;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;puppet.conf\&amp;quot;, \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  section =&amp;gt; \&amp;quot;main\&amp;quot;, \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  setting =&amp;gt; \&amp;quot;certname\&amp;quot;, \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  value   =&amp;gt; $CERTNAME, \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;opt&#x2F;puppetlabs&#x2F;bin&#x2F;puppet agent -t -w 5&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>My tablet history and Kindle Fire (7th Gen) review</title>
        <published>2017-06-09T13:00:00+00:00</published>
        <updated>2017-06-09T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-06-09-kindle-fire-7th-gen-review/" type="text/html"/>
        <id>/2017-06-09-kindle-fire-7th-gen-review/</id>
        
            <content type="html">&lt;p&gt;My first tablet was an Acer A500 which ran Honeycomb (Android 3.0). I used that laptop for everything - reading, pictures, studying, and using it to project games in the children&#x27;s class I taught at the time. It was used more than my laptop, phone, and desktop combined. It served its purpose until my wife accidentally knocked it off the kitchen counter (it was laying flat) and it got a huge dent. It never was the same after that incident. I eventually got rid of it after it no longer held a charge due to the damage it received. &lt;&#x2F;p&gt;
&lt;p&gt;The next tablet I purchased was a Kindle fire 2nd gen which I gave to my wife and borrowed it when needed. Life was great. Then, as a reward for good behavior, we let our children play the games and apps we purchased on the Kindle. Our children are so well behaved (thanks to some awesome parentig tips we received in our Adult Bible Class at church) that my wife no longer had enough Kindle time to do her reading. This is when I bought her a 5th gen Kindle fire. The difference between versions impressed me. I liked the thinner design and the new UI was very intriguing. I made a determination if I ever wanted a new tablet I would get myself a Kindle fire. (I was not in the market for one as I was a happy 6 inch phablet user.)&lt;&#x2F;p&gt;
&lt;p&gt;Recently, I have had a desire to reduce my reading list by actually reading the books. At first I tried reading from my phablet, but alas, a 6inch screen is not ideal for reading large amounts of text - even if you have a high DPI phone such as my Google Nexus 6. This has led me to purchase a Kindle fire 7th gen which was released on June 7th 2017.&lt;&#x2F;p&gt;
&lt;p&gt;It has the same intriguing design as the 5th gen device, but has better battery life and more external storage capacity. When I first unboxed and turned on the device, I was happy at how little I had to do to get my new Kindle operational. After 10 minutes of using Kindle fire OS (which is just Android without Google), I quickly realized just how attached I am to Google services. Most of my daily use apps - such as Dropbox and JuiceSSH - were not available. Did I make a mistake buying this $70 device (+$30 case and $9 tax)? Thankfully, &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forum.xda-developers.com&#x2F;amazon-fire&#x2F;general&#x2F;how-to-install-google-play-store-fire-t3486603&quot;&gt;there is an alternative and it works quite well&lt;&#x2F;a&gt; - it doesn&#x27;t even require rooting your device either!&lt;&#x2F;p&gt;
&lt;p&gt;Wow, after installing the four apps, running a Google play services update, and downloading my needed apps, I am really enjoying my Kindle fire 7th gen! Everything is working as expected; albeit, I have to wait a few milliseconds longer over my phablet to do common tasks. The screen size is perfect, the weight and style is also perfect, and I was able to be different and get a yellow one. (My wife has blue, black is the color I usually get, and red seemed too plastic.)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Moving to Desktop GNU&#x2F;Linux from Windows&#x2F;Mac</title>
        <published>2017-04-14T14:00:00+00:00</published>
        <updated>2017-04-14T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-04-14-moving-to-desktop-gnulinux-from-windowsmac/" type="text/html"/>
        <id>/2017-04-14-moving-to-desktop-gnulinux-from-windowsmac/</id>
        
            <content type="html">&lt;p&gt;There are many curious individuals who tinker with GNU&#x2F;Linux as a Server OS and want to experience what it is like as a Desktop OS. The switch is often hindered by two obstacles:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Some daily use programs are not available. (i.e. Photoshop, iTunes, etc.)&lt;&#x2F;li&gt;
&lt;li&gt;The unknown of what to do if something goes wrong or what do I do to get my 3d graphics driver installed and working.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;While these are valid reasons and definitely show stoppers for some, others can safely migrate to GNU&#x2F;Linux.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-obstacle-of-programs&quot;&gt;The obstacle of programs&lt;&#x2F;h2&gt;
&lt;p&gt;I like Krita as an alternative to Photoshop. The menu options are nearly the same and I do not have to install a silly theme (like I have to do in Gimp) or re-learn photo editing just to recognize where everything is at. I have successfully installed Photoshop CS4 with wine without any issues, but Krita is more featured than CS4. Darktable is also a good alternative to Photoshop RAW&#x2F;bridge.&lt;&#x2F;p&gt;
&lt;p&gt;Rhythmbox connects to iPhones&#x2F;iPods the same way as iTunes does, but without the store. iTunes does run on a recent version of wine quite well. Some might also want to check out &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.clementine-player.org&#x2F;&quot;&gt;Clementine&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Most every program has an alternative. Alternatives can be found via &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;alternativeto.net&#x2F;&quot;&gt;alternativeto.net&lt;&#x2F;a&gt; or software recommendations on StackExchange.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-unknown-obstacles&quot;&gt;The unknown obstacles&lt;&#x2F;h2&gt;
&lt;p&gt;To use GNU&#x2F;Linux successfully as the primary Desktop OS, in my opinion, one must have a desktop with worthy hardware. I consider myself an AMD guy. I like the price for performance and I rarely do CPU intensive tasks on my desktop. When AMD bought ATI, I was also happy as ATI was my favorite graphics card. Unfortunately, most Desktop GNU&#x2F;Linux users are developers and need that extra performance. They have desktop workstations that have Nvidia graphics cards in them with Intel CPUs. You will often find that Desktop GNU&#x2F;Linux performs better, is easier to use, and has more tutorials for Nvidia graphics cards and how to get them working.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Captive Portal Overview</title>
        <published>2017-04-07T15:00:10+00:00</published>
        <updated>2017-04-07T15:00:10+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-04-07-captive-portal-overview/" type="text/html"/>
        <id>/2017-04-07-captive-portal-overview/</id>
        
            <content type="html">&lt;p&gt;I originally authored this on Aug 16, 2016 at &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;303807&quot;&gt;http:&#x2F;&#x2F;unix.stackexchange.com&lt;&#x2F;a&gt;. Considering my tutorial did not include an overview, I thought I would re-post it on my blog.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;To make a captive portal appear, you need to stop all internet traffic and provide a &lt;code&gt;302 redirect&lt;&#x2F;code&gt;to the client&#x27;s browser. To do this, you need to have a firewall (like &lt;code&gt;iptables&lt;&#x2F;code&gt;) redirect all traffic to a webserver (like &lt;code&gt;nginx&lt;&#x2F;code&gt;, &lt;code&gt;apache&lt;&#x2F;code&gt;, etc) where the webserver responds with a &lt;code&gt;302 redirect&lt;&#x2F;code&gt; to the url of your login page.&lt;&#x2F;p&gt;
&lt;p&gt;I have written a &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;andrewwippler.com&#x2F;wifi-captive-portal&#x2F;&quot;&gt;lengthy article&lt;&#x2F;a&gt; on how to do this with a Raspberry Pi. It basically boils down to the &lt;strong&gt;iptables block&#x2F;redirect to webserver&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -p tcp --dport 80 -j DNAT --to-destination 192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and then the webserver (&lt;code&gt;nginx&lt;&#x2F;code&gt;) redirecting to the login page:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# For iOS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if ($http_user_agent ~* (CaptiveNetworkSupport) ) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    return 302 http:&#x2F;&#x2F;hotspot.localnet&#x2F;hotspot.html;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# For others
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;location &#x2F; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    return 302 http:&#x2F;&#x2F;hotspot.localnet&#x2F;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;iOS has to be difficult in that it needs the WISP settings. &lt;code&gt;hotspot.html&lt;&#x2F;code&gt; contents are as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;!--
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;WISPAccessGatewayParam xmlns:xsi=&amp;quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2001&#x2F;XMLSchema-instance&amp;quot; xsi:noNamespaceSchemaLocation=&amp;quot;http:&#x2F;&#x2F;www.wballiance.net&#x2F;wispr_2_0.xsd&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;Redirect&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;MessageType&amp;gt;100&amp;lt;&#x2F;MessageType&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;ResponseCode&amp;gt;0&amp;lt;&#x2F;ResponseCode&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;VersionHigh&amp;gt;2.0&amp;lt;&#x2F;VersionHigh&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;VersionLow&amp;gt;1.0&amp;lt;&#x2F;VersionLow&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;AccessProcedure&amp;gt;1.0&amp;lt;&#x2F;AccessProcedure&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;AccessLocation&amp;gt;Andrew Wippler is awesome&amp;lt;&#x2F;AccessLocation&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;LocationName&amp;gt;MyOpenAP&amp;lt;&#x2F;LocationName&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;LoginURL&amp;gt;http:&#x2F;&#x2F;hotspot.localnet&#x2F;&amp;lt;&#x2F;LoginURL&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;Redirect&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;WISPAccessGatewayParam&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;--&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Tupperware announces new container platform</title>
        <published>2017-04-01T08:01:51+00:00</published>
        <updated>2017-04-01T08:01:51+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-04-01-tupperware-announces-new-container-platform/" type="text/html"/>
        <id>/2017-04-01-tupperware-announces-new-container-platform/</id>
        
            <content type="html">&lt;p&gt;Today, in a surprise move into technology, Tupperware has released a new container platform competing with Docker and rkt. Tupperware’s new platform - named Bowl - has been in alpha for the past 6 months, but now has achieved public beta status.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File%3ATupperware_party.jpg&quot;&gt;&lt;img alt=&quot;Tupperware party&quot; src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;f&#x2F;f9&#x2F;Tupperware_party.jpg&quot; height=&quot;370&quot; width=&quot;491&quot; &#x2F;&gt;&lt;&#x2F;a&gt;An early photograph of a Tupperware party. This announcement was made at a similar one.&lt;&#x2F;p&gt;
&lt;p&gt;What’s unique about Bowl is that it introduces a new concept to containers - Lid. A Lid goes neatly on top of the container and seals the contents from evildoers and prevents bad code from escaping. Bowls, due to their circular shape, require burping the attached Lid. This burping maneuver was demonstrated live to the audience and was described as a method to keep the containerized application fresh across hybrid clouds. With Burping, we no longer have to worry about our code going stale inside of the container.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike other containers, when done with a Bowl, they go through a cleaning cycle and are available for reuse immediately or stacked in a cupboard for later. Lids, associated with Bowls, are placed underneath to keep the associated roles in relative proximity. Unlike some deployments &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lhartikk&#x2F;AstroBuild&quot;&gt;which require planetary alignment&lt;&#x2F;a&gt;, Bowl comes in several predetermined sizes which negate this prerequisite. If for some reason your code does not fit in a Bowl size, multiple Bowls can be used. This feature instantly transforms your monolith application into a microservice architecture - all without refactoring your workflow!&lt;&#x2F;p&gt;
&lt;p&gt;Bowl will be showcased at global parties as early as next week, but preview respondents have come across the following remarks about Bowl:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is so good that Tupperware has launched into the tech business. Tupperware already has such a good influence on minority groups and bringing an interest of tech to them is really a great idea.&lt;&#x2F;p&gt;
&lt;p&gt;Joan P&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This isn’t your grandma’s container technology.&lt;&#x2F;p&gt;
&lt;p&gt;Jon S&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I was surprised how well Bowl stacked up to the challenge.&lt;&#x2F;p&gt;
&lt;p&gt;Andrew B&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;And when you&#x27;re done, it doubles as a barber aid!&lt;&#x2F;p&gt;
&lt;p&gt;Rob N&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This is exactly the kind of container I was looking for - Lightweight, secure, reusable, and dishwasher safe.&lt;&#x2F;p&gt;
&lt;p&gt;Chris B&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Bowl is expected to integrate nicely with the next version of Kubernetes, which is due out next year.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Captive Portal Restaurant Menu</title>
        <published>2017-03-24T14:00:00+00:00</published>
        <updated>2017-03-24T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-03-24-captive-portal-restaurant-menu/" type="text/html"/>
        <id>/2017-03-24-captive-portal-restaurant-menu/</id>
        
            <content type="html">&lt;p&gt;I have been contacted several times in regards to my captive portal post. In India there seems to be a surge in popularity for restaurants to have an open WiFi that prompts a user to open up a menu&#x2F;splash page. The caveat being the legal issues encountered when providing free, open wireless internet. In order to avoid legal issues, the device that broadcasts must be disconnected from the internet. Although I am curious if just blocking internet access for those connecting is enough. &lt;&#x2F;p&gt;
&lt;p&gt;It seems like an interesting issue to tackle, but I think creating something out of a WiFi captive portal would be like hammering a square peg through a round hole. It might work (if given enough time and effort), but in the end, it is probably not the right tool for the job.&lt;&#x2F;p&gt;
&lt;p&gt;While writing this post, I was reminded how Google appears to be tackling this problem. On my Android phone, I let the NSA spy on my whereabouts by enabling location services. It also lets my wife pinpoint where I am physically located. With it enabled, I can visit most shops in my area and get a Google maps prompt with the business information, reviews, and a few pictures. (Side note: if you appear in court over a childish&#x2F;dumb action, you validate the judge&#x27;s decision when you post a negative review of the court house. Also please do not butcher the English language when trying to review places.)&lt;&#x2F;p&gt;
&lt;p&gt;Utilizing GPS location as well as having an app that provides the information seems like the best route to go in this circumstance. An alternative would be to have an app with WiFi credentials hardcoded in, listen for when a WiFi connection is made, check to see if it matches a predefined SSID, and attempt to communicate with a local app server to process data. Of course doing something like that is outside the scope of my tutorials.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Jumping the ship on Evernote</title>
        <published>2017-03-17T15:00:37+00:00</published>
        <updated>2017-03-17T15:00:37+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-03-17-jumping-the-ship-on-evernote/" type="text/html"/>
        <id>/2017-03-17-jumping-the-ship-on-evernote/</id>
        
            <content type="html">&lt;p&gt;I am a long time user of Evernote. Currently it has the best browser extensions, a wide range of supported operating systems, and it has a free tier; however, I am getting frustrated with it. In the past year, they have changed plans twice - now the free tier is only supported on 2 platforms. This has cost me to re-evaluate my use of Evernote. Lately all I have been using Evernote for is to sync a grocery list between devices and keeping my children&#x27;s memories in one location - their sayings, artwork, etc. In the past I also used it for note taking, article saving, and inputting ideas. I have also seriously considered buying a subscription just so I can continue uninterrupted.&lt;&#x2F;p&gt;
&lt;p&gt;While this may be a rant about a free user using a free service, I contribute to the monitization of their service by the viewing of advertisements. The free tier limits (except for maximum devices) are adequate for my occasional use and probably have cost Evernote around $3 total in the past several years. The valuation Evernote has placed on their second-level tier ($35&#x2F;year) is much higher than I value it (~$12&#x2F;year). While I may not be able to set the price on what Evernote costs, I can put a price on what I am willing to pay for a simple note service.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opensource.com&#x2F;alternatives&#x2F;evernote&quot;&gt;recent article&lt;&#x2F;a&gt; on opensource.com opened my eyes to looking at note taking alternatives. I was surprised at how mature Paperwork was; however, it contained one simple flaw that throws my grocery list experience out the window - no checkbox option. This caused me to evaluate Google Keep - yes, has check boxes, but functions more like sticky notes. Then I remembered Atlassian&#x27;s confluence has checkboxes. Their paid version is $10 for up to ten users (per year if it self hosted, monthly if in the cloud). This fits my budget, I can create grocery lists, take notes, and create notebooks&#x2F;spaces. While I have not switched away yet, confluence seems like a viable option as I already have an always-on home server.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>I do not use the kuerig - here is why...</title>
        <published>2017-02-24T14:00:00+00:00</published>
        <updated>2017-02-24T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-02-24-i-do-not-use-the-kuerig-here-is-why/" type="text/html"/>
        <id>/2017-02-24-i-do-not-use-the-kuerig-here-is-why/</id>
        
            <content type="html">&lt;p&gt;The kuerig device is a visually pleasing design. It appears to belong in the modern kitchen. A few months ago, I was given a kuerig first generation with a reusable filter and used it as my primary coffee consumption device. It gave me a sense of faster coffee delivery in the morning - I was happy until I discovered these flaws:&lt;&#x2F;p&gt;
&lt;p&gt;Flaw #1 - I spent more time making coffee than with a drip machine.&lt;&#x2F;p&gt;
&lt;p&gt;While it had a reservoir of water, that only lasted for about 6 tall glasses of coffee. I would have to switch out the K cup if I wanted a cup in the morning and one to take with - very common thing for me to do. This led me to another flaw.&lt;&#x2F;p&gt;
&lt;p&gt;Flaw #2 - the kuerig is designed for casual coffee drinkers.&lt;&#x2F;p&gt;
&lt;p&gt;By casual I mean 3-6 cups a month. Even with a refillable K cup, I was spending twice the amount on coffee and found myself adding 5 minutes to my normal routine just for use of the kuerig.&lt;&#x2F;p&gt;
&lt;p&gt;Flaw #3 - coffee dust&lt;&#x2F;p&gt;
&lt;p&gt;The coffee ground too much in store bought K cups and my refillable K cup often found itself in the bottom of my glass. This was disgusting and I could not stand throwing away the last sip of coffee because it had coffee dust at the bottom. To combat this, I had to cut filters in the shape of my K cup.&lt;&#x2F;p&gt;
&lt;p&gt;After 2 months of trouble with the kuerig, I got frustrated with drinking coffee. What was designed to be a pleasant, easy experience in making coffee turned out to be painful, time consuming, and more expensive. I evaluated my habit with the kuerig and found I was doing the same exact items with my old drip system, but spent more time affixing it to the kuerig. Once I realized that, I switched back to my old ways, sold the kuerig and bought more coffee with the money.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Debugging PHP web applications</title>
        <published>2017-02-03T14:00:58+00:00</published>
        <updated>2017-02-03T14:00:58+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-02-03-debugging-php-web-applications/" type="text/html"/>
        <id>/2017-02-03-debugging-php-web-applications/</id>
        
            <content type="html">&lt;p&gt;In 2017, this topic seems a little dated and will probably not get me an opportunity to speak at a conference. While all of the elite programmers, cool kids, and CS grads are talking languages such as Go and Erlang - how to do tracing, performance testing, and the like - it seems very juvenile for me to write about PHP.&lt;&#x2F;p&gt;
&lt;p&gt;PHP is a language made specifically for the web. It is the first web language I learned after HTML 4&#x2F;CSS. I learned it because it was easy. The syntax was easy, the variables - easy, running it - easy; however, when something broke, it was difficult as a beginner to troubleshoot. I would spend several hours looking at the code I just wrote only to find out I missed a semicolon or quote. This post is several things I wish I knew when I started with PHP.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;white-pages&quot;&gt;White Pages&lt;&#x2F;h2&gt;
&lt;p&gt;When coding in PHP, you will often find a blank white page with nothing printed on it. This means PHP was unable to complete the page construction due to an error in the code.&lt;&#x2F;p&gt;
&lt;p&gt;In the early days, PHP had error reporting on by default. Rather than being greeted with a white page on error, you would have the error code presented to you - making it very obvious where the issue is located. Due to novice SysAdmins&#x2F;Devs who would leave error reporting on in production, PHP maintainers switched this default behavior to off.&lt;&#x2F;p&gt;
&lt;p&gt;I find it easier to debug code when the process goes like:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Write code&lt;&#x2F;li&gt;
&lt;li&gt;Load page in browser&lt;&#x2F;li&gt;
&lt;li&gt;See error message&lt;&#x2F;li&gt;
&lt;li&gt;Fix code&lt;&#x2F;li&gt;
&lt;li&gt;Repeat&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;With current defaults, the workflow is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Write code&lt;&#x2F;li&gt;
&lt;li&gt;Load page in browser&lt;&#x2F;li&gt;
&lt;li&gt;Open terminal&lt;&#x2F;li&gt;
&lt;li&gt;Tail log file&lt;&#x2F;li&gt;
&lt;li&gt;See error message&lt;&#x2F;li&gt;
&lt;li&gt;Fix code&lt;&#x2F;li&gt;
&lt;li&gt;Repeat&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;While it is only 2 steps more, consider the time wasted trying to find the correct path to the log file. Would it be in nginx&#x27;s error log file or would it be in the www fpm pool&#x27;s www-error.log?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;application-deployment&quot;&gt;Application deployment&lt;&#x2F;h2&gt;
&lt;p&gt;It is 2017, if you have not tried nginx as your webserver, you are missing out. I have wrote an article on&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;andrewwippler.com&#x2F;2016&#x2F;04&#x2F;26&#x2F;linux-nginx-mysql-5-7-and-php-7-lemp-on-aws-with-free-ssl&#x2F;&quot;&gt; how to deploy a LEMP stack&lt;&#x2F;a&gt; which you should read. Not only is nginx syntax easier to read, it is much easier to tune, and it forces you to use PHP-FPM which is currently the best way to run PHP applications. In the early days, PHP was run as a process of the apache web server. This made applications spawn a new apache worker to run simple PHP code.&lt;&#x2F;p&gt;
&lt;p&gt;If your application code and web server reside on the same server, make sure PHP is listening as a unix socket. Why should the flow of bits go through the network stack back to the same machine? This is inefficient.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-php-fpm&quot;&gt;Setting up PHP-FPM&lt;&#x2F;h3&gt;
&lt;p&gt;On RHEL&#x2F;Fedora&#x2F;CentOS PHP-FPM settings are in &lt;code&gt;&#x2F;etc&#x2F;php-fpm.d&#x2F;&amp;lt;pool name&amp;gt;.conf&lt;&#x2F;code&gt; To set up a unix socket, find the listen directive and change it to a file path - such as &#x2F;var&#x2F;run&#x2F;php.sock. You will then have to alter the listen.user, listen.group, and listen.mode settings. These three settings determine which level of access your user will have to the PHP application socket. For instance if the listen.user is andrew, your web server will have to be running as andrew. The andrew user would also need access to the directory on your system with the application code (typically &lt;code&gt;&#x2F;var&#x2F;www&#x2F;html&#x2F;&amp;lt;application name&amp;gt;&#x2F;&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;In the old days before git, many web developers ssh&#x27;ed into a box and edited the same code base. The same group would be applied to all users ssh&#x27;ing in and the application directory would have the group own the folder like the example below.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;drwxrws---. 2 nginx webadmins 4096 Dec 22 07:38 &#x2F;var&#x2F;www&#x2F;html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Users would then have to be the nginx user or a member of the webadmins group to access this folder - all other access was prohibited. Before cloud computing, many people shared the same server and groups would differentiate who had access to what.&lt;&#x2F;p&gt;
&lt;p&gt;The listen.group directive in the PHP-FPM pool is which group you want to be able to access the socket. The listen.mode determines which access the user, group, and other have to this socket. Permissions of 0444 would prevent anything being written to the PHP socket.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;know-thy-logs&quot;&gt;Know thy logs&lt;&#x2F;h2&gt;
&lt;p&gt;Production machines should not be writing logs to disks that are local. Production machines should have a separate NIC that is connected to an internal network - over which logs should be sent. The separate NIC is there to ensure your logs are not interfering with web traffic. Below are the 4 logs of PHP applications.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nginx-apache-access-log&quot;&gt;nginx&#x2F;apache access.log&lt;&#x2F;h3&gt;
&lt;p&gt;The access log shows what people are trying to access on your server. Log formats can be adjusted, but I have found the default works quite well. The default format shows the originating IP, the HTTP status code, time accessed, the URI being accessed, and other useful information. The access log is not generally used in debugging, but it does give some great insights as to who is visiting your application.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nginx-apache-error-log&quot;&gt;nginx&#x2F;apache error.log&lt;&#x2F;h3&gt;
&lt;p&gt;The error log contains the errors your application presents to your web server. If your application produces a T_STRING php error, the line will show up here. This log is your friend. You must understand everything he says and fix it. :)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;php-fpm-pool-error-log&quot;&gt;&amp;lt;php-fpm pool&amp;gt;-error.log&lt;&#x2F;h3&gt;
&lt;p&gt;This log informs you about the stability of your process workers. If you restart them, it logs that action here. If there is something wrong with your compiled version of PHP, it will show up here.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;php-fpm-pool-slow-log&quot;&gt;&amp;lt;php-fpm pool&amp;gt;-slow.log&lt;&#x2F;h3&gt;
&lt;p&gt;The slow log is also your friend, but it has to be enabled and configured first. The slow log is set by enabling it in the PHP-FPM pool (&lt;code&gt;slowlog = &#x2F;path&#x2F;to&#x2F;$pool-slow.log&lt;&#x2F;code&gt;) and configuring a threshold of when it should begin logging (&lt;code&gt;request_slowlog_timeout = 0&lt;&#x2F;code&gt;). Any PHP script that runs longer than the threshold will have the stack trace written to the slow log.&lt;&#x2F;p&gt;
&lt;p&gt;In one instance when the slow log was very useful, I was asked to investigate why the &lt;code&gt;admin-ajax.php&lt;&#x2F;code&gt; of a wordpress multisite was performing poorly. When I turned on the slow log, I saw the below output.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[19-Jan-2017 19:46:02] [pool www] pid 9705
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;script_filename = &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-admin&#x2F;admin-ajax.php
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5e1e88] curl_exec() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;Requests&#x2F;Transport&#x2F;cURL.php:162
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5e14c8] request() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-requests.php:379
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5e0dd0] request() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-http.php:366
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5df2d0] request() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-http.php:593
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5df120] get() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;http.php:170
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5def98] wp_remote_get() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-content&#x2F;plugins&#x2F;nginx-helper&#x2F;purger.php:304
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5dea90] _do_remote_get() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-content&#x2F;plugins&#x2F;nginx-helper&#x2F;purger.php:242
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5de120] purgeUrl() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-content&#x2F;plugins&#x2F;nginx-helper&#x2F;purger.php:394
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007ffd2e85c9e0] purgeImageOnEdit() unknown:0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5ddbd0] call_user_func_array() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-wp-hook.php:298
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5dd420] apply_filters() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-wp-hook.php:323
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5dd218] do_action() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;plugin.php:453
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5dc798] do_action() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;post.php:3430
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5d8ff8] wp_insert_post() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;post.php:4836
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5d8d70] wp_insert_attachment() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;post.php:3576
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5d8638] wp_update_post() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-admin&#x2F;includes&#x2F;ajax-actions.php:2497
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007ffd2e85d630] wp_ajax_save_attachment() unknown:0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5d79a8] call_user_func_array() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-wp-hook.php:298
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5d71f8] apply_filters() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;class-wp-hook.php:323
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[0x00007f1f7a5d6ff0] do_action() &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;wp-includes&#x2F;plugin.php:453
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The slow log first showed the script filename of which met the threshold of taking too long to execute and then shows a stack trace of what PHP methods were called in order to get to this location. The more I work with wordpress, the more I understand the issues with wordpress are not from core, but stem from the plugins a user adds to their website. In this case the issue stemmed from the &lt;code&gt;nginx-helper&lt;&#x2F;code&gt; plugin. I had manually set the two multisite settings in the nginx configuration and no longer needed this helper plugin. Unknowingly, an infinite loop was happening. Once the plugin was disabled, the infinite loop ended, and the customer was happy with the results.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;I did not cover everything there is to debugging PHP applications. Most find it helpful to use syntax highlighting (something I was not aware of when I first started) as well as an IDE that has PHP linting, code completion, and other features built-in. You may also want to look into using &lt;code&gt;pm = static&lt;&#x2F;code&gt; and manually determining how many child workers FPM should have. Another option is to enable the &lt;code&gt;&#x2F;status&lt;&#x2F;code&gt; page and configuring your monitoring application to poll that URL. All of these settings are found and set in the PHP pool&#x27;s config file.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Few posts in the works</title>
        <published>2017-01-28T15:00:52+00:00</published>
        <updated>2017-01-28T15:00:52+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2017-01-28-few-posts-in-the-works/" type="text/html"/>
        <id>/2017-01-28-few-posts-in-the-works/</id>
        
            <content type="html">&lt;p&gt;I have not posted in a few weeks. This was mainly due to getting a rest from posting every week of 2016! I have a few posts coming in the next few weeks. The first one will be about debugging PHP applications. The second one will be deploying a high availability MySQL cluster - what it looked like 10 years ago, and what it will look like 10 years from now. (HINT: Kubernetes + GlusterFS ;) )&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>2016 behind, 2017 forward</title>
        <published>2016-12-30T14:00:00+00:00</published>
        <updated>2016-12-30T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-12-30-2016-behind-2017-forward/" type="text/html"/>
        <id>/2016-12-30-2016-behind-2017-forward/</id>
        
            <content type="html">&lt;p&gt;With a year drawing to a close, I have a habit of looking back at my goals I set for myself, see how I have done, and set goals for the new year. My new year&#x27;s resolution for 2017 will be 1920x1080 (same as last year). I wish I could upgrade it to 5k, but it will have to do for now.&lt;&#x2F;p&gt;
&lt;p&gt;In 2016, I set a goal to post to my blog every week - I met that goal. I also planned to get more certs - of which I achieved my LFCE, COA, and Puppet Certified Professional. I also sharpened my ruby skills.&lt;&#x2F;p&gt;
&lt;p&gt;For 2017, I am not going to write on my blog every week. Instead I will write more lengthy blog posts and tutorials.&lt;&#x2F;p&gt;
&lt;p&gt;In 2016 we saw the Cubs win the world series, Microsoft join the Linux foundation, Google join the ASP.net foundation, and pigs actually flew. I can only imagine what 2017 will hold.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Easy unix epoch timestamps from CLI</title>
        <published>2016-12-23T14:00:27+00:00</published>
        <updated>2016-12-23T14:00:27+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-12-23-easy-unix-epoch-timestamps-from-cli/" type="text/html"/>
        <id>/2016-12-23-easy-unix-epoch-timestamps-from-cli/</id>
        
            <content type="html">&lt;p&gt;While working on various projects and ultimately the need for a Unix timestamp for expiring swift objects in OpenStack, I needed a quick way to convert past, present, and future timestamps to the Unix epoch. Traditionally, I went to google, searched for a Unix timestamp converter, and retrieved my seconds that way. Unfortunately in exams, you are not allowed to visit external websites.&lt;&#x2F;p&gt;
&lt;p&gt;If you know how to read documentation, you will already know that the &lt;code&gt;date&lt;&#x2F;code&gt; command has this feature already built in. An excerpt from the docs is as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       Show the local time for 9AM next Friday on the west coast of the US
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;              $ date --date=&amp;#39;TZ=&amp;quot;America&#x2F;Los_Angeles&amp;quot; 09:00 next Fri&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;DATE STRING
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       The  --date=STRING  is  a mostly free format human readable date string
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       such as &amp;quot;Sun, 29 Feb 2004 16:21:42 -0800&amp;quot; or &amp;quot;2004-02-29  16:21:42&amp;quot;  or
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       even  &amp;quot;next Thursday&amp;quot;.  A date string may contain items indicating cal‐
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       endar date, time of day, time zone, day of week, relative  time,  rela‐
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       tive date, and numbers.  An empty string indicates the beginning of the
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       day.  The date string format is more complex than is easily  documented
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       here but is fully described in the info documentation.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Further reading of the docs will point you in specifically formatting a return string by doing a &lt;code&gt;date +%s&lt;&#x2F;code&gt;. So when the time comes to expire an object from swift at 17:00 next Friday, you can do something like:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;swift post container file -H &#x27;X-Delete-On: &lt;&#x2F;code&gt;date +%s --date=&quot;17:00 next Friday&quot;&lt;code&gt;&#x27;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>OpenStack PS1 snippet</title>
        <published>2016-12-16T14:00:27+00:00</published>
        <updated>2016-12-16T14:00:27+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-12-16-openstack-ps1-snippet/" type="text/html"/>
        <id>/2016-12-16-openstack-ps1-snippet/</id>
        
            <content type="html">&lt;p&gt;I have been studying for my OpenStack certification test (the COA) which is scheduled next week. One thing that was painful to keep track of was the user I was using to interface with OpenStack as the rc file you download from OpenStack does not update your PS1 prompt. I came up with the following solution and placed it in my &lt;code&gt;~&#x2F;.bashrc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;function parse_os_user() {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    if [ ! &amp;quot;${OS_USERNAME}&amp;quot; == &amp;quot;&amp;quot; ]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        echo &amp;quot;(${OS_USERNAME})&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    else
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        echo &amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;PS1=&amp;#39;\u@\h \w `parse_os_user` \$ &amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>OpenStack certification</title>
        <published>2016-12-09T14:00:00+00:00</published>
        <updated>2016-12-09T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-12-09-openstack-certification/" type="text/html"/>
        <id>/2016-12-09-openstack-certification/</id>
        
            <content type="html">&lt;p&gt;On Dec 20th, I am scheduled to take my COA exam. &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.openstack.org&#x2F;coa&#x2F;requirements&quot;&gt;From the exam requirements page&lt;&#x2F;a&gt;, it appears to be a somewhat moderately difficult exam. The few points I need work on are heat templates and swift object administration. A few things I know about the exam are what are &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;results?search_query=pass+openstack+COA&quot;&gt;publicly available via YouTube videos&lt;&#x2F;a&gt; of the OpenStack summit sessions.&lt;&#x2F;p&gt;
&lt;p&gt;One of my troubles of studying for exams is creating content to test myself on the objectives of the exam. I look at the requirements and say to myself, &quot;I know that,&quot; and nothing gets written for that aspect. One thing I have done in the past is to search Github for exam prep questions. One I have found for OpenStack is &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AJNOURI&#x2F;COA&quot;&gt;AJNOURI&#x2F;COA&lt;&#x2F;a&gt;. He also made a nifty &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ajnouri.github.io&#x2F;coa&#x2F;&quot;&gt;website&lt;&#x2F;a&gt; for his test prep questions.&lt;&#x2F;p&gt;
&lt;p&gt;A key aspect that has helped me pass all of my open book exams is to recall the locations of my troubled areas. Looking at the docs&#x2F;reading the manual has often come a best practice of mine. Most of the time, exam questions are covered in the docs as the exams expect you to have read them.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Docker is not a source to blame</title>
        <published>2016-12-02T14:00:44+00:00</published>
        <updated>2016-12-02T14:00:44+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-12-02-docker-is-not-a-source-to-blame/" type="text/html"/>
        <id>/2016-12-02-docker-is-not-a-source-to-blame/</id>
        
            <content type="html">&lt;p&gt;I have been reading a few articles that have been published recently regarding the use of docker in production. Of the articles I read, all seem to complain about the instability of docker, the docker ecosystem, and they lament persistent storage. While I have not run docker in production for a lengthy amount of time, I can determine these issues are from operator error and are not entirely docker&#x27;s fault.&lt;&#x2F;p&gt;
&lt;p&gt;One article I read came out and boldly said that docker created a new file system in one year and it is not humanly possible to have created one in such a short amount of time. I think this article writer has never heard of the DevOps philosophy nor the minimum viability product (MVP). Basically, you do not need 100% of the features to have a working product. This makes it clearly possible to build a single file system - though not have all of the features - within a short time frame. It is also noted that a year in this development process, a second file system was created. Just like in real life, if you wait to ship a product with 100% of the features, you will never ship the product.&lt;&#x2F;p&gt;
&lt;p&gt;If you are losing data due to not properly mounting the volumes to a HA storage network (such as GlusterFS or DRBD) - you deserve to have lost the data. I know what it is like to lose 50TB of unique data due to a failed storage device, no current backups, and the shame and cost of having to send it over to DriveSavers (which they are!) for recovery. That is a painful experience and not worth repeating. If you do the same thing and expect different results, the issue lies with the operator and not the tool. Drastic changes were made when loss occurred including developing a new backup solution and having 1-to-1 replication of the data. It has also fine grained a permanent memory in my subsystem to not let that happen ever again.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, I think running docker in a public cloud is a waste of company resources - there is no price difference between a VM and 1 docker image on AWS&#x27; EC2 container platform of the same capacity. Even if you spun up an Atomic Host or similar, you still have to deal with networking constraints for your file storage. This is something best handled in house as you can scale your network infrastructure to match your workload.&lt;&#x2F;p&gt;
&lt;p&gt;The most important factor in all of this fuss about docker is that it is open source software. If you do not have the capacity to find flaws, make patches, and submit those patches for review to upstream, you are better off using a proprietary product that does not have such needs. Again, the issue lies in the operators and not the tools.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Day after Thanksgiving ritual</title>
        <published>2016-11-25T14:00:00+00:00</published>
        <updated>2016-11-25T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-11-25-day-after-thanksgiving-ritual/" type="text/html"/>
        <id>/2016-11-25-day-after-thanksgiving-ritual/</id>
        
            <content type="html">&lt;p&gt;My wife and I adopted a tradition on the day after Thanksgiving - after a full night&#x27;s sleep - we visit stores and go shopping around 10am. Yes, the lines are still crazy, but the people who woke up at 5am to wait in line are already gone. With grandparents watching our children, it is one of our best stress-free shopping experiences. No doubt - we are doing it again today.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Using Puppet to host a private RPM repository</title>
        <published>2016-11-18T14:00:46+00:00</published>
        <updated>2016-11-18T14:00:46+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-11-18-using-puppet-to-host-a-private-rpm-repository/" type="text/html"/>
        <id>/2016-11-18-using-puppet-to-host-a-private-rpm-repository/</id>
        
            <content type="html">&lt;p&gt;A repository is a place where files are stored, indexed, and available through a package manager to anyone who has the repository information. With &lt;code&gt;rpm&lt;&#x2F;code&gt; based systems, a repository is created with a tool called &lt;code&gt;createrepo&lt;&#x2F;code&gt;. Most of the time, publicly available repositories already offer the packages your server needs. When you have a custom application you want to deploy (or even rebuild an existing application with your patches), it is best to distribute that package with a repository rather than a file share or some other means. Often a folder structure is created so that differing client OS versions can connect to the same repository and access versions compiled to that specific release. In my example below, I am not creating this folder structure as I am only serving one major release - Centos 7 - and the packages I am generating are website directories which are just a collection of portable code.&lt;&#x2F;p&gt;
&lt;p&gt;A private repository is not a tricky feat - all you have to do is serve the repository via https and require http basic authentication. You then configure the clients to connect to the repository with the basic authentication in the URL string (i.e. &lt;code&gt;baseurl=https:&#x2F;&#x2F;user:pass@repo.example.com&#x2F;&lt;&#x2F;code&gt;). The HTTPS protocol is not required to serve a repository, but it does prevent network snoopers from seeing your repository credentials.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we know what is needed for a private repository, we can then define it in our puppet code.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node &amp;#39;repo.example.com&amp;#39; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  file { &amp;#39;&#x2F;var&#x2F;yumrepos&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure =&amp;gt; directory,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  createrepo { &amp;#39;yumrepo&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    repository_dir =&amp;gt; &amp;#39;&#x2F;var&#x2F;yumrepos&#x2F;yumrepo&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    repo_cache_dir =&amp;gt; &amp;#39;&#x2F;var&#x2F;cache&#x2F;yumrepos&#x2F;yumrepo&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    enable_cron    =&amp;gt; false, #optional cron job to generate new rpms every 10 minutes
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  package { &amp;#39;httpd&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure =&amp;gt; installed,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  httpauth { &amp;#39;repouser&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure    =&amp;gt; present,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    file      =&amp;gt; &amp;#39;&#x2F;usr&#x2F;local&#x2F;nagios&#x2F;etc&#x2F;htpasswd.users&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    password  =&amp;gt; &amp;#39;some-long-password&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    mechanism =&amp;gt; basic,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    require   =&amp;gt; Package[&amp;#39;httpd&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  file { &amp;#39;&#x2F;usr&#x2F;local&#x2F;nagios&#x2F;etc&#x2F;htpasswd.users&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ensure =&amp;gt; file,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    owner  =&amp;gt; &amp;#39;nginx&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    mode   =&amp;gt; &amp;#39;0644&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  class{&amp;#39;nginx&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    manage_repo    =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    package_source =&amp;gt; &amp;#39;nginx-mainline&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  nginx::resource::vhost{&amp;quot;$::fqdn&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    www_root             =&amp;gt; &amp;#39;&#x2F;var&#x2F;yumrepos&#x2F;yumrepo&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    index_files          =&amp;gt; [],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    autoindex            =&amp;gt; &amp;#39;on&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    rewrite_to_https     =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ssl                  =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    auth_basic           =&amp;gt; &amp;#39;true&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    auth_basic_user_file =&amp;gt; &amp;#39;&#x2F;usr&#x2F;local&#x2F;nagios&#x2F;etc&#x2F;htpasswd.users&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ssl_cert             =&amp;gt; &amp;quot;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;ssl&#x2F;public_keys&#x2F;$::fqdn.pem&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ssl_key              =&amp;gt; &amp;quot;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;ssl&#x2F;private_keys&#x2F;$::fqdn.pem&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    vhost_cfg_prepend    =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      &amp;#39;default_type&amp;#39;     =&amp;gt; &amp;#39;text&#x2F;html&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the above code to work, we need the required modules:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mod &amp;#39;palli&#x2F;createrepo&amp;#39;, &amp;#39;1.1.0&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mod &amp;quot;puppet&#x2F;nginx&amp;quot;, &amp;quot;0.4.0&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mod &amp;quot;jamtur01&#x2F;httpauth&amp;quot;, &amp;quot;0.0.3&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then use the following declaration on our nodes to use this repository.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;yumrepo {&amp;#39;private-repo&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  descr           =&amp;gt; &amp;#39;My Private Repo - x86_64&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  baseurl         =&amp;gt; &amp;#39;https:&#x2F;&#x2F;repouser:some-long-password@repo.example.com&#x2F;&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  enabled         =&amp;gt; &amp;#39;true&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  gpgcheck        =&amp;gt; &amp;#39;false&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  metadata_expire =&amp;gt; &amp;#39;1&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You now have a fully functional private repository - deploy your awesome software.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Website protection</title>
        <published>2016-11-11T14:00:00+00:00</published>
        <updated>2016-11-11T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-11-11-website-protection/" type="text/html"/>
        <id>/2016-11-11-website-protection/</id>
        
            <content type="html">&lt;p&gt;There are several factors that go into securing a web application. Most are second nature to seasoned system administrators, but it is still too common to talk to someone who does not know how to properly secure a web application. Here is the common checklist I go through when I determine if a website is secured.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is it using a firewall?&lt;&#x2F;li&gt;
&lt;li&gt;Am I using unique passwords that are over 20 characters?&lt;&#x2F;li&gt;
&lt;li&gt;Are passwords required to alter data?&lt;&#x2F;li&gt;
&lt;li&gt;Is my codebase up to date?&lt;&#x2F;li&gt;
&lt;li&gt;Are the only public facing ports HTTP and HTTPS?&lt;&#x2F;li&gt;
&lt;li&gt;Do I protect data in transit from the user to my site by enforcing HTTPS?&lt;&#x2F;li&gt;
&lt;li&gt;Do I protect data from my website to the database with SSL?&lt;&#x2F;li&gt;
&lt;li&gt;Is my database only accessible to my application?&lt;&#x2F;li&gt;
&lt;li&gt;Do I have my database and application on different servers?&lt;&#x2F;li&gt;
&lt;li&gt;Can a malicious user drop&#x2F;delete&#x2F;alter data from my database from a form&#x2F;switch&#x2F;button that is publicly accessible on my website or do they need to login to perform that operation?&lt;&#x2F;li&gt;
&lt;li&gt;Do I have separate connections and users to the database for writing and reading data?&lt;&#x2F;li&gt;
&lt;li&gt;Do I rate limit connections via web application firewall or utility like fail2ban?&lt;&#x2F;li&gt;
&lt;li&gt;Am I reading and blocking malicious inputs via web application firewall or mod_security?&lt;&#x2F;li&gt;
&lt;li&gt;Can anyone brute force a login or am I blocking it after 5 tries?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>So the Cubs won the world series</title>
        <published>2016-11-09T15:00:00+00:00</published>
        <updated>2016-11-09T15:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-11-09-so-the-cubs-won-the-world-series/" type="text/html"/>
        <id>/2016-11-09-so-the-cubs-won-the-world-series/</id>
        
            <content type="html">&lt;p&gt;I am still in shock that the Chicago Cubs won the World Series in Baseball which ended their 108 year drought. Last time the Cubs won the world series, they won it back-to-back. I can expect nothing less this time around. ?&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>GlusterFS overview</title>
        <published>2016-11-04T13:00:00+00:00</published>
        <updated>2016-11-04T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-11-04-glusterfs-overview/" type="text/html"/>
        <id>/2016-11-04-glusterfs-overview/</id>
        
            <content type="html">&lt;p&gt;GlusterFS is a distributed file system. Think of it as a replacement of traditional file storage (a single NFS&#x2F;samba server), an alternative to Microsoft&#x27;s DFS, or a modern implementation of SAN. It really shines when you have multiple locations and need a file server which must have the same data and be continually in sync. It is also superb for virtual machine disks as they will then become highly available.&lt;&#x2F;p&gt;
&lt;p&gt;You can use GlusterFS in a replica, distributed, and distributed-replica models. Replica is where a copy of file a is located on all GlusterFS hosts. Distributed is where file a is on some hosts and file b is on the other hosts. Distributed-replica is a combination of both - in other words a subset of two distributed hosts in a parent of replicas.&lt;&#x2F;p&gt;
&lt;p&gt;To get started with GlusterFS, all you need is commodity hardware. Nothing has to match - not even the harddrive space. GlusterFS will configure the storage allocation pool automatically. I do recommend at least a 1GB NIC connection and a large internet pipe between locations. Partitioning your system appropriately must also be considered - have a separate mount for &lt;code&gt;&#x2F;var&#x2F;log&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;data&lt;&#x2F;code&gt;. Keeping &lt;code&gt;&#x2F;data&lt;&#x2F;code&gt; as the location of your shares makes adding and removing nodes consistent with the documentation.&lt;&#x2F;p&gt;
&lt;p&gt;You need at least a multiple of 2 GlusterFS hosts to experience replica, distributed (minimum of 2 hosts), and (minimum of 4) distributed-replica. If you plan on serving Virtual machines off of the GlusterFS volume, multiples of 3 are recommended. Clusters can also be geographically bound so that if one node fails, your clients will connect to another gluster server in that region rather than just any gluster node.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;gluster.readthedocs.io&#x2F;en&#x2F;latest&#x2F;Quick-Start-Guide&#x2F;Quickstart&#x2F;&quot;&gt;quick start documentation&lt;&#x2F;a&gt; goes over setting up two nodes, pairing them together, connecting via the GlusterFS protocol on your client, and creating 100 files. In total, this is about 6 commands.&lt;&#x2F;p&gt;
&lt;p&gt;For managing a large cluster of GlusterFS servers, one may want to take a look at &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;heketi&#x2F;heketi&quot;&gt;heketi&lt;&#x2F;a&gt; which manages the lifecycle of GlusterFS. Facebook also developed a tool called AntFarm, but it is currently closed source.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>A journey to LFCE</title>
        <published>2016-10-28T13:00:00+00:00</published>
        <updated>2016-10-28T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-10-28-a-journey-to-lfce/" type="text/html"/>
        <id>/2016-10-28-a-journey-to-lfce/</id>
        
            <content type="html">&lt;p&gt;I began my Linux hobby in 1999. I was given a CD of RedHat Linux which I installed on an old computer. At first use, it was slow and buggy and uninstalled in favor of Windows 98. I installed Debian a few months later and discovered I could install a different desktop environment - KDE which looked like Windows, but was different. After playing with it for a few weeks, I discovered Knoppix - a live CD that didn&#x27;t overwrite my hard drive and let me play around without grave consequences. A friend then introduced me to Gentoo which allowed for complete customization for my 1ghz single core processor. After a few failed misconfigurations and a desire to get back to binary installs, I switched to Fedora Core 1 and used it on my desktop. Another friend showed me a new distribution called Ubuntu - similar to Debian, but more up to date. This was then installed on my laptop that I used for college. I switched completely to Ubuntu after the release of Fedora core 4 as I got frustrated with yum.&lt;&#x2F;p&gt;
&lt;p&gt;After college, I started working in a help desk position. It was mainly servicing Windows desktops and a few OSX machines. I then received a task from my boss to create a simple lookup website. I got to choose the server OS, create the VM on a Hyper-V host, and use any tools I could muster to perform this simple task. The project was a success and I received another - parse a text file and output it to a standard CSV. At the time, I only knew PHP and none of the cool features of sed and awk. PHP turned out to be a good choice for this project as I was later informed a user would use my creation every day to convert a text file to this new format. I simply had to create a web front end, parse the uploaded file, and give the user an option to download this file.&lt;&#x2F;p&gt;
&lt;p&gt;I began to develop more skills in Linux as my various work tasks involved more and more Enterprise level responsibility - such as LDAP authentication for websites, Active Directory maintenance, converting databases from Access to MySQL with a front end, Migration of Exchange 2003 to 2007, and introducing Google Apps for Education to about 700 students. &lt;&#x2F;p&gt;
&lt;p&gt;When my boss left the organization, I assumed his role and provided oversight for network connectivity (switch&#x2F;router config), overseeing two, 6 figure technology budgets, and also my regular responsibilities. I was able to attend training events as well as attend online courses regarding Linux. At that time, I began reading more books on tech practices, management, and Linux. I felt I learned enough to prove my skills with certification - even though I was doing the work successfully without being certified. The Linux Foundation released their equivalent to Red Hat&#x27;s RHCSA - the Linux Foundation Certified SysAdmin (LFCS). The domains and competencies covered described all the tasks I have done since setting up my first Linux box - create users, partitions, edit text files, etc. I took the introduction to Linux course offered by the Linux Foundation on edx, and scheduled an exam for my LFCS. On my first try, I misconfigured RAID, and rebooted the server. (Whoops!) The Linux Foundation was gracious to allow a free retake which I passed. I kept going around to my co-workers (after being certified) and quoting my favorite Dilbert comic: &quot;Step away from that network server... I AM CERTIFIED!&quot;&lt;&#x2F;p&gt;
&lt;p&gt;At this time, my skilled co-workers left (not all at once) and my team turned out to be just me for a period of eight months to cover 1,100 network attached devices and 1,300 users. It was about this time I researched CMEs (Chef, CFEngine, and Puppet) to help do tasks. I eventually picked puppet and successfully deployed RPi-wayfinding with it. A year and a half later, I passed the Puppet Certified Professional exam. With that out of the way, I turned my attention to the LFCE - especially since the Linux Foundation had a sale on the course and test for less than the test amount. &lt;&#x2F;p&gt;
&lt;p&gt;The LFCE was the easiest certification test of all the ones I took. I scored an 88 out of 100, and I think the things I missed were saving the iptables rules :&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;My next step is to take an AWS certificate test as I have been using AWS for nearly 2 years, but I will probably take an OpenStack cert first as I was given a discounted rate for the cert + course from the Linux Foundation.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Deploying Puppet Open Source</title>
        <published>2016-10-21T14:00:00+00:00</published>
        <updated>2016-10-21T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-10-21-deploying-puppet-open-source/" type="text/html"/>
        <id>/2016-10-21-deploying-puppet-open-source/</id>
        
            <content type="html">&lt;p&gt;&lt;strong&gt;Update: (5&#x2F;28&#x2F;17)&lt;&#x2F;strong&gt; yes, there is the puppet&#x2F;r10k which supercedes the zack&#x2F;r10k. While you are free to deviate from the article in your own environment, the below steps still work as intended. I will have to update this article as well as explain why having r10k and dynamic environments is a good idea.&lt;&#x2F;p&gt;
&lt;p&gt;In this guide we will go over best practices to deploy Puppet Open Source using the recommended workflow (r10k), PuppetDB, and the foreman. You can deploy Puppet server on any of their supported *nix distributions. In this tutorial we will assume it to be on CentOS 7 as this seems to have the best support.&lt;&#x2F;p&gt;
&lt;p&gt;The overall scope of this tutorial is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Set up foreman&lt;&#x2F;li&gt;
&lt;li&gt;Set up a control repo&lt;&#x2F;li&gt;
&lt;li&gt;Download r10k module&lt;&#x2F;li&gt;
&lt;li&gt;Run puppet apply on r10k.pp (with web hook)&lt;&#x2F;li&gt;
&lt;li&gt;Set up PuppetDB&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Foreman installation is the easiest. Just head over to &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theforeman.org&#x2F;manuals&#x2F;1.12&#x2F;index.html#2.1Installation&quot;&gt;https:&#x2F;&#x2F;www.theforeman.org&#x2F;manuals&#x2F;1.12&#x2F;index.html#2.1Installation&lt;&#x2F;a&gt;, select CentOS 7 and follow the 5 easy steps. The defaults are fine, but if you want to provision hosts on Digital Ocean or Amazon Web Services, be sure to use interactive mode (the &lt;code&gt;-i&lt;&#x2F;code&gt; switch on &lt;code&gt;foreman-installer&lt;&#x2F;code&gt;) and configure those settings. You can also re-run the installer as it will remember previous settings. Since the foreman installer is built with puppet, it will not override any settings - just enforce them. This allows running the &lt;code&gt;foreman-installer&lt;&#x2F;code&gt; on an already provisioned &lt;code&gt;puppetserver&lt;&#x2F;code&gt; non-destructive.&lt;&#x2F;p&gt;
&lt;p&gt;The control repo is the next step and is also very easy to perform. Just fork the &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;puppetlabs&#x2F;control-repo&quot;&gt;Puppet control-repo&lt;&#x2F;a&gt; to a local git repository or private git location. Instructions are included in the repo on how to set it up on a gitlab server.&lt;&#x2F;p&gt;
&lt;p&gt;Once &lt;code&gt;foreman&lt;&#x2F;code&gt; has installed completely, install the &lt;code&gt;zack&#x2F;r10k&lt;&#x2F;code&gt; module to manage r10k by running &lt;code&gt;puppet module install zack-r10k&lt;&#x2F;code&gt;. This downloads all prerequisites for managing r10k and getting the ball rolling on a great DevOps practice. You will then need to apply a new puppet manifest to manage r10k&#x27;s installation and configuration. You can do that by creating &lt;code&gt;r10k-install.pp&lt;&#x2F;code&gt; with the following contents:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#Fixes Puppet 4 path for webhook
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file {&amp;#39;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;puppet&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ensure =&amp;gt; link,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  target =&amp;gt; &amp;#39;&#x2F;opt&#x2F;puppetlabs&#x2F;bin&#x2F;puppet&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { &amp;#39;r10k&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # Point this to your forked control-repo
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  remote       =&amp;gt; &amp;#39;git@localgitrepo:puppet&#x2F;control-repo.git&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # You will need to create this ssh-key pair
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  git_settings =&amp;gt; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     &amp;#39;private_key&amp;#39; =&amp;gt; &amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppetserver&#x2F;r10k&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Instead of running via mco, run r10k directly
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class {&amp;#39;r10k::webhook::config&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  use_mcollective  =&amp;gt; false,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # replace the file names with the correct cert names
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  public_key_path  =&amp;gt; &amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;ssl&#x2F;certs&#x2F;puppet.example.org.pem&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  private_key_path =&amp;gt; &amp;#39;&#x2F;etc&#x2F;puppetlabs&#x2F;puppet&#x2F;ssl&#x2F;private_keys&#x2F;puppet.example.org.pem&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# this exposes https:&#x2F;&#x2F;0.0.0.0:8088&#x2F;payload for git webhooks
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class {&amp;#39;r10k::webhook&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  use_mcollective =&amp;gt; false,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  user            =&amp;gt; &amp;#39;root&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  group           =&amp;gt; &amp;#39;0&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  require         =&amp;gt; Class[&amp;#39;r10k::webhook::config&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With that file saved, run &lt;code&gt;puppet apply r10k.pp&lt;&#x2F;code&gt;. This will enforce and set up r10k.&lt;&#x2F;p&gt;
&lt;p&gt;One of the last things I do on a new Puppet 4 installation is set up PuppetDB. PuppetDB is used to collect exported resources and return them to nodes that want them (i.e. the built-in nagios plugin). By now you should already have puppet installed and working without error. To add PuppetDB into the environment, it is as simple as editing the &lt;code&gt;Puppetfile&lt;&#x2F;code&gt; in your control repo to have &lt;code&gt;mod &#x27;puppetlabs&#x2F;puppetdb&#x27;&lt;&#x2F;code&gt; and &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forge.puppet.com&#x2F;puppetlabs&#x2F;puppetdb&#x2F;dependencies&quot;&gt;matching the dependencies for the PuppetDB module&lt;&#x2F;a&gt;. Next edit your &lt;code&gt;site.pp&lt;&#x2F;code&gt; manifest to include the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;node &amp;#39;puppet&amp;#39; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # Configure puppetdb and its underlying database
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  class { &amp;#39;puppetdb&amp;#39;: }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # Configure the Puppet master to use puppetdb
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  class { &amp;#39;puppetdb::master::config&amp;#39;: }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # ... r10k stuff should go here. Make sure to add the module and its dependencies to the Puppetfile!
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the next puppet run, you should have a solid Puppet environment. Your next step would be to set up the git webhook. This is so that every time you push changes to the repo, r10k updates them on your puppet master. Welcome to the club :)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Hobby vs responsibility</title>
        <published>2016-10-14T13:00:00+00:00</published>
        <updated>2016-10-14T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-10-14-hobby-vs-responsibility/" type="text/html"/>
        <id>/2016-10-14-hobby-vs-responsibility/</id>
        
            <content type="html">&lt;p&gt;One of my hobbies is video gaming. In my teen years, I would spend on average of 60-80 hours a week playing either Counter Strike, Team Fortress 2, or any other Valve software title. It was not until I went to college and got a job when my average went to 30-40 hours a week. After being married and having children, my average is now down to 8-12 hours a week. As my responsibilities increased, my hobby time decreased. I would consider myself addicted to video games (i.e. I cannot stop playing them); however, I do not feel like I am missing out from partaking in my hobby. Here is what I have done to lower my addiction to video games:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I stopped playing multiplayer FPS&lt;&#x2F;li&gt;
&lt;li&gt;I only buy video games that run on Linux&lt;&#x2F;li&gt;
&lt;li&gt;I play during specific time frames only&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;My current favorite game is Factorio - you crash landed on a distant planet and have to build a rocket to escape.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Repercussions from a 1.1 Tbsp DDoS</title>
        <published>2016-10-07T13:00:00+00:00</published>
        <updated>2016-10-07T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-10-07-repercussions-from-a-1-1-tbsp-ddos/" type="text/html"/>
        <id>/2016-10-07-repercussions-from-a-1-1-tbsp-ddos/</id>
        
            <content type="html">&lt;p&gt;In case you missed it, &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.google.com&#x2F;search?q=1.1+Tbps+ddos&quot;&gt;the largest recorded Direct Denial of Service (DDoS) occurred&lt;&#x2F;a&gt;. While under DDoS, a victim&#x27;s server (or servers) is under high load and cannot complete all requests that are requested by it. Basically, a DDoS victim is someone the attacker wants silenced on the internet. In order to send a DDoS of that magnitude, the attacker has to have control over many computers - a botnet. It is believed that this attack originated from over 150,000 computers in the IoT category (smart TVs, refrigerators, thermostats, etc.). Due to their poor default security, the IoT devices are easy targets for hackers who intend on adding them to their botnets. &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;arstechnica.com&#x2F;security&#x2F;2016&#x2F;09&#x2F;linux-kernel-security-needs-fixing&#x2F;&quot;&gt;A recent article on Ars Technica points out the current issues with IoT and Linux kernel security&lt;&#x2F;a&gt;, but with most articles of this nature, provides no clear cut solution to the problem we are experiencing. Below are my thoughts to this current situation and how it may be resolved.&lt;&#x2F;p&gt;
&lt;p&gt;We need a governing body to issue a seal of approval for IoT and anything that is compiled with the Linux kernel. Then we, as consumers, must use, buy, and encourage others to buy from the companies that have this seal. The governing body should ensure each company seeking the seal comply with the following criteria:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Every new device created and sent to market has a minimum of 5 years worth of bi-monthly security patches and updates since the day of release to the public.&lt;&#x2F;li&gt;
&lt;li&gt;In the event the company goes bankrupt, dissolves, or cannot support any older product they have released in the past 5 years, the company must provide schematics, instructions, or software that open source enthusiasts can recreate, patch, or upgrade the legacy product.&lt;&#x2F;li&gt;
&lt;li&gt;No known vulnerability must be willingly left unpatched.&lt;&#x2F;li&gt;
&lt;li&gt;When a CVE is identified on a company&#x27;s product, a test case must be created and run on that code base for every future release.&lt;&#x2F;li&gt;
&lt;li&gt;A notification service must be in place when new updates are released and must be available in RSS or email form.&lt;&#x2F;li&gt;
&lt;li&gt;Automatic updates should occur over HTTPS&lt;&#x2F;li&gt;
&lt;li&gt;Backdoors, admin terminals, etc. should require a physical connector be applied on the device in order to grant access.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For a potential company to get this approval, it may seem like an arduous task to get all the controls in place; however, by applying DevOps methodologies, these tasks can be a simple feat. This would require the governing body to not only enforce the list, but also have the training available to comply to this list. For this reason, I suggest the Linux Foundation to become this governing body and issue out seals of approval.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>First puppet module published</title>
        <published>2016-09-30T13:00:00+00:00</published>
        <updated>2016-09-30T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-09-30-first-puppet-module-published/" type="text/html"/>
        <id>/2016-09-30-first-puppet-module-published/</id>
        
            <content type="html">&lt;p&gt;I completed my first public module for puppet and submitted it to the puppet forge. It seems too simple to compile into a build and submit it to the forge; however, I made it public for these reasons:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I needed experience with puppet code testing. This helped me at the most basic level.&lt;&#x2F;li&gt;
&lt;li&gt;I felt like someone else could benefit from the code - even if it is one person.&lt;&#x2F;li&gt;
&lt;li&gt;I wanted to do it.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Still, the code seems too juvenile to be submitted to the forge. All it does is take the hostname of a Digital Ocean droplet and submit its IP address as a new DNS record inside of Digital Ocean DNS. The code is &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;do_dns&quot;&gt;located here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I almost want to follow up with this and develop my duplicity module into reusable code for the community.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Signs you are doing IT wrong</title>
        <published>2016-09-23T08:01:47+00:00</published>
        <updated>2016-09-23T08:01:47+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-09-23-signs-you-are-doing-it-wrong/" type="text/html"/>
        <id>/2016-09-23-signs-you-are-doing-it-wrong/</id>
        
            <content type="html">&lt;ol&gt;
&lt;li&gt;You still use FTP&lt;&#x2F;li&gt;
&lt;li&gt;You use SFTP&lt;&#x2F;li&gt;
&lt;li&gt;You have a single server hosting 1 website, MySQL, and PHP. It has 4+ GB of RAM and you only have ~2,000 visitors a day.&lt;&#x2F;li&gt;
&lt;li&gt;You login via root&lt;&#x2F;li&gt;
&lt;li&gt;You don&#x27;t use version control&lt;&#x2F;li&gt;
&lt;li&gt;You use a control panel for servers which you have SSH access.&lt;&#x2F;li&gt;
&lt;li&gt;It takes you over an hour to migrate 1 website&lt;&#x2F;li&gt;
&lt;li&gt;Your DNS TTL records are over 10 minutes&lt;&#x2F;li&gt;
&lt;li&gt;Your SQL server is not accessible over SSL&#x2F;TLS&lt;&#x2F;li&gt;
&lt;li&gt;You use mod_php instead of reverse proxying to php-fpm&lt;&#x2F;li&gt;
&lt;li&gt;You develop for the web on Windows&lt;&#x2F;li&gt;
&lt;li&gt;You chmod 777&lt;&#x2F;li&gt;
&lt;li&gt;You use modules&#x2F;plugins that require chmod 777&lt;&#x2F;li&gt;
&lt;li&gt;You have no backups&lt;&#x2F;li&gt;
&lt;li&gt;You host multiple websites on one server (internal-only websites excluded)&lt;&#x2F;li&gt;
&lt;li&gt;You SSH with passwords&lt;&#x2F;li&gt;
&lt;li&gt;You reuse passwords&lt;&#x2F;li&gt;
&lt;li&gt;You don&#x27;t read books&lt;&#x2F;li&gt;
&lt;li&gt;You don&#x27;t attend conferences&lt;&#x2F;li&gt;
&lt;li&gt;You attend more than 6 conferences a year&lt;&#x2F;li&gt;
&lt;li&gt;You use skype for communication&lt;&#x2F;li&gt;
&lt;li&gt;You make a separate mobile site&lt;&#x2F;li&gt;
&lt;li&gt;You add more RAM to fix your memory leaks&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Iced coffee is the best</title>
        <published>2016-09-16T13:00:00+00:00</published>
        <updated>2016-09-16T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-09-16-iced-coffee-is-the-best/" type="text/html"/>
        <id>/2016-09-16-iced-coffee-is-the-best/</id>
        
            <content type="html">&lt;p&gt;I am not a very big fan of hot drinks, but I enjoy drinking a cup&#x2F;glass&#x2F;thermos&#x2F;pot&#x2F;gallon of coffee. I especially drink it more when my taste buds dance around and say, &quot;Wow! That was some good, quality coffee!&quot; A few weeks ago I set out to find a better way to make my favorite drink - iced coffee. In my opinion, the best method of procuring coffee is in whole bean form. I tend to buy a brand that is roasted in my region - supporting the local economy - that also tastes good. I store the whole bean bag in my freezer and the grounded bean in a small coffee can in my refrigerator.&lt;&#x2F;p&gt;
&lt;p&gt;At first, I tried pouring hot coffee over Frozen coffee cubes, then added my refrigerated creamer. This lasted for a few weeks, but I couldn&#x27;t notice a huge difference in taste between water iced cubes and coffee iced cubes.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, I tried cold brewing coffee - placing ground coffee beans in cold water into the refrigerator overnight. This only resulted in weak, flavorless coffee.&lt;&#x2F;p&gt;
&lt;p&gt;Next, I tried hot brewing coffee, pouring it into a container, and letting it sit in the refrigerator overnight. This seems to be the best option so far. I still get to keep my 1.5 tbsp ratio for coffee beans and resulting liquid. The iced cubes do not melt when the coffee is poured over them. I think I will stick to this option for now.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>My IoT device history</title>
        <published>2016-09-09T13:00:00+00:00</published>
        <updated>2016-09-09T13:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-09-09-my-iot-device-history/" type="text/html"/>
        <id>/2016-09-09-my-iot-device-history/</id>
        
            <content type="html">&lt;p&gt;The internet of things (IoT) is getting pretty saturated with devices most of which are either smart watches or activity trackers. Smart watches do not appeal to me as I have a very nasty habit of destroying the clock face of my watches. Last November, I was able to get a Vivosmart from Garmin for $60 plus tax and shipping. It was great - did step tracking, allowed for notifications, allowed me to dismiss calls and see texts. My brother-in-law also received one as a gift a few months later (he preferred it over the Fitbit which did less and cost more).&lt;&#x2F;p&gt;
&lt;p&gt;A month ago we both noticed the pixels disappearing on the Garmin Vivosmart display. I was able to submit a warranty request through their website quite painlessly, and the offered to upgrade me to a Garmin Vivosmart HR! Of course I took the upgrade offer and paid the shipping for the old device to be sent back. My brother-in-law had a complete different experience. The website at first said his Garmin Vivosmart was out of warranty (even though it was newer than mine) then it eventually - a day later - said it was in warranty. He was given the option to replace the Garmin Vivosmart with a non-HR model, but they gave him a shipping label. It is quite odd that we both had different experiences within a few days of submitting our warranty requests.&lt;&#x2F;p&gt;
&lt;p&gt;I recently received the newer model after waiting the RMA process and I am quite impressed. At first, the font was too skinny and hard to read, but all I had to do was upgrade to the latest firmware and it was fixed. One neat feature that was added (besides the obvious HR function) was the ability to see the weather - up to a 4 day forecast. Two new goal trackers were also added - a stair counter and strenuous activity counter. The plain Garmin Vivosmart&#x27;s battery lasted over a week. I haven&#x27;t depleted the new model all the way, but I am assuming it will last 4-5 days depending on my use.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Provisioning VMs with cloud init</title>
        <published>2016-09-02T14:00:00+00:00</published>
        <updated>2016-09-02T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-09-02-provisioning-vms-with-cloud-init/" type="text/html"/>
        <id>/2016-09-02-provisioning-vms-with-cloud-init/</id>
        
            <content type="html">&lt;p&gt;One of the easiest ways to deploy a virtual machine in oVirt is first to install the OS then turn it into a template. This will allow you to copy that template to deploy new instances. One mundane task after a new template is copied to a new instance is logging in, changing the IP, setting the hostname, setting up Puppet, running puppet, etc. &lt;code&gt;cloud-init&lt;&#x2F;code&gt; is the tool designed to fix that mundane task process by allowing those steps to be automated. oVirt&#x2F;RHEV (as well as OpenStack, AWS, and others) allow you to pass in user data which is then supplied to &lt;code&gt;cloud-init&lt;&#x2F;code&gt; after the template is copied over and turned on. This allows for scripting on the new VM - easing deployment.&lt;&#x2F;p&gt;
&lt;p&gt;For my environment, I wanted a CentOS 7 template. To have that, I must first install CentOS on a new VM and seal it (Windows calls this Sysprep). Before I seal it, I must install &lt;code&gt;cloud-init&lt;&#x2F;code&gt; and any other tools I might use for deployment - such as &lt;code&gt;puppet&lt;&#x2F;code&gt;. Here are the steps to obtain just that:&lt;&#x2F;p&gt;
&lt;p&gt;* Install CentOS 7.2 Minimal on any new VM. Ensure to have LVM partitioning as you may want to extend the disk later. I have found that 10 GB is a good starting size.&lt;&#x2F;p&gt;
&lt;p&gt;* Install your base files - things you cannot live without (i.e. &lt;code&gt;vim&lt;&#x2F;code&gt;,&lt;code&gt;puppet&lt;&#x2F;code&gt;, etc).&lt;&#x2F;p&gt;
&lt;p&gt;* Seal the VM &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;access.redhat.com&#x2F;documentation&#x2F;en-US&#x2F;Red_Hat_Enterprise_Virtualization&#x2F;3.5&#x2F;html&#x2F;Administration_Guide&#x2F;sect-Sealing_Virtual_Machines_in_Preparation_for_Deployment_as_Templates.html#sect-Sealing_a_Linux_Virtual_Machine_for_Deployment_as_a_Template&quot;&gt;per RedHat instructions&lt;&#x2F;a&gt;. I suggest following the instructions for sysunconfig:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Log in to the virtual machine.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Remove ssh host keys:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# rm -rf &#x2F;etc&#x2F;ssh&#x2F;ssh_host_*
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Set &lt;code&gt;HOSTNAME=localhost.localdomain&lt;&#x2F;code&gt; in &lt;code&gt;&#x2F;etc&#x2F;sysconfig&#x2F;network&lt;&#x2F;code&gt; for Red Hat Enterprise Linux 6&#x2F;CentOS 6 or &lt;code&gt;&#x2F;etc&#x2F;hostname&lt;&#x2F;code&gt; for Red Hat Enterprise Linux 7&#x2F;CentOS 7.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Remove the &lt;code&gt;HWADDR&lt;&#x2F;code&gt; line and &lt;code&gt;UUID&lt;&#x2F;code&gt; line from &lt;code&gt;&#x2F;etc&#x2F;sysconfig&#x2F;network-scripts&#x2F;ifcfg-eth*&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Optionally, delete all the logs from &lt;code&gt;&#x2F;var&#x2F;log&lt;&#x2F;code&gt; and build logs from &lt;code&gt;&#x2F;root&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;sys-unconfig&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;code&gt;sys-unconfig&lt;&#x2F;code&gt; will turn off the VM when it is completed. When it is turned off, right click the VM and select copy to template.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Securing PWM</title>
        <published>2016-08-26T14:49:51+00:00</published>
        <updated>2016-08-26T14:49:51+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-08-26-securing-pwm/" type="text/html"/>
        <id>/2016-08-26-securing-pwm/</id>
        
            <content type="html">&lt;p&gt;In &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;andrewwippler.com&#x2F;2016&#x2F;08&#x2F;19&#x2F;password-management-portal-for-end-users&#x2F;&quot;&gt;last week&#x27;s post&lt;&#x2F;a&gt; we set up PWM insecurely. In this post, we are going to secure it down and install mysql to store the reset questions. This guide assumes you have this CentOS 7 server publicly accessible with ports 80 and 443 available to the entire world. First, we will need to install mysql, set up a database, and add a user to that database. To do that, we need to edit our &lt;code&gt;manifest.pp&lt;&#x2F;code&gt; and append the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; class { &amp;#39;::mysql::server&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     root_password           =&amp;gt; &amp;#39;My4cc0unt$$password!&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     remove_default_accounts =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     package_name            =&amp;gt; &amp;#39;mariadb-server&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     package_ensure          =&amp;gt; &amp;#39;installed&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     service_name            =&amp;gt; &amp;#39;mariadb&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; mysql::db { &amp;#39;pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     user     =&amp;gt; &amp;#39;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     password =&amp;gt; &amp;#39;pwm_passworD2!&amp;#39;, # Can&amp;#39;t do a password hash here :(
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; class { &amp;#39;mysql::bindings&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     java_enable =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file { &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;lib&#x2F;mysql-connector-java.jar&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ensure  =&amp;gt; link,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     target  =&amp;gt; &amp;#39;&#x2F;usr&#x2F;share&#x2F;java&#x2F;mysql-connector-java.jar&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     require =&amp;gt; Class[&amp;#39;mysql::bindings&amp;#39;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will also need to install additional modules:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install puppetlabs-firewall
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install jfryman-nginx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install jfryman-selinux
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install danzilio-letsencrypt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can set up our web server and directories by appending the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file {&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ensure =&amp;gt; &amp;#39;directory&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     owner  =&amp;gt; &amp;#39;nginx&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file {&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&#x2F;index.html&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ensure  =&amp;gt; &amp;#39;file&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     owner   =&amp;gt; &amp;#39;nginx&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     content =&amp;gt; &amp;#39;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0;URL=&#x2F;pwm&amp;quot; &#x2F;&amp;gt;&amp;lt;&#x2F;head&amp;gt;&amp;lt;&#x2F;html&amp;gt;&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     require =&amp;gt; File[&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;firewall { &amp;#39;100 allow http, https access&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     dport  =&amp;gt; [80, 443],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     proto  =&amp;gt; tcp,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     action =&amp;gt; accept,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;selinux::fcontext {&amp;#39;set-httpd-context&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     context  =&amp;gt; &amp;quot;httpd_sys_content_t&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     pathname =&amp;gt; &amp;quot;&#x2F;var&#x2F;www(&#x2F;.*)?&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;selinux::boolean {&amp;#39;httpd_can_network_connect&amp;#39;: }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { &amp;#39;nginx&amp;#39;: }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nginx::resource::upstream { &amp;#39;pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     members =&amp;gt; [ &amp;#39;localhost:8080&amp;#39; ],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nginx::resource::vhost { &amp;quot;${::hostname}.${::domain}&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ensure           =&amp;gt; present,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     www_root         =&amp;gt; &amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&#x2F;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     #ssl              =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     index_files      =&amp;gt; [],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     try_files        =&amp;gt; [&amp;#39;$uri&amp;#39;,&amp;#39;$uri&#x2F;index.html&amp;#39;,&amp;#39;@pwm&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     #rewrite_to_https =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     #ssl_cert         =&amp;gt; &amp;quot;&#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;${::fqdn}&#x2F;fullchain.pem&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     #ssl_key          =&amp;gt; &amp;quot;&#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;${::fqdn}&#x2F;privkey.pem&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nginx::resource::location{&amp;#39;@pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     proxy =&amp;gt; &amp;#39;http:&#x2F;&#x2F;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     vhost =&amp;gt; &amp;quot;${::hostname}.${::domain}&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ssl   =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;``` Leave the ssl options commented out for now. We need the web server set up before running letsencrypt. After we save the file and run another&lt;&#x2F;code&gt;puppet apply manifest.pp` we can add the letsencrypt information and uncomment the ssl information.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { ::letsencrypt:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     email   =&amp;gt; &amp;#39;andrew.wippler@example.com&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     require =&amp;gt; Class[&amp;#39;nginx&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;letsencrypt::certonly { &amp;#39;pwm cert&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     domains       =&amp;gt; [&amp;quot;${::fqdn}&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     plugin        =&amp;gt; &amp;#39;webroot&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     webroot_paths =&amp;gt; [&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     manage_cron   =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply the manifest one more time and enjoy your new instance of PWM. As a reference, my entire manifest can be seen below:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include git
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include java
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tomcat::install { &amp;#39;&#x2F;opt&#x2F;tomcat8&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  source_url =&amp;gt; &amp;#39;https:&#x2F;&#x2F;www.apache.org&#x2F;dist&#x2F;tomcat&#x2F;tomcat-8&#x2F;v8.5.3&#x2F;bin&#x2F;apache-tomcat-8.5.3.tar.gz&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tomcat::instance { &amp;#39;tomcat8-pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  catalina_home =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  catalina_base =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tomcat::war { &amp;#39;pwm.war&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  catalina_base =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  war_source    =&amp;gt; &amp;#39;&#x2F;path&#x2F;to&#x2F;pwm.war&amp;#39;, # or http:&#x2F;&#x2F;domain.tld&#x2F;pwm.war
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  before        =&amp;gt; File[&amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;lib&#x2F;mysql-connector-java.jar&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;augeas { &amp;#39;web.xml&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  incl =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;webapps&#x2F;pwm&#x2F;WEB-INF&#x2F;web.xml&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  context =&amp;gt; &amp;#39;&#x2F;files&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;webapps&#x2F;pwm&#x2F;WEB-INF&#x2F;web.xml&#x2F;web-app&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  lens    =&amp;gt; &amp;#39;Xml.lns&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  changes =&amp;gt; &amp;#39;set context-param[1]&#x2F;param-value&#x2F;#text &#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;webapps&#x2F;pwm&#x2F;WEB-INF&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { &amp;#39;::mysql::server&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  root_password           =&amp;gt; &amp;#39;My4cc0unt$$password!&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  remove_default_accounts =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  package_name            =&amp;gt; &amp;#39;mariadb-server&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  package_ensure   	  =&amp;gt; &amp;#39;installed&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  service_name            =&amp;gt; &amp;#39;mariadb&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mysql::db { &amp;#39;pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  user     =&amp;gt; &amp;#39;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  password =&amp;gt; &amp;#39;pwm_passworD2!&amp;#39;, # Can&amp;#39;t do a password hash here :(
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { &amp;#39;mysql::bindings&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  java_enable =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file { &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;lib&#x2F;mysql-connector-java.jar&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ensure  =&amp;gt; link,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  target  =&amp;gt; &amp;#39;&#x2F;usr&#x2F;share&#x2F;java&#x2F;mysql-connector-java.jar&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  require =&amp;gt; Class[&amp;#39;mysql::bindings&amp;#39;]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file {&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ensure =&amp;gt; &amp;#39;directory&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  owner  =&amp;gt; &amp;#39;nginx&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file {&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&#x2F;index.html&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ensure  =&amp;gt; &amp;#39;file&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  owner   =&amp;gt; &amp;#39;nginx&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  content =&amp;gt; &amp;#39;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;0;URL=&#x2F;pwm&amp;quot; &#x2F;&amp;gt;&amp;lt;&#x2F;head&amp;gt;&amp;lt;&#x2F;html&amp;gt;&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  require =&amp;gt; File[&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;firewall { &amp;#39;100 allow http, https access&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  dport   =&amp;gt; [80, 443],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  proto  =&amp;gt; tcp,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  action =&amp;gt; accept,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;selinux::fcontext {&amp;#39;set-httpd-context&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  context  =&amp;gt; &amp;quot;httpd_sys_content_t&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  pathname =&amp;gt; &amp;quot;&#x2F;var&#x2F;www(&#x2F;.*)?&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;selinux::boolean {&amp;#39;httpd_can_network_connect&amp;#39;: }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { &amp;#39;nginx&amp;#39;: }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nginx::resource::upstream { &amp;#39;pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  members =&amp;gt; [ &amp;#39;localhost:8080&amp;#39; ],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nginx::resource::vhost { &amp;quot;${::hostname}.${::domain}&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ensure           =&amp;gt; present,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     index_files      =&amp;gt; [],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     www_root         =&amp;gt; &amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&#x2F;&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ssl              =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     try_files        =&amp;gt; [&amp;#39;$uri&amp;#39;, &amp;#39;$uri&#x2F;index.html&amp;#39;, &amp;#39;@pwm&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     rewrite_to_https =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ssl_cert         =&amp;gt; &amp;quot;&#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;${::fqdn}&#x2F;fullchain.pem&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ssl_key          =&amp;gt; &amp;quot;&#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;${::fqdn}&#x2F;privkey.pem&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nginx::resource::location{&amp;#39;@pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     proxy =&amp;gt; &amp;#39;http:&#x2F;&#x2F;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     vhost =&amp;gt; &amp;quot;${::hostname}.${::domain}&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     ssl   =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class { ::letsencrypt:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    email   =&amp;gt; &amp;#39;andrew.wippler@example.com&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    require =&amp;gt; Class[&amp;#39;nginx&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;letsencrypt::certonly { &amp;#39;pwm cert&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    domains       =&amp;gt; [&amp;quot;${::fqdn}&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    plugin        =&amp;gt; &amp;#39;webroot&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    webroot_paths =&amp;gt; [&amp;quot;&#x2F;var&#x2F;www&#x2F;${::hostname}&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    manage_cron   =&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Password management portal for end users</title>
        <published>2016-08-19T14:00:00+00:00</published>
        <updated>2016-08-19T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-08-19-password-management-portal-for-end-users/" type="text/html"/>
        <id>/2016-08-19-password-management-portal-for-end-users/</id>
        
            <content type="html">&lt;p&gt;We in IT have heard it often, the #1 request coming into help desk ticket systems is password resets, account lockouts, and the like. PWM is a password reset web application written in Java for use with LDAP directories. You can configure it to work with Active Directory, OpenLDAP, FreeIPA, and others. There are already a handful of good tutorials on how to set up PWM (&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.serveradventures.com&#x2F;the-adventures&#x2F;installing-pwm-open-source-password-self-service-for-ldap&quot;&gt;I think of this one in particular&lt;&#x2F;a&gt;); however, I want to demonstrate the &lt;code&gt;puppet apply&lt;&#x2F;code&gt; command in this tutorial.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;&#x2F;h3&gt;
&lt;p&gt;This guide assumes you have an Active Directory server with TLS set up (to change passwords) which is beyond the scope of this post. It also assumes you have a CentOS 7 instance which can communicate to the Active Directory server. It also assumes this is in an environment without a puppet master&#x2F;server. The end manifest can be uploaded to a master and used that way.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;obtaining-pwm&quot;&gt;Obtaining PWM&lt;&#x2F;h3&gt;
&lt;p&gt;PWM is available in zip format &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.pwm-project.org&#x2F;artifacts&#x2F;pwm&#x2F;&quot;&gt;on their website&lt;&#x2F;a&gt; or in source format &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pwm-project&#x2F;pwm&quot;&gt;on GitHub&lt;&#x2F;a&gt;. We are going to use the war file so grab the zip from off of their website, extract it, and place it on a webserver or locally on the server.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;yum install wget unzip -y
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;wget http:&#x2F;&#x2F;www.pwm-project.org&#x2F;artifacts&#x2F;pwm&#x2F;pwm-1.8.0-SNAPSHOT-2016-05-23T22%3A36%3A58Z-pwm-bundle.zip
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;unzip pwm*.zip
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;installing-puppet-and-puppet-modules&quot;&gt;Installing puppet and puppet modules&lt;&#x2F;h3&gt;
&lt;p&gt;Our next step is to get puppet and relevant puppet modules&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;rpm -ivh http:&#x2F;&#x2F;yum.puppetlabs.com&#x2F;puppetlabs-release-pc1-el-7.noarch.rpm
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;yum install puppet -y
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;source &#x2F;etc&#x2F;profile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install puppetlabs-mysql
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install puppetlabs-java
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install puppetlabs-git
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install puppetlabs-concat
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;puppet module install puppetlabs-tomcat --ignore-dependencies
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are &lt;code&gt;--ignore-dependencies&lt;&#x2F;code&gt; because there is a conflicting staging module that the &lt;code&gt;mysql&lt;&#x2F;code&gt; module already installed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;vim manifest.pp
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The contents of this file are as below:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include git
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include java
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tomcat::install { &amp;#39;&#x2F;opt&#x2F;tomcat8&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  source_url =&amp;gt; &amp;#39;https:&#x2F;&#x2F;www.apache.org&#x2F;dist&#x2F;tomcat&#x2F;tomcat-8&#x2F;v8.5.3&#x2F;bin&#x2F;apache-tomcat-8.5.3.tar.gz&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tomcat::instance { &amp;#39;tomcat8-pwm&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  catalina_home =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  catalina_base =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tomcat::war { &amp;#39;pwm.war&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  catalina_base =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  war_source    =&amp;gt; &amp;#39;&#x2F;path&#x2F;to&#x2F;pwm.war&amp;#39;, # or http:&#x2F;&#x2F;domain.tld&#x2F;pwm.war
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;augeas {&amp;#39;web.xml&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	incl    =&amp;gt; &amp;#39;&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;webapps&#x2F;pwm&#x2F;WEB-INF&#x2F;web.xml&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	context =&amp;gt; &amp;#39;&#x2F;files&#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;webapps&#x2F;pwm&#x2F;WEB-INF&#x2F;web.xml&#x2F;web-app&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	lens    =&amp;gt; &amp;#39;Xml.lns&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	changes =&amp;gt; &amp;#39;set context-param[1]&#x2F;param-value&#x2F;#text &#x2F;opt&#x2F;tomcat8&#x2F;pwm&#x2F;webapps&#x2F;pwm&#x2F;WEB-INF&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now enforce the environment by issuing a &lt;code&gt;puppet apply manifest.pp&lt;&#x2F;code&gt;. This will install PWM (insecurely), java, git, and tomcat. PWM is insecure in this state as passwords can be intercepted before they hit the web server. &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;andrewwippler.com&#x2F;2016&#x2F;08&#x2F;26&#x2F;securing-pwm&#x2F;&quot;&gt;In a follow-up tutorial next week&lt;&#x2F;a&gt;, I will explain how to install mysql (to store the password reset questions) as well as placing nginx in front of tomcat to offer SSL and http to https redirection.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Avoiding Catastrophic Failure</title>
        <published>2016-08-12T15:00:18+00:00</published>
        <updated>2016-08-12T15:00:18+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-08-12-avoiding-catastrophic-failure/" type="text/html"/>
        <id>/2016-08-12-avoiding-catastrophic-failure/</id>
        
            <content type="html">&lt;p&gt;You may have already heard the news about &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.nbcnews.com&#x2F;news&#x2F;us-news&#x2F;delta-system-outage-triggers-delays-worldwide-n625141&quot;&gt;Delta Airlines catastrophic failure&lt;&#x2F;a&gt;. &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;arstechnica.com&#x2F;business&#x2F;2016&#x2F;08&#x2F;data-center-disaster-disrupts-delta-airlines&#x2F;&quot;&gt;Ars Technica reports&lt;&#x2F;a&gt; the true cause of the failure - &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.flyertalk.com&#x2F;forum&#x2F;27032000-post135.html&quot;&gt;routine maintenance of the power generators&lt;&#x2F;a&gt;. While it may be a little presumptuous or high on the bragging scale to have only one datacenter to house your entire infrastructure - this is not the best method. The blame is often placed on the IT personnel when computer systems go down, but in this case the error is shared. There was a maintenance individual who did not spot the potential of a fire, there is the building planning committee that placed the power sources too close together, there is the IT budgeting team that did not have an off-site solution, and there is the CTO misinformed on the infrastructure needs of a worldwide company. A catastrophic failure is anything that damages a company&#x27;s reputation.&lt;&#x2F;p&gt;
&lt;p&gt;I can understand the single point of failure - it is often found in SMB&#x2F;non-profit environments. The single point of failure happening is marginal at best. This causes it to be overlooked many times over as some will hope it never comes to encountering that scenario. Budgetary constraints are often the first road block, the second being time to implement, the third being the internal security practices of customer data, and the fourth being the time to restore after a catastrophic failure is less than 24 hours - these also minimizes the single point of failure in our minds. We so often minimize the single point of failure to where it loses its place as #1 concern to #100 on &quot;do someday task.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;We live in the best computer age right now. Catastrophic failures can be avoided. Here are a few ways to prevent catastrophic failures.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Keep up-to-date on current software trends&#x2F;best practices.&lt;&#x2F;li&gt;
&lt;li&gt;Don&#x27;t keep all of your eggs in one basket. Keep your services separated.&lt;&#x2F;li&gt;
&lt;li&gt;Research and obtain certifications relevant to IT, but not necessarily directly related to your field of work. For instance, a network engineer achieving a Linux certification or a SysAdmin getting a CCNA.&lt;&#x2F;li&gt;
&lt;li&gt;Get IT audited. If the audit returns no suggestions, get audited by another company within 3 months.&lt;&#x2F;li&gt;
&lt;li&gt;Simulate all the disaster recovery scenarios twice every 5 years. Have different managers perform the restore, meet with their findings (how long it takes, what is needed, budget), and record it in documentation.&lt;&#x2F;li&gt;
&lt;li&gt;Ease the restore time by having everything in a configuration management engine (Like Puppet, Chef, Anisble, Salt, and others)&lt;&#x2F;li&gt;
&lt;li&gt;Reward IT employees if there have been no service disruptions in the past month. Yes, do it regularly. It can be as simple as a thank-you card, gift card, or the ability to leave early one day in the next week.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I do not know Delta Airlines&#x27; software&#x2F;hardware stack, but I would estimate that they have at least a database and a front end that communicates with the database. With that estimation, it would be easy to set up an AWS environment where an auto scaling group contained a replica of the datacenter database. Even if it required a manual switch from on-premise to the cloud database, the total downtime would have been less than 20 minutes (10-15 minutes for the IT manager to find the wiki entry and delegate the task to the right guy, 5 minutes for DNS propagation). Maintaining something like this would be around $500&#x2F;month for the AWS VPN connection and database servers. If they go this route or not time will only tell. One thing is certain, change is going to be made to their infrastructure.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Common problems with Web Developers configuring LAMP&#x2F;LEMP</title>
        <published>2016-08-05T14:00:00+00:00</published>
        <updated>2016-08-05T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-08-05-common-problems-with-web-developers-configuring-lamplemp/" type="text/html"/>
        <id>/2016-08-05-common-problems-with-web-developers-configuring-lamplemp/</id>
        
            <content type="html">&lt;p&gt;I am a SysAdmin who likes to code. I would say I know a fair amount of web developing, but do not understand it like a web developer uunderstands it. I think the reverse is true as well - web developers know how to set up a LAMP&#x2F;LAMP stack, but they do not understand it as well as SysAdmin might understand it.&lt;&#x2F;p&gt;
&lt;p&gt;To be a successful SysAdmin, you need to relearn your field every 3-5 years. New versions of software come out, new OSes, new features, new methods, and new ideas come out every several months. It takes somebody dedicated to read news blogs, mailing lists, and following the appropriate people on social media to keep up with the rapid trends. Web developers do not have that time to dedicate to operations work. They only need infrastructure to work for their project and it doesn&#x27;t matter how well tuned the software is - if it works, that is all they need. Below are some common pitfalls I see with web developers.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Using Apache with mod_fastcgi&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;While this is the only option for php-fpm in Apache 2.2, Apache 2.4 brings along the better, high performing mod_proxy_fcgi. This method should be the standard in deploying an application in Apache. Using nginx with reverse proxy is also an alternative.&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Not befriending a SysAdmin.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Contrary to popular belief, SysAdmins are not the preventers of productivity. Some Web Developers would benefit from being nice to a SysAdmin, speaking to them, and interacting more often. SysAdmins like to tell their &quot;server stories&quot; of how their application, server, or network equipment is actually performing in production.&lt;&#x2F;p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Using maximum power on their dev machine&#x27;s VM&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Most dev VMs I see are over 2 vCPU and 4GB RAM. This brings an unreliable view of how the application will perform in production. A better way would be to create a 1 vCPU with 512 RAM and test on that. The smaller server footprint your application needs, the easier, faster, and cheaper we can scale it.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>The future without Microsoft Office products </title>
        <published>2016-07-29T14:00:00+00:00</published>
        <updated>2016-07-29T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-07-29-the-future-without-microsoft-office-products/" type="text/html"/>
        <id>/2016-07-29-the-future-without-microsoft-office-products/</id>
        
            <content type="html">&lt;p&gt;I recently submitted a proposal to remove Microsoft Office from off my network and switch to Google Apps for Work and LibreOffice. This would incur a cost savings of ~$17.50 per user per month (GAFW $5 plan versus Office 2016 Professional Plus, Corporate, Open License, License Only). Some may argue that there are better license options with Microsoft and the $508 per user per 2 years (with the open license; source: http:&#x2F;&#x2F;mla.microsoft.com) is not a fair estimation, however, it is not fair to compare a stagnant version of Office versus the always updated version of GAFW or LibreOffice.&lt;&#x2F;p&gt;
&lt;p&gt;With LibreOffice, I can contribute a patch, submit it upstream, get it reviewed, and have it accepted into main stream. If I couldn&#x27;t wait for it to get to upstream, I could recompile with my patch and get it deployed in a matter of hours. This is the power and strength of open source software. Even with Google Apps, I submit a feature request, wait for it, and get the updated version when it arrives - I don&#x27;t have to buy a new version to get this new feature. This is the power of SaaS.
Word processing is also not proprietary. What you see on the screen in Microsoft Office, Google Apps, or LibreOffice will be what you get when you print it out or email it. LibreOffice and Microsoft Office save in formats that are compatible with each other. LibreOffice reads and writes docx and xlsx, and Microsoft Office reads and writes odf and ods.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest hurdle to switch is that Microsoft Office included odbc connectors in a spreadsheet program (Excel) instead of directing users to a database program (access). LibreOffice did it right by making a spreadsheet program (calc) do spreadsheet things only and their database (base) connect via odbc to other databases. LibreOffice has Microsoft beat in that you can open more odbc types such as a MySQL database.&lt;&#x2F;p&gt;
&lt;p&gt;Before marrying me, my wife was a secretary for 5 years. All she used was Microsoft Office products until she used my computer to type a recipe document. Her response was, &quot;this is different.&quot; She told me later that she had to look for her formatting tools, but when she found them there was no difference except the tools she used were in different places than where they were in Microsoft Office. This is by far the best reason to use LibreOffice and Google Apps - you can save money and lose none of the features.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Refreshing Ruby Knowledge</title>
        <published>2016-07-22T14:00:45+00:00</published>
        <updated>2016-07-22T14:00:45+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-07-22-refreshing-ruby-knowledge/" type="text/html"/>
        <id>/2016-07-22-refreshing-ruby-knowledge/</id>
        
            <content type="html">&lt;p&gt;I see a trend in system administration tasks moving toward the Ruby programming language. Yes, you can still code in Perl, Python, Shell, etc., but Ruby seems to be growing in popularity as a choice in scripting language. It should be - it is certainly easier to type and it has a big community to go with it. I was first introduced to Ruby in 2009 and immediately after learning Ruby, I learned Ruby on Rails. At the time, Rails and the MVC model was too advanced for me and so I never used my knowledge. Mostly because Rails had many &quot;does this automatically so you do not need to include it in your code&quot; so it was difficult for a beginner.&lt;&#x2F;p&gt;
&lt;p&gt;Now nearly 7 years later, I am taking Ruby off my virtual bookshelf and blowing the bugs off of it and refreshing my knowledge - this time leaving Rails out of the picture. So far I am liking plain Ruby. Below are some resources I have used to sharpen my Ruby skills.&lt;&#x2F;p&gt;
&lt;p&gt;https:&#x2F;&#x2F;rubymonk.com&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;http:&#x2F;&#x2F;rubykoans.com&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;http:&#x2F;&#x2F;exercism.io&#x2F;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bonus-setting-up-the-exercism-client-on-fedora-24&quot;&gt;Bonus: Setting up the exercism client on Fedora 24&lt;&#x2F;h3&gt;
&lt;p&gt;The exercism client is written in Go. Go can fetch and install other Go programs as long as you have a Go workspace set up. To do that we will issue the following commands:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# To install go
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dnf install golang
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# To set up the workspace
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkdir -p ~&#x2F;gocode&#x2F;{bin,src,pkg}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo &amp;#39;export GOPATH=$HOME&#x2F;gocode&amp;#39; &amp;gt;&amp;gt; ~&#x2F;.profile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo &amp;#39;export export PATH=$PATH:$GOROOT&#x2F;bin:$GOPATH&#x2F;bin&amp;#39; &amp;gt;&amp;gt; ~&#x2F;.profile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;source ~&#x2F;.profile
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Those commands will set up the Go workspace and allow you to issue the next command: &lt;code&gt;go get -u github.com&#x2F;exercism&#x2F;cli&#x2F;exercism&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Linux training on sale until 7&#x2F;31&#x2F;16</title>
        <published>2016-07-21T12:40:19+00:00</published>
        <updated>2016-07-21T12:40:19+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-07-21-linux-training-on-sale-until-73116/" type="text/html"/>
        <id>/2016-07-21-linux-training-on-sale-until-73116/</id>
        
            <content type="html">&lt;p&gt;The Linux Foundation is offering select courses at a discount until 7&#x2F;31&#x2F;16. Some offers are up to 55% off. You can also get an additional 10% off in check-out by using the code &lt;code&gt;GSHOP&lt;&#x2F;code&gt;. That brings the prices down to:&lt;&#x2F;p&gt;
&lt;p&gt;$180 - For &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;training.linuxfoundation.org&#x2F;linux-courses&#x2F;system-administration-training&#x2F;essentials-of-system-administration&quot;&gt;Essentials of System Administration (LFS201)&lt;&#x2F;a&gt; or &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;training.linuxfoundation.org&#x2F;linux-courses&#x2F;system-administration-training&#x2F;linux-networking-and-administration&quot;&gt;Linux Networking and Administration (LFS211)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;$315 - &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;training.linuxfoundation.org&#x2F;linux-courses&#x2F;system-administration-training&#x2F;essentials-of-system-administration&quot;&gt;Essentials of System Administration&lt;&#x2F;a&gt; &lt;strong&gt;AND&lt;&#x2F;strong&gt; &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;training.linuxfoundation.org&#x2F;linux-courses&#x2F;system-administration-training&#x2F;linux-networking-and-administration&quot;&gt;Linux Networking and Administration&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;$269.10 - Certified Linux SysAdmin or Certified Linux Engineer&lt;&#x2F;p&gt;
&lt;p&gt;$495 - Certified Linux Rockstar&lt;&#x2F;p&gt;
&lt;p&gt;You can find these prices by using their special &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;go.linuxfoundation.org&#x2F;sysadminday2016&quot;&gt;system administrator appreciation sale page&lt;&#x2F;a&gt; and using the checkout code &lt;code&gt;GSHOP&lt;&#x2F;code&gt;. If you were looking for a time to level up your Linux knowledge, now is the time to do it.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>OpenWRT Captive Portal</title>
        <published>2016-07-15T14:00:34+00:00</published>
        <updated>2016-07-15T14:00:34+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-07-15-openwrt-captive-portal/" type="text/html"/>
        <id>/2016-07-15-openwrt-captive-portal/</id>
        
            <content type="html">&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;andrewwippler.com&#x2F;2016&#x2F;03&#x2F;11&#x2F;wifi-captive-portal&#x2F;&quot;&gt;In a previous post&lt;&#x2F;a&gt;, I explained how to set up a captive portal on a Raspberry Pi which was running Raspbian (Debian). If you read that article, you can skip the next paragraph.&lt;&#x2F;p&gt;
&lt;p&gt;A captive portal is a piece of software that prompts for user interaction before allowing the client to access the internet or other resources on the network. It is a combination of a firewall and a webserver. In this tutorial, I will explain how to create an open WiFi network on OpenWRT firmware. Before deploying an open WiFi network, you may want to consult a lawyer of the legality and restrictions for having one. You can also review what has been said by lawyers &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.mbm-law.net&#x2F;newsletter-articles&#x2F;wi-fi-hotspots-and-liability-concerns&#x2F;1229&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openwireless.org&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To set up a captive portal on a wireless access point (WAP), you will need to have the OpenWRT firmware installed and have at least 5mb of free space. My &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;amzn.to&#x2F;29fnwFa&quot;&gt;TP-Link 1043ND&lt;&#x2F;a&gt; had enough space and this article was tested against it. This article assumes you have OpenWRT installed without any additional addons and have plenty of space to spare.&lt;&#x2F;p&gt;
&lt;p&gt;Before you run any command on your device, be sure to check syntax and my comments of what the code does. You have the possibility of placing your WAP into a hard-to-recover state. At one point I placed my access point into a solid firewall that did not allow any traffic in or out! If you encounter this same scenario: stop, take a deep breath, and do a &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.openwrt.org&#x2F;doc&#x2F;howto&#x2F;generic.failsafe&quot;&gt;factory reset&lt;&#x2F;a&gt; from failsafe mode. In my particular model, I have the broadcast packet which made it easier to reset. It is not my intention with this article to brick your device. By following this article you acknowledge that I am not liable for any damages you may encounter and will not hold me responsible for the outcome on the device.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-the-router&quot;&gt;Setting up the router&lt;&#x2F;h3&gt;
&lt;p&gt;There is not much software needed after a fresh install of OpenWRT. It comes with all the bells and whistles and basically turns your $100 router into a $1,000 router. Since the commands need to run on the device, you will need to login via SSH or Telnet. You can enable SSH on the &lt;em&gt;System &amp;gt; Administration&lt;&#x2F;em&gt; page. Once connected, you will need to run the following 3 commands and keep the information safe. You will need these to revert back to using the LuCI admin interface.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci get uhttpd.main.index_file
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci get uhttpd.main.index_page
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci get uhttpd.main.cgi_prefix
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci get uhttpd.main.home
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;uci&lt;&#x2F;code&gt; is the program that interfaces with OpenWRT settings. We could manually edit the config files, but using this program makes life easier.&lt;&#x2F;p&gt;
&lt;p&gt;Next we need to install the two packages we need:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;opkg update
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;opkg install nginx iptables-mod-ipopt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we are ready to configure our hotspot.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setting-up-the-webserver&quot;&gt;Setting up the webserver&lt;&#x2F;h3&gt;
&lt;p&gt;The web server was the trickiest part in all of this. On one hand, you need to execute a scripting language and on the other hand, you had limited space so scripting languages were difficult to install. The micro httpd server which shipped with OpenWRT was sufficient to run the scripts needed, but I was unable to get the magic packet to work properly. My solution was to install &lt;code&gt;nginx&lt;&#x2F;code&gt; and have it listen on port 81.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set up nginx.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;etc&#x2F;nginx&#x2F;nginx.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;user nobody nogroup;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;worker_processes  1;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;events {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    worker_connections  2048;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;http {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    include       mime.types;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    sendfile        on;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    keepalive_timeout  65;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    server {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        listen       81 default_server;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location &#x2F; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            root   html;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            index  index.html index.htm;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            return 302 http:&#x2F;&#x2F;hotspot.localnet&#x2F;hotspot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;   }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;setting-up-the-redirection&quot;&gt;Setting up the redirection&lt;&#x2F;h3&gt;
&lt;p&gt;I had to change the form method from a POST to a GET. This puts my passphrase (so I know they read and acknowledged the TOS) in the URL. There might be a better way to do this. This line of code will set up the hotspot file that will serve my content.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;www&#x2F;cgi-bin&#x2F;hotspot
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo &amp;quot;Content-type: text&#x2F;html&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo &amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if [ &amp;quot;$QUERY_STRING&amp;quot; = &amp;quot;&amp;quot; ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#Do captive portal detection
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	CNS=$(echo &amp;quot;$HTTP_USER_AGENT&amp;quot; | grep -o CaptiveNetworkSupport)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	if [ &amp;quot;$CNS&amp;quot; = &amp;quot;CaptiveNetworkSupport&amp;quot; ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;		echo &amp;quot;&amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	 &amp;lt;!--
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	 &amp;lt;?xml version=\&amp;quot;1.0\&amp;quot; encoding=\&amp;quot;UTF-8\&amp;quot;?&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;   &amp;lt;WISPAccessGatewayParam xmlns:xsi=&amp;quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2001&#x2F;XMLSchema-instance&amp;quot; xsi:noNamespaceSchemaLocation=&amp;quot;http:&#x2F;&#x2F;www.wballiance.net&#x2F;wispr_2_0.xsd&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;Redirect&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;MessageType&amp;gt;100&amp;lt;&#x2F;MessageType&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;ResponseCode&amp;gt;0&amp;lt;&#x2F;ResponseCode&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;VersionHigh&amp;gt;2.0&amp;lt;&#x2F;VersionHigh&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;VersionLow&amp;gt;1.0&amp;lt;&#x2F;VersionLow&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;AccessProcedure&amp;gt;1.0&amp;lt;&#x2F;AccessProcedure&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;AccessLocation&amp;gt;Andrew Wippler is awesome&amp;lt;&#x2F;AccessLocation&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;LocationName&amp;gt;MyOpenAP&amp;lt;&#x2F;LocationName&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;LoginURL&amp;gt;http:&#x2F;&#x2F;hotspot.localnet&#x2F;?r=1&amp;lt;&#x2F;LoginURL&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;Redirect&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;WISPAccessGatewayParam&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	 --&amp;gt;&amp;lt;&#x2F;html&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	 else
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	  echo &amp;quot;&amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	  &amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	    &amp;lt;title&amp;gt;Redirecting&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	    &amp;lt;META http-equiv=\&amp;quot;refresh\&amp;quot; content=\&amp;quot;0;URL=http:&#x2F;&#x2F;hotspot.localnet&#x2F;hotspot?r=1\&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	  &amp;lt;&#x2F;head&amp;gt; &amp;lt;body&amp;gt;&amp;lt;&#x2F;body&amp;gt;&amp;lt;&#x2F;html&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	  fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# After captive portal redirection
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Check to see if accepted TOS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;PASSPHRASE=$(echo &amp;quot;$QUERY_STRING&amp;quot; | grep -o andrew-wippler-is-cool )
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if [ &amp;quot;$PASSPHRASE&amp;quot; != &amp;quot;andrew-wippler-is-cool&amp;quot; ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  	echo &amp;quot;&amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      &amp;lt;title&amp;gt;&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      &amp;lt;h1&amp;gt;Authorization Required&amp;lt;&#x2F;h1&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      &amp;lt;p&amp;gt;Before continuing, you must first agree to the &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Terms of Service&amp;lt;&#x2F;a&amp;gt; and be of the legal age to do that in your selective country or have Parental Consent.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      &amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;      &amp;lt;form method=&amp;#39;GET&amp;#39; action=&amp;#39;&#x2F;hotspot&amp;#39;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &amp;lt;input type=&amp;#39;hidden&amp;#39; name=&amp;#39;security_code&amp;#39; value=&amp;#39;andrew-wippler-is-cool&amp;#39; &#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &amp;lt;input type=&amp;#39;checkbox&amp;#39; name=&amp;#39;checkbox1&amp;#39; CHECKED &#x2F;&amp;gt;&amp;lt;label for=&amp;#39;checkbox1&amp;#39;&amp;gt;I Agree to the terms&amp;lt;&#x2F;label&amp;gt;&amp;lt;br &#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &amp;lt;input type=&amp;#39;submit&amp;#39; value=&amp;#39;Connect&amp;#39; &#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &amp;lt;&#x2F;form&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;&#x2F;html&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  # User accepted TOS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  else
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # Grab the MAC address
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    MAC_ADDRESS=$(cat &#x2F;proc&#x2F;net&#x2F;arp | grep $REMOTE_ADDR | awk {&amp;#39;print $4&amp;#39;})
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # Add device to the firewall
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    iptables -t mangle -A wlan0_Outgoing -m mac --mac-source &amp;quot;$MAC_ADDRESS&amp;quot; -j MARK --set-mark 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    sleep 5
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    echo &amp;quot;&amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;title&amp;gt;&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;h1&amp;gt;You are now free to browse the internet.&amp;lt;&#x2F;h1&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;&#x2F;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;&#x2F;html&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;setting-up-the-firewall&quot;&gt;Setting up the firewall&lt;&#x2F;h3&gt;
&lt;p&gt;The following commands will set up the firewall to be just like the one in my other post. The difference here is that we are adding them to our custom firewall file which is preserved through reboots.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt;&amp;gt; &#x2F;etc&#x2F;firewall.user
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -N wlan0_Trusted
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -N wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -N wlan0_Incoming
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -I PREROUTING 1 -i br-lan -j wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -I PREROUTING 1 -i br-lan -j wlan0_Trusted
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -I POSTROUTING 1 -o br-lan -j wlan0_Incoming
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Router
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A PREROUTING -i br-lan -j wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Outgoing -d 192.168.24.1 -j wlan0_Router
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Router -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Outgoing -j wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Internet -m mark --mark 0x2 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Internet -j wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -j wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -j wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -p tcp --dport 80 -j DNAT --to-destination 192.168.24.1:81
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Known
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -I FORWARD -i br-lan -j wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -m state --state INVALID -j DROP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -o eth0.2 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -j wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_AuthServers -d 192.168.24.1 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -j wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Global -d andrewwippler.com -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -m mark --mark 0x2 -j wlan0_Known
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Known -d 0.0.0.0&#x2F;0 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -j wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p udp --dport 53 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p tcp --dport 53 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p udp --dport 67 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p tcp --dport 67 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -j REJECT --reject-with icmp-port-unreachable
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A POSTROUTING -o eth0.2 -j MASQUERADE
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;final-steps&quot;&gt;Final steps&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we are done with the preliminary work, we are ready to switch from the LuCI admin website to our own captive portal solution. The below commands will get you in that state. Once you do these commands, the admin section will be disabled (unless you reverse the four commands I told you to write down the values for).&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set up dnsmasq
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set dhcp.lan.start=&amp;#39;3&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set dhcp.lan.limit=&amp;#39;254&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set dhcp.lan.leasetime=&amp;#39;1h&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set network.lan.ipaddr=&amp;#39;192.168.24.1&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# set up static DNS entry
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci add dhcp domain
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci add_list dhcp.@domain[0].ip=192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci add_list dhcp.@domain[0].name=hotspot.localnet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set dns servers to be the router
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set dhcp.lan.dhcp_option=&amp;#39;6,192.168.24.1&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set WAP Name
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set wireless.@wifi-iface[0].ssid=MyOpenAP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Point uhttpd to our new document root
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set uhttpd.main.index_file=&amp;#39;hotspot&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set uhttpd.main.index_page=&amp;#39;hotspot&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set uhttpd.main.cgi_prefix=&amp;#39;&#x2F;&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci set uhttpd.main.home=&amp;#39;&#x2F;www&#x2F;cgi-bin&#x2F;&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Save to NVRAM
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;uci commit
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Turn on our work
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;etc&#x2F;init.d&#x2F;nginx start
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;etc&#x2F;init.d&#x2F;uhttpd restart
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;etc&#x2F;init.d&#x2F;firewall restart
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If all went well, you should be prompted with a captive portal alert on your device.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Puppet with Mac and GNU&#x2F;Linux</title>
        <published>2016-07-08T14:00:00+00:00</published>
        <updated>2016-07-08T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-07-08-puppet-with-mac-and-gnulinux/" type="text/html"/>
        <id>/2016-07-08-puppet-with-mac-and-gnulinux/</id>
        
            <content type="html">&lt;p&gt;Puppet on Mac is a mixture of Puppet on Linux and Windows. Registry settings are called &quot;secrets&quot; and to make things easier, you need to install homebrew.&lt;&#x2F;p&gt;
&lt;p&gt;Enforcing a local admin is a little bit tedious. In the past few OSX releases, the have changed their password hashing algorithm several times. This causes a few case statements based on release version in order to set up one single local admin.&lt;&#x2F;p&gt;
&lt;p&gt;Secret management is a little more complicated than Windows registry management. First, you need to find your secret decoder website (&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20150409073759&#x2F;http:&#x2F;&#x2F;secrets.blacktree.com&#x2F;&quot;&gt;which is now only available in the archive&lt;&#x2F;a&gt;), next you need to&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;halyard&#x2F;puppet-boxen&#x2F;blob&#x2F;master&#x2F;manifests&#x2F;osx_defaults.pp&quot;&gt; rip out the puppet code to manage secrets&lt;&#x2F;a&gt; (because nobody thought it wise to follow Puppet best practice and make a module do only one thing) and make your own personal company module, and finally you are ready to define an OSX secret. I use &lt;code&gt;boxen::osx_defaults&lt;&#x2F;code&gt; to set up the Mac equivalent of legalNoticeText with this code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  boxen::osx_defaults { &amp;quot;loginwindowtext&amp;quot; :
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    domain =&amp;gt; &amp;#39;&#x2F;Library&#x2F;Preferences&#x2F;com.apple.loginwindow.plist&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    key    =&amp;gt; &amp;#39;LoginwindowText&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    value  =&amp;gt; &amp;quot;This computer system is the property of ....&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Managing a GNU&#x2F;Linux workstation is similar to OSX and Windows only you know what you are doing and everything makes sense because smart people write and manage the software. I choose to use KDM as the greeter is easier to customize and make the default Desktop Environment to be GNOME. On my greeter background, I have the legalNoticeText properly formatted to my liking and saved in the background image. So far I am the only GNU&#x2F;Linux workstation on Puppet so I haven&#x27;t configured it to a great extent. It does help between re-installs though :)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Puppet with Windows</title>
        <published>2016-07-01T14:00:00+00:00</published>
        <updated>2016-07-01T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-07-01-puppet-with-windows/" type="text/html"/>
        <id>/2016-07-01-puppet-with-windows/</id>
        
            <content type="html">&lt;p&gt;Using Puppet on Windows workstations can be a challenge. The different architectures (x86 and x86_64) can have an impact on declaring packages. I have decided to ignore 32 bit systems and treat all as 64 bit - after all, it is 2016 and 32 bit should not be deployed.&lt;&#x2F;p&gt;
&lt;p&gt;Since everything is stored in the registry (and I am no registry expert), I find myself first making a change in the GPO, searching for the change in the registry, and converting what I found to Puppet manifests. There are a few modules that also help with local policy settings.&lt;&#x2F;p&gt;
&lt;p&gt;I have my Windows workstations checking in to Puppet every hour as it is not critical for them to be in-sync as often as multi-user servers.&lt;&#x2F;p&gt;
&lt;p&gt;I have found PuppetDB to be a great alternative to inventory software. The modules to get it in that state are:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;ody-pkginventory&quot;&gt;ody&#x2F;pkginventory&lt;&#x2F;a&gt; (using my pull request for Windows support)&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jhaals&#x2F;jhaals-warranty&quot;&gt;jhaals&#x2F;warranty&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Several other modules help Windows become easier to manage - they are:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forge.puppet.com&#x2F;puppetlabs&#x2F;registry&quot;&gt;puppetlabs&#x2F;registry&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forge.puppet.com&#x2F;chocolatey&#x2F;chocolatey&quot;&gt;chocolatey&#x2F;chocolatey&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forge.puppet.com&#x2F;puppetlabs&#x2F;powershell&quot;&gt;puppetlabs&#x2F;powershell&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forge.puppet.com&#x2F;ayohrling&#x2F;local_security_policy&quot;&gt;ayohrling&#x2F;local_security_policy&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Puppet-Finland&#x2F;local_group_policy&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Puppet-Finland&#x2F;local_group_policy&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My roles::workstation manifest includes the base profile, an anti-virus software install, company-wide fonts, and a few key utilities I like to use on customer computers - Defraggler, LibreOffice, and &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;helgeklein.com&#x2F;free-tools&#x2F;delprof2-user-profile-deletion-tool&#x2F;&quot;&gt;DelProf2&lt;&#x2F;a&gt;. Being that it is Puppet, I can deploy either exe, msi, or Chocolatey packages to computers.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Puppet as a GPO replacement</title>
        <published>2016-06-24T14:00:00+00:00</published>
        <updated>2016-06-24T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-06-24-puppet-as-a-gpo-replacement/" type="text/html"/>
        <id>/2016-06-24-puppet-as-a-gpo-replacement/</id>
        
            <content type="html">&lt;p&gt;When you have a mixed client workstation environment (Windows, Linux, Mac) using GPOs only covers a portion of the environment. Sure, there are some AD plugins for Mac and Linux to let them read and apply those settings, however, those tools cost an exuberant amount of money compared to the open source version Puppet.&lt;&#x2F;p&gt;
&lt;p&gt;I haven&#x27;t scratched the surface of totally replacing GPO. I still have to push out the puppet client using GPO, but my goal is to be solely dependent upon puppet.&lt;&#x2F;p&gt;
&lt;p&gt;In the upcoming weeks, I am going to post a few articles regarding the idiosyncrasies of the different OSes. For now, here are a few generic tips:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Use Roles and Profiles&lt;&#x2F;li&gt;
&lt;li&gt;Set the default node to have roles:: workstation 3. Use kernel case statements in roles:: workstation, profiles::base, and modules only.&lt;&#x2F;li&gt;
&lt;li&gt;Write Puppet modules with all workstations in mind.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Why I went with Puppet over other CMEs</title>
        <published>2016-06-17T14:00:00+00:00</published>
        <updated>2016-06-17T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-06-17-why-i-went-with-puppet-over-other-cmes/" type="text/html"/>
        <id>/2016-06-17-why-i-went-with-puppet-over-other-cmes/</id>
        
            <content type="html">&lt;p&gt;Configuration management engines (CME) have increased in popularity over the past several years. When I evaluated all the potential options, I needed one to be free in cost, work on Mac and Windows, and be easy to set up and use. At the time, only Chef, CFEngine, and Puppet had Windows clients so I tested them all out. Puppet came the victor for several reasons:&lt;&#x2F;p&gt;
&lt;p&gt;The open source version had a windows client. Chef&#x27; and CFEngine&#x27;s windows client was available if you paid. There is nothing wrong with this approach, but if your main goal was to run it on Windows workstations (not servers), $120&#x2F;seat seemed too much.&lt;&#x2F;p&gt;
&lt;p&gt;Puppet code was easy to read - especially for a beginner. Whereas others could mix in other languages in their declaration manifests. This made me feel like there wasn&#x27;t a clear standard on how to write code for that platform. I tend to stay away from projects where anyone can do anything.&lt;&#x2F;p&gt;
&lt;p&gt;I was given a free book on Puppet and it was easy to read. Simple to read and understand means someone else with limited knowledge in technology would be able to read and understand it. This also makes it easier for that person to pick up where I leave off.&lt;&#x2F;p&gt;
&lt;p&gt;With Puppet, clients call home (even when out of network) instead of having to wait for them to be on network to receive updates.&lt;&#x2F;p&gt;
&lt;p&gt;These few reasons made me invest my time and effort into a Puppet infrastructure. I have it on my workstations and servers. If only I had switches that supported Puppet.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Learn GNU&#x2F;Linux the easy way</title>
        <published>2016-06-10T14:00:00+00:00</published>
        <updated>2016-06-10T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-06-10-learn-gnulinux-the-easy-way/" type="text/html"/>
        <id>/2016-06-10-learn-gnulinux-the-easy-way/</id>
        
            <content type="html">&lt;p&gt;Let&#x27;s face it, Linux is a kernel and no matter what distribution you use, it is all the same. You have a repository of packages, you get a package manager to manage your packages, you get a desktop environment, and you get freedom to tinker down to the lowest level of the kernel to configure things like IP routing and forwarding.&lt;&#x2F;p&gt;
&lt;p&gt;Differences lie in the release cycle of the distribution, package names, and the default desktop environment - though you can find spins to even change that part. Each are trying to tackle a specific problem and come with a solution. It may be security, research, UI, stability, or even high performance computing.&lt;&#x2F;p&gt;
&lt;p&gt;If starting out, pick a user friendly distribution like Ubuntu or Debian. Use it with the defaults for 6 months while trying to learn as much as you can. Then move onto the specific use cases for Enterprise, you can use CentOS, RedHat, Ubuntu, or SUSE (you will get the best hardware&#x2F;software support if you go that route) for home use, you may want to go with Debian, Ubuntu, Arch, Gentoo, Fedora or anything you want to use; for embedded, you may go with Debian, Yocto, Gentoo, OpenEmbedded, OpenWRT, and others; for stability and security, you may want to go with Debian or one of the Enterprise distributions.&lt;&#x2F;p&gt;
&lt;p&gt;At the end of the day, it is all built upon the Linux kernel - unless you are using the Debian BSD fork.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Why I can&#x27;t use Ubuntu on Production Servers</title>
        <published>2016-06-03T15:00:42+00:00</published>
        <updated>2016-06-03T15:00:42+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-06-03-why-i-cant-use-ubuntu-on-production-servers/" type="text/html"/>
        <id>/2016-06-03-why-i-cant-use-ubuntu-on-production-servers/</id>
        
            <content type="html">&lt;p&gt;Do not get me wrong - I use Ubuntu and try to contribute to bugs (making and fixing). In fact, I am testing out 16.04 on my Chromebook and work computer right now (Fedora 23 is on my Home Desktop). However, I can&#x27;t find myself placing an Ubuntu server in production for one simple reason:&lt;&#x2F;p&gt;
&lt;p&gt;Security&lt;&#x2F;p&gt;
&lt;p&gt;While Ubuntu has a good security team, I can&#x27;t recall in previous years a security patch introduced because an Ubuntu security individual found it. I do read about RedHat, SUSE, and Debian teams finding and submitting CVEs and patches; however it raises several questions as to why Ubuntu is not more seen in the discovery side.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Is it because Ubuntu relies heavily upon upstream security?&lt;&#x2F;em&gt; That&#x27;s not a bad thing. It just needs to be more transparent if it is.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Is it because Ubuntu security team members label themselves as Debian security team?&lt;&#x2F;em&gt; That&#x27;s not a huge problem - it just means their loyalty lies with upstream and not the current working branch.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Is it because Ubuntu makes backdoors?&lt;&#x2F;em&gt; I hope not!&lt;&#x2F;p&gt;
&lt;p&gt;The absence in this particular area just makes me wonder if Security is top priority in Canonical or if it is an afterthought. This feeling is enough to keep me from deploying Ubuntu in production. I would rather use and support distributions that make a high priority on security patches as they are on my side to keep unauthorized access of my servers to zero.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Access Samba shares from Chromebook</title>
        <published>2016-05-24T14:10:50+00:00</published>
        <updated>2016-05-24T14:10:50+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-05-24-access-samba-shares-from-chromebook/" type="text/html"/>
        <id>/2016-05-24-access-samba-shares-from-chromebook/</id>
        
            <content type="html">&lt;p&gt;Chromebooks are cloud focused. Many Chromebooks come with very limited storage in hopes you would be storing everything in the cloud. While this is a great habit to practice, in all reality, how likely are you to store 2tb of data in the cloud? Not many cloud providers even offer plans for that much storage.&lt;&#x2F;p&gt;
&lt;p&gt;Today marks a milestone - &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;chrome.google.com&#x2F;webstore&#x2F;detail&#x2F;network-file-share-for-ch&#x2F;ndjpildffkeodjdaeebdhnncfhopkajk&quot;&gt;Google has released an extension to the Chromebook file app to access Samba shares&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Samba is the implementation in which Windows file shares are broadcasted across the network. There is also an open source version of the implementation known by the name of Samba which is found on most Linux distributions as well as at &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;samba.org&quot;&gt;http:&#x2F;&#x2F;Samba.org&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Enjoy accessing your network shares on ChromeOS, and don&#x27;t forget to &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleChrome&#x2F;chromeos_network_file_share&#x2F;issues&quot;&gt;file bug reports&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Cloud computing cost analysis</title>
        <published>2016-05-20T14:00:00+00:00</published>
        <updated>2016-05-20T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-05-20-cloud-computing-cost-analysis/" type="text/html"/>
        <id>/2016-05-20-cloud-computing-cost-analysis/</id>
        
            <content type="html">&lt;p&gt;Having a server in the cloud scared me at first. It wasn&#x27;t the fact that being in a multi-tenant environment posed the possibility of others gaining access to my code&#x2F;files - it was the cost that scared me. Not knowing if I was getting the best deal always plagued my mind. Especially since electricity, a&#x2F;c, and hardware maintenance were never factored into my budgets it made it hard to justify a server in the cloud when on-premise appeared to be so cheap.&lt;&#x2F;p&gt;
&lt;p&gt;Before I give the table of cost comparisons, I would like to point out that it is 2016. The past several years have seen a stabling of CPU power on the x86 architecture. The benchmarks have been leveling out and the CPU cycles are not really noticeable in a standard web app. I know different cloud providers have different versions of Xeon processors, but for this table, I am just going to label them as a CPU - even if they are vCPUs.&lt;&#x2F;p&gt;
&lt;p&gt;All these prices assume that there is at least 1 TB of transfer a month and 20 GB SSD storage. I found the closest and cheapest solution to the below labels. For the AWS Reserved instances, it is assumed a 1 year full upfront payment.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1 CPU, 512 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-F16F9CDC-9F9A-40B6-925D-9025995C1019&quot;&gt;$98.83&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$97.23&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1 CPU, 1024 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-8C247408-5FEC-48C9-8DC9-A8AD6C4C9EBA&quot;&gt;$103.59&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$100.32&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$10&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;$10&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;$193.36&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;$24.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;N&#x2F;A&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1 CPU, 2048 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-CE8CDA0D-495C-4B96-9BFE-CE37674207CA&quot;&gt;$113.11&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$106.65&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;$20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;$216.72&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;$29.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;$30&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;1 CPU, 4096 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-C36233DE-8FAF-4782-82E5-A31AA73148A9&quot;&gt;$132.14&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$119.24&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$40&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;$40&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;$263.44&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;$49.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;$50&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;2 CPU, 2048 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-07662374-6DAB-445D-BBBC-D1CF3E47B784&quot;&gt;$170.93&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$139.23&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;$20&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;$216.72&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;$29.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;$30&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;2 CPU, 4096 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-C36233DE-8FAF-4782-82E5-A31AA73148A9&quot;&gt;$132.14&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$119.24&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$40&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;$40&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;$263.44&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;$49.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;$50&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;4 CPU, 8096 RAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Host&lt;&#x2F;th&gt;&lt;th&gt;Cost&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;AWS On-Demand&lt;&#x2F;td&gt;&lt;td&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html#r=IAD&amp;amp;s=EC2&amp;amp;key=calc-EB336CBC-E414-447B-846D-A417A129BB6B&quot;&gt;$247.06&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AWS Reserved&lt;&#x2F;td&gt;&lt;td&gt;$189.98&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Digital Ocean&lt;&#x2F;td&gt;&lt;td&gt;$80&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Linode&lt;&#x2F;td&gt;&lt;td&gt;$80&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Rackspace&lt;&#x2F;td&gt;&lt;td&gt;$356.88&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoDaddy&lt;&#x2F;td&gt;&lt;td&gt;$99.99&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Media Temple&lt;&#x2F;td&gt;&lt;td&gt;$100&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;While some may think - why ever go with AWS when it costs $113.11 for 1 CPU and 2 GB of RAM. Most of the cost is with the 1TB transfer limit. In fact, $92.07 of the cost of every AWS quote is bandwidth and $2 for the storage. In all reality, you will never transfer 1TB from an EC2 instance - you would do it from an S3 bucket (which would be $92.67 - a savings of $1.40). However, if you have less than 6,100,000 requests to your website per month and you are not hosting files over 7mb, then the cost of AWS would be less than $20 - making it the cheapest option.&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;So the moral of the cloud hosting story is find a host which caters to your biggest need - Bandwidth or compute resources. Once you know that answer, picking an option is easy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sources&quot;&gt;Sources:&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mediatemple.net&#x2F;webhosting&#x2F;vps&#x2F;developer&#x2F;&quot;&gt;https:&#x2F;&#x2F;mediatemple.net&#x2F;webhosting&#x2F;vps&#x2F;developer&#x2F;&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.godaddy.com&#x2F;pro&#x2F;managed-vps&quot;&gt;https:&#x2F;&#x2F;www.godaddy.com&#x2F;pro&#x2F;managed-vps&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rackspace.com&#x2F;en-us&#x2F;calculator&quot;&gt;https:&#x2F;&#x2F;www.rackspace.com&#x2F;en-us&#x2F;calculator&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webcache.googleusercontent.com&#x2F;search?q=cache:GXODedVaOvoJ:https:&#x2F;&#x2F;www.linode.com&#x2F;pricing+&amp;amp;cd=1&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;gl=us&amp;amp;client=ubuntu&quot;&gt;https:&#x2F;&#x2F;webcache.googleusercontent.com&#x2F;search?q=cache:GXODedVaOvoJ:https:&#x2F;&#x2F;www.linode.com&#x2F;pricing+&amp;amp;cd=1&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;gl=us&amp;amp;client=ubuntu&lt;&#x2F;a&gt; (linode was down at the time of the writing)&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;pricing&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;pricing&#x2F;&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html&quot;&gt;https:&#x2F;&#x2F;calculator.s3.amazonaws.com&#x2F;index.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;technet.microsoft.com&#x2F;en-us&#x2F;library&#x2F;cc785130%28v=ws.10%29.aspx&quot;&gt;https:&#x2F;&#x2F;technet.microsoft.com&#x2F;en-us&#x2F;library&#x2F;cc785130%28v=ws.10%29.aspx&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.free-webhosts.com&#x2F;bandwidth-calculator.php&quot;&gt;http:&#x2F;&#x2F;www.free-webhosts.com&#x2F;bandwidth-calculator.php&lt;&#x2F;a&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;webmasters.stackexchange.com&#x2F;a&#x2F;19179&quot;&gt;http:&#x2F;&#x2F;webmasters.stackexchange.com&#x2F;a&#x2F;19179&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Wayfinding with RPi</title>
        <published>2016-05-13T14:00:00+00:00</published>
        <updated>2016-05-13T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-05-13-wayfinding-with-rpi/" type="text/html"/>
        <id>/2016-05-13-wayfinding-with-rpi/</id>
        
            <content type="html">&lt;p&gt;A few years ago I was tasked at looking at solutions for digital, static wayfinding. While there are some cool solutions available now for free with minimum setup, none of these were available to me. We currently were locked in with a digital signage company that charged $7,000&#x2F;year for generating 640x480 graphics with events that showed up in our Exchange 2007 calendar.&lt;&#x2F;p&gt;
&lt;p&gt;The jump to Exchange 2010&#x2F;2013 was dependant upon our vendor to upgrade their software to support the new EWS protocol over the older protocols. This was a classic case of vendor lock-in which is a horrible state to be in. Maintaining legacy software to keep an outdated system running should be avoided like the plague.&lt;&#x2F;p&gt;
&lt;p&gt;After taking a trip to Google HQ in mountain view, CA (back when they did tours), I was encouraged by the motto they plastered all over the buildings: &quot;the most complex problems are rarely solved with blunt force objects.&quot; What also intrigued me was their form of digital wayfinding. It was an e-ink display with a wireless antenna which showed all of its circuitry - definitely made in house. This allowed me to formulate my own configuration after seeing the release of the Raspberry Pi.&lt;&#x2F;p&gt;
&lt;p&gt;After about a week of coding, I was able to make &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;rpi-wayfinding&quot;&gt;RPi-wayfinding&lt;&#x2F;a&gt;. It is a simple PHP website that pulls in information from Exchange 2007+ (using EWS), a Google Calendar, or Planning Center Online Resources and displays it on a 1920x1080 resolution. This setup has been running smoothly for close to 3 years.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>5 Things to do after installing X</title>
        <published>2016-05-06T14:00:00+00:00</published>
        <updated>2016-05-06T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-05-06-5-things-to-do-after-installing-x/" type="text/html"/>
        <id>/2016-05-06-5-things-to-do-after-installing-x/</id>
        
            <content type="html">&lt;p&gt;Congratulations, you have installed X! Here are 5 things to do right now:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Change your background&lt;&#x2F;li&gt;
&lt;li&gt;Install needless software&lt;&#x2F;li&gt;
&lt;li&gt;Customize your font size&lt;&#x2F;li&gt;
&lt;li&gt;Take a screenshot&lt;&#x2F;li&gt;
&lt;li&gt;Share about your experience on social media!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This post is mainly a response to all of those 10 things to do after installing Ubuntu 16.04 blog posts.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Post this week</title>
        <published>2016-04-29T14:00:00+00:00</published>
        <updated>2016-04-29T14:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-04-29-post-this-week/" type="text/html"/>
        <id>/2016-04-29-post-this-week/</id>
        
            <content type="html">&lt;p&gt;I messed up on the post this week. It had a previous date when I clicked submit. I wrote an article on the next generation web stack (LEMP) with SSL. To view that article click &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;andrewwippler.com&#x2F;linux-nginx-mysql-5-7-and-php-7-lemp-on-aws-with-free-ssl&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Linux, nginx, MySQL 5.7, and PHP 7 (LEMP) on AWS with free SSL</title>
        <published>2016-04-26T13:01:00+00:00</published>
        <updated>2016-04-26T13:01:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-04-26-linux-nginx-mysql-5-7-and-php-7-lemp-on-aws-with-free-ssl/" type="text/html"/>
        <id>/2016-04-26-linux-nginx-mysql-5-7-and-php-7-lemp-on-aws-with-free-ssl/</id>
        
            <content type="html">&lt;p&gt;A stack is a group of software that creates a foundation to build upon. The LEMP stack is a web software stack which allows for delivering web applications. It is one of the most common of the web stacks to deliver a PHP application. LEMP uses a Linux kernel, Nginx for the webserver, MySQL or MariaDB for the database, and PHP for the scripting language.&lt;&#x2F;p&gt;
&lt;p&gt;Nearly all distributions of GNU&#x2F;Linux will have the same instructions to install the required packages. There is also little change between versions of Ubuntu to warrant a special blog post entitled &quot;LEMP on Ubuntu 14.04&quot; and &quot;LEMP on Ubuntu 16.04&quot; as they will contain the same exact instructions. There are a few oddities on the Amazon Linux AMI to get Let&#x27;s Encrypt working on the t2.nano (1 CPU, 512 RAM) instance which I will cover here.&lt;&#x2F;p&gt;
&lt;p&gt;Once you launch your instance, the packages you need to install are:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo yum localinstall http:&#x2F;&#x2F;rpms.famillecollet.com&#x2F;enterprise&#x2F;remi-release-6.rpm
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo yum localinstall https:&#x2F;&#x2F;dev.mysql.com&#x2F;get&#x2F;mysql57-community-release-el6-8.noarch.rpm
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo yum install nginx.x86_64 php70-php-fpm php70-php-cli php70-php-mysqlnd mysql-community-server --enablerepo=epel
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now enable the services to run at boot:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chkconfig nginx on
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chkconfig mysqld on
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chkconfig php70-php-fpm on
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo service nginx start
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo service mysqld start
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo service php70-php-fpm start
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Congratulations, you installed a LEMP stack! Now let us go a step further and set up SSL and a WordPress website. Type the following commands to set up our document root and create our virtual host:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo -i
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;etc&#x2F;nginx&#x2F;conf.d&#x2F;wordpress.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Upstream to abstract backend connection(s) for php
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;upstream php {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        server unix:&#x2F;tmp&#x2F;php-cgi.socket;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        server 127.0.0.1:9000 backup;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# comment the below if not using SSL
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;server {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        listen 80 default_server;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;       listen [::]:80 default_server;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        server_name _;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        return 301 https:&#x2F;&#x2F;$host$request_uri;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;server {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # comment the next line when not using SSL. Don&amp;#39;t forget to comment out the above server block and uncomment the listen 80 line below.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        listen 443 ssl default_server;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        #listen 80 default_server;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        server_name example.com www.example.com;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ## Your only path reference.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        root &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # comment if not using SSL
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ssl_certificate &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;example.com&#x2F;fullchain.pem;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ssl_certificate_key &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;example.com&#x2F;privkey.pem;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        index maint.php index.php;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # Disables serving gzip content to IE 6 or below
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        gzip_disable        &amp;quot;MSIE [1-6]\.&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        gzip_static     on;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # Sets the default type to text&#x2F;html so that gzipped content is served
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # as html, instead of raw uninterpreted data.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        default_type text&#x2F;html;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location &#x2F;.well-known&#x2F;acme-challenge {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;           root &#x2F;var&#x2F;www&#x2F;html&#x2F;letsencrypt&#x2F;wordpress&#x2F;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location = &#x2F;favicon.ico {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                log_not_found off;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                access_log off;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location = &#x2F;robots.txt {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                allow all;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                log_not_found off;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                access_log off;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        # Use cached or actual file if they exists, otherwise pass request to WordPress
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location &#x2F; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                try_files \$uri \$uri&#x2F; &#x2F;index.php?\$args ;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location ~ \.php$ {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                #NOTE: You should have &amp;quot;cgi.fix_pathinfo = 0;&amp;quot; in php.ini
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                include fastcgi.conf;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                fastcgi_intercept_errors on;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                fastcgi_pass php;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location ~* \.(ico|jpg|webp|jpeg|gif|css|png|js|ico|bmp|zip|woff|woff2)$ {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                access_log off;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                log_not_found off;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                add_header Pragma public;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                add_header Cache-Control &amp;quot;public&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                expires max;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        location ~* \.(php|html)$ {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                access_log on;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                log_not_found on;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                add_header Pragma public;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                add_header Cache-Control &amp;quot;public&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                expires 3d;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#including this file which some caching plugins use
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress&#x2F;nginx.conf;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# We don&amp;#39;t want to allow the browsers to see .hidden linux&#x2F;unix files or our own custom file
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;location ~ &#x2F;\.ht { deny  all; access_log off; log_not_found off; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;location ~ &#x2F;nginx.conf { deny all; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The above commands are intended to be copied and pasted into a terminal. If you edited the file and pasted the contents in, remove the backslashes ( &lt;code&gt;\&lt;&#x2F;code&gt; ) from the &lt;code&gt;try_files&lt;&#x2F;code&gt; line. Next let&#x27;s verify our php-fpm configuration to see how it is listening for requests.&lt;code&gt;sudo grep -in ^listen &#x2F;etc&#x2F;opt&#x2F;remi&#x2F;php70&#x2F;php-fpm.d&#x2F;www.conf&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We can either edit the listen directive in &lt;code&gt;&#x2F;etc&#x2F;opt&#x2F;remi&#x2F;php70&#x2F;php-fpm.d&#x2F;www.conf&lt;&#x2F;code&gt; to match our unix socket in our &lt;code&gt;wordpress.conf&lt;&#x2F;code&gt; nginx virtual host file or leave it as is. We have already made nginx look at the unix socket first (which is faster) and revert to the IP address as a backup option.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s make our document root, download WordPress, and extract it to our specified directory.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo mkdir -p &#x2F;var&#x2F;www&#x2F;html&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cd &#x2F;var&#x2F;www&#x2F;html
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;wget https:&#x2F;&#x2F;wordpress.org&#x2F;latest.tar.gz
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tar xvf latest.tar.gz
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our next step is to set the appropriate permissions on the files and directories.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chown nginx:apache -R &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo find &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress -type d -exec chmod 755 {} \;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo find &#x2F;var&#x2F;www&#x2F;html&#x2F;wordpress -type f -exec chmod 644 {} \;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now let&#x27;s create a database user and secure our database. If you &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;andrewwippler.com&#x2F;2016&#x2F;04&#x2F;15&#x2F;secure-mysql-5-7-installation&#x2F;&quot;&gt;remember from a previous post&lt;&#x2F;a&gt; mysql generates a temporary password. Let us grab that and run &lt;code&gt;mysql_secure_installation&lt;&#x2F;code&gt;. Answer all questions and provide a secure root password.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo grep &amp;#39;temporary password&amp;#39; &#x2F;var&#x2F;log&#x2F;mysqld.log
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo mysql_secure_installation
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;New we need to set up a database for WordPress.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mysql -u root -p
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mysql&amp;gt; CREATE DATABASE word_press;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mysql&amp;gt; GRANT ALL PRIVILEGES ON word_press.* TO &amp;quot;word_press_user&amp;quot;@&amp;quot;localhost&amp;quot; IDENTIFIED BY &amp;quot;S3cur3_WordPress_DB!Password&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mysql&amp;gt; FLUSH PRIVILEGES;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mysql&amp;gt; EXIT;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now let&#x27;s set up our SSL certificate with Let&#x27;s Encrypt. To install the client, we need additional software and a swap file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo yum install make automake gcc gcc-c++ kernel-devel git-core python27-devel
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# change to python 2.7 if you have an old Amazon AMI
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo alternatives --config python
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo easy_install pip
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo pip install pip virtualenv --upgrade
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;git clone https:&#x2F;&#x2F;github.com&#x2F;letsencrypt&#x2F;letsencrypt &#x2F;home&#x2F;ec2-user&#x2F;letsencrypt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cd &#x2F;home&#x2F;ec2-user&#x2F;letsencrypt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# create a 2GB RAM swap for machines with less than 2GB RAM
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dd if=&#x2F;dev&#x2F;zero of=&#x2F;swapfile bs=16M count=128
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo mkswap &#x2F;swapfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chmod 0600 &#x2F;swapfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo swapon &#x2F;swapfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# now to build letsencrypt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.&#x2F;letsencrypt-auto --help --debug
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Optional: Disable swapfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo swapoff &#x2F;swapfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Request certificates
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo mkdir -p &#x2F;var&#x2F;www&#x2F;html&#x2F;letsencrypt&#x2F;wordpress&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chown apache:nginx &#x2F;var&#x2F;www&#x2F;html&#x2F;letsencrypt&#x2F;wordpress&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo service nginx reload
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.&#x2F;letsencrypt-auto certonly --webroot -w &#x2F;var&#x2F;www&#x2F;html&#x2F;letsencrypt&#x2F;wordpress&#x2F; -d example.com -d www.example.com
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fill out the prompted information to get a certificate (we have already filled out the pertinent information in our nginx conf). All that is left to do is to make sure we get automatic renewals. To do that set up your crontab (&lt;code&gt;sudo crontab -e&lt;&#x2F;code&gt;) to include this line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;@monthly &#x2F;home&#x2F;ec2-user&#x2F;letsencrypt&#x2F;letsencrypt-auto renew &amp;amp;&amp;amp; &#x2F;sbin&#x2F;service nginx reload
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are now all set to continue with the installation of WordPress using the built in installer. This can be accessed by visiting your website at https:&#x2F;&#x2F;example.com&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;After installing WordPress, I recommend installing the jetpack module. Not only does it allow for posting to social media, but it has a setting to keep your WordPress installation on the latest version (a huge security plus).&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>oVirt mobile</title>
        <published>2016-04-22T14:05:00+00:00</published>
        <updated>2016-04-22T14:05:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-04-22-ovirt-mobile/" type="text/html"/>
        <id>/2016-04-22-ovirt-mobile/</id>
        
            <content type="html">&lt;p&gt;I particularly enjoy using a web browser to administer GUI appliances. In the case of oVirt, it does become a little painful to do the Chrome-zoom-click on my massive 4k Android phone. It appears the oVirt devs have also seen this pain point and have released an Android app to make adminstration easier on Android.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=org.ovirt.mobile.movirt&quot;&gt;moVirt&lt;&#x2F;a&gt; (mobile oVirt) makes common administrative tasks easier - migrating VMs, spinning down servers, spinning up stopped servers, etc.&lt;&#x2F;p&gt;
&lt;p&gt;moVirt has become an essential tool that I use on an infrequent basis. Now, if I can only figure out how to spin up VMs with Puppet.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Secure MySQL 5.7 installation</title>
        <published>2016-04-15T15:00:52+00:00</published>
        <updated>2016-04-15T15:00:52+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-04-15-secure-mysql-5-7-installation/" type="text/html"/>
        <id>/2016-04-15-secure-mysql-5-7-installation/</id>
        
            <content type="html">&lt;p&gt;With the release of MySQL 5.7, I was pleasantly surprised to see the install generated a random, secure password. This prevented me from going through the normal step of running &lt;code&gt;mysql_secure_installation&lt;&#x2F;code&gt; after starting and enabling services. To find the generated password, issue one of the commands below:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;on-rhel-centos-fedora&quot;&gt;On RHEL&#x2F;CentOS&#x2F;Fedora&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;grep &amp;#39;temporary password&amp;#39; &#x2F;var&#x2F;log&#x2F;mysqld.log
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;on-sles&quot;&gt;On SLES&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;grep &amp;#39;temporary password&amp;#39; &#x2F;var&#x2F;log&#x2F;mysql&#x2F;mysqld.log
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After issuing one of these commands, I was able to resume running the &lt;code&gt;mysql_secure_installation&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>The Linux Academy (review)</title>
        <published>2016-04-08T15:00:18+00:00</published>
        <updated>2016-04-08T15:00:18+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-04-08-the-linux-academy-review/" type="text/html"/>
        <id>/2016-04-08-the-linux-academy-review/</id>
        
            <content type="html">&lt;p&gt;I recently received a subscription to &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;linuxacademy.com&#x2F;&quot;&gt;Linux Academy&lt;&#x2F;a&gt;. Linux Academy has courses in Linux, AWS, DevOps, and OpenStack to help users achieve professional certificates such as the LFCS, LFCE, RHSCA, RHCE, and others. Since my LFCS is expiring this year (and I hope to achieve a RHCE), Linux Academy seemed like a place to help me achieve that goal.&lt;&#x2F;p&gt;
&lt;p&gt;The first thing I noticed is that the Introduction to Linux Academy videos were current. The content was exactly how I saw it, and I did not have to alter the steps in anyway to follow the videos. The videos even described how to switch from Flash to HTML5 so that you could use the playback speed controls. This appealed to me as I like listening to videos in 2.0x speed (especially if the instructor is a slow talker). Keeping videos current in a rapidly changing environment speaks volumes of how dedicated these instructors are at teaching me the latest material. So far they have proven to be on top of things.&lt;&#x2F;p&gt;
&lt;p&gt;One of the neat features I found is what they call a learning plan. This is a tool that you use to input your free time to learn material (in increments of half hours) and it calculates what videos to watch on particular days by setting due dates. You can then set reminders to be notified before your free time so that you can achieve course completion.&lt;&#x2F;p&gt;
&lt;p&gt;The instructors speak at a good pace so you can type along as you watch the videos - even at 2x speed.&lt;&#x2F;p&gt;
&lt;p&gt;The Linux Academy aims to be your single resource for learning and achieving certifications. There is no extra cost in purchasing additional resources to read or view. Everything is included in the subscription price. I would recommend the Linux Academy for anyone who wants to know GNU&#x2F;Linux. At the time of this writing; however, there is one issue I have found. They encourage you to take the quiz at the end to test your knowledge, but doing so only moves the progress bar of completion by 1%. It should at least move to 100% and give a message of quizzed-out. :)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Blame as a service (BlaaS)</title>
        <published>2016-04-01T08:01:46+00:00</published>
        <updated>2016-04-01T08:01:46+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-04-01-blame-as-a-service-blaas/" type="text/html"/>
        <id>/2016-04-01-blame-as-a-service-blaas/</id>
        
            <content type="html">&lt;p&gt;Today I am pleased to announce a new offering - Blame as a Service (BlaaS).&lt;&#x2F;p&gt;
&lt;p&gt;With the ever increase of SaaS offerings and cloud providers with high resiliency and low downtime, there will be the inevitable glitch or hiccup whenever a CEO views your team&#x27;s area of responsibility. With the recent passing of Murphy&#x27;s Law in IEEE this has become more frequent in day-to-day operations.&lt;&#x2F;p&gt;
&lt;p&gt;BlaaS helps you by receiving the blame for your incompetence by providing you with simple, easy-to-use templates that you can share with your CEO. These templates shift the blame from your SaaS choosing and put it on your BlaaS application making you the hero and us the bad guy.&lt;&#x2F;p&gt;
&lt;p&gt;BlaaS has already saved several Developers from embarrassment and System Administrators from potential job loss and it can help you too!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;BlaaS saved my job after the datacenter burned down. I just pulled out one of BlaaS&#x27; pre-made templates, edited a few words and sent it off to my boss!&lt;&#x2F;p&gt;
&lt;p&gt;Simon Sysmin&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;With BlaaS&#x27; CI plugin, I was able to automate failures with reasons why it didn&#x27;t work. This saved me a ton of time with email correspondence.&lt;&#x2F;p&gt;
&lt;p&gt;Joe Jenkins&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Thanks to BlaaS, I can keep on claiming to be the brains behind the fastest latency-free network around.&lt;&#x2F;p&gt;
&lt;p&gt;Ned Nederlander&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;pricing&quot;&gt;Pricing&lt;&#x2F;h3&gt;
&lt;p&gt;BlaaS pricing is very simple and to understand!&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Pricing (Monthly)&lt;&#x2F;th&gt;&lt;th&gt;Basic&lt;&#x2F;th&gt;&lt;th&gt;Professional&lt;&#x2F;th&gt;&lt;th&gt;Enterprise&lt;&#x2F;th&gt;&lt;th&gt;Super Admin&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Price per device&lt;&#x2F;td&gt;&lt;td&gt;$0.05&lt;&#x2F;td&gt;&lt;td&gt;$0.07&lt;&#x2F;td&gt;&lt;td&gt;$0.10&lt;&#x2F;td&gt;&lt;td&gt;Call *&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Max devices&lt;&#x2F;td&gt;&lt;td&gt;1000&lt;&#x2F;td&gt;&lt;td&gt;2000&lt;&#x2F;td&gt;&lt;td&gt;5000&lt;&#x2F;td&gt;&lt;td&gt;Unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Unique templates&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;10&lt;&#x2F;td&gt;&lt;td&gt;Unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Lawsuits&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;Unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Network Cabling Coverage&lt;&#x2F;td&gt;&lt;td&gt;5ft&lt;&#x2F;td&gt;&lt;td&gt;20ft&lt;&#x2F;td&gt;&lt;td&gt;50ft&lt;&#x2F;td&gt;&lt;td&gt;Unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Plugins&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;10&lt;&#x2F;td&gt;&lt;td&gt;Unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Slack Integration&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;* Call so we may throw a party based upon how much we will charge and receive from you monthly.&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;April fools!&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>The greatest story ever told</title>
        <published>2016-03-25T14:51:33+00:00</published>
        <updated>2016-03-25T14:51:33+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-03-25-the-greatest-story-ever-told/" type="text/html"/>
        <id>/2016-03-25-the-greatest-story-ever-told/</id>
        
            <content type="html">&lt;p&gt;The greatest story ever told is how an Almighty God came down to earth, lived a perfect life, and offered Himself as a sacrifice for the sins of the whole world (past, present, and future). This is what the Easter weekend represents. There is a penalty for sin which must be paid. Jesus paid that penalty with his life. Those that confess that Jesus took their place and put their trust in Him will receive a pardon from sin, peace with God, and a prepared home in heaven.&lt;&#x2F;p&gt;
&lt;p&gt;Because God is so righteous, He cannot have unrighteousness near Him.&lt;&#x2F;p&gt;
&lt;p&gt;Because God is so holy, sin cannot come before Him.&lt;&#x2F;p&gt;
&lt;p&gt;Because I can be biased, I am unrighteous.&lt;&#x2F;p&gt;
&lt;p&gt;Because I am human, I have sinned.&lt;&#x2F;p&gt;
&lt;p&gt;Because God is so merciful, He provided a scapegoat to take my place.&lt;&#x2F;p&gt;
&lt;p&gt;Because God is loving, He placed my unrighteousness and sin upon Himself and died on the cross.&lt;&#x2F;p&gt;
&lt;p&gt;Because God is gracious, He offers a pardon to all those who trust in Him.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Sunday is awesome</title>
        <published>2016-03-20T22:02:51+00:00</published>
        <updated>2016-03-20T22:02:51+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-03-20-sunday-is-awesome/" type="text/html"/>
        <id>/2016-03-20-sunday-is-awesome/</id>
        
            <content type="html">&lt;p&gt;Sunday is so awesome that cron repeats it! (0,7)&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Atom editor on Fedora</title>
        <published>2016-03-18T15:00:07+00:00</published>
        <updated>2016-03-18T15:00:07+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-03-18-atom-editor-on-fedora/" type="text/html"/>
        <id>/2016-03-18-atom-editor-on-fedora/</id>
        
            <content type="html">&lt;p&gt;The atom editor has quickly become my favorite IDE for working with web projects. I still use Vi&#x2F;Vim for CLI stuff, but atom is the icon I click when I want a GUI program.&lt;&#x2F;p&gt;
&lt;p&gt;It was becoming a little mundane to go to the atom website and download the new version to install. This is why package managers exist - so users don&#x27;t have to visit your website to download a new update. A quick search at &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;copr.fedorainfracloud.org&#x2F;coprs&#x2F;&quot;&gt;copr&lt;&#x2F;a&gt; yielded mosquito&#x27;s repo of atom - success! Below is how to add the repo and keep atom updated for Fedora.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dnf install dnf-plugins-core
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dnf copr enable mosquito&#x2F;atom
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dnf install atom
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>WiFi Captive Portal</title>
        <published>2016-03-11T14:00:06+00:00</published>
        <updated>2016-03-11T14:00:06+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-03-11-wifi-captive-portal/" type="text/html"/>
        <id>/2016-03-11-wifi-captive-portal/</id>
        
            <content type="html">&lt;p&gt;A captive portal is a piece of software that prompts for user interaction before allowing the client to access the internet or other resources on the network. It is a combination of a firewall and a webserver. In this tutorial, I will explain how to create an open WiFi network. Before deploying an open WiFi network, you may want to consult a lawyer of the legality and restrictions for having one. You can also review what has been said by lawyers &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.mbm-law.net&#x2F;newsletter-articles&#x2F;wi-fi-hotspots-and-liability-concerns&#x2F;1229&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openwireless.org&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;When a device first connects to any network, it sends out a HTTP request and expects an HTTP status code of 200. If the device receives a HTTP 200 status code, it assumes it has unlimited internet access. Captive portal prompts are displayed when you are able to manipulate this first HTTP message to return a HTTP status code of 302 (redirect) to the captive portal of your choice.&lt;&#x2F;p&gt;
&lt;p&gt;To set up a captive portal on a Raspberry Pi, you will need a wired network (I will refer to this as WAN or uplink) and a wireless network (such as the &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.amazon.com&#x2F;gp&#x2F;product&#x2F;B00P5UNKZW&#x2F;ref=as_li_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B00P5UNKZW&amp;amp;linkCode=as2&amp;amp;tag=personal0964-20&amp;amp;linkId=VP3IYQ4U57L2RQ6L&quot;&gt;Ralink RT5372&lt;&#x2F;a&gt; or the &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.amazon.com&#x2F;gp&#x2F;product&#x2F;B00ABD6IKC&#x2F;ref=as_li_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B00ABD6IKC&amp;amp;linkCode=as2&amp;amp;tag=personal0964-20&amp;amp;linkId=7DO6IU2JNGHN2QRD&quot;&gt;Ralink RT5370&lt;&#x2F;a&gt;) which you can set into AP mode. A server with 2 NICs would also suffice if you want to perform this on a wired LAN instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2&#x2F;15&#x2F;2017:&lt;&#x2F;strong&gt; If you get the too many redirects error, look at the &lt;code&gt;hotspot.localnet&lt;&#x2F;code&gt; nginx configuration. It could be that the dollar signs &lt;code&gt;$&lt;&#x2F;code&gt; are not present. The below block is what the location &#x2F; block should look like in the &lt;code&gt;hotspot.localnet&lt;&#x2F;code&gt; virtual host.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     location &#x2F; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         try_files $uri $uri&#x2F; index.php;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;operating-system&quot;&gt;Operating System&lt;&#x2F;h3&gt;
&lt;p&gt;The operating system assumed will be Rapsbian Jessie. You can also follow this tutorial with a Debian server with two NICs - as long as one is dedicated to the WAN and the other to the LAN. It is also possible to use another Linux Distribution, but converting the commands will be up to you. In a later article, I will describe how to perform the steps on OpenWRT.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;required-packages&quot;&gt;Required Packages&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo apt-get install iptables-persistent conntrack dnsmasq nginx php5 php5-common php5-fpm hostapd
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;configuring-dnsmasq&quot;&gt;Configuring dnsmasq&lt;&#x2F;h3&gt;
&lt;p&gt;You can certainly use other DNS and DHCP servers, but I like to use &lt;code&gt;dnsmasq&lt;&#x2F;code&gt; as it is lightweight and found on many routers already. This indicates to me that &lt;code&gt;dnsmasq&lt;&#x2F;code&gt; is pretty stable and able to perform in the enterprise.&lt;&#x2F;p&gt;
&lt;p&gt;The contents of my &lt;code&gt;dnsmasq.conf&lt;&#x2F;code&gt; are as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Never forward addresses in the non-routed address spaces.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;bogus-priv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Add other name servers here, with domain specs if they are for
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# non-public domains.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;server=&#x2F;localnet&#x2F;192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Add local-only domains here, queries in these domains are answered
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# from &#x2F;etc&#x2F;hosts or DHCP only.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;local=&#x2F;localnet&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# If you want dnsmasq to listen for DHCP and DNS requests only on
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# specified interfaces (and the loopback) give the name of the
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# interface (eg eth0) here.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Repeat the line for more than one interface.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;interface=wlan0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set the domain for dnsmasq. this is optional, but if it is set, it
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# does the following things.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# 1) Allows DHCP hosts to have fully qualified domain names, as long
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#     as the domain part matches this setting.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# 2) Sets the &amp;quot;domain&amp;quot; DHCP option thereby potentially setting the
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#    domain of all systems configured by DHCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# 3) Provides the domain part for &amp;quot;expand-hosts&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;domain=localnet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Uncomment this to enable the integrated DHCP server, you need
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# to supply the range of addresses available for lease and optionally
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# a lease time. If you have more than one network, you will need to
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# repeat this for each network on which you want to supply DHCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# service.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dhcp-range=192.168.24.50,192.168.24.250,2h
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Override the default route supplied by dnsmasq, which assumes the
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# router is the same machine as the one running dnsmasq.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dhcp-option=3,192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#DNS Server
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dhcp-option=6,192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Set the DHCP server to authoritative mode. In this mode it will barge in
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# and take over the lease for any client which broadcasts on the network,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# whether it has a record of the lease or not. This avoids long timeouts
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# when a machine wakes up on a new network. DO NOT enable this if there&amp;#39;s
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# the slightest chance that you might end up accidentally configuring a DHCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# server for your campus&#x2F;company accidentally. The ISC server uses
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# the same option, and this URL provides more information:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# http:&#x2F;&#x2F;www.isc.org&#x2F;files&#x2F;auth.html
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;dhcp-authoritative
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;dnsmasq&lt;&#x2F;code&gt; also reads in the &lt;code&gt;&#x2F;etc&#x2F;hosts&lt;&#x2F;code&gt; file and adds that information into the dns. Since we want to use pretty hostnames in our captive portal urls, we need to add a few entries to our hosts file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Contents of &#x2F;etc&#x2F;hosts
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;127.0.0.1	localhost
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;192.168.24.1	hotspot.localnet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;::1		localhost ip6-localhost ip6-loopback
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fe00::0		ip6-localnet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ff00::0		ip6-mcastprefix
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ff02::1		ip6-allnodes
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ff02::2		ip6-allrouters
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;network&quot;&gt;Network&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we have DNS and DHCP set up, we need to set up the interfaces. Edit &lt;code&gt;&#x2F;etc&#x2F;network&#x2F;interfaces&lt;&#x2F;code&gt; and place in the following information:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The loopback network interface
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;auto lo eth0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iface lo inet loopback
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The &amp;quot;wan&amp;quot; network interface
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iface eth0 inet dhcp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The &amp;quot;lan&amp;quot; network interface
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iface wlan0 inet static
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  address 192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  netmask 255.255.255.0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also need to tell the kernel to forward IP packets between interfaces. To do that, enter the following command&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo &amp;quot;net.ipv4.ip_forward=1&amp;quot; &amp;gt;&amp;gt; &#x2F;etc&#x2F;sysctl.conf
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You will need to reboot in order for that change to take effect, but do not do that quite yet.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hostapd&quot;&gt;Hostapd&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;hostapd&lt;&#x2F;code&gt; will be the service that sets up the SSID and ensures it is broadcasting over the wireless card. If you are setting up the captive portal on a server with 2 NICs you can skip to the next section.&lt;&#x2F;p&gt;
&lt;p&gt;While you may certainly set up &lt;code&gt;hostapd&lt;&#x2F;code&gt; in WPA2 mode, I am assuming that because we are setting up a captive portal, this will be our authentication method rather than the encryption setting on the access point. To set up an open WiFi network, edit &lt;code&gt;&#x2F;etc&#x2F;hostapd&#x2F;hostapd.conf&lt;&#x2F;code&gt; with the following information&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;interface=wlan0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ssid=MyOpenAP # name of the WiFi access point
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;hw_mode=g
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;channel=6 #use 1, 6, or 11
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;auth_algs=1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;wmm_enabled=0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You will now have to set up the daemon by editing the contents of &lt;code&gt;&#x2F;etc&#x2F;default&#x2F;hostapd&lt;&#x2F;code&gt; and change the line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#DAEMON_CONF=&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;DAEMON_CONF=&amp;quot;&#x2F;etc&#x2F;hostapd&#x2F;hostapd.conf&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;iptables&quot;&gt;Iptables&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt; is our firewall. This is how we are going to block all connections that we have not authorized. Below are the commands to set up the firewall:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Turn into root
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo -i
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Flush all connections in the firewall
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -F
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Delete all chains in iptables
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -X
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# wlan0 is our wireless card. Replace with your second NIC if doing it from a server.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# This will set up our structure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -N wlan0_Trusted
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -N wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -N wlan0_Incoming
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -I PREROUTING 1 -i wlan0 -j wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -I PREROUTING 1 -i wlan0 -j wlan0_Trusted
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t mangle -I POSTROUTING 1 -o wlan0 -j wlan0_Incoming
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Router
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -N wlan0_temp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A PREROUTING -i wlan0 -j wlan0_Outgoing
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Outgoing -d 192.168.24.1 -j wlan0_Router
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Router -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Outgoing -j wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Internet -m mark --mark 0x2 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Internet -j wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -j wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -j wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -j wlan0_temp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# forward new requests to this destination
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A wlan0_Unknown -p tcp --dport 80 -j DNAT --to-destination 192.168.24.1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_temp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Known
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -N wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -I FORWARD -i wlan0 -j wlan0_Internet
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -m state --state INVALID -j DROP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -j wlan0_AuthServers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_AuthServers -d 192.168.24.1 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -j wlan0_Global
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# allow access to my website :)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Global -d andrewwippler.com -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#allow unrestricted access to packets marked with 0x2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -m mark --mark 0x2 -j wlan0_Known
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Known -d 0.0.0.0&#x2F;0 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Internet -j wlan0_Unknown
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# allow access to DNS and DHCP
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# This helps power users who have set their own DNS servers
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p udp --dport 53 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p tcp --dport 53 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p udp --dport 67 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -d 0.0.0.0&#x2F;0 -p tcp --dport 67 -j ACCEPT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t filter -A wlan0_Unknown -j REJECT --reject-with icmp-port-unreachable
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#allow forwarding of requests from anywhere to eth0&#x2F;WAN
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#save our iptables
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;iptables-save &amp;gt; &#x2F;etc&#x2F;iptables&#x2F;rules.v4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;nginx&quot;&gt;nginx&lt;&#x2F;h3&gt;
&lt;p&gt;Now we need to set up &lt;code&gt;nginx&lt;&#x2F;code&gt; to send a magic packet that prompts the user for action (i.e MyOpenAP requires you to sign in). To do that, we will run the following commands:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Make the HTML Document Root
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkdir &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;chown nginx:www-data &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;chmod 755 &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# create the nginx hotspot.conf file
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;etc&#x2F;nginx&#x2F;sites-available&#x2F;hotspot.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;server {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # Listening on IP Address.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # This is the website iptables redirects to
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    listen       80 default_server;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    root         &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # For iOS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    if ($http_user_agent ~* (CaptiveNetworkSupport) ) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        return 302 http:&#x2F;&#x2F;hotspot.localnet&#x2F;hotspot.html;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # For others
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    location &#x2F; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        return 302 http:&#x2F;&#x2F;hotspot.localnet&#x2F;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; upstream php {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    #this should match value of &amp;quot;listen&amp;quot; directive in php-fpm pool
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;		server unix:&#x2F;tmp&#x2F;php-fpm.sock;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;		server 127.0.0.1:9000;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;server {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     listen       80;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     server_name  hotspot.localnet;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     root         &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     location &#x2F; {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;         try_files $uri $uri&#x2F; index.php;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    # Pass all .php files onto a php-fpm&#x2F;php-fcgi server.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    location ~ [^&#x2F;]\.php(&#x2F;|$) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	fastcgi_split_path_info ^(.+?\.php)(&#x2F;.*)$;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	if (!-f $document_root$fastcgi_script_name) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    		return 404;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	# This is a robust solution for path info security issue and works with &amp;quot;cgi.fix_pathinfo = 1&amp;quot; in &#x2F;etc&#x2F;php.ini (default)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	include fastcgi_params;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	fastcgi_index index.php;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    	fastcgi_pass php;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Enable the website and reload nginx
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ln -s &#x2F;etc&#x2F;nginx&#x2F;sites-available&#x2F;hotspot.conf &#x2F;etc&#x2F;nginx&#x2F;sites-enabled&#x2F;hotspot.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;systemctl reload nginx
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have just set up the path &lt;code&gt;&#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal&lt;&#x2F;code&gt; to serve web pages if accessed via IP (note the &lt;code&gt;default_server&lt;&#x2F;code&gt; directive) as well as if accessed by the hostname &lt;code&gt;hotspot.localnet&lt;&#x2F;code&gt;. If accessed via IP, it will trigger a 302 redirect to the hostname &lt;code&gt;hotspot.localnet&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;html-php&quot;&gt;HTML &#x2F; PHP&lt;&#x2F;h3&gt;
&lt;p&gt;When it comes to the coding aspect, we only want to allow access if the webserver has determined the user has clicked the &lt;strong&gt;I agree to the terms&lt;&#x2F;strong&gt; button. To do that, I will add a &lt;code&gt;&amp;lt;input type=&quot;hidden&quot; name=&quot;security_code&quot; value=&quot;andrew-wippler-is-cool&quot; &#x2F;&amp;gt;&lt;&#x2F;code&gt; to my form field. This will stop a few script kiddies from gaining access without clicking the button, but one may want to add additional security features if deploying this in the enterprise (or just buy an appliance that has a captive portal already).&lt;&#x2F;p&gt;
&lt;p&gt;We will need two files added to &lt;code&gt;&#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;portal&lt;&#x2F;code&gt;. They are the following:&lt;&#x2F;p&gt;
&lt;h6 id=&quot;index-php&quot;&gt;index.php&lt;&#x2F;h6&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;?php
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; Grant access if the Security code is accurate.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if ($_POST[&amp;#39;security_code&amp;#39;] == &amp;quot;andrew-wippler-is-cool&amp;quot;) {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; Grab the MAC address
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$arp = &amp;quot;&#x2F;usr&#x2F;sbin&#x2F;arp&amp;quot;; &#x2F;&#x2F; Attempt to get the client&amp;#39;s mac address
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$mac = shell_exec(&amp;quot;$arp -a &amp;quot;.$_SERVER[&amp;#39;REMOTE_ADDR&amp;#39;]);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;preg_match(&amp;#39;&#x2F;..:..:..:..:..:..&#x2F;&amp;#39;,$mac , $matches);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$mac2 = $matches[0];
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; Reconnect the device to the firewall
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;exec(&amp;quot;sudo rmtrack &amp;quot; . $_SERVER[&amp;#39;REMOTE_ADDR&amp;#39;]);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;$i = &amp;quot;sudo iptables -t mangle -A wlan0_Outgoing  -m mac --mac-source &amp;quot;.$_GET[&amp;#39;mac&amp;#39;].&amp;quot; -j MARK --set-mark 2&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;exec($i);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sleep(5);
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;?&amp;gt; &amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;title&amp;gt;&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;h1&amp;gt;You are now free to browse the internet.&amp;lt;&#x2F;h1&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;body&amp;gt; &amp;lt;&#x2F;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;?php } else {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &#x2F;&#x2F; this is what is seen when first viewing the page
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  ?&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;title&amp;gt;&amp;lt;&#x2F;title&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;&#x2F;head&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;body&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;h1&amp;gt;Authorization Required&amp;lt;&#x2F;h1&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;p&amp;gt;Before continuing, you must first agree to the &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Terms of Service&amp;lt;&#x2F;a&amp;gt; and be of the legal age to do that in your selective country or have Parental Consent.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;&#x2F;p&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;index.php&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;security_code&amp;quot; value=&amp;quot;andrew-wippler-is-cool&amp;quot; &#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;checkbox1&amp;quot; CHECKED &#x2F;&amp;gt;&amp;lt;label for=&amp;quot;checkbox1&amp;quot;&amp;gt;I Agree to the terms&amp;lt;&#x2F;label&amp;gt;&amp;lt;br &#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Connect&amp;quot; &#x2F;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;&#x2F;form&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  &amp;lt;&#x2F;body&amp;gt; &amp;lt;&#x2F;html&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;?php } ?&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h6 id=&quot;hotspot-html&quot;&gt;hotspot.html&lt;&#x2F;h6&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;!--
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;WISPAccessGatewayParam xmlns:xsi=&amp;quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2001&#x2F;XMLSchema-instance&amp;quot; xsi:noNamespaceSchemaLocation=&amp;quot;http:&#x2F;&#x2F;www.wballiance.net&#x2F;wispr_2_0.xsd&amp;quot;&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;Redirect&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;MessageType&amp;gt;100&amp;lt;&#x2F;MessageType&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;ResponseCode&amp;gt;0&amp;lt;&#x2F;ResponseCode&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;VersionHigh&amp;gt;2.0&amp;lt;&#x2F;VersionHigh&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;VersionLow&amp;gt;1.0&amp;lt;&#x2F;VersionLow&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;AccessProcedure&amp;gt;1.0&amp;lt;&#x2F;AccessProcedure&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;AccessLocation&amp;gt;Andrew Wippler is awesome&amp;lt;&#x2F;AccessLocation&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;LocationName&amp;gt;MyOpenAP&amp;lt;&#x2F;LocationName&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;LoginURL&amp;gt;http:&#x2F;&#x2F;hotspot.localnet&#x2F;&amp;lt;&#x2F;LoginURL&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;&#x2F;Redirect&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; &amp;lt;&#x2F;WISPAccessGatewayParam&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt; --&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;additional-configurations&quot;&gt;Additional Configurations&lt;&#x2F;h3&gt;
&lt;p&gt;We are almost done; however, you may have noticed the line 14 in &lt;code&gt;index.php&lt;&#x2F;code&gt; which includes executing &lt;code&gt;rmtrack&lt;&#x2F;code&gt;. What is &lt;code&gt;rmtrack&lt;&#x2F;code&gt;? It is the code of &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;andy-beverley-94116215&quot;&gt;Andy Beverley&lt;&#x2F;a&gt; which is licensed under the &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.gnu.org&#x2F;copyleft&#x2F;fdl.html&quot;&gt;GNU Free Documentation License 1.3&lt;&#x2F;a&gt;. In Andy&#x27;s &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.andybev.com&#x2F;index.php&#x2F;Using_iptables_and_PHP_to_create_a_captive_portal&quot;&gt;tutorial for a captive portal&lt;&#x2F;a&gt;, &lt;code&gt;rmtrack&lt;&#x2F;code&gt; is used to remove the connection information in the kernel to prevent login loops. Let&#x27;s create that file now:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;usr&#x2F;bin&#x2F;rmtrack
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;sbin&#x2F;conntrack -L \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    |grep $1 \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    |grep ESTAB \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    |grep &amp;#39;dport=80&amp;#39; \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    |awk \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &amp;quot;{ system(\&amp;quot;conntrack -D --orig-src $1 --orig-dst \&amp;quot; \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            substr(\$6,5) \&amp;quot; -p tcp --orig-port-src \&amp;quot; substr(\$7,7) \&amp;quot; \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;            --orig-port-dst 80\&amp;quot;); }&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;chmod +x &#x2F;usr&#x2F;bin&#x2F;rmtrack
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also have to allow our web server user &lt;code&gt;www-data&lt;&#x2F;code&gt; access to run privileged commands. We can do that by typing &lt;code&gt;visudo&lt;&#x2F;code&gt; and appending the below lines to the file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;www-data ALL = NOPASSWD: &#x2F;usr&#x2F;bin&#x2F;rmtrack [0-9]*.[0-9]*.[0-9]*.[0-9]*
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;www-data ALL = NOPASSWD: &#x2F;sbin&#x2F;iptables -t mangle -A wlan0_Outgoing  -m mac --mac-source ??\:??\:??\:??\:??\:?? -j MARK --set-mark 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the &lt;code&gt;sudoers&lt;&#x2F;code&gt; file saved, you are now ready to reboot the Raspberry Pi and enjoy offering a fairly simplistic captive portal.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>7 essential Android IT tools</title>
        <published>2016-03-04T15:00:40+00:00</published>
        <updated>2016-03-04T15:00:40+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-03-04-7-essential-android-it-tools/" type="text/html"/>
        <id>/2016-03-04-7-essential-android-it-tools/</id>
        
            <content type="html">&lt;p&gt;I have been using an Android phone for the past several years (since version 2.3.2). It has turned out to be the swiss army knife in my IT toolkit. Here are 7 apps that I cannot live without and help me perform my daily job duties.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;activedir-manager&quot;&gt;ActiveDir Manager&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=net.bealsystems.ADUserManager&quot;&gt;ActiveDir Manager&lt;&#x2F;a&gt; is a $4.99 app that allows you to do 80% of Active Directory management tasks including: changing user passwords, locking&#x2F;unlocking user accounts, adding users to groups, and editing basic user information. It comes in handy when someone stop you in the hall and mentions their account is locked out. Instead of writing it down in Evernote, then walking to your desk and unlocking the user, you can whip out this app and get it done in under 10 seconds!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wifi-analyzer&quot;&gt;WiFi Analyzer&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.farproc.wifi.analyzer&quot;&gt;WiFi Analyzer&lt;&#x2F;a&gt; is the most widely used app for wireless network troubleshooting. I have used it to hunt down missing access points, see signal strength in the location I am presently standing, and pick out an open channel for my home network. If this app is not on your phone, you obviously are not a network administrator!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;juicessh&quot;&gt;JuiceSSH&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.sonelli.juicessh&quot;&gt;JuiceSSH&lt;&#x2F;a&gt; is another neat little app. I use it to manage my fleet of Raspberry PIs that power my campus display TVs and wayfinding signs. The feature that got me most locked into this app is the ability to sync connections and accounts between my old phone and new phone.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ring-scheduler&quot;&gt;Ring Scheduler&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.farproc.ring.scheduler&quot;&gt;Ring Scheduler&lt;&#x2F;a&gt; was developed by the same guy who made WiFi Analyzer. Its purpose is to silence your phone on a schedule. You can also use it to ensure your ringer is on at specific times. For me I use it to silence my phone at 10 pm and re-enable it at 6am.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;microsoft-remote-desktop-client&quot;&gt;Microsoft Remote Desktop Client&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.microsoft.rdc.android&quot;&gt;Microsoft Remote Desktop Client&lt;&#x2F;a&gt; is a perfect app to connect to the GUI of Microsoft servers. Right-clicking is still kind of annoying, but this simple app keeps me from having to install 3rd party software on my servers just for remote desktop access.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;es-file-explorer&quot;&gt;ES File Explorer&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.estrongs.android.pop&quot;&gt;ES File Explorer&lt;&#x2F;a&gt; is a utility I use to connect to remote network shares as well as navigate and cleanup my android device.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;screebl&quot;&gt;Screebl&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.google.com&#x2F;store&#x2F;apps&#x2F;details?id=com.keyes.screebl.full&quot;&gt;Screebl&lt;&#x2F;a&gt; has made my reading more enjoyable. Ever read a news article or book only to have your phone go black in the middle of the good part? Screebl solves that. I have often come to rely so much on Screebl&#x27;s function that I find using any device without it to be deemed as a dumb phone (including other android phones).&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>How to get users to switch from X to X and use it</title>
        <published>2016-02-26T15:00:00+00:00</published>
        <updated>2016-02-26T15:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-02-26-how-to-get-users-to-switch-from-x-to-x-and-use-it/" type="text/html"/>
        <id>/2016-02-26-how-to-get-users-to-switch-from-x-to-x-and-use-it/</id>
        
            <content type="html">&lt;p&gt;There are many free, open source programs available which are equal (if not better) than paid counterparts, but the biggest hurdle to overcome is getting people to switch. It is imperative that you remember what caused you to switch and realize the two reasons for change:&lt;&#x2F;p&gt;
&lt;p&gt;&quot;You change for two reasons: Either you learn enough that you want to, or you&#x27;ve been hurt enough that you have to.&quot; - Unknown&lt;&#x2F;p&gt;
&lt;p&gt;So how do we get users to switch from X to X? Here are some quick ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Share what you have learned about X&lt;&#x2F;li&gt;
&lt;li&gt;Explain why you switched to X&lt;&#x2F;li&gt;
&lt;li&gt;Show someone how to use X&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For example, I switched to OpenOffice (now LibreOffice) back in 2005. While I had a licensed copy of Microsoft Office 2003, one key feature was missing: saving as PDFs. OpenOffice has a simple button to save as a PDF. Once my friend showed me how to use it and where the button was, I was eager to learn more about OpenOffice. That is when I took the plunge and went all in.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Understanding the cloud</title>
        <published>2016-02-19T15:00:00+00:00</published>
        <updated>2016-02-19T15:00:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-02-19-understanding-the-cloud/" type="text/html"/>
        <id>/2016-02-19-understanding-the-cloud/</id>
        
            <content type="html">&lt;p&gt;It&#x27;s 2016, the cloud computing has been around for nearly two decades, but there still seems to be a lack of knowledge in what cloud computing actually is and how to do it.&lt;&#x2F;p&gt;
&lt;p&gt;In diagrams, a cloud is the typified icon of the equipment of which you do not control; however, to those in the public internet, your diagram is the cloud. To them, your infrastructure is unknown, but to you it is known. Therefore, you can claim all servers under your control as being &quot;in the cloud&quot; even if they are not hosted in a public space such as Amazon Web Services or Microsoft Azure.&lt;&#x2F;p&gt;
&lt;p&gt;Your cloud can be a raspberry pi, a single server, or multiple servers. The amount of hardware needed for a cloud service is based upon the usage of the service provided. Your reliability of the service depends on how well redundancy is set up on your part. When you get into warehouse computing (a single datacenter for one service), it might be difficult to wrap your head around how it operates to perform access to this service, but it is as easy as building a single, large computer. When building a single computer, you buy hard drives, ram, motherboard, a network card, and network equipment. Next you assemble the server, install the operating system, and finally configure the software.&lt;&#x2F;p&gt;
&lt;p&gt;In warehouse computing, you break up the parts of your server to perform a specific task. In the storage realm, instead of attaching hard drives directly to the motherboard, they are connected via TCP&#x2F;IP via either an iSCSI, SAN, or a network share (Samba or NFS). You also separate processes to different machines. Your database software (such as MySQL) will be the only program installed on a group of servers dedicated to run the database of your application. Additionally, you will have a cluster of servers running your application&#x27;s server (php-fpm, django, etc.) with a load balancer in front.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>High performant chat application</title>
        <published>2016-02-12T15:00:52+00:00</published>
        <updated>2016-02-12T15:00:52+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-02-12-high-performant-chat-application/" type="text/html"/>
        <id>/2016-02-12-high-performant-chat-application/</id>
        
            <content type="html">&lt;p&gt;In a fictitious world where I started my own company and developed a LEMP-stack chat application, this is how I would do it in 2016:&lt;&#x2F;p&gt;
&lt;p&gt;I would use WebSockets as the protocol in which data is being sent to and from the server. WebSockets has built-in support by nginx (since version 1.3). For caching, I would use the &lt;code&gt;expires max;&lt;&#x2F;code&gt; function of nginx for my static content (images, css, js, fonts, etc). I would also ensure static content was named in the scheme of &lt;code&gt;name-md5hash.ext&lt;&#x2F;code&gt;. This would allow the caching on the client side to shine.&lt;&#x2F;p&gt;
&lt;p&gt;I would ensure my php files are gzip compressed (with .gz extension) to allow fast transferring of data between client and server. Nginx finds the .gz files when gzip compression is turned on and uses them if they exist. I would design small php-fpm servers that can support ~2,000 users at a time (basically, a dual core processor with 4gb of ram). This would allow ease of scaling at lower costs.&lt;&#x2F;p&gt;
&lt;p&gt;I would use GlusterFS for fault-tolerant storage. I would use the &lt;code&gt;mount -t gluster&lt;&#x2F;code&gt; option on the servers as it would allow distributed nfs capability for storage of uploaded content.&lt;&#x2F;p&gt;
&lt;p&gt;I would use MariaDB MaxScale as the database as it would allow for ease of scaling.&lt;&#x2F;p&gt;
&lt;p&gt;In short, it would look similar to the following diagram:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2016&#x2F;01&#x2F;chatapp.png&quot;&gt;&lt;img src=&quot;&#x2F;2016&#x2F;01&#x2F;chatapp.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>How to fix Error: Transaction check error with dnf&#x2F;yum</title>
        <published>2016-02-08T15:00:06+00:00</published>
        <updated>2016-02-08T15:00:06+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-02-08-how-to-fix-error-transaction-check-error-with-dnfyum/" type="text/html"/>
        <id>/2016-02-08-how-to-fix-error-transaction-check-error-with-dnfyum/</id>
        
            <content type="html">&lt;p&gt;When a &lt;code&gt;dnf&lt;&#x2F;code&gt; or &lt;code&gt;yum&lt;&#x2F;code&gt; process gets interrupted, you may get the below error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Running transaction check
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Transaction check succeeded.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Running transaction test
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;The downloaded packages were saved in cache until the next successful transaction.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;You can remove cached packages by executing &amp;#39;dnf clean packages&amp;#39;.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Error: Transaction check error:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file &#x2F;usr&#x2F;share&#x2F;doc&#x2F;avahi-libs&#x2F;README from install of avahi-libs-0.6.32-0.4.rc.fc23.i686 conflicts
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;with file from package avahi-libs-0.6.31-43.fc23.x86_64
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When presented with &lt;code&gt;Error: Transaction check error&lt;&#x2F;code&gt;, you are unable to install, update, or upgrade your system. The solution is to attempt to install the program (or download the files), locate them on your system, and manually update them using rpm.&lt;&#x2F;p&gt;
&lt;p&gt;In the example above, I want to update &lt;code&gt;avahi-libs&lt;&#x2F;code&gt; to a later version, but an older version still exists on my system. The &lt;code&gt;dnf&lt;&#x2F;code&gt; process was interrupted before it could erase the older version. Hence, the error means manual intervention of the problem is required. To fix, one needs to locate the newer version and use the &lt;code&gt;rpm&lt;&#x2F;code&gt; command to forcefully install the update. In other words, do the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;find &#x2F;var&#x2F;cache&#x2F;dnf&#x2F; -iname avahi-libs-0.6.32* -type f
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;rpm -Uvh --replacefiles &#x2F;path&#x2F;to&#x2F;avahi-libs-0.6.32-0.4.rc.fc23.i686.rpm
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is a good chance that the file you need is in &lt;code&gt;&#x2F;var&#x2F;cache&#x2F;dnf&#x2F;&lt;&#x2F;code&gt; already and does not need to be downloaded from a mirror.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>To-do for 2016</title>
        <published>2016-02-05T15:00:11+00:00</published>
        <updated>2016-02-05T15:00:11+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-02-05-to-do-for-2016/" type="text/html"/>
        <id>/2016-02-05-to-do-for-2016/</id>
        
            <content type="html">&lt;p&gt;As an IT worker, I have to re-learn my position every 3 years. This is due to the fact that Microsoft releases a new version (of their Server software, Exchange, office suite, etc.), or there has been a technology shift from one Linux specialty to another.&lt;&#x2F;p&gt;
&lt;p&gt;To combat this change and to stay ahead of the technology bubble, I have to be self-motivated to be on the front-end. Here is what I have scheduled for 2016:Reading Goals&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Databases for Small Business by Anna Manning&lt;&#x2F;li&gt;
&lt;li&gt;Programming in Go by Mark Summerfield&lt;&#x2F;li&gt;
&lt;li&gt;The Rails 4 Way by Obie Fernandez&lt;&#x2F;li&gt;
&lt;li&gt;Bootstrap for Rails by Syed Fazle Rahman&lt;&#x2F;li&gt;
&lt;li&gt;Bible in a Year (McCheyne)&lt;&#x2F;li&gt;
&lt;li&gt;The Varnish Book by Varnish Software&lt;&#x2F;li&gt;
&lt;li&gt;Nginx HTTP Server Second Edition by Clement Nedelcu&lt;&#x2F;li&gt;
&lt;li&gt;Nginx High Performance by Rahul Sharma&lt;&#x2F;li&gt;
&lt;li&gt;Making Home Work by Paul Chappell&lt;&#x2F;li&gt;
&lt;li&gt;MySQL High Availability by Charles Bell, Mats Kindahl, and Lars Thalmann&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Video Course Goals&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.lynda.com&#x2F;Ruby-tutorials&#x2F;essential-training&#x2F;47905-2.html&quot;&gt;Ruby Essential Training&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.lynda.com&#x2F;Ruby-Rails-tutorials&#x2F;Ruby-Rails-4-Essential-Training&#x2F;139989-2.html&quot;&gt;Ruby on Rails 4 Essential Training&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.lynda.com&#x2F;Ruby-tutorials&#x2F;RSpec-Testing-Framework-Ruby&#x2F;183884-2.html&quot;&gt;RSpec Testing Framework with Ruby&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Personal Goals&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Achieve RHSCA Certification&lt;&#x2F;li&gt;
&lt;li&gt;Make 15 commits to an Open Source project&lt;&#x2F;li&gt;
&lt;li&gt;Take my family on a monthly activity&lt;&#x2F;li&gt;
&lt;li&gt;Blog once a week (Fridays)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>VoIP Troubleshooting Checklist</title>
        <published>2016-01-29T15:00:29+00:00</published>
        <updated>2016-01-29T15:00:29+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-01-29-voip-troubleshooting-checklist/" type="text/html"/>
        <id>/2016-01-29-voip-troubleshooting-checklist/</id>
        
            <content type="html">&lt;p&gt;Voice over IP is very robust and reliable when set up properly. There are only four key areas to set up and check for issues. I have compiled the below list as things to check when an issue occurs. All of the steps are pretty basic and are known by every VoIP professional; however, it is handy to have to show a non-technical person or somebody who has little knowledge on VoIP systems.&lt;&#x2F;p&gt;
&lt;p&gt;Phone&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure the phone is compatible with the PBX you selected&lt;&#x2F;li&gt;
&lt;li&gt;Ensure voice is on the voice vlan and data is on the data vlan&lt;&#x2F;li&gt;
&lt;li&gt;Ensure the audio codec being used on the phone is supported by the server&lt;&#x2F;li&gt;
&lt;li&gt;Ensure the codec you want to use is listed first in the settings&lt;&#x2F;li&gt;
&lt;li&gt;Switch codecs to see if voice quality improves or declines in quality&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Phone-to-PBX&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure voice traffic is on a separate vlan&lt;&#x2F;li&gt;
&lt;li&gt;Ensure the voice vlan has priority on the network (QoS)&lt;&#x2F;li&gt;
&lt;li&gt;Ensure there are no faulty Ethernet lines and that all 8 wires go to a single port (for PoE and best practice)&lt;&#x2F;li&gt;
&lt;li&gt;Ensure switches are voice vlan capable&lt;&#x2F;li&gt;
&lt;li&gt;Ensure the switch has enough voltage to power the amount of phones connected to it (if using PoE)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;PBX&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure it is powered on&lt;&#x2F;li&gt;
&lt;li&gt;Ensure services are running&lt;&#x2F;li&gt;
&lt;li&gt;Check call quality between internal-to-internal extension&lt;&#x2F;li&gt;
&lt;li&gt;Check call quality between internal-to-internal extension on separate PBX host (if clustered)&lt;&#x2F;li&gt;
&lt;li&gt;Check inbound call routing rules&lt;&#x2F;li&gt;
&lt;li&gt;Check outbound call routing rules&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;PBX-to-Service Provider&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ensure you have phone service and it is turned on&lt;&#x2F;li&gt;
&lt;li&gt;Ensure the service provider allows self-managing of the Caller ID&lt;&#x2F;li&gt;
&lt;li&gt;Ensure voice traffic is not being sent out on the public internet (on-net) if using SIP trunking&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>My Review of Digium</title>
        <published>2016-01-22T15:00:41+00:00</published>
        <updated>2016-01-22T15:00:41+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-01-22-my-review-of-digium/" type="text/html"/>
        <id>/2016-01-22-my-review-of-digium/</id>
        
            <content type="html">&lt;p&gt;In a previous post, I mentioned that we switched to Digium Switchvox. Here are some features I really enjoy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-extension-has-access-to-everything&quot;&gt;An extension has access to everything&lt;&#x2F;h2&gt;
&lt;p&gt;There are no receptionist licenses. There are no addons for basic features such as faxing or voicemail. There is no confusion when it comes to determining a cost. Every extension has access to everything for one low yearly subscription fee.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-admin-interface-is-accessed-via-web-browser&quot;&gt;The admin interface is accessed via web browser&lt;&#x2F;h2&gt;
&lt;p&gt;I like web browser software. It means I do not have to install an application to configure a setting and I can access the interface from my mobile phone, tablet, or Chromebook.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-works-well-with-asterisk&quot;&gt;It works well with Asterisk&lt;&#x2F;h2&gt;
&lt;p&gt;While the extension licenses are cheap ($12&#x2F;year&#x2F;extension for titanium support), I have difficulty buying a license for a phone that will probably be used once in a 5 year time span - such as a lobby phone, dorm room phone, or classroom. These extensions just need dial tone and no advanced functionality (contact listing, switchboard, etc.) - having them as an Asterisk extension works great.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phones-are-easy-to-add&quot;&gt;Phones are easy to add&lt;&#x2F;h2&gt;
&lt;p&gt;Our installer set us up several templates. Using these templates, I can create an extension in under 10 seconds. Adding it to the phone takes an additional 10-60 seconds depending upon the state of the phone.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-can-use-any-phone&quot;&gt;I can use any phone&lt;&#x2F;h2&gt;
&lt;p&gt;There are 3 specific spots in my environment where a cordless phone is vital. With Digium, I can deploy a Grandstream DP715 and call it a day.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-servers-are-smart&quot;&gt;The servers are &quot;smart&quot;&lt;&#x2F;h2&gt;
&lt;p&gt;The servers are smart in that they start up after a power outage. Not that power outages happen all the time, but occasionally when the UPS battery is depleted, it is nice to know the default is set to power up when there is a power source.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>VoIP implementation and tests</title>
        <published>2016-01-15T15:00:47+00:00</published>
        <updated>2016-01-15T15:00:47+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-01-15-voip-implementation-and-tests/" type="text/html"/>
        <id>/2016-01-15-voip-implementation-and-tests/</id>
        
            <content type="html">&lt;p&gt;In 2014, we decided to transition from a Mitel sx200 to a VoIP solution. We researched Cisco UM, Mitel, Lync, Shoretel, Avaya, Digium, a few hosted solutions, and a few Asterisk clones. I was one of three who sat through several presentations of &lt;strong&gt;the same features of every single phone system&lt;&#x2F;strong&gt;. Two weeks into this process, we narrowed the field down to Avaya and Digium with cost-to-implement for 650 extensions being the main deciding factor. The other deciding factor was these two companies did not give a speech about we should choose them because such-and-so research company rated them #1 in customer satisfaction. In the second round of finding a VoIP solution, we asked if we could do a one week test of a demo system. Both parties agreed to this test and we were sent demo units. With the test units, we selected 6 secretaries, 1 programmer, myself, and 2 receptionists to participate in making internal calls and testing each of the functions. During the week, we deployed several tests:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Phone server interruption (I unplugged the server ethernet for 10-30 seconds)&lt;&#x2F;li&gt;
&lt;li&gt;Call audio quality&lt;&#x2F;li&gt;
&lt;li&gt;Phone restart time&lt;&#x2F;li&gt;
&lt;li&gt;The time it took to set up 1 phone&lt;&#x2F;li&gt;
&lt;li&gt;Admin user interface&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After the week was done, we asked each participant which system they liked better. Everyone liked the Digium handsets. We also received reports that call audio quality was better with Digium (I believe Avaya adds white noise). During the &quot;Phone server interruption&quot; the Digium phones reconnected without rebooting whereas the Avaya phones rebooted as soon as the server went offline.&lt;&#x2F;p&gt;
&lt;p&gt;After looking at a 20 year TCO (with updates and phone upgrades), both phone systems came out to be nearly equal in cost. Ultimately we chose to go with Digium based upon internal experiences and haven&#x27;t regretted it.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>oVirt pitfalls</title>
        <published>2016-01-08T15:00:03+00:00</published>
        <updated>2016-01-08T15:00:03+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-01-08-ovirt-pitfalls/" type="text/html"/>
        <id>/2016-01-08-ovirt-pitfalls/</id>
        
            <content type="html">&lt;p&gt;After you use something for a bit, you notice the issues associated with it. While oVirt has solved my pain points of high availability, there are a few which stand out.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;logging-in&quot;&gt;Logging in&lt;&#x2F;h3&gt;
&lt;p&gt;To log in to oVirt for administration, you visit the landing page of the oVirt-engine website. This is perfect - it means I can administrate it from the web browser on my mobile phone. The issue comes when you actually need to log in - you have to click another link on the landing page to see the spot to enter your credentials. It would be nice if the landing page had the username and password fields and, after authentication, would bring up the appropriate view based on permissions (reporting, user, or admin view). Another thought is to have another drop-down box with the area to load right next to the profile to use. It could be that the design of the landing page is different than what I am used to, but there is clearly room for improvement.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;without-dns-the-engine-website-doesn-t-work&quot;&gt;Without DNS, the engine website doesn&#x27;t work&lt;&#x2F;h3&gt;
&lt;p&gt;If you have your DNS server virtualized and the storage gluster goes into a rebuild mode, your oVirt engine doesn&#x27;t work. You can&#x27;t log in quickly, you can&#x27;t shutdown&#x2F;turn on VMs, and you can&#x27;t select anything (if you have managed to log in). You have to resort to the cli interface in order to do anything! Apparently oVirt queries each server via DNS before it lets you type in the login fields. This is easily fixed by managing the hosts file on each server via Puppet, but it seems like bad IT practice to do this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-web-interface-has-too-many-tabs&quot;&gt;The web interface has too many tabs&lt;&#x2F;h3&gt;
&lt;p&gt;This makes it difficult to tell co-workers how to operate the interface via email, sms, or telephone conversation. Often I find myself clicking through 5 tabs because I forgot how to get to a previous page. This could be from my inexperience with the interface, but I think it could be improved. This also makes it difficult to use on a mobile web browser.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Read the Bible this year</title>
        <published>2016-01-01T15:00:14+00:00</published>
        <updated>2016-01-01T15:00:14+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2016-01-01-read-the-bible-this-year/" type="text/html"/>
        <id>/2016-01-01-read-the-bible-this-year/</id>
        
            <content type="html">&lt;p&gt;Most Christians read the Bible every day. Bible reading schedules are either in paper form only or there is a charge in obtaining the digital copy of one. Such was the case for my wife. She liked the McCheyne reading schedule which takes you through the new testament twice and the old once. A digital copy of the schedule was not within easy reach (we searched Amazon books) and our Church switched to distributing a different reading schedule at the beginning of the new year. This is how my &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;Bible-in-a-year&quot;&gt;Bible-in-a-year github repository&lt;&#x2F;a&gt; was expanded.&lt;&#x2F;p&gt;
&lt;p&gt;I already made a Bible reading schedule for myself to start from Genesis and end in Revelation for the kindle. It was easy to use this information I learned to create another kindle book for my wife - after all, kindle books are just compiled HTML.&lt;&#x2F;p&gt;
&lt;p&gt;You may download the &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;Bible-in-a-year&#x2F;raw&#x2F;master&#x2F;McCheyne&#x2F;McCheyne.mobi&quot;&gt;McCheyne version&lt;&#x2F;a&gt; or &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewwippler&#x2F;Bible-in-a-year&#x2F;raw&#x2F;master&#x2F;Old_New&#x2F;Compiled-KJVinaYear.opf&#x2F;KJVinaYear.mobi&quot;&gt;Genesis-to-Revelation version&lt;&#x2F;a&gt; for free! Then start this year on the right foot by uploading them to your kindle or mobi reader.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Merry Christmas</title>
        <published>2015-12-25T15:00:22+00:00</published>
        <updated>2015-12-25T15:00:22+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-12-25-merry-christmas/" type="text/html"/>
        <id>/2015-12-25-merry-christmas/</id>
        
            <content type="html">&lt;p&gt;For those who read my blog, I want to wish a Merry Christmas. It always gives me great joy to remember the virgin birth of Jesus Christ. Not only does Jesus&#x27; life impact so many, but it was his death that payed the price of my sin. I am one of those who believe that he took my spot as a scapegoat for my sin. I have placed my trust in him alone for salvation from sin&#x27;s penalty, power, and preeminence in my life.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Switching from Active Directory to Samba4</title>
        <published>2015-12-21T14:00:46+00:00</published>
        <updated>2015-12-21T14:00:46+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-12-21-switching-from-active-directory-to-samba4/" type="text/html"/>
        <id>/2015-12-21-switching-from-active-directory-to-samba4/</id>
        
            <content type="html">&lt;p&gt;Active Directory is solid, secure, and stable platform for user, group, and computer management. I would go as far and say that it is probably the backbone of 99.9% of all organizations world wide. So why would anyone want to switch away from Active Directory? The answer to that question is varied, but the most common reason why are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Reduce licensing costs (per user&#x2F;device cals)&lt;&#x2F;li&gt;
&lt;li&gt;Reduce Windows foot print&lt;&#x2F;li&gt;
&lt;li&gt;Advanced features of AD are not needed&lt;&#x2F;li&gt;
&lt;li&gt;Less than 5,000 users&lt;&#x2F;li&gt;
&lt;li&gt;Because &amp;lt;insert_favorite_software&amp;gt; is greater than &amp;lt;insert_hated_software&amp;gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let us get started on switching to a Samba4 backend.&lt;&#x2F;p&gt;
&lt;p&gt;This guide assumes the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You already have a domain environment&lt;&#x2F;li&gt;
&lt;li&gt;The forest functional level is 2003 or greater&lt;&#x2F;li&gt;
&lt;li&gt;The domain functional level is not greater than 2008 R2&lt;&#x2F;li&gt;
&lt;li&gt;You are running CentOS&#x2F;RedHat 7 as your Samba4 host and it is a vanilla minimal install with no added repositories (i.e. you just installed it)&lt;&#x2F;li&gt;
&lt;li&gt;Your domain is: AD.ANDREWWIPPLER.COM and your NETBIOS is AD.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;installing-samba4&quot;&gt;Installing Samba4&lt;&#x2F;h2&gt;
&lt;p&gt;The samba version that ships with CentOS is compiled in legacy NT4 emulation mode. In order to get the AD emulation, we will need to compile Samba4 (Don&#x27;t worry, it is very easy and compiles under 20 minutes with a 2 core processor.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cd &#x2F;usr&#x2F;src&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;wget https:&#x2F;&#x2F;download.samba.org&#x2F;pub&#x2F;samba&#x2F;stable&#x2F;samba-4.3.2.tar.gz
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo tar xf samba-4.3.2.tar.gz
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cd samba-4.3.2&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we need to install the build tools. (The most updated list is located &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.samba.org&#x2F;index.php&#x2F;Operating_system_requirements&#x2F;Dependencies_-_Libraries_and_programs#Red_Hat_Enterprise_Linux_.2F_CentOS_.2F_Scientific_Linux&quot;&gt;here&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo yum install perl gcc attr libacl-devel libblkid-devel \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    gnutls-devel readline-devel python-devel gdb pkgconfig \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    krb5-workstation zlib-devel setroubleshoot-server libaio-devel \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    setroubleshoot-plugins policycoreutils-python \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    libsemanage-python perl-ExtUtils-MakeMaker perl-Parse-Yapp \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    perl-Test-Base popt-devel libxml2-devel libattr-devel \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    keyutils-libs-devel cups-devel bind-utils libxslt \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    docbook-style-xsl openldap-devel autoconf python-crypto
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The next step is to compile and run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;.&#x2F;configure
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;make -j 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# The number 2 should be relative to the number of cores on your machine
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo make install
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This process should take less than 20 minutes. After it is done compiling, it will install to &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;samba&#x2F;&lt;&#x2F;code&gt;. To make it easier to run the new commands, let us add the paths to our global path:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;etc&#x2F;profile.d&#x2F;samba.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;##add samba to PATH
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;export PATH=&#x2F;usr&#x2F;local&#x2F;samba&#x2F;bin&#x2F;:&#x2F;usr&#x2F;local&#x2F;samba&#x2F;sbin&#x2F;:$PATH
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chmod 0644 &#x2F;etc&#x2F;profile.d&#x2F;samba.sh
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;. &#x2F;etc&#x2F;profile
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;preparing-the-system-to-join-ad&quot;&gt;Preparing the system to join AD&lt;&#x2F;h2&gt;
&lt;p&gt;Now that Samba is installed, we need to configure our system to interact with Active Directory as well and set up BIND9.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network-related&quot;&gt;Network related&lt;&#x2F;h3&gt;
&lt;p&gt;A static IP as well as DNS must be configured properly for this to work. Ensure the appropriate settings are in &lt;code&gt;&#x2F;etc&#x2F;sysconfig&#x2F;network-scripts&#x2F;ifcfg-(iface-name)&lt;&#x2F;code&gt;. The DNS servers must be an Active Directory domain controller and you should be able to ping it. If modification is done to this file, you will need to restart NetworkManager for changes to take effect. The desired result is to have &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt; appear like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Generated by NetworkManager
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;search ad.andrewwippler.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;nameserver 192.168.1.201
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my lab, 192.168.1.201 is a Windows 2008 R2 server named DC1.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hostname-related&quot;&gt;Hostname related&lt;&#x2F;h3&gt;
&lt;p&gt;If you have not named your CentOS install, it is best to do it now. You will also need to verify that pinging your hostname works and it returns with the ip of the interface you set and not the loopback interface.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo hostname dc2.ad.andrewwippler.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo echo &amp;#39;dc2.ad.andrewwippler.com&amp;#39; &amp;gt; &#x2F;etc&#x2F;hostname
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo &amp;#39;192.168.1.202 dc2 dc2.ad.andrewwippler.com&amp;#39; &amp;gt;&amp;gt; &#x2F;etc&#x2F;hosts
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;kerberos-related&quot;&gt;Kerberos related&lt;&#x2F;h3&gt;
&lt;p&gt;Ensure &lt;code&gt;&#x2F;etc&#x2F;krb5.conf&lt;&#x2F;code&gt; has the following. The domain needs to be in all caps.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[libdefaults]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ...
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    dns_lookup_realm = false
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    dns_lookup_kdc = true
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    default_realm = AD.ANDREWWIPPLER.COM
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;testing&quot;&gt;Testing&lt;&#x2F;h3&gt;
&lt;p&gt;We can now test our DNS and Kerberos settings with two simple commands.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;kinit administrator
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This should ask you for the domain administrator&#x27;s password. Once entered you can verify everything is working with &lt;code&gt;klist&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;joining-active-directory&quot;&gt;Joining Active Directory&lt;&#x2F;h2&gt;
&lt;p&gt;At this point, we have not started Samba, nor do we need to until the very end. We can now issue the join command (with BIND9 support)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo samba-tool domain join ad.andrewwippler.com DC -Uadministrator --realm=AD.ANDREWWIPPLER.COM --dns-backend=BIND9_DLZ
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we will have to configure bind. For convenience sake, I have included my &lt;code&gt;&#x2F;etc&#x2F;named.conf&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F; named.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;options {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	listen-on port 53 { any; };
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	listen-on-v6 port 53 { any; };
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	directory 	&amp;quot;&#x2F;var&#x2F;named&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	dump-file 	&amp;quot;&#x2F;var&#x2F;named&#x2F;data&#x2F;cache_dump.db&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	statistics-file &amp;quot;&#x2F;var&#x2F;named&#x2F;data&#x2F;named_stats.txt&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	memstatistics-file &amp;quot;&#x2F;var&#x2F;named&#x2F;data&#x2F;named_mem_stats.txt&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	allow-query     { any; };
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	recursion yes;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	dnssec-enable yes;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	dnssec-validation yes;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	dnssec-lookaside auto;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	&#x2F;* Path to ISC DLV key *&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	bindkeys-file &amp;quot;&#x2F;etc&#x2F;named.iscdlv.key&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	managed-keys-directory &amp;quot;&#x2F;var&#x2F;named&#x2F;dynamic&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	pid-file &amp;quot;&#x2F;run&#x2F;named&#x2F;named.pid&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	session-keyfile &amp;quot;&#x2F;run&#x2F;named&#x2F;session.key&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        &#x2F;&#x2F;samba
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        tkey-gssapi-keytab &amp;quot;&#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns.keytab&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;logging {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        channel default_debug {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                file &amp;quot;data&#x2F;named.run&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                severity dynamic;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        };
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;zone &amp;quot;.&amp;quot; IN {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	type hint;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	file &amp;quot;named.ca&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include &amp;quot;&#x2F;etc&#x2F;named.rfc1912.zones&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include &amp;quot;&#x2F;etc&#x2F;named.root.key&amp;quot;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;&#x2F;samba
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;include &amp;quot;&#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;named.conf&amp;quot;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;allowing-access&quot;&gt;Allowing access&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a functioning samba server (even though it hasn&#x27;t started yet), we need to allow it through SELinux and the firewall. Below are the commands to do just that:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;firewall&quot;&gt;Firewall&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=389&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=389&#x2F;udp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=636&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=53&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=53&#x2F;udp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=88&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=88&#x2F;udp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=464&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=464&#x2F;udp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=135&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=137&#x2F;udp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=139&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=138&#x2F;udp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=445&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --add-port=3268&#x2F;tcp --permanent
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo firewall-cmd --reload
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;selinux&quot;&gt;SELinux&lt;&#x2F;h3&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chown named:named &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chgrp named &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns.keytab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chmod g+r &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns.keytab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chmod 775 &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chown named:named &#x2F;usr&#x2F;local&#x2F;samba&#x2F;lib&#x2F;bind9&#x2F;dlz_bind9_9.so
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chcon -t named_conf_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns.keytab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chcon -t named_conf_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;named.conf.update
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chcon -t named_var_run_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chcon -t named_var_run_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;lib&#x2F;bind9&#x2F;dlz_bind9_9.so
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo semanage fcontext -a -t named_conf_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns.keytab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo semanage fcontext -a -t named_conf_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;named.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo semanage fcontext -a -t named_conf_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;named.conf.update
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo semanage fcontext -a -t named_var_run_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;private&#x2F;dns
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo semanage fcontext -a -t named_var_run_t &#x2F;usr&#x2F;local&#x2F;samba&#x2F;lib&#x2F;bind9&#x2F;dlz_bind9_9.so
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we need to run SELinux in permissive mode and add the policy.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo setenforce 0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo systemctl restart named
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sleep 60
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo systemctl stop named
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cd ~
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo grep named &#x2F;var&#x2F;log&#x2F;audit&#x2F;audit.log | audit2allow -M named &amp;gt; named.te
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo semodule -i named.pp
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo setenforce 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo systemctl start named
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;init-files&quot;&gt;Init files&lt;&#x2F;h2&gt;
&lt;p&gt;Samba does not ship with an init file so we will have to create one and enable it to start at boot.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo cat &amp;lt;&amp;lt; EOF &amp;gt; &#x2F;etc&#x2F;init.d&#x2F;samba
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# samba4        This shell script takes care of starting and stopping
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#               samba4 daemons.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# chkconfig: - 58 74
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# description: Samba 4.0 will be the next version of the Samba suite
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# and incorporates all the technology found in both the Samba4 alpha
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# series and the stable 3.x series. The primary additional features
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# over Samba 3.6 are support for the Active Directory logon protocols
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# used by Windows 2000 and above.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;### BEGIN INIT INFO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Provides: samba4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Required-Start: $network $local_fs $remote_fs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Required-Stop: $network $local_fs $remote_fs
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Should-Start: $syslog $named
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Should-Stop: $syslog $named
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Short-Description: start and stop samba4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Description: Samba 4.0 will be the next version of the Samba suite
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# and incorporates all the technology found in both the Samba4 alpha
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# series and the stable 3.x series. The primary additional features
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# over Samba 3.6 are support for the Active Directory logon protocols
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# used by Windows 2000 and above.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;### END INIT INFO
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Source function library.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;. &#x2F;etc&#x2F;init.d&#x2F;functions
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Source networking configuration.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;. &#x2F;etc&#x2F;sysconfig&#x2F;network
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;prog=samba
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;prog_dir=&#x2F;usr&#x2F;local&#x2F;samba&#x2F;sbin&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;lockfile=&#x2F;var&#x2F;lock&#x2F;subsys&#x2F;$prog
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;start() {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        [ &amp;quot;$NETWORKING&amp;quot; = &amp;quot;no&amp;quot; ] &amp;amp;&amp;amp; exit 1
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#       [ -x &#x2F;usr&#x2F;sbin&#x2F;ntpd ] || exit 5
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                # Start daemons.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                echo -n $&amp;quot;Starting samba4: &amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                daemon $prog_dir&#x2F;$prog -D
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        RETVAL=$?
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                echo
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        [ $RETVAL -eq 0 ] &amp;amp;&amp;amp; touch $lockfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        return $RETVAL
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;stop() {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        [ &amp;quot;$EUID&amp;quot; != &amp;quot;0&amp;quot; ] &amp;amp;&amp;amp; exit 4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                echo -n $&amp;quot;Shutting down samba4: &amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        killproc $prog_dir&#x2F;$prog
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        RETVAL=$?
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;                echo
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        [ $RETVAL -eq 0 ] &amp;amp;&amp;amp; rm -f $lockfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        return $RETVAL
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# See how we were called.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;case &amp;quot;$1&amp;quot; in
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;start)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        start
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;stop)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        stop
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;status)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        status $prog
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;restart)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        stop
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        start
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        ;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;*)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        echo $&amp;quot;Usage: $0 {start|stop|status|restart}&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        exit 2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;esac
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;EOF
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chmod +x &#x2F;etc&#x2F;init.d&#x2F;samba
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo chkconfig samba on
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;flipping-the-switch&quot;&gt;Flipping the switch&lt;&#x2F;h2&gt;
&lt;p&gt;You are now ready to either restart the system or start samba. The next steps to fully migrate to a Samba4 AD backend would be to migrate the FSMO roles to this server. Managing this AD instance is done by loading the Remote Server Administration Tools (RSAT) on a windows client.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;&#x2F;h2&gt;
&lt;p&gt;Here are the list of sources and references to compile this tutorial:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.samba.org&#x2F;index.php&#x2F;Join_an_additional_Samba_DC_to_an_existing_Active_Directory&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.samba.org&#x2F;index.php&#x2F;Build_Samba_from_source&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.samba.org&#x2F;index.php&#x2F;Samba4&#x2F;InitScript&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;wiki.samba.org&#x2F;index.php&#x2F;Configure_BIND_as_backend_for_Samba_AD&lt;&#x2F;li&gt;
&lt;li&gt;https:&#x2F;&#x2F;lists.samba.org&#x2F;archive&#x2F;samba&#x2F;2013-March&#x2F;172397.html (Thanks &lt;strong&gt;Thomas Simmons&lt;&#x2F;strong&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Converting Debian&#x2F;Ubuntu to oVirt</title>
        <published>2015-12-18T15:00:08+00:00</published>
        <updated>2015-12-18T15:00:08+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-12-18-converting-debianubuntu-to-ovirt/" type="text/html"/>
        <id>/2015-12-18-converting-debianubuntu-to-ovirt/</id>
        
            <content type="html">&lt;p&gt;oVirt 3.6 will have a better way to import virtual machines. In the mean time, here is the best method for getting an already made ova into oVirt. The example I am using is the open source log analyzer - &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.graylog.org&#x2F;&quot;&gt;graylog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A prerequisite is the script located at &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;git.annexia.org&#x2F;git&#x2F;import-to-ovirt.git&quot;&gt;http:&#x2F;&#x2F;git.annexia.org&#x2F;git&#x2F;import-to-ovirt.git&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;git clone http:&#x2F;&#x2F;git.annexia.org&#x2F;git&#x2F;import-to-ovirt.git
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Verify the type of the downloaded file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;file graylog.ova
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;graylog.ova: POSIX tar archive
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is wrapped archive, extract it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tar xf graylog.ova
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whether converting from Hyper-V or OVA, the following steps will be the same except Hyper-V&#x27;s format will be &lt;code&gt;vpc&lt;&#x2F;code&gt; instead of &lt;code&gt;vmdk&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo qemu-img convert -f vmdk -O qcow2 graylog-disk1.vmdk graylog.qcow2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This line will import the image into oVirt.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo import-to-ovirt.pl graylog.qcow2 ovirt-nfs-storage:&#x2F;exports&#x2F;import_export
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The VM can then be imported using the import tab of the storage domain where you uploaded the file.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Converting VMs for oVirt</title>
        <published>2015-12-11T15:00:14+00:00</published>
        <updated>2015-12-11T15:00:14+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-12-11-converting-vms-for-ovirt/" type="text/html"/>
        <id>/2015-12-11-converting-vms-for-ovirt/</id>
        
            <content type="html">&lt;p&gt;My existing Hyper-V infrastructure consisted of Windows, a few CentOS, and Debian&#x2F;Ubuntu guests. The best method I found to importing into oVirt was using the &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;oirase.annexia.org&#x2F;virt-p2v&#x2F;&quot;&gt;virt-p2v disc&lt;&#x2F;a&gt;. This required down time of the server (approx 3 hours per 100GB on gigabit backbone) and a dedicated Fedora or Debian server which had &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; installed. I used my Acer C710 Chromebook to serve as the &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; converter. (This is possibly the reason I had slow conversion times.)&lt;&#x2F;p&gt;
&lt;p&gt;Once you boot into &lt;code&gt;virt-p2v&lt;&#x2F;code&gt;, you enter the IP address of an ssh server with &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; installed. Unfortunately, I had to log in with root credentials as using the sudo method did not work when I tried. In some instances, my virtual machines needed the legacy Hyper-V network adapter to get an IP from DHCP and be able to ping the conversion server. It would have been helpful if &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; mentioned this rather than giving a general username&#x2F;password is invalid error.&lt;&#x2F;p&gt;
&lt;p&gt;After successfully testing the server and logging in, the next step is to enter the target properties. These are what you will name the image, how many virtual CPUs to allocate, and the desired RAM. Next the output options have to be set. Since I was using oVirt, I selected the &lt;em&gt;Output to (-o)&lt;&#x2F;em&gt; as rhev. I then had to enter the &lt;em&gt;Output storage (-os)&lt;&#x2F;em&gt; which is required when converting for oVirt&#x2F;rhev. Since these settings are relative to the &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; server, I could have mounted the nfs import domain (defaults in getting started guide - &lt;em&gt;nfs-server:&#x2F;exports&#x2F;import_export&lt;&#x2F;em&gt; ) as &#x2F;var&#x2F;tmp on the &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; converter; however, I decided to enter the nfs server and path instead as this value. Next, you select the discs to convert as well as any network interfaces and removable media. I found that you only need to select the harddrives - everything else can be configured in oVirt.&lt;&#x2F;p&gt;
&lt;p&gt;Once you click start conversion, &lt;code&gt;virt-p2v&lt;&#x2F;code&gt; boots into the virtual machine and forwards data to your &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; server. The &lt;code&gt;virt-v2v&lt;&#x2F;code&gt; process removes devices and adds the special ones needed to prevent a BSOD when you boot your Windows server for the first time on oVirt. Something similarly happens on CentOS based VMs.&lt;&#x2F;p&gt;
&lt;p&gt;Once that is done you need to go into the storage tab of the cluster (in my case, Default) and select the import storage domain. This will then open up the lower third of the web interface with another tab that is labeled &lt;em&gt;import&lt;&#x2F;em&gt;. This will list all VM guests that have successfully been converted by &lt;code&gt;virt-p2v&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Planning the Deployment of oVirt</title>
        <published>2015-12-04T15:00:46+00:00</published>
        <updated>2015-12-04T15:00:46+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-12-04-planning-the-deployment-of-ovirt/" type="text/html"/>
        <id>/2015-12-04-planning-the-deployment-of-ovirt/</id>
        
            <content type="html">&lt;p&gt;After I played with oVirt I needed to do several items:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Migrate the oVirt engine to a new host&lt;&#x2F;li&gt;
&lt;li&gt;Migrate the storage from a single NFS share to GlusterFS&lt;&#x2F;li&gt;
&lt;li&gt;Move my VMs from Hyper-V to oVirt&lt;&#x2F;li&gt;
&lt;li&gt;Test my setup&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;migrate-the-ovirt-engine-to-a-new-host&quot;&gt;Migrate the oVirt Engine to a new host&lt;&#x2F;h2&gt;
&lt;p&gt;This task was to prepare me for the disaster recovery scenario - what if my server room blew up - how would I recover my virtualization backbone? It might not be that important (considering I back up my VMs and can restore them anywhere), but when disaster strikes, tasks need to be simple because concentration will be difficult. As of version 3.5, oVirt had a good back up and restore operation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#backup example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;share&#x2F;ovirt-engine&#x2F;bin&#x2F;engine-backup.sh --mode=backup --scope=all --file=&#x2F;root&#x2F;engine_backup --log=&#x2F;root&#x2F;backup_log
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#restore example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&#x2F;usr&#x2F;share&#x2F;ovirt-engine&#x2F;bin&#x2F;engine-backup.sh --mode=restore --scope=all --file=&#x2F;root&#x2F;engine_backup --log=restore_lg
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;engine-setup
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All I had to do was run the backup script, copy the file, restore it, and run &lt;code&gt;engine-setup&lt;&#x2F;code&gt;. To further harden my installation, I placed the backup line in my daily &lt;code&gt;crontab&lt;&#x2F;code&gt; an hour earlier than my scheduled &lt;code&gt;duplicity&lt;&#x2F;code&gt; run.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;migrate-the-storage-from-a-single-nfs-share-to-glusterfs&quot;&gt;Migrate the storage from a single NFS share to GlusterFS&lt;&#x2F;h2&gt;
&lt;p&gt;This next step was a bit under-sighted on my part. In my test lab, I had 4 VMs running on 1 NFS server. The NFS server I chose in the lab environment began to choke around 30 VMs and eventually crashed when I hit the 35 mark. It was not a limitation on oVirt or NFS, but on my hardware. &lt;code&gt;GlusterFS&lt;&#x2F;code&gt; was extremely simple to set up and their documentation is easy to follow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;move-my-vms-from-hyper-v-to-ovirt&quot;&gt;Move my VMs from Hyper-V to oVirt&lt;&#x2F;h2&gt;
&lt;p&gt;I will discuss this in more detail in a following post. It was mostly running &lt;code&gt;virt-p2v&lt;&#x2F;code&gt; on Windows and CentOS and &lt;code&gt;import-to-ovirt.pl&lt;&#x2F;code&gt; on Debian and Ubuntu VMs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-my-setup&quot;&gt;Test my setup&lt;&#x2F;h2&gt;
&lt;p&gt;During the transition, I had the opportune time to experience what it was like when my single point of failure (the one NFS server) crashed. It was also painful when DNS and DHCP were on servers on the failed storage server (oVirt didn&#x27;t like that). Through this process, I have formulated several key steps to prevent a failure like that from happening again.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Switching from Hyper-V to oVirt</title>
        <published>2015-11-27T15:00:31+00:00</published>
        <updated>2015-11-27T15:00:31+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-11-27-switching-from-hyper-v-to-ovirt/" type="text/html"/>
        <id>/2015-11-27-switching-from-hyper-v-to-ovirt/</id>
        
            <content type="html">&lt;p&gt;For quite some time I have heard that Hyper-V was a low player when it came to virtualization. It came with Windows and was the hypervisor of choice, but it had its limitations. In my environment, we had local storage and no clustering of hosts and consequently no high availability or fail over. This brought the first pain point - we need high availability.&lt;&#x2F;p&gt;
&lt;p&gt;On one of my hosts, the broadcom Ethernet driver kept triggering flow control and would not resume causing all of the VM Guests to go offline. This triggered the second pain point - I need high availability yesterday.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;What matters most in a hypervisor environment is the tools you use to manage it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I took this principle as a guide when searching for a hypervisor environment. I first looked at Hyper-V and the new licensing costs it would accrue. Next I looked at the popular VMWare ESXi, but I heard the neat features were at a premium price and all I needed was high availability. I looked at Open Source versions like KVM, Xen, and OpenStack (which appeared to be too big for my 40 VM environment). Then I found RHEV&#x27;s community version - oVirt. It had all the bells and whistles I needed - Linux hosts and high availability.&lt;&#x2F;p&gt;
&lt;p&gt;oVirt&#x27;s install documents were surprisingly simple as I quickly found 3 servers to set up: an engine server, a file server, and a VM Host. Once set up, I tinkered with it, and to my delight - everything worked right out of the box (on old hardware too!) My next step was to install a few VMs and test the high availability features. It was evident that oVirt was the solution to my pain points.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Why I can&#x27;t vote for Hillary Clinton</title>
        <published>2015-11-20T14:45:00+00:00</published>
        <updated>2015-11-20T14:45:00+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-11-20-why-i-cant-vote-for-hillary-clinton/" type="text/html"/>
        <id>/2015-11-20-why-i-cant-vote-for-hillary-clinton/</id>
        
            <content type="html">&lt;p&gt;We live in the year 2016 - anyone who does not know how to use basic computer functionality (such as email, using a word processor, decyphering between a spreadsheet and database, etc.) should not be allowed to hold public office. Why? Here is my main reason:&lt;&#x2F;p&gt;
&lt;p&gt;One who does not understand technology will not make the right decision when it comes to a technology issue. Encryption is becoming a major topic with many in office wanting to do away with it or requiring back doors. Will she make the right decision here? After all, not everyone uses encryption for illegal purposes - most use it for company integrity and data leakage protection.&lt;&#x2F;p&gt;
&lt;p&gt;What if some new technology appears which makes self driving cars much more reliable - would she allow it in all 50 states at once or do the dumb move and make every state approve of them?&lt;&#x2F;p&gt;
&lt;p&gt;It has been my experience with people that those who do not understand how technology works in its lowest level (even from a high view) often make the wrong choices in critical matters. Because of that, I see any candidate running for President without basic general computer skills (like checking two different email accounts on the same device) &lt;strong&gt;unelectable&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Paying for Open Source</title>
        <published>2015-11-13T14:59:38+00:00</published>
        <updated>2015-11-13T14:59:38+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-11-13-paying-for-open-source/" type="text/html"/>
        <id>/2015-11-13-paying-for-open-source/</id>
        
            <content type="html">&lt;p&gt;While Open Source software is free to download, use, and depending on the license, free to distribute, it is not free to creator. The Open Source creators have to pay for hosting, branding (domain, etc.), coding (in time), and distribution. While some are offloading the costs by hosting the project on Open Source aware distribution channels such as &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&quot;&gt;GitHub&lt;&#x2F;a&gt; or &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bitbucket.org&#x2F;&quot;&gt;BitBucket&lt;&#x2F;a&gt;, many projects still lack the funds they need.&lt;&#x2F;p&gt;
&lt;p&gt;The general rule is: if you use it, you should pay for it. How you should pay for it is entirely up to you. Below are several ways you can pay for open source software.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;for-corporations&quot;&gt;For Corporations&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Hire an Open Source Developer to work on the project he contributes to&lt;&#x2F;li&gt;
&lt;li&gt;Estimate how much it would cost annually with proprietary software and donate 10-30% of the amount evenly to various projects&lt;&#x2F;li&gt;
&lt;li&gt;Open Source internally developed software&lt;&#x2F;li&gt;
&lt;li&gt;Provide a publicly accessible mirror to an Open Source project&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;for-individuals&quot;&gt;For Individuals&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Donate a fixed amount annually to an Open Source Foundation such as the &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.linuxfoundation.org&#x2F;&quot;&gt;Linux Foundation&lt;&#x2F;a&gt; or the &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.documentfoundation.org&#x2F;&quot;&gt;Document Foundation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Donate a fixed amount to the specific project you use&lt;&#x2F;li&gt;
&lt;li&gt;Submit a patch that fixes a bug&lt;&#x2F;li&gt;
&lt;li&gt;Submit a patch that adds a feature (bonus points if it was previously requested by another user)&lt;&#x2F;li&gt;
&lt;li&gt;Offer support to other users using the program via the channels the creators recognize (mailing lists, forums, etc.)&lt;&#x2F;li&gt;
&lt;li&gt;Create a plugin that enhances the project&lt;&#x2F;li&gt;
&lt;li&gt;Promote the project you use most&lt;&#x2F;li&gt;
&lt;li&gt;Suggest your company switch to the project (using the paid version)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Have a suggestion that was not listed? Submit it in the comments below.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Switching to Wordpress</title>
        <published>2015-11-08T04:44:37+00:00</published>
        <updated>2015-11-08T04:44:37+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-11-07-switching-to-wordpress/" type="text/html"/>
        <id>/2015-11-07-switching-to-wordpress/</id>
        
            <content type="html">&lt;p&gt;I have completed the migration of my blog to Wordpress. The reasons for the change are very simple:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I was spending 45 minutes extra just to post 1 web page&lt;&#x2F;li&gt;
&lt;li&gt;I wanted to post to Google+ for every post I make - the service I was using only allowed for twitter.&lt;&#x2F;li&gt;
&lt;li&gt;I wanted an easier way to manage my RSS feed.&lt;&#x2F;li&gt;
&lt;li&gt;I wanted to spend more time writing and less time coding my website&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        </entry><entry xml:lang="en">
        <title>USB Key Start</title>
        <published>2015-10-03T21:55:06+00:00</published>
        <updated>2015-10-03T21:55:06+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-10-03-usb-key-start/" type="text/html"/>
        <id>/2015-10-03-usb-key-start/</id>
        
            <content type="html">&lt;p&gt;Back in the good &#x27;ole days of floppy drives, I used to install &lt;code&gt;grub&lt;&#x2F;code&gt; onto one. I would use it like a key to my computer and take it out if I did not want anyone using my computer when I was not around. Today, we use LUKS encryption to keep unwanted users out. Once &lt;code&gt;grub&lt;&#x2F;code&gt; became too big to fit on floppy drives (and floppy drives became extinct) I still wanted the physical functionality of removing a part that prevents others from using my desktop&#x2F;laptop. Sure, I could remove the hard drive every time I was done with the computer, but this would become tedious and I want something quick and easy.&lt;&#x2F;p&gt;
&lt;p&gt;I recently stumbled across &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokiclover&#x2F;mkinitramfs-ll&quot;&gt;mkinitramfs-ll&lt;&#x2F;a&gt; which allowed passing in a LUKS keyfile in initrd. I attempted to use this for Fedora, but did not get very far. I then discovered &lt;code&gt;dracut&lt;&#x2F;code&gt; (Fedora&#x27;s initrd maker) already includes support for passing in a LUKS keyfile as an argument. At this point, I raced to get one of my legacy 256mb flash drives and made a fully functional &quot;key&quot; to operate my laptop.&lt;&#x2F;p&gt;
&lt;p&gt;The main points to get it working were simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Have a crypted root file system&lt;&#x2F;li&gt;
&lt;li&gt;Generate a keyfile to use&lt;&#x2F;li&gt;
&lt;li&gt;Format a flash drive with a label&lt;&#x2F;li&gt;
&lt;li&gt;Add the keyfile to the crypted filesystem and flash drive&lt;&#x2F;li&gt;
&lt;li&gt;Configure and run &lt;code&gt;dracut&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Configure and generate &lt;code&gt;grub&lt;&#x2F;code&gt; configs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;**Generate a keyfile to use:**Keyfiles can be anything. Some use a gpg key, but I found it as easy and beneficial just to run: &lt;code&gt;sudo dd if=&#x2F;dev&#x2F;urandom of=&#x2F;root&#x2F;keyfile bs=1024 count=4&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;**Format a flash drive with a label:**As I mentioned before, I already had a worthless flash drive handy. Since this flash drive is essentially the key to my computer, I do not want to risk plugging it into another computer and getting the key stolen or corrupted. It will have to become solely used for the purpose of unlocking my system. Creating the flash drive is the same as any other drive with ext4:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkfs.ext4 -L SECURIKEY &#x2F;dev&#x2F;sdb1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Add the keyfile to the crypted filesystem and flash drive.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo mount &#x2F;dev&#x2F;sdb1 &#x2F;mnt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo cp &#x2F;root&#x2F;keyfile &#x2F;mnt&#x2F;keyfile
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo cryptsetup -v luksAddKey &#x2F;dev&#x2F;mapper&#x2F;fedora-00 &#x2F;mnt&#x2F;keyfile
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Configure &lt;code&gt;dracut&lt;&#x2F;code&gt;:&lt;&#x2F;strong&gt; &lt;code&gt;dracut&lt;&#x2F;code&gt; needs to load two modules in order for us to pass in the keyfile. Additionally systemd has an issue with keyfiles at the time of writing this so we will have to omit it. Both of these settings can be permanently set by &lt;code&gt;sudo vim &#x2F;etc&#x2F;dracut.conf.d&#x2F;00-keyfile.conf&lt;&#x2F;code&gt; and inserting the below contents.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# dracut modules to omit
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;omit_dracutmodules+=&amp;quot;systemd&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# dracut modules to add to the default
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;add_dracutmodules+=&amp;quot;crypt lvm&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Configuring grub:&lt;&#x2F;strong&gt; Open up &lt;code&gt;&#x2F;etc&#x2F;default&#x2F;grub&lt;&#x2F;code&gt; and append &lt;code&gt;rd.luks.key=&#x2F;keyfile:LABEL=SECURIKEY&lt;&#x2F;code&gt; inside the quotes of &lt;code&gt;GRUB_CMDLINE_LINUX&lt;&#x2F;code&gt;. Mine looks like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;GRUB_CMDLINE_LINUX=&amp;quot;rd.lvm.lv=fedora&#x2F;00 rd.luks.uuid=luks-fad7c380-bc0c-4680-917e-1e80eb244476 rhgb quiet rd.luks.key=&#x2F;keyfile:LABEL=SECURIKEY&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;grub&lt;&#x2F;code&gt; can then be regenerated by running &lt;code&gt;sudo grub2-mkconfig -o &#x2F;boot&#x2F;grub2&#x2F;grub.cfg&lt;&#x2F;code&gt;. After &lt;code&gt;grub&lt;&#x2F;code&gt; has been re-generated, we can then regenerate our initrd by issuing &lt;code&gt;dracut --force&lt;&#x2F;code&gt;. Everything is then all set and ready to go! If the keyfile is not present, you will be prompted to enter your encryption password upon next boot to unlock the root filesystem. I would advise leaving the password as you would be unable to access your files if the flash drive was ever lost or picked up by one of your kids and thrown in the toilet.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>My Review of Arch</title>
        <published>2015-09-26T21:49:51+00:00</published>
        <updated>2015-09-26T21:49:51+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-09-26-my-review-of-arch/" type="text/html"/>
        <id>/2015-09-26-my-review-of-arch/</id>
        
            <content type="html">&lt;p&gt;After my minimal install of Arch, I was greeted by a terminal console upon booting the kernel. With &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.archlinux.org&#x2F;packages&#x2F;?sort=&amp;amp;arch=i686&amp;amp;repo=Community&amp;amp;repo=Core&amp;amp;repo=Extra&amp;amp;repo=Multilib&amp;amp;q=&amp;amp;maintainer=&amp;amp;flagged=&quot;&gt;5,013 packages in the 32 bit stable repositories&lt;&#x2F;a&gt; (compare that to &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;stable&#x2F;allpackages?format=txt.gz&quot;&gt;Debian Stable&#x27;s 56,865&lt;&#x2F;a&gt;), I was not getting very far by relying on the built-in package manager &lt;code&gt;pacman&lt;&#x2F;code&gt;. &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aur.archlinux.org&#x2F;packages&#x2F;?O=0&amp;amp;SeB=nd&amp;amp;K=&amp;amp;outdated=off&amp;amp;SB=n&amp;amp;SO=a&amp;amp;PP=50&amp;amp;do_Search=Go&quot;&gt;The package count increased another 27,023&lt;&#x2F;a&gt; once I began using the Arch Users Repository (AUR) scripts.&lt;&#x2F;p&gt;
&lt;p&gt;After installing a few packages, I realized Arch&#x27;s greatest weaknesses: customizability and project collaboration. Arch is like a snowflake - no two systems are exactly alike. From a SysAdmin&#x27;s viewpoint, I can&#x27;t determine what state the operating system is just by looking at it. In certain circumstances where time is of the most urgent matter, one cannot spend time comparing program versions with unknown and known bugs. I envision managing two or more devices would be quite painful in the long run.&lt;&#x2F;p&gt;
&lt;p&gt;Project collaboration is still in the early stages. With two great AUR package managers (&lt;code&gt;yaourt&lt;&#x2F;code&gt; and &lt;code&gt;cower&lt;&#x2F;code&gt;) and the
realization that neither have been pushed to upstream, I have an eerie feeling that &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;927&#x2F;&quot;&gt;xkcd&#x27;s standards statement&lt;&#x2F;a&gt; is at play in the Arch environment.&lt;&#x2F;p&gt;
&lt;p&gt;**For those that do not know how collaboration works, here is a quick overview:**I use project A. Project A is lacking feature B. I fork project A, write feature B, and continue using project A with feature B. If people other than myself can benefit from feature B, I push my changes to upstream. If my changes are not accepted in mainstream, I have two choices: keep feature B to myself or write feature B to match upstream&#x27;s policy.&lt;&#x2F;p&gt;
&lt;p&gt;**This is how not to collaborate:**Project A is missing feature B. I fork project A, call it project V, write feature B, C, and D with a wrapper for project A. If somebody wants feature E in project A, tell them to use project C which is a fork&#x2F;clone of project V.&lt;&#x2F;p&gt;
&lt;p&gt;Contrary to public thinking, Arch is not a GNU&#x2F;Linux distribution geared towards intermediate to advanced users. It is a primitive distribution that only intermediate-level and above understand. We understand the basics of how to compile a program and how to find the one line command to run that is nested in 5 sub-links on the wiki. We overlook the high level of expert documentation that isn&#x27;t spelled out clearly, gives a recommended setting to new users, or in some cases doesn&#x27;t actually tell you how to do what you are seeking to do.&lt;&#x2F;p&gt;
&lt;p&gt;I claim Arch is still primitive because when I was installing packages, I felt like a caveman digging up &lt;code&gt;xf86-input-mouse&lt;&#x2F;code&gt; after I installed &lt;code&gt;gdm&lt;&#x2F;code&gt; and GNOME 3. (A clever person might think that would be at least a requirement of one of the packages that installs rather than an optional one - Oh, wait - GUI is never used by anybody on a desktop.) It might be that I was spoiled by reading &lt;a class=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wiki.gentoo.org&#x2F;wiki&#x2F;Handbook:Main_Page&quot;&gt;Gentoo&#x27;s Handbook&lt;&#x2F;a&gt; back when I was a noob and trying out an advanced distribution, or it could be that I have used distributions that have worked out all of these kinks for too long, but making GNU&#x2F;Linux users dig like cavemen to find appropriate packages is harmful towards our primary objective: dominating the desktop OS marketplace.&lt;&#x2F;p&gt;
&lt;p&gt;Even with these prominent issues, Arch will probably stay installed on my Acer C710 for awhile - at least until Fedora 23 becomes stable.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Jumping on the Arch Bandwagon</title>
        <published>2015-09-19T21:46:47+00:00</published>
        <updated>2015-09-19T21:46:47+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-09-19-jumping-on-the-arch-bandwagon/" type="text/html"/>
        <id>/2015-09-19-jumping-on-the-arch-bandwagon/</id>
        
            <content type="html">&lt;p&gt;Well, after avoiding it for a few years, I have decided to install the Arch GNU&#x2F;Linux distribution on my Acer C710. At first glance, it was nice to just install the necessary packages and have a working system within 20 minutes. The downside to having everything up and running in 20 minutes is that I did not install the base packages that come with most distributions - such as a GUI terminal program (i.e. &lt;code&gt;gnome-terminal&lt;&#x2F;code&gt;). That was OK since I still had my favorite tty - 3. I am going to miss the delta packages (DRPMS) from Fedora as I particularly enjoy saving bandwidth.&lt;&#x2F;p&gt;
&lt;p&gt;Installing Arch was pretty simple compared to Gentoo or Funtoo, but not as simple as Fedora or Ubuntu. In Ubuntu, you load a LiveDVD, click the install icon on the desktop and follow the prompts. In Arch, you are presented with a terminal and are not given much instruction. The basic steps are to partition your drive, create a filesystem, mount your root partition as &lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt;, run the package initializer, and chroot into the environment. In other words, it is as simple as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fdisk &#x2F;dev&#x2F;sda
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkfs.ext4 &#x2F;dev&#x2F;sda2
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mount &#x2F;dev&#x2F;sda2 &#x2F;mnt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pacstrap &#x2F;mnt base
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;genfstab -p &#x2F;mnt &amp;gt;&amp;gt; &#x2F;mnt&#x2F;etc&#x2F;fstab
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;arch-chroot &#x2F;mnt
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo wipplertop &amp;gt; &#x2F;etc&#x2F;hostname
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ln -sf &#x2F;usr&#x2F;share&#x2F;zoneinfo&#x2F;America&#x2F;Los_Angeles &#x2F;etc&#x2F;localtime
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sed -i &amp;#39;s&#x2F;^#en_US.UTF-8$&#x2F;en_US.UTF-8&#x2F;g&amp;#39; &#x2F;etc&#x2F;locale.gen
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;locale-gen
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;echo LANG=en_US.UTF-8 &amp;gt; &#x2F;etc&#x2F;locale.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkinitcpio -p linux
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;passwd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;useradd -m andrew
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;passwd andrew
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;pacman -S grub os-prober
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;grub-install --recheck &#x2F;dev&#x2F;sda
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;grub-mkconfig -o &#x2F;boot&#x2F;grub&#x2F;grub.cfg
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;exit
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;reboot
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Expect with expect</title>
        <published>2015-08-30T22:41:50+00:00</published>
        <updated>2015-08-30T22:41:50+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-08-30-expect-with-expect/" type="text/html"/>
        <id>/2015-08-30-expect-with-expect/</id>
        
            <content type="html">&lt;p&gt;Wouldn&#x27;t it be nice to program a script that expects a certain line of text then sends a predetermined string? How about copy your ssh id to 40 different RPi units without typing the command for every one? Expect is that sort of program we all have been dreaming about. Just look at this script:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;expect -f
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;set timeout 3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;set serv [lindex $argv 0];
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spawn ssh-copy-id pi@$serv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sleep 4
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;expect &amp;quot;Are you sure you want to continue connecting (yes&#x2F;no)?&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;send &amp;quot;yes\r&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;expect &amp;quot;pi@{$serv}&amp;#39;s password: &amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;send &amp;quot;p@ssw0rd\r&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;interact
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When this block of code is saved as &lt;code&gt;copy_pi.sh&lt;&#x2F;code&gt; and invoked as &lt;code&gt;.&#x2F;copy_pi.sh 192.168.1.42&lt;&#x2F;code&gt;, it will attemp to connect as the pi user, copy the current public key, say yes to the prompt, send the password (provided it is escaped properly), and drop you into the process you spawned.&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s look at the script in more detail as to what expect has to offer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;expect -f
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This line has to be the absolute path of expect with the &lt;code&gt;-f&lt;&#x2F;code&gt; switch. This is to tell the program that it is being passed a file with a list of commands. On Debian&#x2F;Fedora, this path is where &lt;code&gt;expect&lt;&#x2F;code&gt; is located. On other systems, you will need to run &lt;code&gt;which expect&lt;&#x2F;code&gt; to find the absolute location.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;set timeout 3
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;set serv [lindex $argv 0];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first line tells &lt;code&gt;expect&lt;&#x2F;code&gt; to wait up to 3 seconds for a new line before it times out. The second line is grabbing the variable being passed into this script. Normally, one would think arg 0 would be the name of the program (i.e. &lt;code&gt;copy_pi.sh&lt;&#x2F;code&gt;); however, &lt;code&gt;expect&lt;&#x2F;code&gt; captures the variables into &lt;code&gt;$argv&lt;&#x2F;code&gt; (&lt;code&gt;$argc&lt;&#x2F;code&gt; is the length of the variables).You can also specify a range of variables into one: &lt;code&gt;set range [lrange $argv 0 2];&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;spawn ssh-copy-id pi@$serv
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sleep 4
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is we are initializing the process of copying our ssh key to &lt;code&gt;$serv&lt;&#x2F;code&gt;.
This is the part we would normally be typing ourselves. &lt;code&gt;sleep 4&lt;&#x2F;code&gt; tells expect to wait 4 seconds before continuing.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;expect &amp;quot;Are you sure you want to continue connecting (yes&#x2F;no)?&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;send &amp;quot;yes\r&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;expect &amp;quot;pi@{$serv}&amp;#39;s password: &amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;send &amp;quot;p@ssw0rd\r&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;interact
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;expect&lt;&#x2F;code&gt; line could either be regex or what will be exactly shown. Since I know exactly what will appear in the process, I have chosen to go that route. The &lt;code&gt;send&lt;&#x2F;code&gt; command is transmitting the text into the spawned program. Special characters such as &amp;amp; need to be escaped with a backslash. The &lt;code&gt;\r&lt;&#x2F;code&gt; simulates a carriage return (enter key). Since the &lt;code&gt;ssh-copy-id&lt;&#x2F;code&gt; is completed by the time &lt;code&gt;interact&lt;&#x2F;code&gt; is called, you will not be in the remote pi&#x27;s shell. I have sometimes found it necessary to include &lt;code&gt;interact&lt;&#x2F;code&gt; so that the password is actually sent.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;expect&lt;&#x2F;code&gt; is a great tool that uses TCL syntax. &lt;code&gt;expect&lt;&#x2F;code&gt; has prooved useful to me many times over - especially when I had to re-key my puppet deployment after Heartbleed.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>The Arrow Law</title>
        <published>2015-08-16T22:02:52+00:00</published>
        <updated>2015-08-16T22:02:52+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-08-16-the-arrow-law/" type="text/html"/>
        <id>/2015-08-16-the-arrow-law/</id>
        
            <content type="html">&lt;p&gt;When I first started out with Linux, I was having trouble understanding the basic commands such as &lt;code&gt;ln&lt;&#x2F;code&gt;, andrew&lt;code&gt;mv&lt;&#x2F;code&gt;, &lt;code&gt;scp&lt;&#x2F;code&gt;, &lt;code&gt;rsync&lt;&#x2F;code&gt;, etc. What got me with those commands was the SOURCE and DEST options until I figured out the arrow law.&lt;&#x2F;p&gt;
&lt;p&gt;A typical &lt;code&gt;rsync&lt;&#x2F;code&gt; command looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;rsync -av &#x2F;home&#x2F;andrew&#x2F;file1.txt &#x2F;opt&#x2F;andrew&#x2F;file2.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where as a basic tar command looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tar -cJf tarfile.xz &#x2F;home&#x2F;andrew&#x2F;file1.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the &lt;code&gt;rsync&lt;&#x2F;code&gt; example, the SOURCE came first. In the &lt;code&gt;tar&lt;&#x2F;code&gt; example, the DEST came first. Did I really have to learn every command to know which order my commands were supposed to be in?&lt;&#x2F;p&gt;
&lt;p&gt;There are a few quirks, but most commands follow the arrow law:&lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt; . SOURCE should come first - then DEST.&lt;&#x2F;p&gt;
&lt;p&gt;To place the &lt;code&gt;tar&lt;&#x2F;code&gt; command in the arrow law way, we would write the command like the example below. Tar allows the use of multiple source locations in the form of files or folders. Each source is then compress and place in the file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tar -cJ &#x2F;home&#x2F;andrew&#x2F;file1.txt &#x2F;opt &#x2F;folder -f files.xz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At a glance, one should easily recognize that the &lt;code&gt;-f&lt;&#x2F;code&gt; indicates the DEST&#x2F;SOURCE file to be worked on by the &lt;code&gt;tar&lt;&#x2F;code&gt; command. Thus by typing the extraction command as the below is following the arrow law.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;tar -xvJf files.xz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The command that really confused me the most was the &lt;code&gt;ln&lt;&#x2F;code&gt;. By using the arrow law, it was easy to figure this one out. (note: in the below example &lt;code&gt;-s&lt;&#x2F;code&gt; is the option for making a symbolic link - not to indicate the source.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ln -s &#x2F;opt &#x2F;home&#x2F;andrew&#x2F;opt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In human readable terms, the above command means the following: take &lt;code&gt;&#x2F;opt&lt;&#x2F;code&gt; and make it accessible by going to &lt;code&gt;&#x2F;home&#x2F;andrew&#x2F;opt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Installing fonts on Windows using Puppet</title>
        <published>2015-08-08T22:38:59+00:00</published>
        <updated>2015-08-08T22:38:59+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-08-08-installing-fonts-on-windows-using-puppet/" type="text/html"/>
        <id>/2015-08-08-installing-fonts-on-windows-using-puppet/</id>
        
            <content type="html">&lt;p&gt;I was recently tasked to install a group of fonts on windows systems. In order to do it the Internet way, you have to:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Install the font on a system&lt;&#x2F;li&gt;
&lt;li&gt;Export the registry file&lt;&#x2F;li&gt;
&lt;li&gt;Create a GPO&lt;&#x2F;li&gt;
&lt;li&gt;Place the font in an accessible location (domain readable)&lt;&#x2F;li&gt;
&lt;li&gt;Make sure the GPO has the .reg and the font file installing&lt;&#x2F;li&gt;
&lt;li&gt;Reboot the machine 2-3 times&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Some have also suggested to install fonts via a packaged .msi - Something I also tried which did not work. Since my machines already have puppet installed, I went that route.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkdir fonts&#x2F;files&#x2F; #where the FontReg file resides
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkdir fonts&#x2F;files&#x2F;fonts #where the fonts reside
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;mkdir fonts&#x2F;manifests&#x2F; #where the below init.pp file resides
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Contents of init.pp are below:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;class fonts {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;case $operatingsystem {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	windows: {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			exec { &amp;#39;FontReg&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				command		=&amp;gt; &amp;#39;C:\Windows\FontReg.exe&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				path		=&amp;gt; $::path,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				refreshonly	=&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				require		=&amp;gt; File[&amp;#39;C:\Windows\FontReg.exe&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			exec { &amp;#39;FixFonts&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				command 	=&amp;gt; &amp;#39;cmd.exe &#x2F;c C:\Windows\font_ownership.bat&amp;#39;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				path		=&amp;gt; $::path,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				refreshonly	=&amp;gt; true,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				require		=&amp;gt; File[&amp;#39;C:\Windows\font_ownership.bat&amp;#39;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			file { &amp;#39;C:\Windows\font_ownership.bat&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				ensure			=&amp;gt; present,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				notify 			=&amp;gt; Exec[&amp;quot;FixFonts&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				source_permissions	=&amp;gt; ignore,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				content			=&amp;gt; &amp;quot;attrib -r -s c:\Windows\Fonts
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;takeown &#x2F;f c:\Windows\Fonts &#x2F;r &#x2F;d n
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cacls c:\Windows\Fonts &#x2F;e &#x2F;t &#x2F;g users:c
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;cacls c:\Windows\System32\FNTCACHE.DAT &#x2F;e &#x2F;t &#x2F;g users:c&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			file {	&amp;#39;C:\Windows\FontReg.exe&amp;#39;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				source 			=&amp;gt; $architecture ? {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;						&amp;quot;x86&amp;quot; 	=&amp;gt; &amp;quot;puppet:&#x2F;&#x2F;&#x2F;modules&#x2F;fonts&#x2F;FontReg32.exe&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;						&amp;quot;x64&amp;quot; 	=&amp;gt; &amp;quot;puppet:&#x2F;&#x2F;&#x2F;modules&#x2F;fonts&#x2F;FontReg64.exe&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;						default =&amp;gt; &amp;quot;unsupported architecture&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;						},
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				source_permissions	=&amp;gt; ignore,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			$fonts = [&amp;quot;font-name1.otf&amp;quot;,&amp;quot;fontname2.ttf&amp;quot;];
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			$fonts.each |$font| {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				file {&amp;quot;C:\\Windows\\Fonts\\${font}&amp;quot;:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				source  		=&amp;gt; &amp;quot;puppet:&#x2F;&#x2F;&#x2F;modules&#x2F;fonts&#x2F;fonts&#x2F;${font}&amp;quot;,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				ensure			=&amp;gt; present,
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				notify 			=&amp;gt; Exec[&amp;quot;FontReg&amp;quot;],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				require			=&amp;gt; [File[&amp;#39;C:\Windows\FontReg.exe&amp;#39;],File[&amp;#39;C:\Windows\font_ownership.bat&amp;#39;],],
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;				source_permissions	=&amp;gt; ignore
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;			}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;		}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;required-programs&quot;&gt;Required programs:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;FontReg - &lt;a class=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;code.kliu.org&#x2F;misc&#x2F;fontreg&#x2F;&quot;&gt;http:&#x2F;&#x2F;code.kliu.org&#x2F;misc&#x2F;fontreg&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Puppet Future Parser (3.7.5+)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;known-limitations&quot;&gt;Known Limitations&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;In order to actually place the files on UAC systems, you have to take ownership of the font folder. This is done in the puppet script.&lt;&#x2F;li&gt;
&lt;li&gt;I am using an iterator because there are some fonts that are installed on your system which prevent overwriting (even after you forcibly take ownership of the folder). ADP.ttf ... I am looking at you!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Installing TeamViewer over SSH</title>
        <published>2015-08-02T22:05:43+00:00</published>
        <updated>2015-08-02T22:05:43+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-08-02-installing-teamviewer-over-ssh/" type="text/html"/>
        <id>/2015-08-02-installing-teamviewer-over-ssh/</id>
        
            <content type="html">&lt;p&gt;The recommended way to install TeamViewer is from a desktop environment using a package manager such as Synaptic, Yum, or apt-get. Sometimes you find yourself in a circumstance when ssh is the only way you have access to your server. This tutorial will help you get it installed on Ubuntu Server 14.04.2.&lt;&#x2F;p&gt;
&lt;p&gt;As a reminder, TeamViewer is free for personal use. If you are using TeamViewer for commercial purposes - PURCHASE A LICENSE! Purchasing a license ensures TeamViewer will be available for years to come.&lt;&#x2F;p&gt;
&lt;p&gt;First of all, download the latest teamviewer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;wget http:&#x2F;&#x2F;download.teamviewer.com&#x2F;download&#x2F;teamviewer_i386.deb
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, update your apt sources.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo apt-get update
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;TeamViewer needs a desktop manager and desktop environment to run. The Ubuntu Server edition does not have a GUI. The below command makes the server edition turn into the desktop edition and installs a command line page installer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo apt-get install ubuntu-desktop gdebi -y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, install teamviewer with the following command. I like using gdebi because you do not have to run &lt;code&gt;sudo apt-get install -f&lt;&#x2F;code&gt; to fix dependencies.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo gdebi teamviewer_i386.deb
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;TeamViewer is now installed, but we have to jump through a few hoops to get it to allow us to remotely conenct. The first configuration we have to do is set up a password and then we need to enable the TeamViewer daemon. Both of these steps can be accomplished by doing the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#set up teamviewer&amp;#39;s password
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo teamviewer passwd password946
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#make teamviewer start at boot and start if it is not currently running
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo teamviewer daemon enable
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At this point, you will be able to get your TeamViewer ID by running &lt;code&gt;sudo teamviewer info&lt;&#x2F;code&gt;; however, if you try to connect now, it will time out after you log in to your desktop environment. This is because TeamViewer requires the end user to accept their EULA. Since we installed TeamViewer over ssh, we were never prompted to accept the EULA. If you were to watch the monitor of the server, you would see the EULA be presented (as seen below), but not shown on the TeamViewer session.
&lt;a href=&quot;&#x2F;2015&#x2F;10&#x2F;teamviewer-eula.png&quot;&gt;&lt;img src=&quot;&#x2F;2015&#x2F;10&#x2F;teamviewer-eula.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To get past the license agreement, you can accept it by running the following command and answering the question with a &lt;code&gt;y&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo teamviewer license
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now TeamViewer to your host, use the specified password you set above, log in to your desktop environment, and enjoy accessing your GUI over TeamViewer. Remember to play fair.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Setting the I&#x2F;O scheduler for a single disk on Fedora</title>
        <published>2015-07-26T22:35:41+00:00</published>
        <updated>2015-07-26T22:35:41+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-07-26-setting-the-io-scheduler-for-a-single-disk-on-fedora/" type="text/html"/>
        <id>/2015-07-26-setting-the-io-scheduler-for-a-single-disk-on-fedora/</id>
        
            <content type="html">&lt;p&gt;You can set your IO scheduler on-the-fly by echoing the scheduler you want into &lt;code&gt;&#x2F;sys&#x2F;block&#x2F;{DEVICE-NAME}&#x2F;queue&#x2F;scheduler&lt;&#x2F;code&gt;. This setting, however, does not persist across system reboots. The legacy method is to place this command in &lt;code&gt;&#x2F;etc&#x2F;rc.local&lt;&#x2F;code&gt; or by placing an elevator variable in &lt;code&gt;grub.cfg&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Beginning with Fedora 20, a better way of tuning your system has emerged: &lt;code&gt;tuned&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;tuned&lt;&#x2F;code&gt; is a daemon that monitors your system and updates it based upon the variables at that moment. For instance, it will scale back your network interface - reducing power consumption - when it is not in use and will return it to full throttle when you are downloading the latest Fedora ISO. Enabling &lt;code&gt;tuned&lt;&#x2F;code&gt; on Fedora 22 is as simple as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo dnf install tuned
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;systenctl enable tuned
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;systemctl start tuned
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;tuned&lt;&#x2F;code&gt; comes pre-installed with default profiles (listed by running &lt;code&gt;tuned-adm list&lt;&#x2F;code&gt;). By default the IO scheduler is set for all disks on the system. Since this is not the behavior we intend, nor the result we want, we will have to create our own profile for &lt;code&gt;tuned&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;System profiles are stored in &lt;code&gt;&#x2F;usr&#x2F;lib&#x2F;tuned&lt;&#x2F;code&gt; and custom profiles are stored in &lt;code&gt;&#x2F;etc&#x2F;tuned&lt;&#x2F;code&gt;. Creating a custom profile is as simple as finding the recommended for your system, copying it to a new profile, editing it, and applying it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo mkdir &#x2F;etc&#x2F;tuned&#x2F;andrewwippler
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;sudo cp &#x2F;usr&#x2F;lib&#x2F;tuned&#x2F;$(tuned-adm recommend)&#x2F;tuned.conf &#x2F;etc&#x2F;tuned&#x2F;andrewwippler&#x2F;tuned.conf
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;tuned.conf&lt;&#x2F;code&gt; has a simple structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[NAME]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type=TYPE
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;devices=DEVICES
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;setting1=value
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;setting2=value
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the event of your &lt;code&gt;NAME&lt;&#x2F;code&gt; being the same as the &lt;code&gt;TYPE&lt;&#x2F;code&gt;, you can omit the type line. For example, a normal disk declaration looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[disk]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Comma separated list of devices, all devices if commented out.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# devices=sda
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;alpm=medium_power
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now all we have to do is append our declaration to &lt;code&gt;&#x2F;etc&#x2F;tuned&#x2F;andrewwippler&#x2F;tuned.conf&lt;&#x2F;code&gt; for sda&#x27;s elevator switch and enable it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[my_ssd_disk]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;type=disk
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;devices=sda
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;elevator=noop
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I can then enable my custom tuned profile by running &lt;code&gt;tuned-adm profile andrewwippler&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Send Aliases over SSH connections</title>
        <published>2015-07-18T22:12:35+00:00</published>
        <updated>2015-07-18T22:12:35+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-07-18-send-aliases-over-ssh-connections/" type="text/html"/>
        <id>/2015-07-18-send-aliases-over-ssh-connections/</id>
        
            <content type="html">&lt;p&gt;Bash reads aliases from a file only; however, this file does not have to reside on the server you are connecting to. With OpenSSH, we have to ability to send environment variables that the server allows.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;On Debian&#x2F;Ubuntu systems, the default accept environment variables are:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Allow client to pass locale environment variables
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AcceptEnv LANG LC_*
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;On CentOS&#x2F;Fedora systems, the default accept environment variables are:
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Accept locale-related environment variables
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;AcceptEnv XMODIFIERS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you remote into a mixed environment of servers - whether they be Debian, Ubuntu, or CentOS, you will need to find a common &lt;code&gt;AcceptEnv&lt;&#x2F;code&gt; variable. Since Debian and Ubuntu allow LC_* (everything with the prefix LC_), we are limited to forwarding our aliases over one of CentOS&#x27;s variables. For me, it was easy to decide on a variable to overwrite - &lt;code&gt;LC_PAPER&lt;&#x2F;code&gt;. I hardly print anything and I especially do not print on remote servers.&lt;&#x2F;p&gt;
&lt;p&gt;In order to send your aliases into a remote server, you have to set up your environment first.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;code&gt;~&#x2F;.ssh&#x2F;config&lt;&#x2F;code&gt;, you need a line that sends the environment variable of your choice. These two lines denote that for every host, we will send the environment variable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;Host *
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;     SendEnv LC_PAPER
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we will have to set an alias file we want to transfer. For my test, I create &lt;code&gt;~&#x2F;.bash_aliases_xfer&lt;&#x2F;code&gt; and had the contents of:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# .bash_aliases_xfer
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;# Source global definitions
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if [ -f &#x2F;etc&#x2F;bashrc ]; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    . &#x2F;etc&#x2F;bashrc
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;alias lollypop=&amp;quot;echo lollypop&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;alias lolp=&amp;quot;lollypop&amp;quot;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#My servers display useful information in the motd.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;[ ! -z &amp;quot;$TERM&amp;quot; -a -r &#x2F;etc&#x2F;motd ] &amp;amp;&amp;amp; cat &#x2F;etc&#x2F;motd
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, we have to craft our ssh command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;LC_PAPER=$(cat ~&#x2F;.bash_aliases_xfer; exec 3&amp;lt;&amp;amp;-) \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;ssh -t user@remote \
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    &amp;#39;exec bash --rcfile &#x2F;dev&#x2F;fd&#x2F;3 3&amp;lt; &amp;lt;(printf %s &amp;quot;$LC_PAPER&amp;quot;)&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first line defines the environment variable - an output of our local file and places that information in file descriptor 3. The second line is where we actually connect to the server. The third line is the command executed on the remote server: cleanly print the contents of our environment variable, put that information in file descriptor 3, and reload bash with that file as the only configuration file.&lt;&#x2F;p&gt;
&lt;p&gt;To make the process easier, I have place the following function in my .bashrc. Since the function has $@ variable, I can use it as a replacement to ssh and I can pass any needed ssh switches to my new function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;function ssha() {
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;LC_BASHRC=$(cat ~&#x2F;.bash_aliases_xfer; exec 3&amp;lt;&amp;amp;-) ssh -t &amp;quot;$@&amp;quot; &amp;#39;exec bash --rcfile &#x2F;dev&#x2F;fd&#x2F;3 3&amp;lt; &amp;lt;(printf %s &amp;quot;$LC_BASHRC&amp;quot;)&amp;#39;;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After I reload my bashrc ( &lt;code&gt;source ~&#x2F;.bashrc&lt;&#x2F;code&gt; ), I can then pass my aliases into my new ssh session: &lt;code&gt;ssha user@remote -i ~&#x2F;.ssh&#x2F;remote_id -X&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Kodi Shutdown Script</title>
        <published>2015-07-06T22:30:02+00:00</published>
        <updated>2015-07-06T22:30:02+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-07-06-kodi-shutdown-script/" type="text/html"/>
        <id>/2015-07-06-kodi-shutdown-script/</id>
        
            <content type="html">&lt;p&gt;I am currently using 14.2 of Kodi on my home media center. In order to save money and energy, our rule of thumb is to keep the media center powered off during the night. At first thought, it would make sense to use Kodi&#x27;s built-in sleep function; however, it gets too mundane to open the setting option &lt;em&gt;every time&lt;&#x2F;em&gt; you want to watch something on the media center. Our second choice was to install a cron job to shutdown every night before we went to sleep. Our trouble with this aspect is that while we normally would be in bed before 2230, sometimes our kids would not fall asleep until 2100. This would make our together time begin later than normal. If we chose to watch a movie in our together time, we often found out we had to restart our media center just to get the last 5 minutes of the movie.&lt;&#x2F;p&gt;
&lt;p&gt;This led to our third and optimal solution: find a script to do the job or make one. I searched and could not find an already made script that did what I want:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Initiate a shutdown at a certain time&lt;&#x2F;li&gt;
&lt;li&gt;Do not interrupt viewing when a video is playing past the certain time&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;With those criteria, I was able to make the following bash script and placed it in my crontab:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#set up curl env
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#username= #good idea to have one
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#password=#good idea to have one
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;baseurl=http:&#x2F;&#x2F;127.0.0.1:8080&#x2F;jsonrpc
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;curl_cmd=&amp;quot;curl --user ${username}:${password} --silent &amp;quot; #remove --user ${username}:${password} if you do not have one set up
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#Retun playerid
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#for the json command to work with kodi, the json format has to be &amp;#39;{&amp;quot;key&amp;quot;:&amp;quot;value&amp;quot;}&amp;#39;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;${curl_cmd} -H &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data &amp;#39;{&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;Player.GetActivePlayers&amp;quot;, &amp;quot;id&amp;quot;: 1}&amp;#39; $baseurl &amp;gt; &#x2F;tmp&#x2F;kodiOutput
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;#if playerid is found, run the scripts, otherwise, shutdown now
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;if grep --quiet playerid &#x2F;tmp&#x2F;kodiOutput; then
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;  #Get necessary items
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	${curl_cmd} -H &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data &amp;#39;{&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;Player.GetProperties&amp;quot;, &amp;quot;params&amp;quot;: { &amp;quot;playerid&amp;quot;: 1, &amp;quot;properties&amp;quot;: [&amp;quot;time&amp;quot;] }, &amp;quot;id&amp;quot;: 1}&amp;#39; $baseurl &amp;gt; &#x2F;tmp&#x2F;kodiCurrent.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	${curl_cmd} -H &amp;quot;Content-Type: application&#x2F;json&amp;quot; --data &amp;#39;{&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;method&amp;quot;: &amp;quot;Player.GetProperties&amp;quot;, &amp;quot;params&amp;quot;: { &amp;quot;playerid&amp;quot;: 1, &amp;quot;properties&amp;quot;: [&amp;quot;totaltime&amp;quot;] }, &amp;quot;id&amp;quot;: 1}&amp;#39; $baseurl &amp;gt; &#x2F;tmp&#x2F;kodiTotal.json
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	#Convert time
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	CHOURS=$[$(cat &#x2F;tmp&#x2F;kodiCurrent.json | awk -F: -v RS=&amp;quot;,&amp;quot; &amp;#39;&#x2F;&amp;quot;hours&amp;quot;&#x2F; {print $4}&amp;#39;)*60]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	CMINS=$[$(cat &#x2F;tmp&#x2F;kodiCurrent.json | awk -F: -v RS=&amp;quot;,&amp;quot; &amp;#39;&#x2F;&amp;quot;minutes&amp;quot;&#x2F; {print $2}&amp;#39;)]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	THOURS=$[$(cat &#x2F;tmp&#x2F;kodiTotal.json | awk -F: -v RS=&amp;quot;,&amp;quot; &amp;#39;&#x2F;&amp;quot;hours&amp;quot;&#x2F; {print $4}&amp;#39;)*60]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	TMINS=$[$(cat &#x2F;tmp&#x2F;kodiTotal.json | awk -F: -v RS=&amp;quot;,&amp;quot; &amp;#39;&#x2F;&amp;quot;minutes&amp;quot;&#x2F; {print $2}&amp;#39;)+5] #adding 5 minutes to the shutdown time to overlap for remaining seconds and milliseconds that may be present.
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	REMAININGSECONDS=$[$[$THOURS+$TMINS]-$[$CHOURS+$CMINS]]
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        sleep $REMAININGSECONDS
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        sleep 300
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;        $0
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;	shutdown -h now &amp;amp;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;required-programs&quot;&gt;Required programs:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;curl&lt;&#x2F;li&gt;
&lt;li&gt;awk&lt;&#x2F;li&gt;
&lt;li&gt;cat&lt;&#x2F;li&gt;
&lt;li&gt;grep&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;known-limitations&quot;&gt;Known Limitations&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;The Kodi web interface has to be enabled.&lt;&#x2F;li&gt;
&lt;li&gt;You have 5 minutes after the script was launched from cron to queue another video.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        </entry><entry xml:lang="en">
        <title>About</title>
        <published>2015-06-25T04:41:44+00:00</published>
        <updated>2015-06-25T04:41:44+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/about/" type="text/html"/>
        <id>/about/</id>
        
            <content type="html">&lt;p&gt;&lt;em&gt;Andrew Wippler&#x27;s Sketchpad&lt;&#x2F;em&gt; is where I express my interests. I love Jesus, my family, and technology. &lt;em&gt;My current interests are:&lt;&#x2F;em&gt; (in no particular order)&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Nicole and my 4 children&lt;&#x2F;li&gt;
&lt;li&gt;Linux&lt;&#x2F;li&gt;
&lt;li&gt;Fedora&lt;&#x2F;li&gt;
&lt;li&gt;Internet Safety&lt;&#x2F;li&gt;
&lt;li&gt;Amazon Web Services (AWS - same initials as this website :) )&lt;&#x2F;li&gt;
&lt;li&gt;Coding&lt;&#x2F;li&gt;
&lt;li&gt;Church Management&lt;&#x2F;li&gt;
&lt;li&gt;SQL&lt;&#x2F;li&gt;
&lt;li&gt;Open Source&lt;&#x2F;li&gt;
&lt;li&gt;Vi&#x2F;Vim&lt;&#x2F;li&gt;
&lt;li&gt;Reading&lt;&#x2F;li&gt;
&lt;li&gt;Documentation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;From time-to-time&lt;&#x2F;em&gt; I will post articles about things I am working on, have done, or something I want to do. My philosophy on technology is - Stay with the known. By this, I mean when new technology arises, keep it in training or development until it has become understood and known - then place it into production.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I formerly held the position&lt;&#x2F;em&gt; of Director of Information Technology at Lancaster Baptist Church. I have done some interesting things such as: Setting up a controller website for OpenSprinkler units, replacing digital signage, replacing a room reservation system, setting up a Puppet environment, deploying network monitoring solutions, and devising ways to cut costs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;I am licensing&lt;&#x2F;em&gt; this entire website&#x27;s content under the Creative Commons Attribution-ShareAlike 4.0 International License. Feel free to share any articles or use the code in your own work as long as you link back to the article in which you found it on this website or (if applicable) link it to the project on github.&lt;&#x2F;p&gt;
</content>
        </entry><entry xml:lang="en">
        <title>Named Virtual Hosts on AWS EC2</title>
        <published>2015-06-11T22:25:42+00:00</published>
        <updated>2015-06-11T22:25:42+00:00</updated>
        <author>
            <name>Andrew Wippler</name>
        </author>
        <link rel="alternate" href="/2015-06-11-named-virtual-hosts-on-aws-ec2/" type="text/html"/>
        <id>/2015-06-11-named-virtual-hosts-on-aws-ec2/</id>
        
            <content type="html">&lt;p&gt;Named virtual hosts are not enabled by default on an Amazon AMI. To enable them, edit &#x2F;etc&#x2F;httpd&#x2F;conf&#x2F;httpd.conf and uncomment line 991:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;NameVirtualHost *:80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can then begin adding your named virtual hosts in the &#x2F;etc&#x2F;httpd&#x2F;conf.d&#x2F; directory. Below is an example of a named virtual host file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;z-code&quot;&gt;&lt;code&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;VirtualHost *:80&amp;gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ServerAdmin me@example.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    DocumentRoot &#x2F;var&#x2F;www&#x2F;example.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ServerName example.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ServerAlias     www.example.com
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    ErrorLog &#x2F;var&#x2F;log&#x2F;httpd&#x2F;error_example_com.log
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;    CustomLog &#x2F;var&#x2F;log&#x2F;httpd&#x2F;access_example_com.log common
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-plain&quot;&gt;&amp;lt;&#x2F;VirtualHost&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The difference between a named virtual host and an IP-based virtual host is that you need an additional IP address on your server for each virtual host you want to implement. Named virtual hosts come in handy when you only have 1 external IP address or if you want to host multiple websites on the same web server.&lt;&#x2F;p&gt;
</content>
        </entry>
</feed>
