<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>David Spencer</title><link>https://davidspencer.xyz/</link><description>Recent content on David Spencer</description><generator>Hugo -- 0.165.0</generator><language>en-us</language><managingEditor>david@ddemail.us (David Spencer)</managingEditor><webMaster>david@ddemail.us (David Spencer)</webMaster><lastBuildDate>Sat, 13 Nov 2021 10:43:26 -0500</lastBuildDate><atom:link href="https://davidspencer.xyz/index.xml" rel="self" type="application/rss+xml"/><item><title>WireGuard Setup on Pfsense</title><link>https://davidspencer.xyz/posts/wireguard-setup-on-pfsense/</link><pubDate>Sat, 13 Nov 2021 10:43:26 -0500</pubDate><author>david@ddemail.us (David Spencer)</author><guid>https://davidspencer.xyz/posts/wireguard-setup-on-pfsense/</guid><description>&lt;p&gt;In this post I will explain how to setup WireGuard on your pfsense router. Your
pfsense router will be the WireGuard server and I&amp;rsquo;ll show a couple example client
configurations at the end.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="installing-wireguard-on-pfsense"&gt;Installing WireGuard on pfsense&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;pfsense version 2.5.2&lt;/li&gt;
&lt;li&gt;WireGuard version 0.1.5&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Navigate to System &amp;gt; Package Manager &amp;gt; Available Packages&lt;/p&gt;
&lt;p&gt;Search for WireGuard and Install.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="configuring-wireguard-server"&gt;Configuring WireGuard Server&lt;/h2&gt;
&lt;h3 id="create-tunnel"&gt;Create Tunnel&lt;/h3&gt;
&lt;p&gt;Navigate to VPN &amp;gt; WireGuard&lt;/p&gt;
&lt;p&gt;Create a tunnel by clicking Add Tunnel&lt;/p&gt;</description><content:encoded><![CDATA[<p>In this post I will explain how to setup WireGuard on your pfsense router. Your
pfsense router will be the WireGuard server and I&rsquo;ll show a couple example client
configurations at the end.</p>
<hr>
<h2 id="installing-wireguard-on-pfsense">Installing WireGuard on pfsense</h2>
<ul>
<li>pfsense version 2.5.2</li>
<li>WireGuard version 0.1.5</li>
</ul>
<p>Navigate to System &gt; Package Manager &gt; Available Packages</p>
<p>Search for WireGuard and Install.</p>
<hr>
<h2 id="configuring-wireguard-server">Configuring WireGuard Server</h2>
<h3 id="create-tunnel">Create Tunnel</h3>
<p>Navigate to VPN &gt; WireGuard</p>
<p>Create a tunnel by clicking Add Tunnel</p>
<ul>
<li>Disable Tunnel</li>
<li>Add a Description</li>
<li>Change the listen port or leave at default of 51820</li>
<li>Generate New Keys</li>
<li>Copy Public Key, you&rsquo;ll need it later when configuring a client</li>
</ul>
<p>Click Save Tunnel</p>
<h3 id="configure-interface-and-enable-tunnel">Configure Interface and Enable Tunnel</h3>
<p>Navigate to Interfaces &gt; Assignments</p>
<p>On the Available Network Ports row, select the tun_wg0 interface and click add.</p>
<ul>
<li>Enable Interface</li>
<li>Add a Description</li>
<li>Static IPv4</li>
<li>IPv6: None (unless preferred)</li>
<li>IPv4 Address: Choose an IPv4 Address and Subnet Mask</li>
</ul>
<p>Click Save</p>
<p>Navigate to VPN &gt; WireGuard</p>
<p>Click Edit on your new tunnel and enable the tunnel</p>
<h3 id="configure-firewall">Configure Firewall</h3>
<p>Navigate to Firewall &gt; Rules</p>
<p>Create a new WAN Rule</p>
<ul>
<li>Action: Pass</li>
<li>Interface: WAN</li>
<li>Address Family: IPv4</li>
<li>Protocol: UDP</li>
<li>Source: any</li>
<li>Destination: WAN Address</li>
<li>Destination Port Range: 51820</li>
<li>Log Packets, if preferred</li>
<li>Add a description</li>
<li>Tag: vpn (if desired, not used but could be in other rules)</li>
</ul>
<p>Click Save</p>
<p>Create a new VPN Rule (VPN is the name of the interface)</p>
<ul>
<li>Action: Pass</li>
<li>Interface: VPN</li>
<li>Address Family: IPv4</li>
<li>Protocol: Any</li>
<li>Source: any</li>
<li>Destination: LAN net</li>
</ul>
<p>Click Save</p>
<p>Repeat the VPN rules to allow all desired access</p>
<hr>
<h2 id="configuring-a-client">Configuring a Client</h2>
<p>I will use a CentOS Stream system for this example but any client can be used
the configuration is the same, installations will differ though.</p>
<h3 id="install-wireguard">Install WireGuard</h3>
<p><a href="https://www.wireguard.com/install/">WireGuard Installation</a></p>
<p>For CentOS I followed Method 2</p>
<pre tabindex="0"><code>sudo yum install elrepo-release epel-release
sudo yum install kmod-wireguard wireguard-tools
</code></pre><h3 id="key-generation">Key Generation</h3>
<p>Once installed you can follow these instructions to generate a key <a href="https://www.wireguard.com/quickstart/#key-generation">Key Generation</a></p>
<pre tabindex="0"><code>umask 077
wg genkey | tee privatekey | wg pubkey &gt; publickey
</code></pre><p>Your private key is stored in a file &lsquo;privatekey&rsquo;, use this in the next step
Your public key is stored in a file &lsquo;publickey&rsquo;, use this when adding the peer in pfsense later</p>
<h3 id="interface-config-file">Interface Config File</h3>
<pre tabindex="0"><code>vim /etc/wireguard/wg0.conf
[Interface]
PrivateKey = YLzz2QbAowMXx913RyXsr33FVlcNZ+wx96vVKtdL9nk= (privatekey generated in previous step)
Address = IP Address assigned to this client in VPN Subnet

[Peer]
PublicKey = iQSIKmjCbWR57bu0kk774Sg03t80dRyV64UXIv2ADFY= (public key generated during tunnel creation)
AllowedIPs = 192.168.0.0/24 (Any Subnets you want this client to route through the VPN Tunnel, can use 0.0.0.0/0 if you want all traffic routed through VPN)
EndPoint = 1.2.3.4:51820 (PFsense Router WAN IP Address or DNS Name and Wirguard Port configured on tunnel)
</code></pre><hr>
<h2 id="adding-a-peer">Adding a Peer</h2>
<p>Descriptions on the configurations below can be found <a href="https://docs.netgate.com/pfsense/en/latest/vpn/wireguard/settings.html#wireguard-settings-peer">here</a></p>
<p>Navigate to VPN &gt; WireGuard &gt; Peers</p>
<p>Add Peer</p>
<ul>
<li>Enable Peer</li>
<li>Select the tunnel we created</li>
<li>Add a description of the peer</li>
<li>Public Key generated on client during configuring a client</li>
<li>Allowed IPs should be the Interface Address from the client.</li>
</ul>
<p>The Allowed IPs is what was a source of confusion for me when setting up the WireGuard Server.
I couldn&rsquo;t have more than one peer and it was due to setting the allowed IPs to 0.0.0.0/0 for both peers.
Remember the Allowed IPs are what traffic is routed through the tunnel, you can&rsquo;t have 2 default routes in this case.</p>
<p>Click Save Peer</p>
<hr>
<h2 id="testing-client">Testing Client</h2>
<p>On your client run the following command</p>
<pre tabindex="0"><code>wg-quick up wg0
</code></pre><p>You should see some routes created</p>
<pre tabindex="0"><code>[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.10.10.10/32 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] ip -4 route add 0.0.0.0/0 dev wg0
</code></pre><p>You should now be able to test connectivity by pinging your WireGuard tunnel interface IP Address
This was set when the interface was assigned and you chose your WireGuard subnet <a href="#configure-interface">Configure Interface</a></p>
<p>To ensure the interface is configured at startup after any reboots use the following command</p>
<pre tabindex="0"><code>systemctl enable wg-quick@wg0
</code></pre>]]></content:encoded></item><item><title>Vim Cheat Sheet</title><link>https://davidspencer.xyz/posts/vim-cheat-sheet/</link><pubDate>Sun, 01 Aug 2021 22:41:50 -0400</pubDate><author>david@ddemail.us (David Spencer)</author><guid>https://davidspencer.xyz/posts/vim-cheat-sheet/</guid><description>&lt;h3 id="description"&gt;Description&lt;/h3&gt;
&lt;p&gt;VIM can be hard. Remembering all the neat shortcuts achieved by such an awesome tool is harder.&lt;/p&gt;
&lt;p&gt;This won&amp;rsquo;t be a cheat sheet that helps with the basics but rather an ever expanding post on shortcuts that I discover to help improve efficiency.&lt;/p&gt;
&lt;hr&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;command&lt;/th&gt;
&lt;th style="text-align: left"&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;gtd&lt;/td&gt;
&lt;td style="text-align: left"&gt;go to definition, jump to function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;^o / ^i&lt;/td&gt;
&lt;td style="text-align: left"&gt;backward/forward a location&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;di&amp;quot;&lt;/td&gt;
&lt;td style="text-align: left"&gt;delete inside &amp;ldquo;, can delete inside other characters as well&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;ci&amp;rdquo;&lt;/td&gt;
&lt;td style="text-align: left"&gt;change inside &amp;ldquo;, can change inside other characters as well&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&amp;ldquo;+yy&lt;/td&gt;
&lt;td style="text-align: left"&gt;copy to + buffer, can change + to other buffers as well&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;vap&lt;/td&gt;
&lt;td style="text-align: left"&gt;Select a paragraph, useful for easy increase/decrease of indent with &amp;lt; or &amp;gt;. Eliminates need to ctrl+v, move to select lines, and then use &amp;laquo; or &amp;raquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description><content:encoded><![CDATA[<h3 id="description">Description</h3>
<p>VIM can be hard. Remembering all the neat shortcuts achieved by such an awesome tool is harder.</p>
<p>This won&rsquo;t be a cheat sheet that helps with the basics but rather an ever expanding post on shortcuts that I discover to help improve efficiency.</p>
<hr>
<table>
	<thead>
			<tr>
					<th style="text-align: center">command</th>
					<th style="text-align: left">description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: center">gtd</td>
					<td style="text-align: left">go to definition, jump to function</td>
			</tr>
			<tr>
					<td style="text-align: center">^o / ^i</td>
					<td style="text-align: left">backward/forward a location</td>
			</tr>
			<tr>
					<td style="text-align: center">di&quot;</td>
					<td style="text-align: left">delete inside &ldquo;, can delete inside other characters as well</td>
			</tr>
			<tr>
					<td style="text-align: center">ci&rdquo;</td>
					<td style="text-align: left">change inside &ldquo;, can change inside other characters as well</td>
			</tr>
			<tr>
					<td style="text-align: center">&ldquo;+yy</td>
					<td style="text-align: left">copy to + buffer, can change + to other buffers as well</td>
			</tr>
			<tr>
					<td style="text-align: center">vap</td>
					<td style="text-align: left">Select a paragraph, useful for easy increase/decrease of indent with &lt; or &gt;. Eliminates need to ctrl+v, move to select lines, and then use &laquo; or &raquo;</td>
			</tr>
	</tbody>
</table>
]]></content:encoded></item><item><title>Running Hugo Website</title><link>https://davidspencer.xyz/posts/running-hugo-website/</link><pubDate>Sun, 01 Aug 2021 21:27:19 -0400</pubDate><author>david@ddemail.us (David Spencer)</author><guid>https://davidspencer.xyz/posts/running-hugo-website/</guid><description>&lt;p&gt;In order to run a hugo webserver you will need a few things in order first.
I will mention the requirements; however, I will not be going into detail here.&lt;/p&gt;
&lt;p&gt;If you would like me to write a post on these pre-requisites. Please let me know in the comments!&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="pre-requisites"&gt;Pre-Requisites&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Virtual Private Server&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.vultr.com/?ref=8910980"&gt;Vultr&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain Name Registrar&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.epik.com/?affid=ve9na3ca0"&gt;Epik&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS&lt;/td&gt;
&lt;td&gt;&lt;a href="https://dash.cloudflare.com/login"&gt;Cloudflare&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com"&gt;GitHub&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id="domain-vps-and-nginx-configuration"&gt;Domain, VPS, and nginx Configuration&lt;/h3&gt;
&lt;p&gt;Setup your A Record to point your domain name to your webserver&lt;/p&gt;</description><content:encoded><![CDATA[<p>In order to run a hugo webserver you will need a few things in order first.
I will mention the requirements; however, I will not be going into detail here.</p>
<p>If you would like me to write a post on these pre-requisites. Please let me know in the comments!</p>
<hr>
<h3 id="pre-requisites">Pre-Requisites</h3>
<table>
	<thead>
			<tr>
					<th>Service</th>
					<th>Provider</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Virtual Private Server</td>
					<td><a href="https://www.vultr.com/?ref=8910980">Vultr</a></td>
			</tr>
			<tr>
					<td>Domain Name Registrar</td>
					<td><a href="https://www.epik.com/?affid=ve9na3ca0">Epik</a></td>
			</tr>
			<tr>
					<td>DNS</td>
					<td><a href="https://dash.cloudflare.com/login">Cloudflare</a></td>
			</tr>
			<tr>
					<td>Git</td>
					<td><a href="https://github.com">GitHub</a></td>
			</tr>
	</tbody>
</table>
<hr>
<h3 id="domain-vps-and-nginx-configuration">Domain, VPS, and nginx Configuration</h3>
<p>Setup your A Record to point your domain name to your webserver</p>
<table>
	<thead>
			<tr>
					<th>type</th>
					<th>name</th>
					<th>content</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>A</td>
					<td>@</td>
					<td>vps_ipv4_address</td>
			</tr>
	</tbody>
</table>
<p><a href="https://nginx.org/en/linux_packages.html">nginx install</a></p>
<p>Create simple nginx configuration file, <code>/etc/nginx/conf.d/&lt;domain&gt;.conf</code></p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>server {
</span></span><span style="display:flex;"><span>    server_name  &lt;domain-name&gt; www.&lt;domain-name&gt;;
</span></span><span style="display:flex;"><span>    root         /var/www/&lt;domain-name&gt;/public;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    index index.html;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    location / {
</span></span><span style="display:flex;"><span>        try_files <span style="color:#40ffff">$uri</span> <span style="color:#40ffff">$uri</span>/ =404;
</span></span><span style="display:flex;"><span>        add_header Permissions-Policy interest-cohort=();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    listen       80;
</span></span><span style="display:flex;"><span>    listen       [::]:80;
</span></span><span style="display:flex;"><span>    <span style="color:#6ab825;font-weight:bold">return</span> 404; 
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Create a temporary index.html in your website&rsquo;s root directory, <code>/var/www/&lt;domain&gt;/public/index.html</code></p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>&lt;html&gt;
</span></span><span style="display:flex;"><span>&lt;p&gt;&lt;domain&gt;&lt;/p&gt;
</span></span><span style="display:flex;"><span>&lt;/html&gt;
</span></span></code></pre></div><p>Start and Enable nginx</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>systemctl <span style="color:#24909d">enable</span> --now nginx.service
</span></span></code></pre></div><p>If necessary, allow HTTP and HTTPS through firewall</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>firewall-cmd --add-service=http --permanent
</span></span><span style="display:flex;"><span>firewall-cmd --add-service=https --permanent
</span></span><span style="display:flex;"><span>firewall-cmd reload
</span></span></code></pre></div><p>You should be able to verify access to your webserver over port 80 at this point.</p>
<p>After a successful verification you can continue finishing the configuration.</p>
<hr>
<h3 id="ssl-with-acmesh">SSL with acme.sh</h3>
<p>For SSL you can find all Let&rsquo;s Encrypt client options <a href="https://letsencrypt.org/docs/client-options/">here</a></p>
<p>I recommend <a href="https://github.com/acmesh-official/acme.sh">acme.sh</a></p>
<p>Install acme.sh</p>
<p><a href="https://github.com/acmesh-official/get.acme.sh">get.acme.sh</a></p>
<p>Issue cert for your domain</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>acme.sh --issue -d &lt;domain&gt; -w /var/lib/nginx/&lt;domain&gt;
</span></span></code></pre></div><p>Install certificate to an nginx directory</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>acme.sh --install-cert -d &lt;domain&gt; <span style="color:#ed9d13">\
</span></span></span><span style="display:flex;"><span>--key-file       /etc/nginx/&lt;domain&gt;/key.pem  <span style="color:#ed9d13">\
</span></span></span><span style="display:flex;"><span>--fullchain-file /etc/nginx/&lt;domain&gt;/cert.pem <span style="color:#ed9d13">\
</span></span></span><span style="display:flex;"><span>--reloadcmd     <span style="color:#ed9d13">&#34;service nginx force-reload&#34;</span>
</span></span></code></pre></div><p>acme registers a cron job to run daily. This will ensure your certificate is always valid and will restart your webserver.</p>
<hr>
<h3 id="create-hugo-website">Create Hugo Website</h3>
<p><a href="https://gohugo.io/getting-started/installing">Hugo Installation</a></p>
<p><a href="https://themes.gohugo.io/">Locate a Hugo theme you&rsquo;d like to use</a></p>
<p>I&rsquo;m using <a href="https://github.com/adityatelange/hugo-PaperMod">PaperMod</a></p>
<p>PaperMod installation instructions are <a href="https://github.com/adityatelange/hugo-PaperMod/wiki/Installation#guide">here</a></p>
<p>Once you have followed the installation instructions for your theme you can begin customizing your site.</p>
<p>Again, each theme has their own configuration options; however, I&rsquo;ll explain the general layout of the hugo folder structure to help you understand where to go.</p>
<p>Ensure you are inside the websites directory.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#24909d">cd</span> ~/Projects/davidspencer.xyz
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tree -L <span style="color:#3677a9">1</span> .
</span></span><span style="display:flex;"><span>.
</span></span><span style="display:flex;"><span>├── archetypes
</span></span><span style="display:flex;"><span>├── config.yml
</span></span><span style="display:flex;"><span>├── content
</span></span><span style="display:flex;"><span>├── layouts
</span></span><span style="display:flex;"><span>├── resources
</span></span><span style="display:flex;"><span>├── static
</span></span><span style="display:flex;"><span>└── themes
</span></span></code></pre></div><p>Most of the configuration will be done in the config.yml file
You can see my exact configuration at my <a href="https://github.com/Elevate08/davidspencer.xyz">repo</a></p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">baseURL</span>:<span style="color:#666"> </span>https://davidspencer.xyz<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">languageCode</span>:<span style="color:#666"> </span>en-us<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">title</span>:<span style="color:#666"> </span>Title of Website<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">theme</span>:<span style="color:#666"> </span>Theme Name<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">env</span>:<span style="color:#666"> </span>production<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">outputs</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">home</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- HTML<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- RSS<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- JSON<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">params</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">assets</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">disableHLJS</span>:<span style="color:#666"> </span><span style="color:#6ab825;font-weight:bold">true</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">disableFingerprinting</span>:<span style="color:#666"> </span><span style="color:#6ab825;font-weight:bold">false</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">favicon</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/favicon.ico&gt;&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">favicon16x16</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/favicon-16x16.png&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">favicon32x32</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/favicon-32x32.png&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">apple_touch_icon</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/apple-touch-icon.png&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">safari_pinned_tab</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/safari-pinned-tab.svg&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">socialIcons</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;linkedin&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">url</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;https://www.linkedin.com/in/davidjspencer/&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;github&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">url</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;https://github.com/Elevate08&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;email&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">url</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;mailto:david@davidspencer.xyz&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;rss&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">url</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/index.xml&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">editPost</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">URL</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;https://github.com/Elevate08/davidspencer.xyz/blob/master/content&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">Text</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;Suggest Changes&#34;</span><span style="color:#666"> </span><span style="color:#999;font-style:italic"># edit text</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">appendFilePath</span>:<span style="color:#666"> </span><span style="color:#6ab825;font-weight:bold">true</span><span style="color:#666"> </span><span style="color:#999;font-style:italic"># to append file path to Edit link</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">fuseOpts</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">minMatchCharLength</span>:<span style="color:#666"> </span><span style="color:#3677a9">3</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">keys</span>:<span style="color:#666"> </span>[<span style="color:#ed9d13">&#34;title&#34;</span>,<span style="color:#666"> </span><span style="color:#ed9d13">&#34;content&#34;</span>,<span style="color:#666"> </span><span style="color:#ed9d13">&#34;summary&#34;</span>]<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">menu</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">main</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- <span style="color:#6ab825;font-weight:bold">identifier</span>:<span style="color:#666"> </span>tags<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span>tags<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">url</span>:<span style="color:#666"> </span>/tags/<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">weight</span>:<span style="color:#666"> </span><span style="color:#3677a9">20</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span>- <span style="color:#6ab825;font-weight:bold">identifier</span>:<span style="color:#666"> </span>search<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span>search<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">url</span>:<span style="color:#666"> </span>/search/<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span><span style="color:#6ab825;font-weight:bold">weight</span>:<span style="color:#666"> </span><span style="color:#3677a9">30</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">markup</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">highlight</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">codeFences</span>:<span style="color:#666"> </span><span style="color:#6ab825;font-weight:bold">true</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">guessSyntax</span>:<span style="color:#666"> </span><span style="color:#6ab825;font-weight:bold">false</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">style</span>:<span style="color:#666"> </span>native<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">tabWidth</span>:<span style="color:#666"> </span><span style="color:#3677a9">4</span><span style="color:#666">
</span></span></span></code></pre></div><p>Once you have some settings in place for your site you can create a new post.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>hugo new posts/first-post.md
</span></span></code></pre></div><p>Using your editor of choice, write up your first post using Markdown.</p>
<p>You can learn about Markdown here
<a href="https://www.markdownguide.org/">Markdown Guide</a></p>
<p>Once you have some content created run the following command</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>hugo server
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Watching <span style="color:#6ab825;font-weight:bold">for</span> config changes in /home/elevate/Projects/davidspencer.xyz/config.yml
</span></span><span style="display:flex;"><span>Environment: <span style="color:#ed9d13">&#34;development&#34;</span>
</span></span><span style="display:flex;"><span>Serving pages from memory
</span></span><span style="display:flex;"><span>Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
</span></span><span style="display:flex;"><span>Web Server is available at http://localhost:1313/ (<span style="color:#24909d">bind</span> address 127.0.0.1)
</span></span></code></pre></div><p>You should now be able to access your hugo website at the location provided.</p>
<p>This is how most development / testing of new content can be done.</p>
<p>Click around and test out your new site.</p>
<hr>
<h3 id="deploying-hugo-website-using-github-actions">Deploying Hugo Website using GitHub Actions</h3>
<p>Up until now we have just been working locally. You should have a working development environment where you can access your site locally.</p>
<p>To make deployment to your VPS easier and allow you to focus on just creating new content, let&rsquo;s setup some GitHub Actions to do some work for us!</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#24909d">cd</span> ~/Projects/davidspencer.xyz
</span></span><span style="display:flex;"><span>git init
</span></span></code></pre></div><p>Usually at this point I&rsquo;d run <code>git add .</code>; however, you most likely need to configure the git submodule for your theme.</p>
<p>We want to be able to pull a fresh version from the repo every time we deploy.</p>
<p>You should be able to run the following command without error.</p>
<pre tabindex="0"><code>git submodule add &lt;theme clone url&gt;
</code></pre><p>If you do run into an error let me know in the comments and I&rsquo;ll help you troubleshoot.</p>
<p>Once the theme repo is properly added as a submodule we can continue.</p>
<p>At this time you should login to GitHub and create a new repo. Grab the clone URL.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#ed9d13">&#34;initial upload&#34;</span>
</span></span><span style="display:flex;"><span>git remote add origin git@github.com:/Elevate08/davidspencer.xyz
</span></span><span style="display:flex;"><span>git push -u origin master
</span></span></code></pre></div><p>Now to make our github action file, we will need to create a couple directories.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir -p .github/workflows
</span></span><span style="display:flex;"><span>touch .github/workflows/main.yml
</span></span></code></pre></div><p>Add the following text to your main.yml file</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span>Hugo to VPS<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">on</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">push</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">branches</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span>- master <span style="color:#666"> </span><span style="color:#999;font-style:italic"># Set a branch to deploy</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">pull_request</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">jobs</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">  </span><span style="color:#6ab825;font-weight:bold">deploy</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">runs-on</span>:<span style="color:#666"> </span>ubuntu-20.04<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">    </span><span style="color:#6ab825;font-weight:bold">steps</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span>- <span style="color:#6ab825;font-weight:bold">uses</span>:<span style="color:#666"> </span>actions/checkout@v2<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">        </span><span style="color:#6ab825;font-weight:bold">with</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">submodules</span>:<span style="color:#666"> </span><span style="color:#6ab825;font-weight:bold">true</span><span style="color:#666">  </span><span style="color:#999;font-style:italic"># Fetch Hugo themes (true OR recursive)</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">fetch-depth</span>:<span style="color:#666"> </span><span style="color:#3677a9">0</span><span style="color:#666">    </span><span style="color:#999;font-style:italic"># Fetch all history for .GitInfo and .Lastmod</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span>Setup Hugo<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">        </span><span style="color:#6ab825;font-weight:bold">uses</span>:<span style="color:#666"> </span>peaceiris/actions-hugo@v2<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">        </span><span style="color:#6ab825;font-weight:bold">with</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">hugo-version</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#39;latest&#39;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#999;font-style:italic"># extended: true</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span>Build<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">        </span><span style="color:#6ab825;font-weight:bold">run</span>:<span style="color:#666"> </span>hugo --minify<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">      </span>- <span style="color:#6ab825;font-weight:bold">name</span>:<span style="color:#666"> </span>Deploy<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">        </span><span style="color:#6ab825;font-weight:bold">uses</span>:<span style="color:#666"> </span>appleboy/scp-action@master<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">        </span><span style="color:#6ab825;font-weight:bold">with</span>:<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">host</span>:<span style="color:#666"> </span>${{ secrets.HOST }}<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">port</span>:<span style="color:#666"> </span>${{ secrets.PORT }}<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">username</span>:<span style="color:#666"> </span>${{ secrets.USERNAME }}<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">key</span>:<span style="color:#666"> </span>${{ secrets.KEY }}<span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">source</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;./public&#34;</span><span style="color:#666">
</span></span></span><span style="display:flex;"><span><span style="color:#666">          </span><span style="color:#6ab825;font-weight:bold">target</span>:<span style="color:#666"> </span><span style="color:#ed9d13">&#34;/var/www/davidspencer.xyz&#34;</span><span style="color:#666">
</span></span></span></code></pre></div><p>In my workflow, i&rsquo;m using scp-action to copy the generated website files to my server.</p>
<p>This means we&rsquo;ll need to create some secrets on our repo.</p>
<p>In your repository on GitHub create the following secrets
Settings &gt; Secrets &gt; New repository secret</p>
<ul>
<li>HOST</li>
<li>KEY</li>
<li>PORT</li>
<li>USERNAME</li>
</ul>
<p>I&rsquo;ll assume you have knowledge on SSH and what the secrets should contain.</p>
<p>I&rsquo;d encourage you to generate a unique key pair and user for this action.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#24909d">cd</span> ~/Projects/davidspencer.xyz
</span></span><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#ed9d13">&#34;adding github action for automated deployments&#34;</span>
</span></span><span style="display:flex;"><span>git push
</span></span></code></pre></div><p>You can now watch the action run on GitHub and monitor your VPS for the website files to be copied over.</p>
]]></content:encoded></item><item><title>Using Neovim as an IDE for Python</title><link>https://davidspencer.xyz/posts/neovim-as-an-ide-python/</link><pubDate>Sat, 24 Jul 2021 00:00:00 +0000</pubDate><author>david@ddemail.us (David Spencer)</author><guid>https://davidspencer.xyz/posts/neovim-as-an-ide-python/</guid><description>&lt;p&gt;In this post I&amp;rsquo;ll demonstrate my setup of neovim for python development.&lt;/p&gt;
&lt;h3 id="setup"&gt;Setup&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/neovim/neovim"&gt;Install neovim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.python.org/downloads/"&gt;Install Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="neovim-configuration"&gt;neovim configuration&lt;/h3&gt;
&lt;p&gt;All of the config files for neovim will be in our config directory.
If any of the folders or files do not exist we will create them now.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p ~/.config/nvim/lua
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;touch ~/.config/nvim/init.vim
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;touch ~/.config/nvim/lua/{lua_config,lsp_config}.lua
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using neovim, we will edit the init.vim&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-vim" data-lang="vim"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;syntax&lt;/span&gt; on &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;syntax highlighting, see :help syntax&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;filetype&lt;/span&gt; plugin indent on &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;file type detection, see :help filetype&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; number &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;display line number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; relativenumber &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;display relative line numbers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; path+=** &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;improves searching, see :help path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; noswapfile &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;disable use of swap files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; wildmenu &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;completion menu&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; backspace=indent,eol,start &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;ensure proper backspace functionality&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; undodir=~&lt;span style="color:#ed9d13"&gt;/.cache/&lt;/span&gt;nvim/undo &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;undo ability will persist after exiting file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; undofile &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;see :help undodir and :help undofile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; incsearch &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;see results while search is being typed, see :help incsearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; smartindent &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;auto indent on new lines, see :help smartindent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; ic &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;ignore case when searching&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; colorcolumn=&lt;span style="color:#3677a9"&gt;80&lt;/span&gt; &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;display color when line reaches pep8 standards&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; expandtab &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;expanding tab to spaces&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; tabstop=&lt;span style="color:#3677a9"&gt;4&lt;/span&gt; &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;setting tab to 4 columns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; shiftwidth=&lt;span style="color:#3677a9"&gt;4&lt;/span&gt; &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;setting tab to 4 columns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; softtabstop=&lt;span style="color:#3677a9"&gt;4&lt;/span&gt; &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;setting tab to 4 columns&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; showmatch &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;display matching bracket or parenthesis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;set&lt;/span&gt; hlsearch incsearch &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;highlight all pervious search pattern with incsearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;highlight&lt;/span&gt; ColorColumn ctermbg=&lt;span style="color:#3677a9"&gt;9&lt;/span&gt; &lt;span style="color:#999;font-style:italic"&gt;&amp;#34;display ugly bright red bar at color column number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#999;font-style:italic"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#999;font-style:italic"&gt;&amp;#34; Keybind Ctrl+l to clear search&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nnoremap &amp;lt;C-l&amp;gt; :nohl&amp;lt;CR&amp;gt;&amp;lt;C-l&amp;gt;:echo &lt;span style="color:#ed9d13"&gt;&amp;#34;Search Cleared&amp;#34;&lt;/span&gt;&amp;lt;CR&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#999;font-style:italic"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#999;font-style:italic"&gt;&amp;#34; When python filetype is detected, F5 can be used to execute script &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6ab825;font-weight:bold"&gt;autocmd&lt;/span&gt; FileType python nnoremap &amp;lt;buffer&amp;gt; &amp;lt;F5&amp;gt; :w&amp;lt;cr&amp;gt;:exec &lt;span style="color:#ed9d13"&gt;&amp;#39;!clear&amp;#39;&lt;/span&gt;&amp;lt;cr&amp;gt;:exec &lt;span style="color:#ed9d13"&gt;&amp;#39;!python3&amp;#39;&lt;/span&gt; shellescape(expand(&lt;span style="color:#ed9d13"&gt;&amp;#39;%:p&amp;#39;&lt;/span&gt;), &lt;span style="color:#3677a9"&gt;1&lt;/span&gt;)&amp;lt;cr&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I set colorcolumn to 80 instead of 79 due to preferring the red wall, this way I can type up to the wall instead of having one character on the wall.&lt;/p&gt;</description><content:encoded><![CDATA[<p>In this post I&rsquo;ll demonstrate my setup of neovim for python development.</p>
<h3 id="setup">Setup</h3>
<ul>
<li><a href="https://github.com/neovim/neovim">Install neovim</a></li>
<li><a href="https://www.python.org/downloads/">Install Python</a></li>
</ul>
<hr>
<h3 id="neovim-configuration">neovim configuration</h3>
<p>All of the config files for neovim will be in our config directory.
If any of the folders or files do not exist we will create them now.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir -p ~/.config/nvim/lua
</span></span><span style="display:flex;"><span>touch ~/.config/nvim/init.vim
</span></span><span style="display:flex;"><span>touch ~/.config/nvim/lua/{lua_config,lsp_config}.lua
</span></span></code></pre></div><p>Using neovim, we will edit the init.vim</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">syntax</span> on                       <span style="color:#999;font-style:italic">&#34;syntax highlighting, see :help syntax</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">filetype</span> plugin indent on       <span style="color:#999;font-style:italic">&#34;file type detection, see :help filetype</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> number                      <span style="color:#999;font-style:italic">&#34;display line number</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> relativenumber              <span style="color:#999;font-style:italic">&#34;display relative line numbers</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> path+=**                    <span style="color:#999;font-style:italic">&#34;improves searching, see :help path</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> noswapfile                  <span style="color:#999;font-style:italic">&#34;disable use of swap files</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> wildmenu                    <span style="color:#999;font-style:italic">&#34;completion menu</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> backspace=indent,eol,start  <span style="color:#999;font-style:italic">&#34;ensure proper backspace functionality</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> undodir=~<span style="color:#ed9d13">/.cache/</span>nvim/undo  <span style="color:#999;font-style:italic">&#34;undo ability will persist after exiting file</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> undofile                    <span style="color:#999;font-style:italic">&#34;see :help undodir and :help undofile</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> incsearch                   <span style="color:#999;font-style:italic">&#34;see results while search is being typed, see :help incsearch</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> smartindent                 <span style="color:#999;font-style:italic">&#34;auto indent on new lines, see :help smartindent</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> ic                          <span style="color:#999;font-style:italic">&#34;ignore case when searching</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> colorcolumn=<span style="color:#3677a9">80</span>              <span style="color:#999;font-style:italic">&#34;display color when line reaches pep8 standards</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> expandtab                   <span style="color:#999;font-style:italic">&#34;expanding tab to spaces</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> tabstop=<span style="color:#3677a9">4</span>                   <span style="color:#999;font-style:italic">&#34;setting tab to 4 columns</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> shiftwidth=<span style="color:#3677a9">4</span>                <span style="color:#999;font-style:italic">&#34;setting tab to 4 columns</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> softtabstop=<span style="color:#3677a9">4</span>               <span style="color:#999;font-style:italic">&#34;setting tab to 4 columns</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> showmatch                   <span style="color:#999;font-style:italic">&#34;display matching bracket or parenthesis</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> hlsearch incsearch          <span style="color:#999;font-style:italic">&#34;highlight all pervious search pattern with incsearch</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">highlight</span> ColorColumn ctermbg=<span style="color:#3677a9">9</span> <span style="color:#999;font-style:italic">&#34;display ugly bright red bar at color column number</span>
</span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">
</span></span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34; Keybind Ctrl+l to clear search</span>
</span></span><span style="display:flex;"><span>nnoremap &lt;C-l&gt; :nohl&lt;CR&gt;&lt;C-l&gt;:echo <span style="color:#ed9d13">&#34;Search Cleared&#34;</span>&lt;CR&gt;
</span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">
</span></span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34; When python filetype is detected, F5 can be used to execute script </span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">autocmd</span> FileType python nnoremap &lt;buffer&gt; &lt;F5&gt; :w&lt;cr&gt;:exec <span style="color:#ed9d13">&#39;!clear&#39;</span>&lt;cr&gt;:exec <span style="color:#ed9d13">&#39;!python3&#39;</span> shellescape(expand(<span style="color:#ed9d13">&#39;%:p&#39;</span>), <span style="color:#3677a9">1</span>)&lt;cr&gt;
</span></span></code></pre></div><p>I set colorcolumn to 80 instead of 79 due to preferring the red wall, this way I can type up to the wall instead of having one character on the wall.</p>
<p><em>ref: <a href="https://neovim.io/doc/lsp/">pep8</a></em></p>
<hr>
<h3 id="installing-vim-plug-and-lsp-plugins">Installing vim-plug and LSP Plugins</h3>
<p>vim-plug is my plugin manager of choice.
If you use a different plugin manager you can do so.</p>
<p><a href="https://github.com/junegunn/vim-plug#neovim">vim-plug neovim install</a></p>
<p>There are two plugins we will need</p>
<ul>
<li><a href="https://github.com/neovim/nvim-lspconfig#install">nvim-lspconfig</a></li>
<li><a href="https://github.com/nvim-lua/completion-nvim#install">completion-nvim</a></li>
</ul>
<p>To install these using vim-plug we will add the following section to our init.vim</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34;vim-plug configuration, plugins will be installed in ~/.config/nvim/plugged</span>
</span></span><span style="display:flex;"><span>call plug#begin(<span style="color:#ed9d13">&#39;$XDG_CONFIG_HOME/nvim/plugged&#39;</span>) 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Plug <span style="color:#ed9d13">&#39;neovim/nvim-lspconfig&#39;</span>
</span></span><span style="display:flex;"><span>Plug <span style="color:#ed9d13">&#39;nvim-lua/completion-nvim&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>call plug#end()
</span></span></code></pre></div><p>Install plugins</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span>nvim
</span></span><span style="display:flex;"><span>:PlugInstall
</span></span></code></pre></div><hr>
<h3 id="configuring-neovim-language-server-protocol-lsp">Configuring neovim Language Server Protocol (lsp)</h3>
<p>We have a pretty good setup at this point. But to make it better we can add a Language Server using the Language Server Client built into neovim</p>
<p>You can read all about it here. <a href="https://neovim.io/doc/lsp/">neovim lsp</a></p>
<p>Essentially each programming language has it&rsquo;s own language server that needs installed.
The nvim-lspconfig plugin we installed earlier ensures language servers are launched appropriately when needed. However, for this to work we have to install language servers ourselves.</p>
<p>There are other projects that aim to automate the installation of language servers; however, I have not tested them. <em><a href="https://github.com/neovim/nvim-lspconfig/wiki/Installing-language-servers-automatically">automatic language server installation</a></em></p>
<p>I will continue with the manual installation of a language server.</p>
<p>The nvim-lspconfig repo has an exhaustive list of language server options. I recommend using this when looking for a language server to use.</p>
<p>For python, I use <a href="https://github.com/neovim/nvim-lspconfig/blob/master/CONFIG.md#pylsp">pylsp</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pip3 install -U setuptools pip
</span></span><span style="display:flex;"><span>pip3 install <span style="color:#ed9d13">&#39;python-lsp-server[all]&#39;</span>
</span></span></code></pre></div><p>With that installed, we can now configure neovim so that it will load pylsp when we are working on a python project.</p>
<p>Earlier we created some files</p>
<ul>
<li>~/.config/nvim/lua/lsp_config.lua</li>
<li>~/.config/nvim/lua/lua_config.lua</li>
</ul>
<p>Lets edit lua_config.lua first. Add the following to the lua_config.lua file.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>require(<span style="color:#ed9d13">&#39;lsp_config&#39;</span>)
</span></span></code></pre></div><p>Add the following to the lsp_config.lua file</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">local</span> lsp = require(<span style="color:#ed9d13">&#39;lspconfig&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">local</span> completion = require(<span style="color:#ed9d13">&#39;completion&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">local</span> custom_attach = <span style="color:#6ab825;font-weight:bold">function</span>()
</span></span><span style="display:flex;"><span>    completion.on_attach()
</span></span><span style="display:flex;"><span>    <span style="color:#999;font-style:italic">-- Python specifically isn&#39;t setting omnifunc correctly, ftplugin conflict</span>
</span></span><span style="display:flex;"><span>    vim.api.nvim_buf_set_option(<span style="color:#3677a9">0</span>, <span style="color:#ed9d13">&#39;omnifunc&#39;</span>, <span style="color:#ed9d13">&#39;v:lua.vim.lsp.omnifunc&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>lsp.pylsp.setup{on_attach=custom_attach}
</span></span></code></pre></div><p>The lsp_config.lua file contains a couple functions to make loading multiple language servers a bit cleaner.</p>
<p>If you want to add any additional language servers you can add a line to the bottom using the following template.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-lua" data-lang="lua"><span style="display:flex;"><span>lsp.&lt;language_server&gt;.setup{on_attach=custom_attach}
</span></span></code></pre></div><p>The final step will be to add a configuration to our init.vim</p>
<p>Open ~/.config/nvim/init.vim and add the following lines.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-vim" data-lang="vim"><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34; neovim LSP Configuration</span>
</span></span><span style="display:flex;"><span>lua require(<span style="color:#ed9d13">&#39;lua_config&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">
</span></span></span><span style="display:flex;"><span><span style="color:#999;font-style:italic">&#34; Enable Tab / Shift Tab to cycle completion options</span>
</span></span><span style="display:flex;"><span>inoremap &lt;expr&gt; &lt;Tab&gt;   pumvisible() ? <span style="color:#ed9d13">&#34;\&lt;C-n&gt;&#34;</span> : <span style="color:#ed9d13">&#34;\&lt;Tab&gt;&#34;</span>
</span></span><span style="display:flex;"><span>inoremap &lt;expr&gt; &lt;S-Tab&gt; pumvisible() ? <span style="color:#ed9d13">&#34;\&lt;C-p&gt;&#34;</span> : <span style="color:#ed9d13">&#34;\&lt;S-Tab&gt;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">let</span> g:completion_enable_fuzzy_match = <span style="color:#3677a9">1</span>
</span></span><span style="display:flex;"><span><span style="color:#6ab825;font-weight:bold">set</span> completeopt=menuone,noinsert,noselect
</span></span></code></pre></div><hr>
<h3 id="conclusion">Conclusion</h3>
<p>You should now be able to open any python file without any errors.</p>
<p>Additionally, you should have auto-complete and linting enabled.</p>
<p>You should be able to navigate between auto-complete options using Tab / Shift Tab. Or natively Ctrl+n or Ctrl+p.</p>
<p><img alt="neovim as ide for python with lsp" loading="lazy" src="/nvim_python_ide.gif#center"></p>
]]></content:encoded></item><item><title>Building Custom Docker Image With Github Actions</title><link>https://davidspencer.xyz/posts/building-custom-docker-image-with-github-actions/</link><pubDate>Wed, 21 Jul 2021 20:37:51 -0400</pubDate><author>david@ddemail.us (David Spencer)</author><guid>https://davidspencer.xyz/posts/building-custom-docker-image-with-github-actions/</guid><description>&lt;p&gt;This post will explain the process I followed to achieve an automated deployment
of a Docker Hub image with version numbers.&lt;/p&gt;
&lt;p&gt;You will need to have a few things in order before we can get started&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com"&gt;GitHub Account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/"&gt;Docker Hub Account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://podman.io/getting-started/installation.html"&gt;Podman Installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="creating-website-files"&gt;Creating Website Files&lt;/h3&gt;
&lt;p&gt;Create your project directory wherever you prefer. For this tutorial I&amp;rsquo;ll be using &lt;code&gt;~/Projects/container-demo&lt;/code&gt; for the project folder.&lt;/p&gt;
&lt;p&gt;In your terminal, navigate to this project folder and create a content folder.&lt;/p&gt;</description><content:encoded><![CDATA[<p>This post will explain the process I followed to achieve an automated deployment
of a Docker Hub image with version numbers.</p>
<p>You will need to have a few things in order before we can get started</p>
<ul>
<li><a href="https://github.com">GitHub Account</a></li>
<li><a href="https://hub.docker.com/">Docker Hub Account</a></li>
<li><a href="https://podman.io/getting-started/installation.html">Podman Installation</a></li>
</ul>
<hr>
<h3 id="creating-website-files">Creating Website Files</h3>
<p>Create your project directory wherever you prefer. For this tutorial I&rsquo;ll be using <code>~/Projects/container-demo</code> for the project folder.</p>
<p>In your terminal, navigate to this project folder and create a content folder.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#24909d">cd</span> ~/Projects/container-demo
</span></span><span style="display:flex;"><span>mkdir content
</span></span></code></pre></div><p>Using your editor of choice, create an index.html file inside the content folder with the following content</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>&lt;html&gt;
</span></span><span style="display:flex;"><span>Hello World!
</span></span><span style="display:flex;"><span>&lt;/html&gt;
</span></span></code></pre></div><p>Great, now we have our simple website that we&rsquo;re ready to use and Generate our versioned Docker Image.</p>
<hr>
<h3 id="running-container-locally">Running Container Locally</h3>
<p>Now that we have the website data we would like to use, we can add this to an existing Docker image like nginx.
We will start by testing the website files on a nginx container to ensure functionality prior to building the image.</p>
<p>If you&rsquo;re confident, you can skip this step and go to the next section <a href="#building-a-docker-image">Building a Docker Image</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman run -d -p 8008:80 -v ./content:/usr/share/nginx/html:Z,ro nginx
</span></span></code></pre></div><p>At this point you should be able to navigate to the website.
In my case the url is <a href="http://pod1.davidspencer.xyz:8008">http://pod1.davidspencer.xyz:8008</a>.</p>
<p>Yours would most likely be http://localhost:8008 or replace localhost with the hostname/ip of your podman host.</p>
<p>After you have successfully accessed your Hello World! Website, you can stop and remove your container</p>
<p><img alt="Hello World!" loading="lazy" src="/hello_world.png#center"></p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman container list
</span></span><span style="display:flex;"><span>podman container stop &lt;container-name&gt;
</span></span><span style="display:flex;"><span>podman container rm &lt;container-name&gt;
</span></span></code></pre></div><hr>
<h3 id="building-a-docker-image">Building a Docker Image</h3>
<p>We can now build our custom Image.</p>
<p>There are a few benefits to this; however one point I&rsquo;d like to make is that doing this will make it so that we don&rsquo;t have to mount our local files to the container every time.</p>
<p>Add the following text to a new file <code>~/Projects/container-demo/Dockerfile</code></p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>FROM nginx
</span></span><span style="display:flex;"><span>COPY content /usr/share/nginx/html
</span></span></code></pre></div><p>With this file created, you can now run the following command to build and image locally.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman build -t container-demo .
</span></span></code></pre></div><p>You should see container-demo in your images now</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman image list container-demo
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>REPOSITORY                TAG     IMAGE ID      CREATED        SIZE
</span></span><span style="display:flex;"><span>localhost/container-demo  latest  02e3e1343eda  <span style="color:#3677a9">8</span> seconds ago  <span style="color:#3677a9">137</span> MB
</span></span></code></pre></div><p>We can now create a container using this image to see our Hello World! Website</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman run -d -p 8008:80 localhost/container-demo
</span></span></code></pre></div><p>Test the site using the same URL from earlier</p>
<p>After a successful test, stop and remove the new container.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman container list
</span></span><span style="display:flex;"><span>podman container stop &lt;container-name&gt;
</span></span><span style="display:flex;"><span>podman container rm &lt;container-name&gt;
</span></span></code></pre></div><p>You can delete the image after you have removed the container.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>podman image rm &lt;image id&gt;
</span></span></code></pre></div><hr>
<h3 id="initialize-github-repo">Initialize GitHub Repo</h3>
<p>Ensure you are logged into GitHub</p>
<p>Click New</p>
<p><img alt="New Repo" loading="lazy" src="/github_new_repo.png#center"></p>
<p>Enter a name for the repo</p>
<p><img alt="Name Repo" loading="lazy" src="/github_name_repo.png#center"></p>
<p>Click &ldquo;Create Repository&rdquo; at the bottom</p>
<p>Copy either the HTTPS or SSH URL Depending on how you use git</p>
<p><img alt="Repo URL" loading="lazy" src="/github_repo_url.png#center"></p>
<p>Back to your terminal, we&rsquo;ll push our existing content to GitHub</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#24909d">cd</span> ~/Projects/container-demo
</span></span><span style="display:flex;"><span>git init
</span></span><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#ed9d13">&#34;Initial Upload&#34;</span>
</span></span><span style="display:flex;"><span>git remote add origin &lt;repo_url&gt;
</span></span><span style="display:flex;"><span>git push -u origin master
</span></span></code></pre></div><p>Now we should have our repo in GitHub with our project.
We are now ready to build out the GitHub Actions and really tie this whole thing together.</p>
<hr>
<h3 id="build-github-actions">Build GitHub Actions</h3>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#24909d">cd</span> ~/Projects/container-demo
</span></span><span style="display:flex;"><span>mkdir -p .github/workflows
</span></span></code></pre></div><p>Add the following text to a new file,</p>
<p><code>~/Projects/container-demo/.github/workflows/main.yml</code></p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>name: CI to Docker Hub
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>on:
</span></span><span style="display:flex;"><span>  <span style="color:#999;font-style:italic"># Triggers the workflow on push events but only when they are tagged with v*.*.*</span>
</span></span><span style="display:flex;"><span>  push:
</span></span><span style="display:flex;"><span>    tags:
</span></span><span style="display:flex;"><span>      - <span style="color:#ed9d13">&#34;v*.*.*&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  workflow_dispatch:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>jobs:
</span></span><span style="display:flex;"><span>  build:
</span></span><span style="display:flex;"><span>    runs-on: ubuntu-latest
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    steps:
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># Check Out Repo to work with project files</span>
</span></span><span style="display:flex;"><span>      - name: Check out Repo
</span></span><span style="display:flex;"><span>        uses: actions/checkout@v2
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># Login to Docker Hub</span>
</span></span><span style="display:flex;"><span>      - name: Login to Docker Hub
</span></span><span style="display:flex;"><span>        uses: docker/login-action@v1
</span></span><span style="display:flex;"><span>        with:
</span></span><span style="display:flex;"><span>          username: <span style="color:#ed9d13">${</span>{ secrets.DOCKER_HUB_USERNAME <span style="color:#ed9d13">}</span>}
</span></span><span style="display:flex;"><span>          password: <span style="color:#ed9d13">${</span>{ secrets.DOCKER_HUB_ACCESS_TOKEN <span style="color:#ed9d13">}</span>}
</span></span><span style="display:flex;"><span>          
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># Uses Cache to improve build time</span>
</span></span><span style="display:flex;"><span>      - name: Cache Docker layers
</span></span><span style="display:flex;"><span>        uses: actions/cache@v2
</span></span><span style="display:flex;"><span>        with:
</span></span><span style="display:flex;"><span>          path: /tmp/.buildx-cache
</span></span><span style="display:flex;"><span>          key: <span style="color:#ed9d13">${</span>{ runner.os <span style="color:#ed9d13">}</span>}-buildx-<span style="color:#ed9d13">${</span>{ github.sha <span style="color:#ed9d13">}</span>}
</span></span><span style="display:flex;"><span>          restore-keys: |
</span></span><span style="display:flex;"><span>            <span style="color:#ed9d13">${</span>{ runner.os <span style="color:#ed9d13">}</span>}-buildx-
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># Checks-out your repository under $GITHUB_WORKSPACE,</span>
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># so your job can access it.</span>
</span></span><span style="display:flex;"><span>      - name: Set up Docker Buildx
</span></span><span style="display:flex;"><span>        id: buildx
</span></span><span style="display:flex;"><span>        uses: docker/setup-buildx-action@v1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># Sets the steps.get_version.outputs.VERSION variable</span>
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># for proper Docker Hub Image versioning.</span>
</span></span><span style="display:flex;"><span>      - name: Get the version
</span></span><span style="display:flex;"><span>        id: get_version
</span></span><span style="display:flex;"><span>        run: <span style="color:#24909d">echo</span> ::set-output <span style="color:#40ffff">name</span>=VERSION::<span style="color:#ed9d13">${</span><span style="color:#40ffff">GITHUB_REF</span>/refs<span style="color:#ed9d13">\/</span><span style="color:#40ffff">tags</span><span style="color:#ed9d13">\/</span>/<span style="color:#ed9d13">}</span>
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>      <span style="color:#999;font-style:italic"># Build Docker Image and push latest / v*.*.* to Docker Hub</span>
</span></span><span style="display:flex;"><span>      - name: Build and push
</span></span><span style="display:flex;"><span>        id: docker_build
</span></span><span style="display:flex;"><span>        uses: docker/build-push-action@v2
</span></span><span style="display:flex;"><span>        with:
</span></span><span style="display:flex;"><span>          context: ./
</span></span><span style="display:flex;"><span>          file: ./Dockerfile
</span></span><span style="display:flex;"><span>          builder: <span style="color:#ed9d13">${</span>{ steps.buildx.outputs.name <span style="color:#ed9d13">}</span>}
</span></span><span style="display:flex;"><span>          push: <span style="color:#24909d">true</span>
</span></span><span style="display:flex;"><span>          tags: |
</span></span><span style="display:flex;"><span>            <span style="color:#ed9d13">${</span>{ secrets.DOCKER_HUB_USERNAME <span style="color:#ed9d13">}</span>}/container-demo:latest
</span></span><span style="display:flex;"><span>            <span style="color:#ed9d13">${</span>{ secrets.DOCKER_HUB_USERNAME <span style="color:#ed9d13">}</span>}/container-demo:<span style="color:#ed9d13">${</span>{ steps.get_version.outputs.VERSION <span style="color:#ed9d13">}</span>}
</span></span><span style="display:flex;"><span>          cache-from: <span style="color:#40ffff">type</span>=local,src=https://davidspencer.xyz/tmp/.buildx-cache
</span></span><span style="display:flex;"><span>          cache-to: <span style="color:#40ffff">type</span>=local,dest=/tmp/.buildx-cache
</span></span><span style="display:flex;"><span>      
</span></span><span style="display:flex;"><span>      - name: Image digest
</span></span><span style="display:flex;"><span>        run: <span style="color:#24909d">echo</span> <span style="color:#ed9d13">${</span>{ steps.docker_build.output.digest <span style="color:#ed9d13">}</span>}
</span></span></code></pre></div><p>Let&rsquo;s push our changes to the repo now.</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#ed9d13">&#34;Adding GitHub Workflow&#34;</span>
</span></span><span style="display:flex;"><span>git push
</span></span></code></pre></div><p>Now we can generate our Docker Hub personal token
We will also setup our GitHub Secrets.</p>
<table>
	<thead>
			<tr>
					<th>name</th>
					<th>detail</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>DOCKER_HUB_USERNAME</td>
					<td>Username for Docker Hub</td>
			</tr>
			<tr>
					<td>DOCKER_HUB_ACCESS_TOKEN</td>
					<td>Docker Hub Token</td>
			</tr>
	</tbody>
</table>
<p><a href="https://docs.docker.com/docker-hub/access-tokens/">Follow the directions here for generating your access token</a></p>
<p>Once you have your token go to your Repo on GitHub.com</p>
<p><img alt="GitHub Repo Settings" loading="lazy" src="/github_repo_settings.png#center"></p>
<p>Click on Secrets
<img alt="Secrets" loading="lazy" src="/github_secrets.png#center"></p>
<p>Click on New Repository Secrets
<img alt="New Repository Secrets" loading="lazy" src="/github_new_repository_secrets.png#center"></p>
<p><img alt="DOCKER_HUB_USERNAME" loading="lazy" src="/github_docker_hub_username.png#center"></p>
<p>Repeat the same process for DOCKER_HUB_ACCESS_TOKEN</p>
<hr>
<h3 id="push-image-to-docker-hub">Push image to Docker Hub</h3>
<p>Open content/index.html in your editor and make a change</p>
<div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>&lt;html&gt;
</span></span><span style="display:flex;"><span>Hello World!
</span></span><span style="display:flex;"><span>v1.0.0
</span></span><span style="display:flex;"><span>&lt;/html&gt;
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>git tag -a v1.0.0 -m <span style="color:#ed9d13">&#34;v1.0.0&#34;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#ed9d13">&#34;releasing v1.0.0&#34;</span>
</span></span><span style="display:flex;"><span>git push -u origin v1.0.0
</span></span></code></pre></div><p>You can track the action status from the Action tab on your repo</p>
<p><img alt="GitHub Actions Status" loading="lazy" src="/github_actions_status.png#center"></p>
<p>You should eventually see the image in your Docker Hub</p>
<p><img alt="Docker Hub Image Created" loading="lazy" src="/docker_hub_image_creation.png#center"></p>
<p>Lastly you can even see the tags on the image, v1.0.0 and latest</p>
<p>The latest tag will always be the latest and you&rsquo;ll have a history of versions associated with the image as you make changes.</p>
<p><img alt="Docker Hub Image Tags" loading="lazy" src="/docker_hub_image_tags.png#center"></p>
<hr>
<h3 id="conclusion">Conclusion</h3>
<p>I hope you have found this tutorial informative and helpful. If you have any suggestions on how this can be improved, please use the &ldquo;Suggest Edits&rdquo; button at the top or send me an email.</p>
]]></content:encoded></item></channel></rss>