Bryce Vandegrift's Website https://brycev.com/ Updates to Bryce Vandegrift's blog en-us New Domain Name https://brycev.com/blog/new-domain-name/ Wed, 14 May 2025 00:00:00 +0000 https://brycev.com/blog/new-domain-name/ <p>It&rsquo;s about time that I got a new domain name for my website. My current/old domain name, <a href="https://brycevandegrift.xyz">brycevandegrift.xyz</a>, is quite a cumbersome and unorthodox domain name. It&rsquo;s not easy to remember and the <code>.xyz</code> domain name can also be somewhat confusing. Not only that, but I&rsquo;ve had less tech literate people tell me that they thought my domain wasn&rsquo;t actually a real domain name. Add to the fact that many email services automatically mark <code>.xyz</code> domain names as spam, and you can see why I want to change my domain name.</p> <p>I originally got a <code>.xyz</code> domain name because it was fairly cheap (only <strong>99¢</strong>!), however using my <em>full</em> name was probably not the right way to go. My emails also got marked as spam or just filtered by some email servers.</p> <h2 id="new-domain-name">New domain name</h2> <p>I&rsquo;ve been eyeballing <strong><a href="https://brycev.com">brycev.com</a></strong> for quite some time and I finally pulled the trigger and bought it. <code>.com</code> domains are usually the most memorable and trusted domain names out there so I decided to go with that. Right now <code>brycev.com</code> just redirects to <code>brycevandegrift.xyz</code>, but over the next few weeks I will be slowly replacing instances of my old domain name with my new domain name. I will probably also keep <code>brycevandegrift.xyz</code> indefinitely and have it redirect to <code>brycev.com</code>.</p> <p>I&rsquo;ll slowly migrate my website, email, and XMPP server over to using my new domain name. I&rsquo;ll also need to issue a new GPG/PGP key for my new email address. So keep an eye out and I&rsquo;ll post any necessary updates.</p> Blogging on Paper https://brycev.com/blog/blogging-on-paper/ Mon, 31 Mar 2025 00:00:00 +0000 https://brycev.com/blog/blogging-on-paper/ <p>I&rsquo;ve been wanting to post more articles on my blog, however I often find myself away from my computer or I often have more important tasks to take care of on my computer. Either way, I can&rsquo;t write as many articles for my blog as I would like to on my computer.</p> <p>It wasn&rsquo;t until I read a blog post by Ray Patrick (who has sadly taken down his blog) titled <a href="https://web.archive.org/web/20240229190333if_/https://raypatrick.xyz/blog/2024/01/24/in-praise-of-the-manual-typewriter/">&ldquo;In Praise of the Manual Typewriter&rdquo;</a> that I formed an idea. I could type out the articles that I want to compose on a typewriter. This would allow me to formulate any articles that I would like to later post to my blog. I could also handwrite any articles if needed.</p> <p>I&rsquo;ve been in possession of a Royal Mercury typewriter for quite some time now and I have been looking to get some use out of it. It&rsquo;s a somewhat small, portable typewriter that is easy to carry around. This means that I can take it with me almost anywhere that I go. And guess what? I don&rsquo;t have to constantly keep it charged like a laptop&hellip;although it does need paper and ink which could be a slight disadvantage.</p> <p>I also realized that I could use OCR (Optical Character Recognition) programs like <a href="https://tesseract-ocr.github.io/">Tesseract</a> in order to easily convert anything that I type or write while I&rsquo;m away from my computer into text to put on my blog. I might have to do some manual editing and correcting once it&rsquo;s converted into plaintext, but I think that the extra effort would be well worth it.</p> <p>This method of writing articles might very much help me to write more in general, not just for my blog. Keep an eye out though, you might see me putting more on my blog/website within the upcoming months.</p> <hr> <figure ><a href="https://brycev.com/p/paper-blog.webp"><img src="https://brycev.com/p/paper-blog.webp" alt="This post written on paper"></a></figure> OpenBSD Server: smtpd https://brycev.com/blog/openbsd-smtpd/ Fri, 07 Mar 2025 00:00:00 +0000 https://brycev.com/blog/openbsd-smtpd/ <p>At last, the final part to this series. You can catch up on parts 1 and 2 <a href="https://brycev.com/blog/openbsd-server-install">here</a> and <a href="https://brycev.com/blog/openbsd-httpd">here</a> respectively. Setting up an email server is no easy task, it takes a lot of configuration and sometimes trial and error. This guide should be good enough for small email servers that don&rsquo;t get too many emails. So let&rsquo;s go ahead and finally setup an email server for our system.</p> <h2 id="some-needed-packages">Some Needed Packages</h2> <p>First, we need to install some extra packages for our email server to work the way we want it to. We will need <code>rspamd</code> to filter out spam, <code>dovecot</code> in order to use IMAP and or POP3 to view our emails, and we will need <code>dovecot-pigeonhole</code> to help sort our emails:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas pkg_add rspamd-- dovecot-- dovecot-pigeonhole-- opensmtpd-filter-rspamd </span></span></code></pre></div><h2 id="dns-records">DNS Records</h2> <p>In order for our email server to properly work and also to not get filtered or marked as spam, we will need to add some DNS records.</p> <h3 id="mx-record">MX Record</h3> <p>A MX record is required to tell other SMTP servers where to deliver emails sent to our address. For our MX record we can have our emails redirected to <code>mail.example.com</code><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. When creating an MX record, this is what it should look like:</p> <pre tabindex="0"><code>Record Type Host Value MX Priority TTL V V V V V MX @ mail.example.com 0 3600 </code></pre><p>Our record type should (obviously) be MX, our host should be empty (which is sometimes represented as an <code>@</code> symbol), our value is where our mail should go which is <code>mail.example.com</code>, our MX priority should just be 0 for now, and our TTL is set to 3600 seconds (or 1 hour).</p> <p>For reference, this is how my MX record is setup for <code>brycevandegrift.xyz</code>:</p> <figure ><a href="https://brycev.com/p/mx-record.webp"><img src="https://brycev.com/p/mx-record.webp" alt="My personal MX record"></a></figure> <h3 id="spf-record">SPF Record</h3> <p>Our SPF record is vital in order to detect spam. It defines what servers can send emails from a domain. In our case, only <code>mail.example.com</code> will be sending emails on our behalf, so we can set our SPF record accordingly:</p> <pre tabindex="0"><code>Record Type Host Value TTL V V V V TXT @ v=spf1 mx all 3600 </code></pre><p>Our SPF record is just a normal TXT record that has the string &ldquo;v=spf1 mx all&rdquo; in it which allows emails to be sent in reference to our MX record.</p> <h3 id="dkim-record">DKIM Record</h3> <p>We need a DKIM record in order to cryptographically sign and verify the emails we send. Without DKIM your emails will <strong>NOT</strong> be accepted by most email servers and will be marked as spam. In order to use DKIM we will need to generate our private and public keys on our system. We can generate our keys and give them the correct permissions like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># First enter root session</span> </span></span><span style="display:flex;"><span>su </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>umask <span style="color:#ae81ff">077</span> </span></span><span style="display:flex;"><span>install -d -o root -g wheel -m <span style="color:#ae81ff">755</span> /etc/mail/dkim </span></span><span style="display:flex;"><span>install -d -o root -g _rspamd -m <span style="color:#ae81ff">775</span> /etc/mail/dkim/private </span></span><span style="display:flex;"><span>openssl genrsa -out /etc/mail/dkim/private/example.com.key <span style="color:#ae81ff">2048</span> </span></span><span style="display:flex;"><span>openssl rsa -in /etc/mail/dkim/private/example.com.key -pubout -out /etc/mail/dkim/example.com.pub </span></span><span style="display:flex;"><span>chgrp _rspamd /etc/mail/dkim/private/example.com.key /etc/mail/dkim/private/ </span></span><span style="display:flex;"><span>chmod <span style="color:#ae81ff">440</span> /etc/mail/dkim/private/example.com.key </span></span><span style="display:flex;"><span>chmod <span style="color:#ae81ff">775</span> /etc/mail/dkim/private/ </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Exit root session</span> </span></span><span style="display:flex;"><span>exit </span></span></code></pre></div><p>Now that we successfully generated our private and public DKIM keys, we need to put our public DKIM key into our DKIM record. We can get our DKIM public key as a single line by running this <code>awk</code> command:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas awk <span style="color:#e6db74">&#39;/PUBLIC/ { $0=&#34;&#34; } { printf (&#34;%s&#34;,$0) } END { print }&#39;</span> /etc/mail/dkim/example.com.pub </span></span></code></pre></div><p>We can now copy that string and put it into our DKIM record.</p> <pre tabindex="0"><code>Record Type Host Value TTL V V V V TXT dkim._domainkey v=DKIM1;k=rsa;p=&lt;YOUR DKIM KEY&gt; 3600 </code></pre><p>Just replace <code>&lt;YOUR DKIM KEY&gt;</code> with the string you just copied and your DKIM record is good to go.</p> <h3 id="dmarc-record">DMARC Record</h3> <p>We now need to add a DMARC record to our DNS records. DMARC is just another way of preventing email spoofing and spam by telling receiving email servers what to do with potentially invalid emails. Here is a good default to use for you DMARC record:</p> <pre tabindex="0"><code>Record Type Host Value TTL V V V V TXT @ v=DMARC1;p=reject;rua=mailto:dmarc@example.com;sp=reject;aspf=r; 3600 </code></pre><p>Wow, the value for this record is quite long, let&rsquo;s break down what it means. <code>p=reject</code> and <code>sp=reject</code> just means to immediately discard any invalid emails, <code>aspf=r</code> means that <em>any</em> email sent from <em>any</em> subdomain of example.com is valid, and <code>rua=dmarc@example.com</code> tells where the mail server receives DMARC reports (don&rsquo;t worry, you shouldn&rsquo;t care about DMARC reports, they are mostly useless).</p> <h3 id="ptr-record">PTR Record</h3> <p>Finally, our last record! All you need to do is set a PTR record (also called a Reverse DNS pointer) that points to <code>mail.example.com</code>. That&rsquo;s it. This is yet <strong>another</strong> mechanism to prevent spam. Please note that there are different ways to set a PTR record, most ways involve finding a &ldquo;Reverse DNS&rdquo; option for your VPS/hosting provider and using that.</p> <h2 id="email-configuration">Email Configuration</h2> <p>At last, we can now configure the setting for our email server. Our first order of business is to get a valid certificate for our <code>mail.example.com</code> subdomain. This process should be somewhat familiar if you read my last article. Let&rsquo;s first append this to the end of our <code>/etc/acme-client.conf</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">domain</span> <span style="color:#66d9ef">mail.example.com</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">domain</span> <span style="color:#66d9ef">key</span> <span style="color:#e6db74">&#34;/etc/ssl/private/mail.example.com.key&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">domain</span> <span style="color:#66d9ef">full</span> <span style="color:#66d9ef">chain</span> <span style="color:#66d9ef">certificate</span> <span style="color:#e6db74">&#34;/etc/ssl/mail.example.com.fullchain.pem&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">sign</span> <span style="color:#66d9ef">with</span> <span style="color:#66d9ef">letsencrypt</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>Now we just need to add this to <code>/etc/httpd.conf</code> in order to get a certificate for <em>any</em> subdomain of example.com:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> <span style="color:#e6db74">&#34;*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#960050;background-color:#1e0010">*</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">80</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">location</span> <span style="color:#e6db74">&#34;/.well-known/acme-challenge/*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">root</span> <span style="color:#e6db74">&#34;/acme&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">request</span> <span style="color:#66d9ef">strip</span> <span style="color:#ae81ff">2</span> </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">location</span> <span style="color:#960050;background-color:#1e0010">*</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">block</span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">302</span> <span style="color:#e6db74">&#34;https://$HTTP_HOST$REQUEST_URI&#34;</span> </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>Now we just run this command to generate a certificate for <code>mail.example.com</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas acme-client -v mail.example.com </span></span></code></pre></div><p>Finally, we shouldn&rsquo;t forget to automatically renew our certificates, so change <code>/etc/weekly.local</code> as follows:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># Check for new certificates every week</span> </span></span><span style="display:flex;"><span>acme-client example.com </span></span><span style="display:flex;"><span>acme-client mail.example.com </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>rcctl restart httpd smtpd dovecot </span></span></code></pre></div><h3 id="spam">Spam</h3> <p>The first program that we should configure is <code>rspamd</code>. Only a few things need to be set in order for it to work properly. Go ahead and create a file at <code>/etc/rspamd/local.d/dkim_signing.conf</code> and add this to it:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#75715e"># This should always be true </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">allow_username_mismatch</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span><span style="color:#960050;background-color:#1e0010">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Allow rspamd to sign with our DKIM key </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">domain</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">example.com</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">path</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/etc/mail/dkim/private/example.com.key&#34;</span><span style="color:#960050;background-color:#1e0010">;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">selector</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;dkim&#34;</span><span style="color:#960050;background-color:#1e0010">;</span> </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>This is entirely optional, but if you want more performance you can enable and start <code>redis</code> as a cache backend:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas rcctl enable redis </span></span><span style="display:flex;"><span>doas rcctl start redis </span></span></code></pre></div><p>Now enable and start <code>rspamd</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas rcctl enable rspamd </span></span><span style="display:flex;"><span>doas rcctl start rspamd </span></span></code></pre></div><h3 id="smtp">SMTP</h3> <p>Now let&rsquo;s configure OpenSMTPD in order to send and receive emails. We will need to create a config file at <code>/etc/mail/smtpd.conf</code> and configure it like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#75715e"># Set locations to certificates </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">pki</span> <span style="color:#66d9ef">example.com</span> <span style="color:#66d9ef">cert</span> <span style="color:#e6db74">&#34;/etc/ssl/mail.example.com.fullchain.pem&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">pki</span> <span style="color:#66d9ef">example.com</span> <span style="color:#66d9ef">key</span> <span style="color:#e6db74">&#34;/etc/ssl/private/mail.example.com.key&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">pki</span> <span style="color:#66d9ef">example.com</span> <span style="color:#66d9ef">dhe</span> <span style="color:#66d9ef">auto</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Delimiter for email addresses </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">smtp</span> <span style="color:#66d9ef">sub-addr-delim</span> <span style="color:#960050;background-color:#1e0010">&#39;</span><span style="color:#66d9ef">_</span><span style="color:#960050;background-color:#1e0010">&#39;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Sets rspamd as our filter </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">filter</span> <span style="color:#66d9ef">rspamd</span> <span style="color:#66d9ef">proc-exec</span> <span style="color:#e6db74">&#34;filter-rspamd&#34;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Sets ports to use for mail transfer </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#66d9ef">all</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">25</span> <span style="color:#66d9ef">tls</span> <span style="color:#66d9ef">pki</span> <span style="color:#e6db74">&#34;example.com&#34;</span> <span style="color:#66d9ef">filter</span> <span style="color:#e6db74">&#34;rspamd&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#66d9ef">all</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">465</span> <span style="color:#66d9ef">smtps</span> <span style="color:#66d9ef">pki</span> <span style="color:#e6db74">&#34;example.com&#34;</span> <span style="color:#66d9ef">auth</span> <span style="color:#66d9ef">mask-src</span> <span style="color:#66d9ef">filter</span> <span style="color:#e6db74">&#34;rspamd&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#66d9ef">all</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">587</span> <span style="color:#66d9ef">tls-require</span> <span style="color:#66d9ef">pki</span> <span style="color:#e6db74">&#34;example.com&#34;</span> <span style="color:#66d9ef">auth</span> <span style="color:#66d9ef">mask-src</span> <span style="color:#66d9ef">filter</span> <span style="color:#e6db74">&#34;rspamd&#34;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Load mail aliases </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">table</span> <span style="color:#66d9ef">aliases</span> <span style="color:#66d9ef">file</span><span style="color:#960050;background-color:#1e0010">:</span>/etc/mail/aliases </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Actions for mail delievery </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">action</span> <span style="color:#e6db74">&#34;local&#34;</span> <span style="color:#66d9ef">lmtp</span> <span style="color:#e6db74">&#34;/var/dovecot/lmtp&#34;</span> <span style="color:#66d9ef">alias</span> <span style="color:#960050;background-color:#1e0010">&lt;</span><span style="color:#66d9ef">aliases</span><span style="color:#960050;background-color:#1e0010">&gt;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">action</span> <span style="color:#e6db74">&#34;outbound&#34;</span> <span style="color:#66d9ef">relay</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Actions for recieving mail </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">match</span> <span style="color:#66d9ef">from</span> <span style="color:#66d9ef">any</span> <span style="color:#66d9ef">for</span> <span style="color:#66d9ef">domain</span> <span style="color:#e6db74">&#34;example.com&#34;</span> <span style="color:#66d9ef">action</span> <span style="color:#e6db74">&#34;local&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">match</span> <span style="color:#66d9ef">from</span> <span style="color:#66d9ef">local</span> <span style="color:#66d9ef">for</span> <span style="color:#66d9ef">local</span> <span style="color:#66d9ef">action</span> <span style="color:#e6db74">&#34;local&#34;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#75715e"># Actions for sending mail </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">match</span> <span style="color:#66d9ef">from</span> <span style="color:#66d9ef">any</span> <span style="color:#66d9ef">auth</span> <span style="color:#66d9ef">for</span> <span style="color:#66d9ef">any</span> <span style="color:#66d9ef">action</span> <span style="color:#e6db74">&#34;outbound&#34;</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">match</span> <span style="color:#66d9ef">from</span> <span style="color:#66d9ef">local</span> <span style="color:#66d9ef">for</span> <span style="color:#66d9ef">any</span> <span style="color:#66d9ef">action</span> <span style="color:#e6db74">&#34;outbound&#34;</span> </span></span></code></pre></div><p>Now we need to place our mail delievery address in <code>/etc/mail/mailname</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">mail.example.com</span> </span></span></code></pre></div><p>And now we can test our <code>smtpd</code> config by running:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas smtpd -n -f /etc/mail/smtpd.conf </span></span></code></pre></div><p>If everything is all good then you can restart <code>smtpd</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas rcctl restart smtpd </span></span></code></pre></div><h3 id="imappop3">IMAP/POP3</h3> <p>The last part of our email server is <code>dovecot</code> which allows us to view our emails using IMAP and or POP3. In order to use our certificates we will need to configure <code>/etc/dovecot/conf.d/10-ssl.conf</code> like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">ssl_cert</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">&lt;</span>/etc/ssl/mail.example.com.fullchain.pem </span></span><span style="display:flex;"><span><span style="color:#66d9ef">ssl_key</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">&lt;</span>/etc/ssl/private/mail.example.com.key </span></span><span style="display:flex;"><span><span style="color:#66d9ef">ssl_dh</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">&lt;</span>/etc/dovecot/dh.pem </span></span></code></pre></div><p>We need to generate a Diffie-Hellman key in order to make each TLS connection unique (these commands might take a <em>while</em> to generate a key):</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas openssl dhparam -out /etc/dovecot/dh.pem <span style="color:#ae81ff">4096</span> </span></span><span style="display:flex;"><span>doas chown _dovecot:_dovecot /etc/dovecot/dh.pem </span></span><span style="display:flex;"><span>doas chmod <span style="color:#ae81ff">400</span> /etc/dovecot/dh.pem </span></span></code></pre></div><p>Now we need to configure our mailbox and some basic settings for <code>dovecot</code>. Edit <code>/etc/dovecot/conf.d/10-mail.conf</code> so it resembles the following:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#75715e"># Where to put user maildir </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">mail_location</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">maildir</span><span style="color:#960050;background-color:#1e0010">:~</span>/Maildir </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> <span style="color:#66d9ef">inbox</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">inbox</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">yes</span> </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">mmap_disable</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">yes</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">first_valid_uid</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1000</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">mail_plugin_dir</span> <span style="color:#f92672">=</span> /usr/local/lib/dovecot </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">protocol</span> <span style="color:#960050;background-color:#1e0010">!</span><span style="color:#66d9ef">indexer-worker</span> { </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">mbox_write_locks</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">fcntl</span> </span></span></code></pre></div><p>Let&rsquo;s edit <code>/etc/dovecot/conf.d/20-lmtp.conf</code> in order to allow <code>sieve</code> and mail plugins:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">protocol</span> <span style="color:#66d9ef">lmtp</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">mail_plugins</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#66d9ef">mail_plugins</span> <span style="color:#66d9ef">sieve</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>We now meed to modify <code>/etc/dovecot/conf.d/15-mailboxes.conf</code> and add this inside the <code>namespace inbox {</code> section of the file in order to create a Spam folder:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">mailbox</span> <span style="color:#66d9ef">Spam</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">create</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">special_use</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">\</span><span style="color:#66d9ef">Junk</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>If you don&rsquo;t plan on using IMAP and only wish to use POP3 for viewing/sending emails then this last step is entirely optional, however I encourage users to use IMAP instead of POP3. To enable IMAP we just need to edit <code>/etc/dovecot/conf.d/20-imap.conf</code> like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">protocol</span> <span style="color:#66d9ef">imap</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">mail_plugins</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">$</span><span style="color:#66d9ef">mail_plugins</span> <span style="color:#66d9ef">imap_sieve</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">mail_max_userip_connections</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">25</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><h4 id="sieve-and-filtering">Sieve and Filtering</h4> <p>Finally, the last part of setting up <code>dovecot</code> is configuring <code>sieve</code> in order to filter and group emails properly. Go ahead and edit <code>/etc/dovecot/conf.d/90-plugin.conf</code> so it looks like the following:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">plugin</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">sieve_plugins</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">sieve_imapsieve</span> <span style="color:#66d9ef">sieve_extprograms</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#75715e"># Moving to Spam </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">1</span><span style="color:#66d9ef">_name</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">Spam</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">1</span><span style="color:#66d9ef">_causes</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">COPY</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">1</span><span style="color:#66d9ef">_before</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">file</span><span style="color:#960050;background-color:#1e0010">:</span>/usr/local/lib/dovecot/sieve/report-spam.sieve </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#75715e"># Moving from Spam </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">2</span><span style="color:#66d9ef">_name</span> <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">*</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">2</span><span style="color:#66d9ef">_from</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">Spam</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">2</span><span style="color:#66d9ef">_causes</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">COPY</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">imapsieve_mailbox</span><span style="color:#ae81ff">2</span><span style="color:#66d9ef">_before</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">file</span><span style="color:#960050;background-color:#1e0010">:</span>/usr/local/lib/dovecot/sieve/report-ham.sieve </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">sieve_pipe_bin_dir</span> <span style="color:#f92672">=</span> /usr/local/lib/dovecot/sieve </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">sieve_global_extensions</span> <span style="color:#f92672">=</span> <span style="color:#f92672">+</span><span style="color:#66d9ef">vnd.dovecot.pipe</span> <span style="color:#f92672">+</span><span style="color:#66d9ef">vnd.dovecot.environment</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>This configuration allows sieve to &ldquo;learn&rdquo; what types of emails are spam and what types of messages are not spam (sometimes called &ldquo;ham&rdquo; 🍖) depending on where you move them. In order to make these filters functional we need to create two sieve scripts. The first one is <code>/usr/local/lib/dovecot/sieve/report-spam.sieve</code>. Let&rsquo;s create it and add the following to it:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sieve" data-lang="sieve"><span style="display:flex;"><span><span style="color:#f92672">require</span> [<span style="color:#e6db74">&#34;vnd.dovecot.pipe&#34;</span>, <span style="color:#e6db74">&#34;copy&#34;</span>, <span style="color:#e6db74">&#34;imapsieve&#34;</span>, <span style="color:#e6db74">&#34;environment&#34;</span>, <span style="color:#e6db74">&#34;variables&#34;</span>]; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>if <span style="color:#960050;background-color:#1e0010">environment</span> <span style="color:#f92672">:matches</span> <span style="color:#e6db74">&#34;imap.user&#34;</span> <span style="color:#e6db74">&#34;*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">set</span> <span style="color:#e6db74">&#34;username&#34;</span> <span style="color:#e6db74">&#34;${1}&#34;</span>; </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">pipe</span> <span style="color:#f92672">:copy</span> <span style="color:#e6db74">&#34;sa-learn-spam.sh&#34;</span> [ <span style="color:#e6db74">&#34;${username}&#34;</span> ]; </span></span></code></pre></div><p>The second filter is <code>/usr/local/lib/dovecot/sieve/report-ham.sieve</code> and should look like this:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sieve" data-lang="sieve"><span style="display:flex;"><span><span style="color:#f92672">require</span> [<span style="color:#e6db74">&#34;vnd.dovecot.pipe&#34;</span>, <span style="color:#e6db74">&#34;copy&#34;</span>, <span style="color:#e6db74">&#34;imapsieve&#34;</span>, <span style="color:#e6db74">&#34;environment&#34;</span>, <span style="color:#e6db74">&#34;variables&#34;</span>]; </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>if <span style="color:#960050;background-color:#1e0010">environment</span> <span style="color:#f92672">:matches</span> <span style="color:#e6db74">&#34;imap.mailbox&#34;</span> <span style="color:#e6db74">&#34;*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">set</span> <span style="color:#e6db74">&#34;mailbox&#34;</span> <span style="color:#e6db74">&#34;${1}&#34;</span>; </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>if string <span style="color:#e6db74">&#34;${mailbox}&#34;</span> <span style="color:#e6db74">&#34;Trash&#34;</span> { </span></span><span style="display:flex;"><span> stop; </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span>if <span style="color:#960050;background-color:#1e0010">environment</span> <span style="color:#f92672">:matches</span> <span style="color:#e6db74">&#34;imap.user&#34;</span> <span style="color:#e6db74">&#34;*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">set</span> <span style="color:#e6db74">&#34;username&#34;</span> <span style="color:#e6db74">&#34;${1}&#34;</span>; </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">pipe</span> <span style="color:#f92672">:copy</span> <span style="color:#e6db74">&#34;sa-learn-ham.sh&#34;</span> [ <span style="color:#e6db74">&#34;${username}&#34;</span> ]; </span></span></code></pre></div><p>Now we will create two shell scripts for these filters. The first one is <code>/usr/local/lib/dovecot/sieve/sa-learn-ham.sh</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>exec /usr/local/bin/rspamc -d <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>1<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> learn_ham </span></span></code></pre></div><p>The second one is <code>/usr/local/lib/dovecot/sieve/sa-learn-spam.sh</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>exec /usr/local/bin/rspamc -d <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>1<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> learn_spam </span></span></code></pre></div><p>And we need to make them executable:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas chmod +x /usr/local/lib/dovecot/sieve/sa-learn-spam.sh /usr/local/lib/dovecot/sieve/sa-learn-ham.sh </span></span></code></pre></div><p>Now we need to compile the sieve filters to actually use them:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas sievec /usr/local/lib/dovecot/sieve/report-spam.sieve </span></span><span style="display:flex;"><span>doas sievec /usr/local/lib/dovecot/sieve/report-ham.sieve </span></span></code></pre></div><p>Lastly, let&rsquo;s enable and start <code>dovecot</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas rcctl enable dovecot </span></span><span style="display:flex;"><span>doas rcctl start dovecot </span></span></code></pre></div><h2 id="done">Done!</h2> <p><strong>Congrats!</strong> You now have your own email server running on OpenBSD! You can now login to your email server using your preferred email client. If you don&rsquo;t have a preferred email client then you can use <a href="https://thunderbird.net">Thunderbird</a> if you want a GUI or <a href="https://aerc-mail.org/">aerc</a> if you want to view emails from the terminal.</p> <p>You can now enjoy using email knowing that your inbox won&rsquo;t be monitored. 😎</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>Just a friendly reminder to change &ldquo;example.com&rdquo; to your specific domain name.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> OpenBSD Server: httpd https://brycev.com/blog/openbsd-httpd/ Thu, 27 Feb 2025 00:00:00 +0000 https://brycev.com/blog/openbsd-httpd/ <p>I finally got around to writing part 2 of this series. If you have not read part 1 yet, then you can find it <a href="https://brycev.com/blog/openbsd-server-install">here</a>. So now that we have our base server installed, we can go ahead and setup <code>httpd</code> to serve our website.</p> <h2 id="setup-httpd">Setup httpd</h2> <p>Let&rsquo;s go ahead and create a very simple http server using <code>httpd</code> just to make sure that everything is working properly. We can make a config file for <code>httpd</code> at <code>/etc/httpd.conf</code> like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> <span style="color:#e6db74">&#34;example.com&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#960050;background-color:#1e0010">*</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">80</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">alias</span> <span style="color:#e6db74">&#34;www.example.com&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">root</span> <span style="color:#e6db74">&#34;/htdocs/example.com&#34;</span> </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">types</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">include</span> <span style="color:#e6db74">&#34;/usr/share/misc/mime.types&#34;</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>This will create a web server for &ldquo;example.com&rdquo; (make sure to replace &ldquo;example.com&rdquo; with your domain name) on port 80 and will redirect traffic from &ldquo;<a href="https://www.example.com">www.example.com</a>&rdquo; to &ldquo;example.com&rdquo;. Next we need to create <code>/var/www/htdocs/example.com</code> to host our files:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mkdir -p /var/www/htdocs/example.com </span></span></code></pre></div><p>Let&rsquo;s just put a very basic webpage at <code>/var/www/htdocs/example.com/index.html</code> to serve as our homepage.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="color:#75715e">&lt;!DOCTYPE html&gt;</span> </span></span><span style="display:flex;"><span>&lt;<span style="color:#f92672">html</span> <span style="color:#a6e22e">lang</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;en&#34;</span>&gt; </span></span><span style="display:flex;"><span> &lt;<span style="color:#f92672">head</span>&gt; </span></span><span style="display:flex;"><span> &lt;<span style="color:#f92672">title</span>&gt;Example webpage&lt;/<span style="color:#f92672">title</span>&gt; </span></span><span style="display:flex;"><span> &lt;<span style="color:#f92672">meta</span> <span style="color:#a6e22e">charset</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;utf-8&#34;</span>&gt; </span></span><span style="display:flex;"><span> &lt;/<span style="color:#f92672">head</span>&gt; </span></span><span style="display:flex;"><span> &lt;<span style="color:#f92672">body</span>&gt; </span></span><span style="display:flex;"><span> &lt;<span style="color:#f92672">h1</span>&gt;This is an example webpage&lt;/<span style="color:#f92672">h1</span>&gt; </span></span><span style="display:flex;"><span> &lt;<span style="color:#f92672">p</span>&gt;Looks like it works!&lt;/<span style="color:#f92672">p</span>&gt; </span></span><span style="display:flex;"><span> &lt;/<span style="color:#f92672">body</span>&gt; </span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">html</span>&gt; </span></span></code></pre></div><p>Now, in order to make sure that our httpd config file is correct and does not have any errors, we can run this command to check it:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas httpd -n </span></span></code></pre></div><p>If your configuration is correct, then it will spit out <code>configuration ok</code> and you can move on. If not, then it will spit out what error you have to fix in the <code>/etc/httpd.conf</code> file. Finally we can enable httpd on boot and start it using the <code>rcctl</code> command:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas rcctl enable httpd </span></span><span style="display:flex;"><span>doas rcctl start httpd </span></span></code></pre></div><p><strong>Congrats!</strong> You now have a web page on the internet at &ldquo;example.com&rdquo;!</p> <h2 id="getting-a-certificate">Getting a certificate</h2> <p>Now that we verified that a normal web server works, we can go ahead and setup ACME in order to obtain a certificate in order to allow HTTPS connects to our website. First we need to create a file named <code>/etc/acme-client.conf</code> and add this to our file:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">authority</span> <span style="color:#66d9ef">letsencrypt</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">api</span> <span style="color:#66d9ef">url</span> <span style="color:#e6db74">&#34;https://acme-v02.api.letsencrypt.org/directory&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">account</span> <span style="color:#66d9ef">key</span> <span style="color:#e6db74">&#34;/etc/acme/letsencrypt-privkey.pem&#34;</span> </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">domain</span> <span style="color:#66d9ef">example.com</span> { </span></span><span style="display:flex;"><span> <span style="color:#75715e"># Allows an alias </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">alternative</span> <span style="color:#66d9ef">names</span> { <span style="color:#66d9ef">www.example.com</span> } </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">domain</span> <span style="color:#66d9ef">key</span> <span style="color:#e6db74">&#34;/etc/ssl/private/example.com.key&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">domain</span> <span style="color:#66d9ef">full</span> <span style="color:#66d9ef">chain</span> <span style="color:#66d9ef">certificate</span> <span style="color:#e6db74">&#34;/etc/ssl/example.com.fullchain.pem&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">sign</span> <span style="color:#66d9ef">with</span> <span style="color:#66d9ef">letsencrypt</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>The first section defines Let&rsquo;s Encrypt as our certificate authority. The second section defines a domain to fetch a certificate for. It will place our domain key at <code>/etc/ssl/private/example.com.key</code> and our certificate at <code>/etc/ssl/example.com.fullchain.pem</code> (remember to replace &ldquo;example.com&rdquo; with your domain).</p> <p>Now we have to edit <code>/etc/httpd.conf</code> in order to ACME to generate a certificate for our domain:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> <span style="color:#e6db74">&#34;example.com&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#960050;background-color:#1e0010">*</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">80</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">alias</span> <span style="color:#e6db74">&#34;www.example.com&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">root</span> <span style="color:#e6db74">&#34;/htdocs/example.com&#34;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">location</span> <span style="color:#e6db74">&#34;/.well-known/acme-challenge/*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">request</span> <span style="color:#66d9ef">strip</span> <span style="color:#ae81ff">2</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">root</span> <span style="color:#e6db74">&#34;/acme&#34;</span> </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">types</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">include</span> <span style="color:#e6db74">&#34;/usr/share/misc/mime.types&#34;</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>Now we can run this command in order to generate a certificate for our domain:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>acme-client -v example.com </span></span></code></pre></div><h2 id="setup-https">Setup HTTPS</h2> <p>Now that we have our certificate, let&rsquo;s go ahead and edit our <code>/etc/httpd.conf</code> file in order to use HTTPS for our web server:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-lighty" data-lang="lighty"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> <span style="color:#e6db74">&#34;example.com&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#960050;background-color:#1e0010">*</span> <span style="color:#66d9ef">tls</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">443</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">alias</span> <span style="color:#e6db74">&#34;www.example.com&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">root</span> <span style="color:#e6db74">&#34;/htdocs/example.com&#34;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">tls</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">certificate</span> <span style="color:#e6db74">&#34;/etc/ssl/example.com.fullchain.pem&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">key</span> <span style="color:#e6db74">&#34;/etc/ssl/private/example.com.key&#34;</span> </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">location</span> <span style="color:#e6db74">&#34;/.well-known/acme-challenge/*&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">request</span> <span style="color:#66d9ef">strip</span> <span style="color:#ae81ff">2</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">root</span> <span style="color:#e6db74">&#34;/acme&#34;</span> </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">server</span> <span style="color:#e6db74">&#34;example.com&#34;</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">listen</span> <span style="color:#66d9ef">on</span> <span style="color:#960050;background-color:#1e0010">*</span> <span style="color:#66d9ef">port</span> <span style="color:#ae81ff">80</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">alias</span> <span style="color:#e6db74">&#34;www.example.com&#34;</span> </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">block</span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">301</span> <span style="color:#e6db74">&#34;https://example.com$REQUEST_URI&#34;</span> </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">types</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">include</span> <span style="color:#e6db74">&#34;/usr/share/misc/mime.types&#34;</span> </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>Finally we can restart <code>httpd</code> and go to &ldquo;example.com&rdquo; and we will have a secure connection to the website.</p> <h2 id="automatically-renew-certificates">Automatically renew certificates</h2> <p>The final part of this post is going to take care of lose ends by automatically renewing our certificate before it expires. Most certificates expire after only a few months, so we want to automatically renew them. In order to do so we can make a new file at <code>/etc/weekly.local</code>. Any commands that we put in this file will run once a week, so lets put this in <code>/etc/weekly.local</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># Check for new certificates every week</span> </span></span><span style="display:flex;"><span>acme-client -v example.com </span></span><span style="display:flex;"><span>rcctl restart httpd </span></span></code></pre></div><h2 id="almost-done">Almost Done</h2> <p>That&rsquo;s the end of part 2. The final part of this 3 part series will be about setting up an email server using <code>smtpd</code> and setting up spam filtering (as well as other things). So stay tuned for part 3.</p> <hr> <p>You can now read part 3 of this series <a href="https://brycev.com/blog/openbsd-smtpd">here</a>.</p> <hr> OpenBSD Server: Initial Setup https://brycev.com/blog/openbsd-server-install/ Thu, 13 Feb 2025 00:00:00 +0000 https://brycev.com/blog/openbsd-server-install/ <p><em>This is the first part in a series of posts. Find <a href="https://brycev.com/blog/openbsd-httpd">part 2</a> and <a href="https://brycev.com/blog/openbsd-smtpd">part 3</a> when they are ready</em></p> <hr> <p>For those of you who don&rsquo;t follow my blog, in my <a href="https://brycev.com/blog/migrating-my-vps">previous blog post</a> I talked about migrating my VPS to use OpenBSD instead of Debian stable. I recently finished migrating my VPS and would like to document the process in order to help anyone setting up their own OpenBSD server or VPS.</p> <p>Before we get started, make sure that you have your DNS records for your domain name pointing to your server IP address.</p> <figure ><img src="https://brycev.com/p/openbsd.webp" title="OpenBASED" alt="OpenBSD logo"></figure> <h2 id="installing-openbsd">Installing OpenBSD</h2> <p>One thing that might stop most people from using OpenBSD on a VPS specifically is the fact that most hosting providers <strong>don&rsquo;t</strong> allow you to custom operating systems besides the ones that they offer. Luckily, my VPS provider <a href="https://my.frantech.ca/aff.php?aff=6418">Frantech</a><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, allows me to upload my own ISO images in order for you to install <strong>any</strong> OS that I like. So make sure that your VPS provider actually allows you to run OpenBSD.</p> <p>Go ahead and install OpenBSD normally. Here are a few tips when installing OpenBSD for a server:</p> <ul> <li>Make sure to start <code>sshd</code> by default (otherwise you can&rsquo;t login)</li> <li>Create a user for your system</li> <li>Make sure you allow root ssh login (we&rsquo;ll need it temporarily)</li> <li>You can delete the <code>swap</code>, <code>/usr/X11R6</code>, <code>/usr/src/</code>, and <code>/usr/obj</code> partitions when partitioning your disk as we don&rsquo;t need them (make sure to use that free space though)</li> <li>Make sure you select to install <strong>all</strong> sets unless you know what you&rsquo;re doing</li> </ul> <p><strong>Congrats!</strong> You now have a basic OpenBSD installation.</p> <h2 id="configuring">Configuring</h2> <p>First thing is first, we need root privileges. So run this in order to connect as the root user:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>ssh root@example.com </span></span></code></pre></div><p>where <code>example.com</code> is your domain name. As the root user we need to create the <code>/etc/doas.conf</code> file and add the wheel group to it. We can do so by running:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;permit persist :wheel&#34;</span> &gt; /etc/doas.conf </span></span></code></pre></div><p>We can now exit our current ssh session in order to login as the user we created when we installed OpenBSD.</p> <p>Let&rsquo;s first update our system by running these commands using <code>doas</code>:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>doas syspatch </span></span><span style="display:flex;"><span>doas pkg_add -Uu </span></span></code></pre></div><p>The <code>syspatch</code><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> command applies any necessary patches to your system and <code>pkg_add -Uu</code> just updates packages. Speaking of adding packages, you can use <code>pkg_add</code> in order to install your favorite text editor (you&rsquo;ll need it). While we are at it, let&rsquo;s go ahead and disable ssh logins for root since we don&rsquo;t need it anymore. Edit <code>/etc/ssh/sshd_config</code> and add this line to it:</p> <pre tabindex="0"><code>PermitRootLogin no </code></pre><p>Finally, let&rsquo;s create the file <code>/etc/sysctl.conf</code> that will contain system-wide settings. We will put this in <code>/etc/sysctl.conf</code>:</p> <pre tabindex="0"><code>kern.maxproc=8192 kern.maxfiles=32768 kern.maxthread=16384 kern.shminfo.shmall=536870912 kern.shminfo.shmmax=2147483647 kern.shminfo.shmmni=4096 </code></pre><p>Please note that these settings are for <strong>my</strong> system and will chage from system to system. As a rule of thumb:</p> <ul> <li><code>kern.shminfo.shmmax</code> should be set to <strong>half</strong> of your maximum RAM (in bytes)</li> <li><code>kern.shminfo.shmall</code> should be set to <code>kern.shminfo.shmmax</code> divided by 4096 (4096 is the page size in OpenBSD).</li> </ul> <p>These are just a few settings that will get a bit more performance out of our OpenBSD system. It just increases the maximum number of processes able to run at once as well as the maximum amount of shared memory. You can find a detailed explanation of these settings by looking at the man page for <code>sysctl</code> (hint: run <code>man 2 sysctl</code>).</p> <h2 id="stay-tuned">Stay tuned</h2> <p>That&rsquo;s just the beginning of setting up an OpenBSD server, but keep a close eye on my blog as I will upload the next part of this guide somewhat soon which will be about setting up a static web server using <code>httpd</code>&hellip;assuming that I get around to writing it eventually.</p> <hr> <p>You can now read part 2 of this series <a href="https://brycev.com/blog/openbsd-httpd">here</a>.</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>This is an affiliate link&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>Make sure to reboot whenever <code>syspatch</code> applies patches in order to reload the OpenBSD kernel.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> Migrating My VPS https://brycev.com/blog/migrating-my-vps/ Fri, 07 Feb 2025 00:00:00 +0000 https://brycev.com/blog/migrating-my-vps/ <p>Please note that on February 11, 2025 I will be migrating my VPS to a different operating system. This means that my website, email, and XMPP server will be down for most of the day. If you need to contact me please wait until Feburary 12, 2025.</p> <p>I&rsquo;ve been using Debian stable on my VPS ever since I wrote my <a href="https://brycev.com/blog/i-finally-have-a-vps">original post</a> about getting a VPS, however I have decided that I would like to use <a href="https://www.openbsd.org/">OpenBSD</a> on my VPS instead. OpenBSD offers more security while still being very simple which fits my needs a lot more for a server operating system when compared to Debian stable.</p> <p>After migrating my system, I&rsquo;ll most likely create a guide on how to setup an OpenBSD system as it&rsquo;s pretty easy, but not a well documented process.</p> First Livestream Soon https://brycev.com/blog/first-livestream-soon/ Sat, 03 Aug 2024 00:00:00 +0000 https://brycev.com/blog/first-livestream-soon/ <p>I&rsquo;ve recently decided that I&rsquo;m going to do a livestream. This livestream is mostly just a test, but feel free to stop on by if you want to. I have no idea what to expect&hellip;so I&rsquo;ll see how this goes. The stream will start on August 7 at 5:30 PM (EST).</p> <p>The link is here: <a href="https://www.youtube.com/watch?v=y5eZXwXIrBI">https://www.youtube.com/watch?v=y5eZXwXIrBI</a></p> Microwave Transformers https://brycev.com/blog/microwave-transformers/ Sat, 20 Apr 2024 00:00:00 +0000 https://brycev.com/blog/microwave-transformers/ <p>A few years ago I was (and I still am) interested in electrical engineering and learning about how electricity works. I built circuits and repaired various different electronic devices around my house that were broken. My favorite part however, was working with high voltage. The cheapest and most effective gateway drug into high voltage that I encountered was actually the humble microwave oven.</p> <h2 id="the-guts-of-a-microwave-oven">The Guts of a Microwave Oven</h2> <p>Believe it or not, microwave ovens are actually deceptively simple. It really consists of 3 main parts:</p> <ul> <li>The control panel</li> <li>The magnetron</li> <li>The high voltage transformer</li> </ul> <p>The control panel is pretty self explanatory, it lets the user input the time into the microwave oven, change settings, and etc. In fact, a control panel isn&rsquo;t <em>really</em> necessary, all that the control panel does is turn the transformer on and off, which could potentially be done manually. The magnetron is the part that actually generates the microwave radiation needed to cook your food. The high voltage transformer is what provides the necessary power for the magnetron to actually work. The transformer is what we will be focusing on.</p> <h2 id="the-transformer">The Transformer</h2> <p>If you&rsquo;re unfamiliar with transformers and how they work, I would recommend learning a bit about them <a href="http://hyperphysics.phy-astr.gsu.edu/hbase/magnetic/transf.html">here</a>. Otherwise, let&rsquo;s continue.</p> <p>The transformer within a microwave oven is very special. Most high voltage transformers that you can easily get a hold of are very&hellip;limited. Usually these transformers output a high voltage (around 5,000 volts max), but have at a pretty low current (less than 5 milliamps). While this can potentially hurt you and leave burns, it is usually not enough to kill you. Microwave oven transformers are <strong>very</strong> different.</p> <p>While microwave oven transformers are pretty easy to get a hold of, they can output a <strong>scary</strong> amount of power. The average microwave oven transformer can output anywhere from 2,000 to 4,000 volts at around <strong>500 milliamps</strong> (or 0.5 amps). That&rsquo;s around <strong>1-2 thousand watts</strong> of power!</p> <h2 id="some-fun">Some Fun</h2> <p>With high voltage like this, you can do some really cool stuff. But first, a disclaimer:</p> <blockquote> <h3 id="disclaimer">Disclaimer</h3> <p>This should go without saying, but do <strong>NOT</strong> work with microwave ovens and microwave oven transformers unless you know 100% what you are doing! These things can <em>easily</em> kill you.</p> <p>Human skin is usually 100 killoohms, this means that if you touch even a 2,000 volt microwave transformer, then you could have at <em>least</em> 20 milliamps flow through your body<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. This is enough current to seize your muscles so you can&rsquo;t let go. 💀</p> <p>I am <strong>NOT</strong> responsible for anything stupid that you do.</p></blockquote> <p>This is the transformer that I pulled out of a microwave oven. Like most transformers there&rsquo;s two coils, the primary and the secondary<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. These are illustrated below:</p> <figure ><img src="https://brycev.com/p/transformer.webp" alt="Mircowave Transformer"></figure> <p>By hooking up the primary side of the transformer to 120 volts AC (a.k.a. Mains electricity) and attaching wires to the secondary side, I was able to get some pretty cool arcs. I achieved this by bridging the gap between the secondary side with a nail. This setup is called a <a href="https://teslauniverse.com/build/plans/jacobs-ladder">Jacob&rsquo;s Ladder</a>.</p> <video width="640" height="480" preload="none" controls> <source src="https://brycev.com/ac-arcs.webm" type="video/webm"> </video> <p>We can do better. We can build a self-sustaining (non-manual) Jacob&rsquo;s Ladder&hellip;but how?</p> <h2 id="more-power">More Power</h2> <p>In order to create a self-sustaining and self-starting Jacob&rsquo;s Ladder I needed more power. But how exactly can we add more power to this circuit? One microwave oven transformer already draws a lot of power, but how about <strong>two</strong> microwave oven transformers? That&rsquo;s right, I got a hold of <em>another</em> microwave oven transformer.</p> <p>Careful consideration is needed in order to hook up two of these microwave oven transformers. I wired the two transformers in series with a &ldquo;center tap&rdquo; going straight to ground (otherwise my breaker would trip). This gives me anywhere from 4,000 volts to 8,000 volts AC. Next I need to turn that AC voltage into DC voltage.</p> <p>Sadly, I did not have enough high voltage components to make a <em>true</em> AC to DC conversion system&hellip;but I hobbled one together anyways. I was able to use two microwave oven capacitors as resistors<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> since I didn&rsquo;t have any high power resistors on hand. In order to turn AC into &ldquo;DC&rdquo; I took and very simple [but stupid] approach. During the negative AC cycle, all the current is dumped into a pair of diodes&hellip;that&rsquo;s it. Does it waste a <strong>lot</strong> of power? Yes. But does it work? <strong>Yes</strong>. I made a schematic below in order to better illustrate the circuit.</p> <figure ><a href="https://brycev.com/p/circuit.webp"><img src="https://brycev.com/p/circuit.webp" alt="Jacob&#39;s Ladder circuit"></a></figure> <p>And here is the final product. A <strong>working</strong> Jacob&rsquo;s Ladder!</p> <video width="640" height="480" preload="none" controls> <source src="https://brycev.com/dc-arcs.webm" type="video/webm"> </video> <p>I&rsquo;m not sure if you noticed in that video, but my breaker popped. This circuit just draws too much power. I could improve this circuit, but I think I&rsquo;ve decided to end my project here. That being said, I think this was enough high voltage fun for one day. :)</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>These are actually very conservative estimates. In reality, much more current is likely to flow through your body&hellip;which would kill you even faster.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>Most microwave oven transformers actually have a third coil (see the image). This coil usually generates a very low voltage with a high current capability. This is used to heat the magnetron filament, however we are not concerned with it.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:3"> <p>For those who don&rsquo;t know, capacitors behave similar to resistors when passing AC current through them due to <a href="http://hyperphysics.phy-astr.gsu.edu/hbase/electric/accap.html#c2">capacitive reactance</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> My Conversion https://brycev.com/blog/my-conversion/ Mon, 11 Mar 2024 00:00:00 +0000 https://brycev.com/blog/my-conversion/ <p>I&rsquo;ve been putting off writing this blog post for 2 (almost 3) years now. There <strong>is</strong> a good reason for why I did that. Part of it was that I didn&rsquo;t know how to put my experience into words until now, and the other part was just procrastination. So now I feel like I finally have the experience and knowledge to write about something that is very important to me.</p> <h2 id="a-bit-of-background">A Bit of Background</h2> <p>In the past I have never really been a religious person, nor have I really ever liked religion. I always either found it silly, meaningless, or something between those two. In high school I was something akin to Agnostic, I didn&rsquo;t fully believe in God, but I wasn&rsquo;t really sure. In middle school I was a proud Atheist who had a smug satisfaction &ldquo;knowing&rdquo; that God did not exist. So take my word when I say the events within the past few years of my life completely took me by surprise.</p> <h2 id="i-am-now-a-roman-catholic">I Am Now A Roman Catholic</h2> <figure ><img src="https://brycev.com/p/augustine.webp" title="Based Saint Augustine of Hippo" alt="Saint Augustine of Hippo"></figure> <p>Ok, <em>technically</em> I&rsquo;ve been a Catholic for the last 2-3 years and I got confirmed last year, but I&rsquo;ve been putting off &ldquo;officially&rdquo; saying anything until now. I was actually considering Catholicism when I originally started this blog all the way back in November of 2021 (my <a href="https://brycevandegrift.xyz/blog/new-blog/">first blog post</a>), but I didn&rsquo;t start taking it seriously until sometime in 2022. For me, it seemed like it all happened very quickly.</p> <blockquote> <p>&ldquo;But did you consider religion <em>xyz</em>?&rdquo; &ndash;Probably Someone</p></blockquote> <p>I actually did consider quite a few. I considered different forms of Christianity like Anglicanism, Orthodoxy, and even Baptist<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. I even considered things like Islam, Buddhism, and even Hinduism briefly. However, I never found a intellectual tradition that truly rivaled Catholic tradition<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. I also personally looked for the religion that I thought was 100% <strong>true</strong> and Catholicism seemed to fit that bill. It should go without saying, but basing your religious decisions on anything else besides truth (like personal preference) is a very small brained move.</p> <p>I didn&rsquo;t really have a bias either. I used to <strong>hate</strong> the Catholic Church, but I soon grew to find out that my hatred was <em>very</em> much misplaced. As Venerable Archbishop Fulton Sheen put it:</p> <blockquote> <p>&ldquo;Not 100 people in the United States hate the Roman Catholic Church, but millions hate what they think the Roman Catholic Church is.&rdquo; &ndash;Archbishop Fulton J. Sheen</p></blockquote> <p>This very much encapsulates the essence of what stopped me from converting to Catholicism in the past. I hated what I <em>thought</em> Catholicism was, but I soon came to love what it <em>actually</em> is.</p> <h2 id="joining-a-webring">Joining a Webring</h2> <p>After being invited to the <a href="https://heaventree.xyz">Heaven Tree</a> webring almost a year ago, I decided to accept the invitation last month. Now I didn&rsquo;t wait a year to accept the invitation just to be rude. I waited quite a while because I was not sure if I really wanted to identify as a Catholic or even as a Christian for that matter. It really took me the last year to solidify my identity as a Catholic and to accept it. So I sort of think that joining this webring is me cementing myself as a Catholic.</p> <h2 id="what-now">What Now?</h2> <p>Not much about my blog or YouTube channel will change&hellip;at least in the short term. I might post more stuff about theology or other topics related to it, but as always I don&rsquo;t really have a specific direction for my blog or channel. I just post about whatever I feel like saying and that&rsquo;s the way it will probably always be. So don&rsquo;t be surprised if things change over time.</p> <p>I am very grateful for my conversion and all that it has brought me. DEO GRATIAS.</p> <blockquote> <p>&ldquo;Late have I loved you, Beauty so ancient and so new, late have I loved you!</p> <p>Lo, you were within, but I outside, seeking there for you, and upon the shapely things you have made I rushed headlong – I, misshapen. You were with me, but I was not with you. They held me back far from you, those things which would have no being, were they not in you.</p> <p>You called, shouted, broke through my deafness; you flared, blazed, banished my blindness; you lavished your fragrance, I gasped; and now I pant for you; I tasted you, and now I hunger and thirst; you touched me, and I burned for your peace.&rdquo;</p> <p>&ndash;Saint Augustine of Hippo</p></blockquote> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>The only reason I even <strong>remotely</strong> considered Baptist was due to their incredible zeal. Baptist theology is extremely deficient and almost non-sensical.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>I mean, have you even looked at the Summa Theologica?&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> Using a Dot Matrix Printer in 2024 https://brycev.com/blog/using-a-dot-matrix-printer-in-2024/ Wed, 14 Feb 2024 00:00:00 +0000 https://brycev.com/blog/using-a-dot-matrix-printer-in-2024/ <p>Modern printers suck. They&rsquo;re either overpriced, unreliable, ink/toner hogs, or a combination of all 3.</p> <p>Inkjet printers are cheap, have a good picture quality, and can print on many surfaces. However, they are also <strong>very</strong> unreliable and usually don&rsquo;t last over 3 years. Not only that but inkjet printer cartridges can cost and arm and a leg, which is dumb considering ink (outside the cartridge) is dirt cheap. Inkwell printers do solve the ink issue by having an ink reservoir which means that you are not trapped into buying DRM infested ink cartridges.</p> <p>Laser printers are reliable, have a <strong>great</strong> picture quality, and are usually more serviceable. However, they are often <strong>very</strong> large and sometimes overly complicated. Just like with inkjet printers, laser printer toner is insanely expensive and can cost anywhere from $60-$140 per cartridge. It doesn&rsquo;t help that [good] laser printers themselves are also very expensive, costing anywhere from $500-$2,000.</p> <p>Both laser and inkjet printers also suffer from having &ldquo;internet&rdquo; connectivity put on them. I&rsquo;m not talking about a simple LAN connection, I&rsquo;m talking about having your printer connected to Hewlett Packard&rsquo;s, Canon&rsquo;s, or Epson&rsquo;s servers over the internet. Obviously, I&rsquo;m not a big fan of having my printer being able to relay information to anywhere outside my house without my permission.</p> <p>So, what are we left with after laser and inkjet printers. Well, there are thermal printers which are really cheap, require no ink/toner, and can print quickly. However, they require special paper, the prints are usually not high quality, and since a thermal printer <em>burns</em> the image onto paper, the image wears off the paper after a year or so. You also can&rsquo;t print in color.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p> <p>I guess that means we are left with&hellip;</p> <h2 id="dot-matrix-printers">Dot Matrix Printers</h2> <p>Dot matrix printers are relatively cheap, usually costing no more than $500. They&rsquo;re also simple since a dot matrix printer&rsquo;s method of printing is relatively straight forward (I&rsquo;ll explain how they work in a moment). Since they&rsquo;re simple, that also means that they&rsquo;re also <strong>very</strong> reliable and easy to service. Dot matrix ink ribbons are also cheap compared to inkjet ink and laser printer toner. There are also color options for dot matrix printers. The only real apparent downside of dot matrix printers is speed as it usually takes a while to print compared to other printers.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p> <h2 id="how-they-work">How They Work</h2> <p>If you&rsquo;re not familiar with how dot matrix printers work, you would be surprised by how simple they are. A dot matrix printer, as the name implies, prints in a matrix of dots. As the print head moves from left to right, it presses the ink onto the paper via a series of tiny pins that create the final image. It does this line by line until the entire picture is printed. If you want to see one in action look <a href="https://youtu.be/A_vXA058EDY">here</a>.</p> <figure ><img src="https://brycev.com/p/dotmatrix.webp" alt="How a dot matrix printer works"></figure> <p>Sadly, as you can tell from the video, this means that dot matrix printers are somewhat slow and sometimes loud compared to their contenders.</p> <h2 id="my-not-really-new-printer">My (Not Really) New Printer</h2> <p>About a year or two ago I acquired an Apple ImageWriter II off of eBay for about $50. It had some wear and tear on it and was <em>severely</em> yellowed (which I don&rsquo;t mind) and it was also previously used in an industrial setting. But despite all of that, it worked great! The only problem it had was that one of the pins on the print head did not work, which you will see in a moment. Considering there is only <strong>one</strong> problem with it after 30 years of industrial use is amazing and really shows the reliability of these things.</p> <p>I planned to use this thing for a while, but I kept on putting it off for about 1-2 years. It wasn&rsquo;t until the last 2 weeks that I decided to get this thing working.</p> <figure ><img src="https://brycev.com/p/imagewriter.webp" title="The last good Apple product" alt="Apple Imagewriter II"></figure> <h2 id="getting-it-to-work">Getting It To Work</h2> <h3 id="printing-text">Printing Text</h3> <p>The first problem I encountered was how to even hook this thing up to my modern computer. My desktop has a 9 pin serial card and the ImageWriter is a serial printer, so I figured that I should start there. The printer came with a cable to covert the 8 pin DIN socket on the printer to a 25 pin serial connector, so I decided to buy a 25 pin to 9 pin null modem serial cable and a 25 pin serial coupler. I hooked it up as followed:</p> <pre tabindex="0"><code> DB-25 Serial Port | | DB-9 Serial Port-------+ | | +-------DIN 8 Serial Port | | | | | | | | +-----------+ | | +-------+ | | +---------+ | | v v | | v v | | | Computer +-+--+-+Coupler+-+-+-+ Printer | | | | | | | +-----------+ +-------+ +---------+ </code></pre><p>Next, I had to get access to <code>/dev/ttyS1</code> which is where my serial port connected to the printer is located. To do that I just created a simple udev rule to change the permissions of <code>/dev/ttyS1</code> on boot.</p> <pre tabindex="0"><code>KERNEL==&#34;ttyS1&#34;, GROUP=&#34;plugdev&#34;, MODE=&#34;0660&#34; </code></pre><p>Finally, I had to change the settings of the serial port using <code>stty</code>. The settings needed to be:</p> <ul> <li>9600 baud rate</li> <li>8 character bits</li> <li>1 stop bit</li> <li>No parity</li> </ul> <p>So in order to set them accordingly I ran:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>stty -F /dev/ttyS1 <span style="color:#ae81ff">9600</span> cs8 -cstopb -parenb </span></span></code></pre></div><p>And finally, I sent some data to test the printer.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;This is a test&#34;</span> &gt; /dev/ttyS1 </span></span></code></pre></div><p>And&hellip;<strong>it worked!</strong></p> <figure ><img src="https://brycev.com/p/testprint.webp" alt="It works"><figcaption>Success!</figcaption></figure> <h3 id="printing-pdfs">Printing PDFs</h3> <p>Printing text from a modern computer onto a 30 year old printer is pretty cool, but I wanted to see how well it could print PDFs. I actually planned to write a program to translate a PDF to a format that I could output to the ImageWriter, needless to say, this would take a while. Luckily, I found out that <a href="https://www.ghostscript.com/">Ghostscript</a> actually supports output to the Apple ImageWriter family. Four drivers where available:</p> <ul> <li>appledmp (Generic Apple dot matrix driver)</li> <li>iwlo (Apple ImageWriter)</li> <li>iwhi (Apple ImageWriter II)</li> <li>iwlq (Apple ImageWriter LQ)</li> </ul> <p>I choose <a href="https://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png">this</a> as my test image.</p> <p>In order to create a file that I could send to the printer I needed to first convert the PNG into a PDF file with ImageMagick, run Ghostscript, and then output it to the printer:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>convert Tux.png Tux.pdf </span></span><span style="display:flex;"><span>gs -q -dBATCH -dNOPAUSE -sDEVICE<span style="color:#f92672">=</span>iwhi -sPAPERSIZE<span style="color:#f92672">=</span>letter -dFIXEDMEDIA -dPSFitPage -r160x144 -sOutputFile<span style="color:#f92672">=</span>tux Tux.pdf </span></span><span style="display:flex;"><span>cat tux &gt; /dev/ttyS1 </span></span></code></pre></div><p>The output from the printer was&hellip;<em>interesting</em>.</p> <figure ><img src="https://brycev.com/p/tuxtest.webp" alt="Failed print"></figure> <blockquote> <p>Side note, you can see the visible lines that go across the print. That is actually the broken pin on the print head, I plan on replacing the print head eventually.</p></blockquote> <p>This was good and bad. Good because graphics printing works. Bad because I had no idea what was causing this image to corrupt. At this point I had no idea what was wrong. I assumed the problem was that the Ghostscript driver was faulty, however I tried all 4 Apple ImageWriter drivers and they all had a similar result. At one point I thought the serial connection was bad, but these errors were too consistent to be a connection issue. I looked at the <a href="https://mirrors.apple2.org.za/ftp.apple.asimov.net/documentation/hardware/printers/Apple%20ImageWriter%20II%20Technical%20Reference%20Manual.pdf">Apple ImageWriter II Technical Reference Manual</a> and that&rsquo;s when I found the problem.</p> <hr> <h4 id="a-side-note-about-printers">A Side Note About Printers</h4> <p>One thing that I was ignorant about when it came to printers is that almost every printer has a <strong>buffer</strong>. The buffer stores data for the current print job (sometimes future print jobs as well), feeds it to the printer once it needs to print that data, and then disposes of that data once it has been printed. Most modern printers have a decent buffer size to hold print data. Most printing software keeps track of how much data is sent to the printer buffer. This means that we never really have to worry about prints being messed up since print buffers are automatically managed for us.</p> <hr> <p>Once I read that the Apple ImageWriter II only has a print buffer size of <strong>2 kilobytes</strong> I knew what the problem was.</p> <p>The problem about sending data at 9600 baud to the printer was that it was sending data at a faster rate than the printer could actually print, which was overwriting data in the buffer which caused it to print garbage. In order to remedy this I did something no man has ever done&hellip;<em>lower</em> the baud rate.</p> <p>Once I set the baud rate on the printer and my computer&rsquo;s serial port to 2400 baud and printed the image, I got this:</p> <figure ><img src="https://brycev.com/p/matrixtux.webp" alt="Printed image of Tux"></figure> <p><strong>Success!</strong></p> <p>There are a few errors on the right of Tux and a missing line, but that is just a problem with Ghostscript that I can&rsquo;t fix. It usually does not show up on most other prints.</p> <h3 id="printing-faster">Printing Faster</h3> <p>The printer works perfectly at 2400 baud and lower. The only problem is that this printer is now <em>slow</em>. 2400 baud is not fast at all! There are pauses during printing where the printer is waiting to receive serial data from the computer. So how do I increase the data transfer rate but also limit the data transferred to 2kb? Well, that&rsquo;s where a program called <code>split</code> comes in handy. <code>split</code> is a standard POSIX utility that is available on <strong>ALL</strong> POSIX systems. It takes an input file a splits it into multiple output files, but it also has a <code>-b</code> option which allows you to limit the split files to a specific size. In this case, we can limit the file size to 2kb and send them one at a time at 9600 baud. All I have to do is run:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>split -b 2k tux </span></span></code></pre></div><p>And now we have 67 different 2kb files starting with &ldquo;x&rdquo; that we can send one at a time. In order to print them one at a time I wrote a script that just loops over these files:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> </span></span><span style="display:flex;"><span>files<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>ls -1 x*<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> x in $files; <span style="color:#66d9ef">do</span> </span></span><span style="display:flex;"><span> cat $x &gt; /dev/ttyS1 </span></span><span style="display:flex;"><span> sleep <span style="color:#ae81ff">5</span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span> </span></span></code></pre></div><p>Of course this is <strong>not</strong> an efficient way of printing. There are moments where the printer is waiting for data to be received, but this is good enough. In order to achieve close to 100% efficiency, you would need to calculate how fast the print head and page feed move on the host, but I&rsquo;m <em>way</em> too lazy to do that.</p> <h2 id="the-result">The Result</h2> <p>The result is a printer that is somewhat slow, but gets the job done. All I need now is to get <a href="https://en.wikipedia.org/wiki/Continuous_stationery">tractor/continuous feed paper</a> so I don&rsquo;t have to load paper manually. For me, this printer is definitely a good enough solution until I get a new printer (if this one even fails).<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p> <video width="640" height="480" preload="none" controls> <source src="https://brycev.com/print.webm" type="video/webm"> </video> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>I think there actually <em>are</em> thermal printers that can print in color (I have no idea how), but they seem very rare.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>Dot matrix printers <em>do</em> have more downsides like the fact that pins on the print head can break easily, but since you can replace the print heads <strong>and</strong> print heads are relatively cheap this is negligible.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:3"> <p>I&rsquo;ve been keeping my eye on any used Epson dot matrix printers. 👀&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> Why I Switched to Alpine https://brycev.com/blog/why-i-switched-to-alpine/ Mon, 06 Nov 2023 00:00:00 +0000 https://brycev.com/blog/why-i-switched-to-alpine/ <figure ><img src="https://brycev.com/p/alpine.webp" alt="Alpine Linux logo"></figure> <p>I&rsquo;ve been a <a href="https://voidlinux.org/">Void Linux</a> user for about 2 years and I want to say it has been a good run. Void Linux has been an absolutely great Linux distribution and has served me well for quite a while. However, every Linux distribution is not without it&rsquo;s shortcomings. Although Void Linux is a <strong>great</strong> distribution, I still think that it had a few shortcomings that <a href="https://alpinelinux.org/">Alpine Linux</a> fixes.</p> <h2 id="what-alpine-does-better-than-void">What Alpine Does Better Than Void</h2> <h3 id="packages">Packages</h3> <p>Although the main Void Linux repositories have more packages than most other distributions, the selection is still a bit&hellip;lacking. As of writing this, Void Linux has around 13,369 packages. Which is still <strong>a lot</strong> of packages, however Alpine Linux more than <strong>doubles</strong> Void at around 28,583 packages<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p> <p>One thing that bugs me is that even though Void supports musl libc, not all 13,369 packages are available for musl. As you would have guessed, Alpine does not have this problem since musl is the default.</p> <p>Another thing that kind of bugs me is how long it took for packages I submitted to Void&rsquo;s package repos to get accepted. Some of my requests were <strong>never</strong> responded to and others were just forgotten about entirely. When submitting packages to Alpine&rsquo;s packages repos my requests were almost answered the same day and 100% of my packages (so far) have been accepted into the testing branch.</p> <h3 id="xbps">XBPS</h3> <p>Now don&rsquo;t get me wrong, the XBPS package manager is great, however apk (Alpine&rsquo;s package manager) is superior when compared to XBPS. For example, when updating my system after a month on Void it would take around 3-4 minutes to update using XBPS. Whenever I update after a month on Alpine it usually takes less than a minute!</p> <p>A set of packages that show this perfectly are the <code>texlive</code> packages. The time it takes to install an entire texlive distribution on disk is notoriously long. Alpine&rsquo;s apk installs texlive <em>way</em> faster than XBPS. Not only that, but apk manages cached packages in a much better way than XBPS, in my opinion.</p> <p>I don&rsquo;t think I will ever see a package manager as fast, light, and minimal as apk.</p> <h3 id="busybox">BusyBox</h3> <p>One thing that keeps Alpine small is instead of using the GNU Coreutils, Alpine uses the BusyBox Coreutils. For a long time user of the GNU Coreutils like me, the switch can be very jarring, however the payoff is (in my opinion) worth it. The BusyBox Coreutils are actually easier to learn since they have less features and options. They also have the upside of being more POSIX compliant than the GNU Coreutils so writing scripts with BusyBox usually results in more portability.</p> <h3 id="musl-musl-musl-">musl, musl, musl 🐚</h3> <p>Void and Alpine both support musl libc, but a major difference is that Alpine supports <strong>only</strong> musl<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. For those of you who are not well versed in C libraries, musl is essentially a smaller and more tidy C library replacement for glibc (the GNU C library). As I mentioned above, this means that all 28,583 Alpine packages are compiled for musl.</p> <p>For reasons that I won&rsquo;t get into (since it would take too long) musl is generally better than glibc, but sometimes isn&rsquo;t as compatible as glibc, you can find out more about that <a href="https://wiki.musl-libc.org/functional-differences-from-glibc.html">here</a>. I think one of the best comparisons of musl and glibc can be found <a href="https://www.etalabs.net/compare_libcs.html">here</a>. musl binaries tend to be smaller, faster, and more portable compared to glibc.</p> <p>As a C programmer, working with musl is a <strong>dream</strong> compared to glibc.</p> <h3 id="its-great-use-it-already">It&rsquo;s Great, Use It Already</h3> <p>Overall, Alpine Linux fixes almost every gripe that I had with Void Linux and also fixes problems that I didn&rsquo;t even know I had. The entire Alpine Linux distribution is easy to understand, simple, and fast. There are many, many more things that Alpine does better than Void, but if I listed them <em>all</em> then it would take forever. But so far, Alpine Linux is probably one of the <strong>best</strong> Linux distributions that I have ever used.</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>These numbers where obtained by running <code>xbps-query -Rs &quot;*&quot; | wc -l</code> and <code>apk search &quot;*&quot; | wc -l</code> respectively.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>Technically Alpine <em>does</em> support glibc if you wish to install it through apk.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> FFmpeg Video Calls https://brycev.com/blog/ffmpeg-video-calls/ Mon, 18 Sep 2023 00:00:00 +0000 https://brycev.com/blog/ffmpeg-video-calls/ <p>If you have seen any of the <a href="https://youtu.be/VGRHzB8ANAo">videos I made on</a> <a href="https://youtu.be/4NKmEjzfJ98">FFmpeg</a> you would know that I absolutely love it and I think that it is the absolute <strong>BEST</strong> video/multimedia program ever made.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> FFmpeg has so many features and it implements almost all of them extremely well. So it comes to no surprise, after I initially made my FFmpeg videos I found out that FFmpeg can actually be used to create video streams and send them over the internet. After I found out about this I wondered if it could be used as a sort of minimal way to create video calls. After experimenting for just a few <em>minutes</em> I found a way to stream video over the internet via FFmpeg.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>ffmpeg -f alsa -i default <span style="color:#ae81ff">\ </span><span style="color:#75715e"># Get audio from mic</span> </span></span><span style="display:flex;"><span>-i /dev/video0 <span style="color:#ae81ff">\ </span><span style="color:#75715e"># Get video from camera</span> </span></span><span style="display:flex;"><span>-s 640x480 <span style="color:#ae81ff">\ </span><span style="color:#75715e"># Scale down to 640x480</span> </span></span><span style="display:flex;"><span>-c:v libx264 -preset:v ultrafast <span style="color:#ae81ff">\ </span><span style="color:#75715e"># Encode fast!</span> </span></span><span style="display:flex;"><span>-tune zerolatency -intra-refresh <span style="color:#ae81ff">1</span> <span style="color:#ae81ff">\ </span><span style="color:#75715e"># Reduce latency</span> </span></span><span style="display:flex;"><span>-f mpegts <span style="color:#ae81ff">\ </span><span style="color:#75715e"># Put everything into mpegts stream</span> </span></span><span style="display:flex;"><span>-b:v 1M udp://localhost:1313 <span style="color:#75715e"># Send video over localhost:1313</span> </span></span></code></pre></div><p>In order to actually view this video you would need a video player that is able to read/receive from UDP. Luckily such a program exists: <a href="https://youtu.be/iR76e9XUodI">mpv</a>.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mpv --profile<span style="color:#f92672">=</span>low-latency udp://localhost:1313 </span></span></code></pre></div><p>Now to actually send this over the internet and not just over LAN or localhost you would need to replace <code>localhost:1313</code> with the IP address of the recipient for FFmpeg and the IP address of the sender for mpv. This is will let you be able to do peer-to-peer video calls using only FFmpeg and mpv (or any other UDP compatible video player). FFplay, a media player that comes with FFmpeg, can play UDP streams, so technically this can be done using <strong>only</strong> FFmpeg. If you replace <code>-f /dev/video0</code> with <code>-i x11grab</code> you can also screencast to another computer as well, pretty neat.</p> <p>Theoretically, you could do more than just one-on-one video calls, you could have 4, 7, or even 15 people using this method. It would definitely be tedious to set it up, but it would be possible. And of course if you don&rsquo;t want to use video at all you can easily use this method for audio calls.</p> <p>I think this example shows just how versatile FFmpeg can be. Not only that but the settings I used for this example are not actually optimal, it was just a test but it worked great. This is just the tip of the iceberg too, you can also use this to stream movies from another computer, video games, general live streaming, and much more. I personally find it crazy that you can basically do audio and video calls using <strong>only</strong> FFmpeg and this shows just how absolutely amazing it is.</p> <video width="640" height="480" preload="none" controls> <source src="https://brycev.com/cameracast.webm" type="video/webm"> </video> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>In fact, the creator of FFmpeg, Fabrice Bellard, also made QEMU and the Tiny C Compiler (TCC) both of which are very widely used pieces of software that are very well made.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> A Branded Life https://brycev.com/blog/a-branded-life/ Thu, 06 Jul 2023 00:00:00 +0000 https://brycev.com/blog/a-branded-life/ <p>Modern &ldquo;brands&rdquo; are a weird thing when you really think about them. Disney, Hewlett Packard, and Nike. What do all 3 of these have in common? They&rsquo;re all considered brands. But what exactly is a brand? Before the industrial age, a brand was just a way to differentiate a product from a competitor&rsquo;s product. In order to differentiate it one would often <em>brand</em> their name or alias in the product itself.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> However, the concept of a brand has evolved over the last 100-200 years. Instead of being just a name or logo, a brand is often associated with what people hear (jingles/slogans), taste, see, and more. How many times have you heard someone say, &ldquo;Hey, this <strong>X</strong> is just like <strong>Y</strong> brand?&rdquo; As a result of this recognition, modern branding strategies have exploded in popularity. For the companies that brand their products like this, it creates more customer loyalty and therefore more money.</p> <p>But is branding (in the modern sense) a good thing?</p> <h2 id="everything-is-a-brand">Everything is a Brand</h2> <p>One thing that I tend to find very annoying is the modern obsession of brands to the point where <strong>everything</strong> has to be a brand. From homemade crafts to personal websites, it seems like there are so many attempts at creating a modern brand that are just not necessary.</p> <p>Let me share an experience that I had somewhat recently. I had a friend buy me a book from a local book shop as a gift. When I received it I thanked them for the gift and I read it later. I noticed something rather odd about this book&hellip;there was <strong>no</strong> branding. <strong>No</strong> <em>brand name</em>, <strong>no</strong> name, and not even a <strong>copyright notice</strong>. Needless to say I was taken back by this as it seemed abnormal. But why did I think it was abnormal? If I had to guess, it was probably because seeing someone not milking their work and committing a sort of selfless act seemed out of place, especially in this day and age.</p> <p>When was the last time you saw a book without a logo or brand name? I only have two books in my <em>entire</em> collection that fit that criteria. Actually, when is the last time you saw <strong>anything</strong> without a logo or brand name? Go through the room you&rsquo;re in right now and count how many items you have that don&rsquo;t have a brand name and or logo. No, seriously, do it. You will be genuinely surprised.<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p> <h2 id="the-safe-zone">The Safe Zone</h2> <p>One very important downside of modern brands that impact customers is what I like to call the &ldquo;<em>safe zone</em>&rdquo;. The &ldquo;safe zone&rdquo; is a situation in which a customer buys products of specific brands either due to trust, loyalty, familiarity, or a mix of all three. This results in the customer not buying anything else unless it&rsquo;s from one of their chosen brands.</p> <p>This usually results in dependence on a specific brand. This is, of course, intended. And while it is <strong>very</strong> beneficial to the brand itself, it can be detrimental to the customer. On one hand, the customer is provided safety and security knowing that what they get from a specific brand will be (mostly) consistent. On the other hand, this can trap the customer into dependence on a brand since not buying from a trusted brand would be too &ldquo;risky&rdquo; or &ldquo;unsafe&rdquo; (hence the name &ldquo;safe zone&rdquo;).</p> <p>This effect can happen on such a large scale that many brand names are immediately associated with a non-branded objects. For example, do you hear people say cola or Coca-Cola more? Do you hear people say tissue or Kleenex more? Do you hear people say slow cooker or Crock-Pot more? The list goes on and on. Not only does this result in other products being noticed less, but it also draws a negative light on other products and make them seem inferior compared to larger brands.</p> <figure ><img src="https://brycev.com/p/consoom.webp" title="Must consooooome!" alt="consoomer"></figure> <h2 id="drm">DRM</h2> <p><a href="https://www.defectivebydesign.org/what_is_drm">Digital Restrictions Management</a>, more commonly referred to as Digital Rights Management, is one way that a brand keeps customers. DRM essentially restricts what the customer/user can do with a product. This is usually very prevalent among popular companies/brands especially in the technology sector.</p> <p>The best example I can probably think of is ink cartridges for inkjet printers. Most major brands of inkjet printers use proprietary ink cartridges with DRM built into the cartridges themselves. If you try to use a different type of ink cartridge on your printer, <strong>it won&rsquo;t work</strong>. If you try to refill the ink in your cartridge, <strong>it won&rsquo;t work</strong>. If you buy third party ink cartridges, <strong>they won&rsquo;t work</strong>.<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> It&rsquo;s not because it is &ldquo;incompatible&rdquo;, it&rsquo;s ink, it&rsquo;s because the manufacturer wants to force you into brand loyalty and to buy their products.</p> <p>Now it doesn&rsquo;t take a genius to understand that DRM is bad, but for the handful of people who don&rsquo;t understand why DRM is <em>objectively</em> awful, here are a few <a href="https://creativecommons.org/2017/07/09/terrible-horrible-no-good-bad-drm/">links to</a> <a href="https://www.defectivebydesign.org/so_youve_got_some_questions_do_you#examples">understand</a> <a href="https://www.audioholics.com/news/drm-bad-killing-online-music">why</a>.</p> <figure ><img src="https://brycev.com/p/printer.webp" alt="Printer DRM"><figcaption>Classic printer DRM at work.</figcaption></figure> <p>Although the modern conception of branding is very beneficial from an economic and financial standpoint, it can have many negative side effects outside the economic and financial realm. It can result in enforcing restrictions on the customer, physiologically locking them into dependence, and creates obsession with branding. Although this is great for the brand owners, it sucks for the everyday customer. Granted, there are many more factors that go into branding but I think these points really highlight the nature of the current situation.</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>This, of course, is a centuries old tradition and goes all the way back to branding livestock to prove ownership.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>Unless you make it a habit to tear off labels and branding of products that you buy. In which case, I wouldn&rsquo;t blame you for doing that.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:3"> <p>And this isn&rsquo;t made any better by the fact that inkjet printer ink is extremely expensive, especially if it is purchased from the manufacturers themselves.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> Stop Saying C/C++ https://brycev.com/blog/stop-saying-c-and-c++/ Thu, 18 May 2023 00:00:00 +0000 https://brycev.com/blog/stop-saying-c-and-c++/ <p>For as long as I can remember, I have heard people say C/C++ when referring to a project written in C and or C++. A lot of programming/developer jobs also refer to C/C++ when they need a programmer who knows either C or C++. To most people who have never touched C or C++ this might not seem like a big deal. However, the problem is that when people say this term (C/C++) they make it seem like C and C++ are similar or closely related programming languages. <strong>That is not true.</strong> Although C++ was based off of C when it was first created, these two languages have slowly drifted apart over the years to the point where they share less and less in common<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p> <h2 id="c-and-c-are-very-different">C and C++ are VERY Different</h2> <p>There is probably someone who is going to say, &ldquo;Well you can write C code in a C++ program, so technically C is a subset of C++.&rdquo; The only problem is that you can write C code in <a href="https://ziglang.org/documentation/master/#C">Zig</a>, <a href="https://pkg.go.dev/cmd/cgo">Go</a>, <a href="https://github.com/nim-lang/Nim/wiki/Nim-for-C-programmers">Nim</a>, and basically almost every other language out there has a C FFI! So should I refer to Zig, Go, and Nim as C/Zig, C/Go, and C/Nim? Obviously <strong>no</strong>.</p> <h3 id="c-with-classes">C with Classes</h3> <blockquote> <p>&ldquo;But C++ is just C with classes!&rdquo;</p></blockquote> <p><strong>No</strong>, it isn&rsquo;t. Anyone who says this obviously has never worked with C++. C++ has completely different standard libraries, implementations, and standards than C. It is true that when C++ was first made it was just C with classes<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, that has long been false ever since C++ has implemented features separate from C.</p> <h3 id="incompatibility">Incompatibility</h3> <h4 id="void-pointers">Void Pointers</h4> <p>One such case where C++ is incompatible with C is with void pointers. For example, this program will compile with a C compiler (like GCC), but it will not compile with a C++ compiler (like G++):</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e"> </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>() { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>a <span style="color:#f92672">=</span> <span style="color:#a6e22e">malloc</span>(<span style="color:#ae81ff">5</span>); </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>; </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>All this code does is allocate 5 bytes to an integer pointer <code>a</code>. This program works perfectly fine when compiled with GCC, but if I compile this program with G++ this error is returned:</p> <pre tabindex="0"><code>main.c: In function &#39;int main()&#39;: main.c:4:24: error: invalid conversion from &#39;void*&#39; to &#39;int*&#39; [-fpermissive] 4 | int *a = malloc(5); | ~~~~~~^~~ | | | void* </code></pre><p>The reason this happens is that <code>malloc</code> returns a void pointer and C++ cannot convert a void pointer into an integer pointer unless it is specifically cast to an integer pointer.</p> <h4 id="kr-syntax">K&amp;R Syntax</h4> <p>Another big incompatibility with C and C++ is that C++ is actually incompatible with <a href="https://en.wikipedia.org/wiki/C_(programming_language)#K&amp;R_C">K&amp;R</a> syntax. Given this example function formatted in K&amp;R syntax:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">gcd</span>(a, b) </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> a; </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> b; </span></span><span style="display:flex;"><span>{ </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (b <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>) </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> a; </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">gcd</span>(b, (a <span style="color:#f92672">%</span> b)); </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>It will compile perfectly fine for GCC (as expected), however G++ gives us <em>another</em> set of errors&hellip;</p> <pre tabindex="0"><code>gcd.c:3:9: error: &#39;a&#39; was not declared in this scope 3 | int gcd(a, b) | ^ gcd.c:3:12: error: &#39;b&#39; was not declared in this scope 3 | int gcd(a, b) | ^ gcd.c:3:13: error: expression list treated as compound expression in initializer [-fpermissive] 3 | int gcd(a, b) | ^ gcd.c:6:1: error: expected unqualified-id before &#39;{&#39; token 6 | { | ^ </code></pre><p>This makes it almost impossible to use K&amp;R syntax with C++ unless you format your function arguments according to <a href="https://gist.github.com/nicholatian/2d9514feaf9a95e7561a433ac404b141">ANSI C</a>. (I know not many people care about K&amp;R syntax, but I think that it is still an important difference).</p> <p>There are also many other things in C that will not transfer over to C++ like complex numbers, default return types, and more, but I think you already get the picture by now. These incompatibilities are not anything that would break the entire C language if used in conjunction with C++, but these small differences slowly add up.</p> <h3 id="hard-for-beginners">Hard for Beginners</h3> <p>Not differentiating between C and C++ also has the side effect of ostracizing new users. Many beginner programmers are lead by the term &ldquo;C/C++&rdquo; to think that they&rsquo;re basically the same language. In fact there are <a href="https://medium.com/@yekayama/stop-making-c-c-tutorials-2fa9bc114488">many</a> tutorials out there that are advertised as &ldquo;C/C++ tutorials&rdquo;, continuing the confusion. This can also scare away C beginners by making them think that understanding the complexities of C++ are required to understand C (<em>SPOILER</em>: They&rsquo;re not). I have fallen for this trap in the past, as well as many others. C is honestly a very simple programming language, C++ is not.</p> <h2 id="c-and-c-programmers-are-very-different">C and C++ Programmers are VERY Different</h2> <p>With the new C++ standards given throughout the years like C++11, C++20, and etc. C++ programmers have been given more tools and functions that don&rsquo;t exist in standard C. This usually results in modern C programs having more lines of code than modern C++, however this means that modern C is usually more readable than modern C++. Here is an example question from <a href="https://leetcode.com/problems/maximum-count-of-positive-integer-and-negative-integer/">LeetCode</a>. Solutions differ, but most C solutions look something like this:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">maximumCount</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>nums, <span style="color:#66d9ef">int</span> numsSize) { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> pos <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, neg <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> numsSize; i<span style="color:#f92672">++</span>) { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (nums[i] <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>) pos<span style="color:#f92672">++</span>; </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span> (nums[i] <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0</span>) neg <span style="color:#f92672">++</span>; </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> pos <span style="color:#f92672">&gt;</span> neg <span style="color:#f92672">?</span> pos : neg; </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>Even though this code is pretty compact for C standards it is still <em>very</em> readable. Now for the C++ solutions, there are a lot of variations to this solution so I will use one that&rsquo;s different <em>enough</em> from C.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">maximumCount</span>(std<span style="color:#f92672">::</span>vector<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">int</span><span style="color:#f92672">&gt;</span> nums) { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> [a, b] <span style="color:#f92672">=</span> std<span style="color:#f92672">::</span>equal_range(nums.begin(), nums.end(), <span style="color:#ae81ff">0</span>); </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> std<span style="color:#f92672">::</span>max(std<span style="color:#f92672">::</span>distance(nums.begin(), a), std<span style="color:#f92672">::</span>distance(b, nums.end())); </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>This uses <code>vector</code> and <code>algorithm</code> from the C++ standard library<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>. As you can see this code is <em>much</em> more compact but is definitely not as readable as the C code. Although the C solution can be compiled by a C++ compiler I wanted to highlight just how different they can be from each other. This is but one example of how C and C++ programmers have slowly separated when it comes to programming.</p> <h3 id="many-c-programmers-wont-touch-c">Many C Programmers Won&rsquo;t Touch C++</h3> <p>I&rsquo;m pretty sure everyone knows the C programmer stereotype by now, the only thing is that it is <strong>TRUE</strong>. Lots of <a href="https://suckless.org/">Suckless</a> users and developers only use C and POSIX shell in their programs. <a href="https://harmful.cat-v.org/software/c++/">Cat-v</a> endorses C and C-like languages, but despises C++. Even <a href="https://lore.kernel.org/all/alpine.LFD.0.999.0709061839510.5626@evo.linux-foundation.org/">Linus Torvalds</a>, the creator Linux and Git, won&rsquo;t touch C++. Heck, even I love C but I can&rsquo;t stand programming in C++.</p> <p>This is probably the biggest reason why employers <strong>SHOULD NOT</strong> put C/C++ on job descriptions, especially if they&rsquo;re only looking for C developers. All they are doing is scaring away competent C developers.</p> <figure ><a href="https://brycev.com/p/cpp.webp"><img src="https://brycev.com/p/cpp.webp" id="smallimg" alt="Stop doing C&#43;&#43;!"></a></figure> <h2 id="the-solution">The Solution</h2> <p>If you&rsquo;re referring to a C program or programmer just say &ldquo;C&rdquo;. If you&rsquo;re referring to a C++ program or programmer just say &ldquo;C++&rdquo;. If you&rsquo;re referring to both used separately say something like:</p> <ul> <li>C and C++</li> <li>C, C++</li> <li>C++ with C</li> <li>Etc.</li> </ul> <p><strong>NOT C/C++</strong></p> <p>Only if you&rsquo;re using C <em>together</em> with C++ would it be acceptable to say C/C++.</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>Please note that although these are real concerns with C and C++, this is more of a rant than anything else (and somewhat satire).&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:2"> <p>Fun fact: C++ <em>was</em> actually called <a href="https://www.stroustrup.com/bs_faq.html#invention">&ldquo;C with Classes&rdquo;</a> before it was initially released.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> <li id="fn:3"> <p>Credit to <a href="https://youtu.be/U6I-Kwj-AvY">code_report</a> for these two solutions.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> I Finally Have a VPS https://brycev.com/blog/i-finally-have-a-vps/ Sun, 12 Mar 2023 00:00:00 +0000 https://brycev.com/blog/i-finally-have-a-vps/ <p>After a little less than a year of waiting, I finally obtained a VPS from <a href="https://my.frantech.ca/">Frantech/BuyVM</a>. I was told that they are an exceptional VPS provider, and it turns out to be <strong>true</strong>. Their pricing is extremely fair as I can get <em>double</em> what <a href="https://www.vultr.com/">Vultr</a> offers for the same exact price (plus unlimited bandwidth). Their support was also pretty fast so I was able to setup everything relatively quickly. My only complaint is that the number of servers is limited so it might take a while to actually get one. Despite Frantech <em>obviously</em> being better, Vultr is still a solid choice for a VPS and they make it very easy to setup one.</p> <p>I am now hosting my web page from my VPS instead of <a href="https://sourcehut.org/">Sourcehut</a> and I am hosting my email instead of using <a href="https://disroot.org">Disroot</a>. Keep in mind that these services (Sourcehut and Disroot<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>) are great services and I would 100% recommend them, however I believe that hosting everything yourself is better.</p> <p>That being said, I do have unlimited bandwidth and about 19GB of storage space that I still have yet to use. If any of you guys have ideas for what I should do (hosting internet radio, SearX instance, Mastodon instance, forum, etc.) you can let me know by email.</p> <p>If you would like a VPS for yourself, you can use the links above to get one from Frantech, if they&rsquo;re available. If not, Vultr is always a solid option for a VPS (although you do get less). <strong>Or</strong> you can use my referral links to get a VPS below. It&rsquo;s a nice and indirect way to support me.</p> <h3 id="referral-links">Referral Links</h3> <ul> <li><a href="https://my.frantech.ca/aff.php?aff=6418">Frantech/BuyVM</a></li> <li><a href="https://www.vultr.com/?ref=9386356">Vultr</a> (Normal affiliate link)</li> <li><a href="https://www.vultr.com/?ref=9386357-8H">Vultr</a> (<strong>Get $100</strong> to use for a VPS)</li> </ul> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>Disroot provides services like cloud storage, XMPP chat, paste bin, Git, and more. They&rsquo;re an amazing replacement for the Google suite.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> Odysee Channel https://brycev.com/blog/odysee-channel/ Wed, 08 Mar 2023 00:00:00 +0000 https://brycev.com/blog/odysee-channel/ <p>For those of you who don&rsquo;t already know, I recently synced my entire YouTube channel to <a href="https://odysee.com/@bryce:c">Odysee</a>. So for those of you who want to avoid YouTube and Google entirely that is now an option. I will continue to upload videos to YouTube but they will be automaticly synced to Odysee shortly after I upload them (usually takes about an hour). I don&rsquo;t plan on uploading exclusively onto Odysee, but I might post some videos that I normally wouldn&rsquo;t post onto YouTube for one reason or another, so keep an eye out. 🧑‍🚀</p> Updating My GPG Key https://brycev.com/blog/updating-my-gpg-key/ Sun, 15 Jan 2023 00:00:00 +0000 https://brycev.com/blog/updating-my-gpg-key/ <p>I have updated my GPG key. I will <strong>not</strong> be able to read any new encrypted emails that use my old GPG key.</p> <p>You can find my new GPG key <a href="https://brycevandegrift.xyz/bpv.gpg">here</a> or import it directly by running:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>curl -fL <span style="color:#e6db74">&#34;https://brycevandegrift.xyz/bpv.gpg&#34;</span> | gpg --import </span></span></code></pre></div> Why I Am Switching to Firefox https://brycev.com/blog/why-i-am-switching-to-firefox/ Thu, 05 Jan 2023 00:00:00 +0000 https://brycev.com/blog/why-i-am-switching-to-firefox/ <p>For the past year I have used <a href="https://qutebrowser.org/">Qutebrowser</a> almost exclusively as my main web browser. I even made a video on how extensible and great it is <a href="https://youtu.be/N79au5Xq65s">here</a>. However there have been a few glaring issues with it over other browsers like Firefox that I have noticed over the past year. Although Qutebrowser is a great web browser, I think that these issues are too important for me to ignore.</p> <p>Now before I start bashing Qutebrowser on where it falls short of my expectations, I should rightfully praise it for what it does right compared to other web browsers. Qutebrowser does have a lot of cool and innovative features that most web browsers wouldn&rsquo;t even think about implementing.</p> <h2 id="what-qutebrowser-does-right">What Qutebrowser does right</h2> <h3 id="keybindings-and-ui">Keybindings and UI</h3> <p>Unlike most browsers, Qutebrowser has Vim keybindings by default. This means that every single action is bound to a specific key or combination of keys. This makes using and navigating in Qutebrower leagues faster than in other browsers like Firefox. There are extensions for Firefox that do allow you to use Vim keybindings, however they are not as tightly integrated into the browser as Qutebrowser. For Qutebrowser, <strong>every single action has a keybinding</strong>.</p> <p>The user interface for Qutebrowser (or possibly lake thereof), in my opinion, is very clean and nice to look at. Not only does it look nice, but it is also highly customizable so you can change it to suit your personal preference.</p> <h3 id="adblocking-by-default">AdBlocking by default</h3> <p>By default, Qutebrowser has simple hosts adblocking enabled. Even though there are far better adblocking solutions (uBlock Origin is the gold standard), Qutebrowser still earns some points for having some sort of adblocking enabled by default. Qutebrowser also has an adblocking mode simular to Brave Browser&rsquo;s adblocking mode if hosts adblocking isn&rsquo;t enough for you.</p> <h3 id="python">Python</h3> <figure ><a href="https://brycev.com/p/boomer-python.webp"><img src="https://brycev.com/p/boomer-python.webp" alt="Boomer stuff"></a></figure> <p>Now I know that using Python as a language for writing a big application has some serious drawbacks, however in the case of Qutebrowser, writing it in Python gives it some unique traits. For starters, writing Qutebrowser in Python makes it easier to customize and extend in numerous ways. Being able to program in my own keybindings, extra features, and more is (for a lack of a better word) <strong>awesome</strong>. Although there are better language choices than Python (for example Lua is a solid choice<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>) for what it is, having Qutebrowser written in Python comes with some great benefits</p> <h2 id="what-qutebrowser-does-wrong">What Qutebrowser does wrong</h2> <h3 id="bloated">Bloated</h3> <p>This point somewhat ties into the fact that Qutebrowser is written in Python, but Qutebrowser is anything but small or fast. Qutebrowser uses just about the same amount of resources on my computer as Firefox (which is considered a bloated browser) and still runs slower. It also takes up a lot more space on my system than Firefox as well. The executable for Qutebrowser isn&rsquo;t actually that big, however the dependices needed to run it take up more space than Firefox itself.</p> <h3 id="adblocking">Adblocking</h3> <p>Like I stated earlier, Qutebrowser has adblocking enabled by default, which is really nice, however I don&rsquo;t think that its builtin adblocker does enough. My standard for adblocking (as mentoned before) is uBlock Origin, and the adblocking options that Qutebrowser provides are not really too impressive. Compared to uBlock Origin, Qutebrowser&rsquo;s adblockers don&rsquo;t nearly do as much.</p> <h3 id="python-1">Python</h3> <p>Didn&rsquo;t I just say that writing Qutebrowser in Python was a good thing? Well&hellip;yes, but actually no. Python does provide Qutebrowser with an easy language to write the program in as well as configure and extend the program in, but the biggest downside of writing a browser in Python is speed. Qutebrowser, being written in Python, is just a little less resource intensive than Firefox on my system, however it is about half as fast. This compromise in performance is expected for a program written in Python and for a browser, performance is pretty important.</p> <h2 id="why-firefox">Why Firefox?</h2> <p>Firefox is the only web browser that is free software and also mitigates all of the problems I have discussed. Even though Firefox is still a bit bloated, it does fix adblocking (with uBlock Origin) and it is written in a more sane programming language. Firefox does not come with adblocking or keybindings by default like Qutebrowser, but they can be added in with extensions like the aforementioned <a href="https://ublockorigin.com/">uBlock Origin</a> or <a href="https://tridactyl.xyz/">Tridactyl</a>. It is sometimes a pain to change the default settings for Firefox since a lot of useless and harmful things are enabled by default like telemetry, Pocket, Firefox Accounts, and more. After all of that is said and done, Firefox is actually a pretty good web browser.</p> <p>Although Firefox is bloated, sometimes you need a bloated browser for the bloated internet.</p> <div class="footnotes" role="doc-endnotes"> <hr> <ol> <li id="fn:1"> <p>There is actually a web browser written in Lua called <a href="https://luakit.github.io/">LuaKit</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p> </li> </ol> </div> Rust in the Linux Kernel https://brycev.com/blog/rust-in-the-linux-kernel/ Tue, 25 Oct 2022 00:00:00 +0000 https://brycev.com/blog/rust-in-the-linux-kernel/ <p>I know, I know, everyone is talking about support for the <a href="https://www.rust-lang.org/">Rust</a> programming language being <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8aebac82933ff1a7c8eede18cab11e1115e2062b">added to the Linux kernel</a>, and I&rsquo;m no exception. This event is <strong>HUGE</strong> when it comes to Linux kernel development. Since the Linux kernel is predominantly written in C and has been that way for about the last 30 years, this comes as a very big surprise. I honestly would have expected C++ to be integrated in the Linux kernel if it weren&rsquo;t for Linus Torvald&rsquo;s <a href="https://lore.kernel.org/all/alpine.LFD.0.999.0709061839510.5626@evo.linux-foundation.org/">hatred for C++</a> (granted, I dislike C++ as well).</p> <p>Now I&rsquo;m not here to praise Rust as some sort of gift to the Linux kernel, nor am I here to talk horribly about it and say that it has no use in the Linux kernel whatsoever, because it does have a use. I am here to take a look at what Rust does and doesn&rsquo;t do good and see if that lines up with the needs of the Linux kernel.</p> <h2 id="speedperformance">Speed/Performance</h2> <p>The average speed of programs written in Rust is about on par with programs written in C from what I&rsquo;ve seen. You can look at some of the benchmarks <a href="https://programming-language-benchmarks.vercel.app/c-vs-rust">here</a>, but I also have a quick and simple one that I whipped up. This example uses a very lazy and inefficient version of the Fibonacci algorithm that I used a while ago in my <a href="https://brycevandegrift.xyz/blog/the-importance-of-lisp/#recursion">lisp article</a>.</p> <p>Now I&rsquo;m no expert programmer so don&rsquo;t complain if I didn&rsquo;t write either of these programs &ldquo;correctly&rdquo;, it&rsquo;s just a simple benchmark</p> <p><a href="https://brycevandegrift.xyz/hardware/">Machine specs</a></p> <p>Implemented in C:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdio.h&gt;</span><span style="color:#75715e"> </span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;stdlib.h&gt;</span><span style="color:#75715e"> </span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">int32_t</span> <span style="color:#a6e22e">fib</span>(<span style="color:#66d9ef">int32_t</span> num) { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (num <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">1</span>) { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> num; </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">fib</span>(num <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> <span style="color:#a6e22e">fib</span>(num <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>); </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>() { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int32_t</span> result <span style="color:#f92672">=</span> <span style="color:#a6e22e">fib</span>(<span style="color:#ae81ff">45</span>); </span></span><span style="display:flex;"><span> <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;%d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, result); </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>; </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>Implemented in Rust:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">fib</span>(num: <span style="color:#66d9ef">i32</span>) -&gt; <span style="color:#66d9ef">i32</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> num <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">1</span> { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> num; </span></span><span style="display:flex;"><span> } </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> fib(num <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> fib(num <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>); </span></span><span style="display:flex;"><span>} </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span><span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() { </span></span><span style="display:flex;"><span> <span style="color:#66d9ef">let</span> result:<span style="color:#66d9ef">i32</span> <span style="color:#f92672">=</span> fib(<span style="color:#ae81ff">45</span>); </span></span><span style="display:flex;"><span> <span style="color:#a6e22e">println!</span>(<span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#34;</span>, result); </span></span><span style="display:flex;"><span>} </span></span></code></pre></div><p>The average time for C compiled with GCC and <code>-O2</code> optimization was 3.30 seconds and Rust compiled with RustC and <code>-O2</code> as well was 4.32 seconds. C without optimizations was 9.31 seconds and Rust without optimizations was 12.69 seconds on average. So unoptimized Rust is a decent bit slower than C and optimized Rust is about a second behind C which is what I would expect. A bit of a performance hit is what I would expect for a language that focuses more on memory safety rather than pure speed.</p> <h2 id="size">Size</h2> <p>When it comes to size, Rust and C are both around the same as well. Although I sometimes do hear complaints about Rust&rsquo;s standard library being large, the Rust standard library probably isn&rsquo;t going to be included in the Linux kernel. Compiling a &ldquo;Hello, World!&rdquo; program in GCC with <code>-O2</code> is around 21KB normally and 15KB stripped. Compiling the same program in RustC with <code>-O2</code> results in a 21KB binary normally and a 14KB binary stripped (no standard library included). So Rust can actually end up with smaller binaries than C on some occasions, but in reality I would honestly expect the same size (if not slightly bigger) binary sizes for Rust for most cases.</p> <h2 id="compilerfrontend">Compiler/Frontend</h2> <p>The Rust compiler is probably one of Rust&rsquo;s biggest strengths compared to C. The Rust compiler is a very helpful tool for developers. There are other just as helpful tools that the creators of Rust provide separately like <a href="https://github.com/rust-lang/rustfmt">rustfmt</a> (like gofmt if you have used Go before), <a href="https://github.com/rust-lang/rust-clippy">Clippy</a>, and more. But the Rust compiler is probably one of the most straightforward and user friendly (in a mostly good way) compilers that I have ever seen. Just take a look at the difference between an error message in GCC v.s. an error message in RustC. The same mistake is being made in both languages.</p> <p>An error message from GCC:</p> <pre tabindex="0"><code>test.c: In function &#39;main&#39;: test.c:8:32: warning: passing argument 1 of &#39;sumOfSquares&#39; makes integer from pointer without a cast [-Wint-conversion] 8 | int32_t result = sumOfSquares(&#34;Number&#34;); | ^~~~~~~~ | | | char * test.c:3:30: note: expected &#39;int32_t&#39; {aka &#39;int&#39;} but argument is of type &#39;char *&#39; 3 | int32_t sumOfSquares(int32_t x, int32_t y) { | ~~~~~~~~^ test.c:8:19: error: too few arguments to function &#39;sumOfSquares&#39; 8 | int32_t result = sumOfSquares(&#34;Number&#34;); | ^~~~~~~~~~~~ test.c:3:9: note: declared here 3 | int32_t sumOfSquares(int32_t x, int32_t y) { | ^~~~~~~~~~~~ </code></pre><p>An error message from RustC:</p> <pre tabindex="0"><code>error[E0061]: this function takes 2 arguments but 1 argument was supplied --&gt; test.rs:6:19 | 6 | let _result = sum_of_squares(&#34;Number&#34;); | ^^^^^^^^^^^^^^---------- | || | |expected `i32`, found `&amp;str` | an argument of type `i32` is missing | note: function defined here --&gt; test.rs:1:4 | 1 | fn sum_of_squares(x: i32, y: i32) -&gt; i32 { | ^^^^^^^^^^^^^^ ------ ------ help: provide the argument | 6 | let _result = sum_of_squares(/* i32 */, /* i32 */); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error For more information about this error, try `rustc --explain E0061`. </code></pre><p>These error messages may look similar, but in my opinion the error/warning messages from RustC are just a bit more clear than the messages from GCC and definitely a lot clearer than other compilers.</p> <p>When it comes to the Rust frontend, LLVM, I don&rsquo;t really mind it as a frontend. For the Linux kernel, I think that GCC would be a better frontend for Rust to use and there is work being done on just <a href="https://github.com/Rust-GCC/gccrs">that</a>. But many languages use like <a href="https://dlang.org/">D</a> (<a href="https://github.com/ldc-developers/ldc">LDC</a>), newer versions of <a href="https://www.haskell.org/">Haskell</a>, <a href="https://ziglang.org/">Zig</a>, and many other languages use LLVM and they generate pretty good results most of the time. Is it the most ideal frontend when working with the Linux kernel, probably not, but is it the worst? Definitely not.</p> <h2 id="memory-safety">Memory Safety</h2> <p>What everyone knows Rust for, it&rsquo;s memory safety. The biggest tool that Rust has at it&rsquo;s disposal to try to guarantee memory safety is the borrow checker. For those of you who don&rsquo;t know what the borrow checker is, the borrow checker assigns memory to a variable known as an owner. Once the owner of a piece of data is out of scope, it deallocates the memory. You can also &ldquo;borrow&rdquo; the memory (hence the name &ldquo;borrow checker), but I won&rsquo;t go too into detail, since there are plenty of better explaniations of Rust&rsquo;s borrow checker. Just keep in mind that the borrow checker is very important for memory safety.</p> <p>I think that memory safety is Rust&rsquo;s biggest and most important contribution to the Linux kernel. Memory safety can eliminate a lot if not the majority of bugs out there in the wild and I think that the Linux kernel is no exception. If used correctly, I think that Rust&rsquo;s memory safety could make the Linux kernel even more robust than it already is with little to no sacrifices.</p> <h2 id="conclusion">Conclusion</h2> <p>Overall, I think that the inclusion of Rust in the Linux kernel isn&rsquo;t too bad of a decision. Don&rsquo;t get me wrong, there are some bad or not fully fleshed out parts to the language, but otherwise it&rsquo;s pretty solid. Now I&rsquo;m no expert programmer in either C or Rust, but I think that there could be a very good balance within the Linux kernel if Rust is used correctly.</p> <p>That being said, I&rsquo;m personally still not sold on Rust&rsquo;s inclusion into the Linux kernel. Despite the advantages of memory safety and a better compiler there are still lots of parts of Rust that are not fully fleshed out and could cause various problems for the Linux kernel. Although I think that Rust is the best choice of any language out there to add to the Linux kernel, I personally don&rsquo;t think that another language needs to be added to the Linux kernel. I guess all that I can do is wait and see if this addition to the Linux kernel is a good one or not.</p> The Importance of Lisp https://brycev.com/blog/the-importance-of-lisp/ Tue, 13 Sep 2022 00:00:00 +0000 https://brycev.com/blog/the-importance-of-lisp/ <p>Lisp (also known as LISP) is a family of programming languages that have had a significant impact on the world of computing. Lisp has had and still has a great influence on the evolution of programming languages and computing theory as a whole. It remains a very easy language to learn and not that hard to master.</p> <p>For those of you who don&rsquo;t know what Lisp is, Lisp stands for &ldquo;LISt Processor&rdquo;. A Lisp program is made up of at least of at least one &ldquo;list&rdquo; which is indicated by an expression surrounded by parentheses. So for example, if you wanted to multiply 2 and 4, you would give an expression like this to a Lisp interpreter or compiler:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(* <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">4</span>) <span style="color:#75715e">; Results in 8</span> </span></span></code></pre></div><p>The Lisp interpreter or compiler evaluates the contents of the list to produce a result. The first element of the list is the operator being used, in this case its multiplication (<code>*</code>). Any other items in the list are arguments given to the operator, in this case <code>2</code> and <code>4</code>. If you are familiar with Polish Notation or Prefix Notation then this may look very similar, the only difference being the addition of parentheses to enclose the expression.</p> <p>We can easily create compound expressions by just putting lists inside of lists like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(- <span style="color:#ae81ff">10</span> (/ <span style="color:#ae81ff">4</span> <span style="color:#ae81ff">2</span>)) <span style="color:#75715e">; Equivalent to 10 - (4 / 2)</span> </span></span><span style="display:flex;"><span>(+ (* <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">2</span>) (* <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">5</span>)) <span style="color:#75715e">; Equivalent to (2 * 2) + (2 * 5)</span> </span></span></code></pre></div><p>It takes a bit of getting used to, but Lisp&rsquo;s notation makes it very easy to string together compound expressions.</p> <h2 id="practical-lisp">Practical Lisp</h2> <p>Nowadays there are two different major dialects of Lisp, <strong>Common Lisp</strong> and <strong>Scheme</strong>. There are not that many differences between Common Lisp and Scheme so I will use the Scheme dialect in the rest of these examples since I am familiar with it.</p> <p>If we want to, we can define custom operators, functions, or variables just like in any other programming language. To do so in Scheme we use the <code>define</code> keyword:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(<span style="color:#66d9ef">define </span>x <span style="color:#ae81ff">24</span>) <span style="color:#75715e">; Define the variable x as 24</span> </span></span><span style="display:flex;"><span>(<span style="color:#66d9ef">define </span>mult *) <span style="color:#75715e">; Define the operator mult as multiplication</span> </span></span><span style="display:flex;"><span>(<span style="color:#66d9ef">define </span>(<span style="color:#a6e22e">circum</span> radius) (* <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">3.14</span> radius)) <span style="color:#75715e">; Define circumference as 2 * π * radius</span> </span></span></code></pre></div><p>You may have noticed that we defined all three of these with the same <code>define</code> keyword, so what makes a variable different from a function? Nothing really. The great thing about Lisp is that almost everything defined under a <code>define</code> statement is treated the same. This means that almost anything we can do with variables we can do with functions and vice versa. So, for example, we can create a function like this:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(<span style="color:#66d9ef">define </span>(<span style="color:#a6e22e">applyFunc</span> func arg1 arg2) (<span style="color:#a6e22e">func</span> arg1 arg2)) </span></span></code></pre></div><p>This function, <code>applyFunc</code>, takes three arguments: a function and two arguments for the given function. It then applies the two arguments to the given function and spits out a result. We can test our <code>applyFunc</code> function like so:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(<span style="color:#66d9ef">define </span>(<span style="color:#a6e22e">sum-of-squares</span> x y) (+ (* x x) (* y y))) <span style="color:#75715e">; Same as x^2 + y^2</span> </span></span><span style="display:flex;"><span>(<span style="color:#a6e22e">applyFunc</span> sum-of-squares <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">4</span>) </span></span></code></pre></div><p>Now this may look fairly useless at the moment because we can just call <code>sum-of-squares</code> directly and pass it arguments manually. However, being able to pass functions as arguments opens a whole new world of possibilities when it comes to programming.</p> <h2 id="higher-order-functions">Higher-Order Functions</h2> <p>This brings us to an important topic, anonymous functions using the <code>lambda</code> keyword. The <code>lambda</code> keyword creates a one-time use function, this can be very useful for passing to another function as an argument. As an example we can use a lambda function with our <code>applyFunc</code> function.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(<span style="color:#a6e22e">applyFunc</span> (<span style="color:#66d9ef">lambda </span>(<span style="color:#a6e22e">x</span> y) (* x y)) <span style="color:#ae81ff">2</span> <span style="color:#ae81ff">4</span>) <span style="color:#75715e">; Same a 2 * 4</span> </span></span></code></pre></div><p>The example above creates a one-time use function <code>(lambda (x y) (* x y))</code> and passes it to <code>applyFunc</code> with the arguments <code>2</code> and <code>4</code>. Although the result isn&rsquo;t that spectacular, the implications of lambda functions opens up a whole new world of possibilities for programming that only exist in functional languages like Lisp. Functions that take functions or return functions are called <code>higher-order functions</code>.</p> <p>Lisp was one of, if not the first language to implement higher-order functions in a programming language. Other high-level programming languages like Lua, Python, Haskell, and more followed suit much later.</p> <h2 id="recursion">Recursion</h2> <p>Another important concept pioneered by Lisp in the world of programming is recursion. A function is a recursive function when it calls itself, pretty simple. Almost all recursive functions also have a base-case or exit clause in order to stop recurring, otherwise they run forever. If you still don&rsquo;t understand recursion then read this sentence again. ;)</p> <p>As an example, let&rsquo;s translate the equation for Fibonacci numbers into a Lisp expression. The mathematical definition is a follows:</p> <figure ><img src="https://brycev.com/p/fib.webp" title="Recursive Fibonacci Equation" alt="Fibonacci Equation"></figure> <p>A translation from mathematical notation into Lisp would look like this:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scheme" data-lang="scheme"><span style="display:flex;"><span>(<span style="color:#66d9ef">define </span>(<span style="color:#a6e22e">fib</span> n) <span style="color:#75715e">; Begin function</span> </span></span><span style="display:flex;"><span>(<span style="color:#66d9ef">if </span>(&lt;= n <span style="color:#ae81ff">1</span>) n <span style="color:#75715e">; If n &lt;= 1 then return n</span> </span></span><span style="display:flex;"><span>(+ (<span style="color:#a6e22e">fib</span> (- n <span style="color:#ae81ff">1</span>)) (<span style="color:#a6e22e">fib</span> (- n <span style="color:#ae81ff">2</span>))))) <span style="color:#75715e">; Else return fib(n-1) + fib(n-2)</span> </span></span></code></pre></div><p>As you can see, the <code>fib</code> function defined above calls itself until it meets the base requirements to end the recursive loop. Recursion makes it stupidly easy to translate recursive mathematical functions to Lisp expressions. Just like higher-order functions, Lisp was one of the first programming languages to implement this and other languages followed afterwards.</p> <h2 id="hold-up">Hold Up</h2> <p>Now, before you go out and write your next project in Lisp, you should keep something in mind. Lisp is <strong>not</strong> the fastest or smallest language out there, it was not designed to be so. There are some pretty good implementations of Lisp out in the wild, but don&rsquo;t expect them to outperform C, Go, Lua, or even Python most of the time.</p> <p>If you&rsquo;re going to program something in Lisp you should keep these things in mind:</p> <ul> <li>How important is execution speed?</li> <li>How important is program/runtime size?</li> <li>How important is portability?</li> </ul> <p>If you value any three of these too much, then you might not want to write your program in Lisp. You probably don&rsquo;t want to write a program that only takes up a few kilobytes in Lisp, nor would you want to write a program that needs millisecond speed either. However for all other needs Lisp works perfectly fine if not exceptionally great!</p> <p>But this brings us back to the importance of Lisp altogether. Most people look at Lisp and see a language that innovated countless things in the field of programming languages, but eventually got replaced by newer languages. But Lisp as a language is still very much alive and making improvements and innovations to this day. It is still a very good programming language for tackling many tasks and remains one of my favorite programming languages.</p> <figure ><a href="https://brycev.com/p/lisp.webp"><img src="https://brycev.com/p/lisp.webp" alt="LISP machine"></a></figure> Switching to Hugo https://brycev.com/blog/switching-to-hugo/ Sat, 10 Sep 2022 00:00:00 +0000 https://brycev.com/blog/switching-to-hugo/ <p>Over the last couple of days I have been migrating my blog from using a markdown/Pandoc blog system to using <a href="https://gohugo.io/">Hugo</a> for my entire website.</p> <p>For those of you who don&rsquo;t know what Hugo is, Hugo is a static site generator that is written in <a href="https://go.dev/">Go</a>. It takes plain markdown and converts it to plain HTML and CSS just like Pandoc. The biggest difference it has from Pandoc is that Hugo is written specifically for creating static sites. To put it bluntly, Hugo does one thing, and it does it well.</p> <p>I might make a video on Hugo on some point as there&rsquo;s actually a lot of depth to it and it&rsquo;s very customizable and extensible. But despite having a lot of depth to it, Hugo generates relatively small and fast static webpages. It&rsquo;s honestly a very good static site generator and I will be using it over my markdown/Pandoc blog system from now on.</p> Changing My Website Host https://brycev.com/blog/changing-my-website-host/ Sun, 26 Jun 2022 00:00:00 +0000 https://brycev.com/blog/changing-my-website-host/ <p>For the longest time I have used <a href="https://www.infinityfree.net/">Infinity Free</a> as the host for my website since it has free website hosting. However, I haven’t been able to successfully set up a SSL certificate without using Cloudflare. Cloudflare has not had a good reputation and, in my opinion, <a href="https://www.unixsheikh.com/articles/stay-away-from-cloudflare.html">cannot be trusted</a> <a href="https://www.devever.net/~hl/cloudflare">at all</a>.</p> <h2 id="1-sourcehut">1. <a href="https://sourcehut.org/">Sourcehut</a></h2> <p>Sourcehut provides static website hosting, git repository hosting, gemini hosting (sadly no gopher hosting) and many other things. The upside of using Sourcehut versus a lot of other platforms for hosting my website is that they use only free and open source software for hosting.</p> <p>Hosted websites are automatically outfitted with SSL certificates which reduces the hassle (and they don’t use Cloudflare). My git repositories are also hosted at Sourcehut so it would make sense to move my website there. Sourcehut also provides paste bins, mailing lists, wikis, and more useful tools.</p> <p>One caveat is that, even though service is currently 100% free (as in free beer), once Sourcehut is out of alpha, there will probably be a price tag associated with all the services (although, right now the price doesn&rsquo;t look that bad.)</p> <h2 id="2-get-a-vps">2. Get a VPS</h2> <p>This may be my best option in the long run as it’s the closest thing to self hosting that I can get. I can host my website, git repositories, as well as almost anything else that I like including chat servers, forums, email, and etc.</p> <p>The biggest downside of this is the price, which can vary from a couple dozen dollars a year to a few <strong>hundred</strong> dollars a year.</p> <h2 id="3-move-to-some-other-3rd-party-static-site-host">3. Move to some other 3rd party static site host</h2> <p>I’m probably more likely to self host my website before I resort to hosting it using <em>another</em> not well known 3rd party service. My trust in most 3rd party hosts is slowly dwindling as the years go by.</p> <h2 id="the-verdict">The verdict</h2> <p>I currently plan to move my website to Sourcehut hosting for the time being, however I plan to eventually self host everything I need and become self reliant. I also might move my website to a more elegant static site generator as writing and managing everything from scratch is starting to make everything a bit more cumbersome.</p> Corebooting a Thinkpad X220 https://brycev.com/blog/corebooting-a-thinkpad-x220/ Tue, 31 May 2022 00:00:00 +0000 https://brycev.com/blog/corebooting-a-thinkpad-x220/ <figure ><img src="https://brycev.com/p/thinkpad.webp" alt="My Thinkpad X220"><figcaption>My Thinkpad X220</figcaption></figure> <h2 id="you-need">You Need</h2> <ul> <li>A Thinkpad X220</li> <li>A Raspberry Pi</li> <li>Female to female jumper wires</li> <li>SOIC8 test clip</li> <li>Another computer</li> </ul> <h2 id="disassembly">Disassembly</h2> <p>For disassembly you can watch my video <a href="https://www.youtube.com/watch?v=hERguULT7Vo">here</a>.</p> <p>But you’ll just have to remove all the screws with the keyboard icon and all the screws with the box(ish) icon. (Like I said, you can watch the video).</p> <h2 id="attaching-the-clip-to-the-bios-chip">Attaching the clip to the BIOS chip</h2> <p>In order to actually read/write to the BIOS chip you need to attach the SOIC8 clip to the bios chip.</p> <h3 id="x220-bios-pinout">X220 BIOS pinout</h3> <pre tabindex="0"><code> ______ MOSI 5 --| |-- 4 GND CLK 6 --| BIOS |-- 3 No Connection No Connection 7 --| |-- 2 MISO VCC (3.3V) 8 --|______|-- 1 CS </code></pre><h3 id="raspberry-pi-pinout">Raspberry Pi pinout</h3> <pre tabindex="0"><code> CS GND 2 | | 40 +-----------------------v-----v-----------+ | x x x x x x x x x x x x x x x x x x x x | | x x x x x x x x x x x x x x x x x x x x | +-----------------^-^-^-^-----------------+ 1 | | | | 39 VCC | | CLK MOSI/ \MISO </code></pre><h2 id="setting-up-the-raspberry-pi">Setting up the Raspberry Pi</h2> <p>Make sure to update your Raspberry PI and install and the needed packages as well as flashrom using these commands:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt-get update <span style="color:#f92672">&amp;&amp;</span> sudo apt-get upgrade </span></span><span style="display:flex;"><span>sudo apt-get install build-essential pciutils usbutils libpci-dev libusb-dev libftdi1 libftdi-dev zlib1g-dev </span></span><span style="display:flex;"><span>git clone https://review.coreboot.org/flashrom.git </span></span><span style="display:flex;"><span>cd flashrom </span></span><span style="display:flex;"><span>make -j3 <span style="color:#f92672">&amp;&amp;</span> sudo make install </span></span></code></pre></div><p>Now we need to download the Coreboot repo on our Raspberry PI.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git clone --recursive https://review.coreboot.org/coreboot.git ~/coreboot </span></span></code></pre></div><p>Next we need to install ifdtool on the Raspberry PI, you can do that by running:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>cd ~/coreboot/util/ifdtool </span></span><span style="display:flex;"><span>make -j3 <span style="color:#f92672">&amp;&amp;</span> sudo make install </span></span></code></pre></div><h2 id="reading-the-bios">Reading the BIOS</h2> <p>First, we are going to create an alias so we don’t need to type in a long drawn out command every time we want to read/write to the BIOS.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>alias fr<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;sudo flashrom -p linux_spi:dev=/dev/spidev0.0,spispeed=1024&#39;</span> </span></span></code></pre></div><p>Now we can get the name of our BIOS chip by just running <code>fr</code>.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>fr </span></span></code></pre></div><p>The output should give you multiple chip names. All of these are the same chip just with different names so you can use any of them, mine is “MX25L6405”. We are going to use this to set a <code>CHIP</code> variable.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>CHIP<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;MX25L6405&#34;</span> </span></span></code></pre></div><p>We are now ready to read the flash from the BIOS chip. We are going to do this a few times in order to make sure that the connection is consistent when reading and writing.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -r flash01.bin </span></span><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -r flash02.bin </span></span><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -r flash03.bin </span></span><span style="display:flex;"><span>md5sum flash01.bin flash02.bin flash03.bin </span></span></code></pre></div><p>The output for <code>md5sum</code> for all three of the files should be exactly the same. If the checksum for all three files are not the same then <strong>DO NOT CONTINUE!!!</strong> Make sure that your connection is good and retry until everything reads correctly. (If necessary, the spispeed can be lowered from 1024 for a more reliable read).</p> <h2 id="optional-removing-the-management-engine">(Optional) Removing the management engine</h2> <p>First we need to download me_cleaner.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git clone https://github.com/corna/me_cleaner ~/me_cleaner </span></span></code></pre></div><p>Now we can run me_cleaner on our flash file, in this case I will be using <code>flash01.bin</code>.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>~/me_cleaner/me_cleaner.py -S flash01.bin </span></span></code></pre></div><p>If all goes well you should see a message that says: <code>Done! Good Luck!</code></p> <h2 id="separating-the-image">Separating the image</h2> <p>Now we can run ifdtool on our flash image in order to separate it.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>ifdtool -x flash01.bin </span></span></code></pre></div><p>You should now have four different <code>.bin</code> files: 1. <code>flashregion_0_flashdescriptor.bin</code> 2. <code>flashregion_1_bios.bin</code> (Not needed) 3. <code>flashregion_2_intel_me.bin</code> 4. <code>flashregion_3_gbe.bin</code></p> <p>We can now rename all the files to have a shorter name.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mv flashregion_0_descriptor.bin descriptor.bin </span></span><span style="display:flex;"><span>mv flashregion_2_intel_me.bin me.bin </span></span><span style="display:flex;"><span>mv flashregion_3_gbe.bin gbe.bin </span></span></code></pre></div><h2 id="setting-up-coreboot">Setting up Coreboot</h2> <p>If you want to compile Coreboot on your Raspberry PI you can go ahead, however it might take anywhere from a few hours to a few <strong>DAYS</strong>, so be warned. I copied my “.bin” files to my laptop in order to compile faster.</p> <p>Now we want to download the Coreboot repo onto our computer that we are compiling Coreboot on. (This may take a while). (If you are compiling Coreboot on your Raspberry PI you can skip this).</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git clone --recursive https://review.coreboot.org/coreboot.git ~/coreboot </span></span></code></pre></div><blockquote> <h2 id="optional-downloading-vga-bios">(Optional) Downloading VGA BIOS</h2> <p>Windows and some Linux distributions rely on the VGA BIOS in order to display video. So you can optionally download it if you need it.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>curl -fLO <span style="color:#e6db74">&#34;https://github.com/thetarkus/x220-coreboot-guide/raw/master/vga-8086-0126.bin&#34;</span> </span></span></code></pre></div></blockquote> <p>Now we need to make a directory to place our “.bin” files.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mkdir -p ~/coreboot/3rdparty/blobs/mainboard/lenovo/x220 </span></span><span style="display:flex;"><span>mv descriptor.bin ~/coreboot/3rdparty/blobs/mainboard/lenovo/x220/ </span></span><span style="display:flex;"><span>mv me.bin ~/coreboot/3rdparty/blobs/mainboard/lenovo/x220/ </span></span><span style="display:flex;"><span>mv gbe.bin ~/coreboot/3rdparty/blobs/mainboard/lenovo/x220/ </span></span></code></pre></div><h2 id="configuring-coreboot">Configuring Coreboot</h2> <p>On the computer you’re compiling Coreboot with, you’ll need to install these development packages (or their equivalents). On Ubuntu, Debian, or any derivative you can run:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt-get install git build-essential gnat flex bison libncurses5-dev wget zlib1g-dev </span></span></code></pre></div><p>On Void Linux (what I use) I ran:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo xbps-install git base-devel ncurses-devel wget zlib-devel gcc-ada </span></span></code></pre></div><p>Now we can go into the Coreboot directory and run make <code>nconfig</code>.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>cd ~/coreboot </span></span><span style="display:flex;"><span>make nconfig </span></span></code></pre></div><p>You should see a menu pop up, now we can configure our Coreboot build. Below is a list of what needs to be enabled, you can leave the rest of the settings just the way they are.</p> <pre tabindex="0"><code>General Setup - [*] Compress ramstage with LZMA - [*] Include coreboot .config file into the ROM image - [*] Allow use of binary-only repository Mainboard - Mainboard vendor (Lenovo) - Mainboard model (Thinkpad X220) - ROM chip size (8192 KB (8 MB)) - (0x100000) Size of CBFS filesystem in ROM Chipset - [*] Enable VMX for virtualization - Include CPU microcode in CBFS (Generate from tree) - Flash ROM locking on S3 resume (Don&#39;t lock ROM sections on S3 resume) - [*] Add Intel descriptor.bin file (3rdparty/blobs/mainboard/$(MAINBOARDDIR)/descriptor.bin) Path and filename of the descriptor.bin file - [*] Add Intel ME/TXE firmware (3rdparty/blobs/mainboard/$(MAINBOARDDIR)/me.bin) Path to management engine firmware - [*] Add gigabit ethernet firmware (3rdparty/blobs/mainboard/$(MAINBOARDDIR)/gbe.bin) Path to gigabit ethernet firmware Devices - Graphics initialization (Run VGA Option ROMs) - [*] Use native graphics initialization - [*] Add a VGA BIOS image (/home/$USER/vga-8086-0126.bin) VGA BIOS path and filename (8086,0126) VGA device PCI IDs Generic Drivers - [*] PS/2 keyboard init - [*] Support Intel PCI-e WiFi adapters Console - [*] Squelch AP CPUs from early console. - [*] Show POST codes on the debug console System tables - [*] Generate SMBIOS tables Payload - Add a payload (SeaBIOS) - SeaBIOS version (master) - (3000) PS/2 keyboard controller initialization timeout (milliseconds) - [*] Harware init during option ROM execution - [*] Include generated option rom that implements legacy VGA BIOS compatibility - [*] Use LZMA compression for payloads </code></pre><p>You can press <code>F6</code> to save your config and then press <code>F9</code> to exit. Now we can actually compile Coreboot now.</p> <blockquote> <h3 id="optional-create-cross-compiler">(Optional) Create Cross Compiler</h3> <p>If you don’t have an <code>i386</code> cross compiler you can make one by running:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>make crossgcc-i386 </span></span><span style="display:flex;"><span>make iasl </span></span></code></pre></div></blockquote> <p>Let’s compile coreboot by running:</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>make -j<span style="color:#66d9ef">$(</span>nproc<span style="color:#66d9ef">)</span> </span></span></code></pre></div><p>This might take a while.</p> <p><strong>NOTE:</strong> If you can’t compile Coreboot, try checking and making sure you did everything correctly.</p> <h2 id="flashing-coreboot">Flashing Coreboot</h2> <p><strong>WARNING: Proceed with caution, you can possibly brick your computer if you are not careful!!!</strong></p> <p>You should now be left with a file named <code>coreboot.rom</code> in the <code>~/coreboot</code> directory. You can copy this file back to your Raspberry PI into order to flash it.</p> <p>Now let’s go ahead and read our flash chip again to make sure that our connection is still good.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -r flash01.bin </span></span><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -r flash02.bin </span></span><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -r flash03.bin </span></span><span style="display:flex;"><span>md5sum flash01.bin flash02.bin flash03.bin </span></span></code></pre></div><p>And, like before, if all the checksums match, you can go ahead and flash <code>coreboot.rom</code>.</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>fr -c <span style="color:#e6db74">&#34;</span>$CHIP<span style="color:#e6db74">&#34;</span> -w coreboot.rom </span></span></code></pre></div><p>Now, for the moment of truth, go ahead and boot your Thinkpad. If it won’t boot, don’t sweat, just rebuild and try again. If Coreboot won’t work on your Thinkpad no matter what you try, then you can just flash a backup of the BIOS that you read earlier and your computer should work just fine.</p> <h2 id="aftermath">Aftermath</h2> <p><strong>Congrats!!!</strong> You successfully freed your computer from the spying eyes of Intel and your local three letter government agency. You can now enjoy your computing in peace.</p> <h3 id="contact">Contact</h3> <p>If you have any questions or comments you can find my contact info <a href="https://brycevandegrift.xyz/contact/">here</a>.</p> Website Redesign https://brycev.com/blog/website-redesign/ Mon, 07 Mar 2022 00:00:00 +0000 https://brycev.com/blog/website-redesign/ <p>I have decided to redesign most of my website. It’s mostly a facelift, but there are a couple under-the-hood changes done.</p> <p>I have also decided to officially add a link to my <a href="https://www.youtube.com/channel/UCOSqzSTg4QZXdi7jvV-9rUg">YouTube channel</a> on my homepage, as well as add a link to my <a href="https://sr.ht/~bpv/">Sourcehut page</a> and my <a href="https://brycevandegrift.xyz/rss.xml">rss feed</a>.</p> <p>I plan to reorganize my website as time goes on, but for now a simple redesign will do. I also plan to at least convert my homepage to <a href="https://www.w3schools.com/Html/html_xhtml.asp">xhtml</a> in the future, as I think that I would provide a bit more compatibility with web browsers.</p> <p>As time goes on I will make changes to my website as needed.</p> <h2 id="a-note-about-github-and-gitlab">A note about GitHub and GitLab</h2> <p>If you don’t know already, I am not a big fan of GitHub. I don’t like having a GitHub account, but it’s almost necessary for collaborating on projects. I have updated my <a href="https://github.com/BryceVandegrift">GitHub account</a> for hosting my git repos. Don’t expect me to answer issues or accept code from these platforms (for now (although that might change)), for that please visit my Sourcehut page.</p> New Youtube Channel https://brycev.com/blog/new-youtube-channel/ Sun, 20 Feb 2022 00:00:00 +0000 https://brycev.com/blog/new-youtube-channel/ <p>Recently, I have decided to start up a YouTube channel. I mostly plan to upload informative videos, but things could always change. Right now, I am uploading videos about GNU/Linux and other technical topics related to technology, however I believe that I will expand in the future.</p> <p>In the future, I plan to upload all of my past and future videos onto Odysee/LBRY as I think it’s a superior platform compared to YouTube. I might even consider uploading to other niche video sites eventually.</p> <p>You can view my first video about GnuPG (GPG) <a href="https://youtu.be/GhiLR4zRqMI">here</a>.</p> <p><a href="https://www.youtube.com/channel/UCOSqzSTg4QZXdi7jvV-9rUg">YouTube link</a></p> Personal Update https://brycev.com/blog/personal-update/ Tue, 01 Feb 2022 00:00:00 +0000 https://brycev.com/blog/personal-update/ <p>Recently, I have been pretty busy with college classes and haven’t had much time to work on personal projects. In addition to classes I have also been busy with other personal aspects of life which I would not like to disclose currently. I will be active again once I finish the semester (hopefully).</p> <p>If anything comes up, feel free to email me here: <a href="https://brycevandegrift.xyz/contact/">https://brycevandegrift.xyz/contact/</a></p> My Thoughts on BSDs https://brycev.com/blog/my-thoughts-on-bsds/ Fri, 31 Dec 2021 00:00:00 +0000 https://brycev.com/blog/my-thoughts-on-bsds/ <p>For those of you who are not a big fan of Linux but want something that caters more to the Unix philosophy, a distribution of BSD (Berkeley Software Distribution) may be right for you. Unlike Linux, most BSD systems’ tools, kernels, and programs are built from the ground up for that specific BSD distribution. This also means that it can take a while for a feature or program that’s popular on Linux to make its way to a specific BSD distribution. But, BSD it is worth a try nonetheless.</p> <p>There are four major versions of BSD that I believe to be useable as an everyday operating system: FreeBSD, OpenBSD, NetBSD, and DragonFlyBSD.</p> <h2 id="freebsd">FreeBSD</h2> <p><a href="https://www.freebsd.org/">FreeBSD</a> is probably the most popular BSD distribution of all time. FreeBSD has the most packages, the most support, and the most users compared to any other BSD distribution. FreeBSD’s default file system choices are UFS (Unix File System) and ZFS (Z File System) which isn’t that bad considering ZFS is a pretty reliable file system. FreeBSD also has support of other file systems like FAT and EXT as well as Linux binary compatibility which is pretty nice. To be honest FreeBSD has a lot of cool and interesting features that are worth checking out.</p> <h2 id="openbsd">OpenBSD</h2> <p><a href="https://www.openbsd.org/">OpenBSD</a> is another flavor of BSD that is focused more on security than anything other operating system. The people behind OpenBSD are also some of the same people behind projects like OpenSSH, LibreSSL, and even tmux (to some degree). Although OpenBSD lacks a decent amount of software and certain features, it makes up for it in system security and stability. Overall, I would say that it is a pretty solid operating system.</p> <h2 id="netbsd">NetBSD</h2> <p><a href="https://netbsd.org/">NetBSD</a> is a distribution of BSD that is focused on portability more than any other operating system out there. NetBSD is also well known for its low resource usage as well. NetBSD not only has support for amd64, i386, and arm, but it also supports more obscure architectures like mips, powerpc, riscv, and more. NetBSD is also very small and can be stripped down even from it’s very small state. I remember hearing rumors about NetBSD being able to run on a literal toaster in the past, which I find pretty impressive. If you prefer size and portability over anything else, I would recommend NetBSD.</p> <h2 id="dragonflybsd">DragonFlyBSD</h2> <p><a href="https://www.dragonflybsd.org/">DragonFlyBSD</a> is a distribution of BSD that is tailored for performance and speed. I believe that DragonFlyBSD definitely delivers on it’s promise of speed. Overall multi-threading and multi-processor support as well as speed is very competitive with even the fastest of Linux systems. Swapcache, a different type of swap made for DragonFlyBSD, also helps with greatly boosting performance for large workloads. The HAMMER file systems are also very neat. The HAMMER file systems have instant crash recovery, snapshots, support for multiple volumes, and much more. If you want a fast and efficient operating system, I would definitely recommend trying DragonFlyBSD.</p> <figure ><img src="https://brycev.com/p/bsd.webp" title="bsd" alt="BSD"></figure> New Blog https://brycev.com/blog/new-blog/ Mon, 29 Nov 2021 00:00:00 +0000 https://brycev.com/blog/new-blog/ <p>Recently, I have been working on a new blog system that takes Markdown and converts it into a very simple HTML page as well as an RSS feed. The blog system is written entirely in POSIX shell and is around 100 lines of code.</p> <p>If successful, it should generate a blog page, an RSS feed, as well as a rolling blog index page. The only downside is that it requires Pandoc which isn&rsquo;t that small of a package, but it makes making blog posts a lot easier to write as I can write in Markdown instead of HTML.</p> <p>I based some of it from Luke Smith’s blog script <a href="https://github.com/LukeSmithxyz/lb">here</a>. I have added a few quirks of my own and I also plan to greatly expand on it in the future.</p>