diff options
author | 53hornet <atc@53hor.net> | 2021-07-28 10:58:58 -0400 |
---|---|---|
committer | 53hornet <atc@53hor.net> | 2021-07-28 10:58:58 -0400 |
commit | bfaccc32571df8a02f69518d8864244efba3b5b5 (patch) | |
tree | cc71a44054af00e73d0db2a1c79c347db3f31327 | |
parent | dd75b4a341925e4ba3408b018941241d4317dd9f (diff) | |
download | 53hor-bfaccc32571df8a02f69518d8864244efba3b5b5.tar.xz 53hor-bfaccc32571df8a02f69518d8864244efba3b5b5.zip |
php site, templating and partials, faster index generation
77 files changed, 3634 insertions, 5449 deletions
@@ -1,17 +1,17 @@ # Written for FreeBSD make(1), or pmake. Not tested with GNU make. EDITOR = $$EDITOR -POST_T = templates/template.html +POST_T = includes/template.php .PHONY: serve post serve: - python3.7 -m http.server 3000 + php -S localhost:8000 -post: - @read -p "Title: " TITLE; \ +draft: + @read -rp "Title: " TITLE; \ SHORT_DATE=`date +"%Y-%m-%d"`; \ - FILENAME=posts/$$SHORT_DATE-`printf "$$TITLE" | tr -Cs "[:alnum:]" '-' | tr "[:upper:]" "[:lower:]"`.html; \ - cp $(POST_T) $$FILENAME; \ + FILENAME=drafts/$$SHORT_DATE-`printf "$$TITLE" | tr -Cs "[:alnum:]" '-' | tr "[:upper:]" "[:lower:]"`.php; \ sed -i '' "s/{{ title }}/$$TITLE/g" $$FILENAME; \ $$EDITOR $$FILENAME + @@ -7,10 +7,10 @@ ║ ║ ║ - Professional Computer Programmer & Software Developer -║ - Experience with process automation, web applications, and IT operations ║ +║ - Custom ║ ║ -║ https://www.53hor.net +║ http://www.53hor.net ║ mailto:atc@53hor.net ║ ║ diff --git a/cgi-bin/index.sh b/cgi-bin/index.sh deleted file mode 100755 index 3fea5c9..0000000 --- a/cgi-bin/index.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/sh - -# Generates a site index from posts and pages. - -cat << EOH -content-type: text/html - -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Home" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Home</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <header> - <noscript> - JavaScript? Where we're going we don't need JavaScript. - </noscript> - </header> - - <article> - <h1 style="text-align: center"> - The World Wide Web pages of Adam Carpenter (53hornet) - </h1> - <ul> -EOH - -grep '<h1>' posts/*\ - | sort -r\ - | sed -e 's#^#<li><a href="/#' -e 's#:# #' -e 's#<h1#"#' -e 's#</h1>#</a></li>#' - -echo '</ul></article></body></html>' @@ -1,208 +1,188 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - </head> - <body> - <h1>Adam T. Carpenter</h1> - - <label for="email">Email</label> - <a id="email" href="mailto:atc@53hor.net">atc@53hor.net</a> - <label for="www">WWW</label> - <a id="www" href="https://www.53hor.net/info.html" - >www.53hor.net/info.html</a - > - <label for="git">Git</label> - <a id="git" href="https://git.53hor.net">git.53hor.net</a> - - <hr /> - <h2>Summary</h2> - - <p> - I am a computer programmer who has been developing and maintaining native - and web applications since 2018. I have also been providing systems - administration services and technical mentoring since 2016. I aim to - create simple, performant, and well-documented software that solves real - problems with no surprises. - </p> - - <p> - I am fluent in Rust, C#, Python, JavaScript, Bourne Shell, and HTML+CSS. I - am also familiar with Java, PHP, C, C++, TypeScript, and PowerShell. I - have used a variety of frameworks and libraries, as well as a myriad of - web servers, databases, and "DevOps" toolkits. - </p> - - <hr /> - <h2>Skills</h2> - - <h3>Software Development</h3> - - <ul> - <li> - Build performant, correct applications and services with a focus on - automating manual labor and making architects'/operators' lives easier. - </li> - <li> - Contribute to internal and client-facing front-end software that is - simple and easy to use. - </li> - <li> - Integrating with organizational build chains and DevOps pipelines for - deployments with zero surprises. - </li> - </ul> - - <h3>Systems Administration</h3> - - <ul> - <li> - Architect and arrange physical machines and the servers that run on them - for minimal downtime and secure, speedy operation. - </li> - <li> - Administer container orchestration clusters with dozens of - "micro-services" that need to communicate together to achieve a common - goal. Apply zero-downtime upgrade practices as well as high-availability - horizontal replica scaling for high-use applications. - </li> - <li> - Self-host a variety of tools, applications, and web servers for the - purpose of learning and ownership of digital property. - </li> - </ul> - - <h3>Technical Mentoring, Leadership</h3> - - <ul> - <li> - Transfer knowledge and skills in a practical, enjoyable fashion in - language that is [hopefully] easy to comprehend. - </li> - <li> - Take a senior role in directing a flourishing new team of developers to - get started quickly and achieve a state of production in little time. - </li> - <li> - Co-host informal lectures and "lunch and learns" on a variety of topics, - especially but not limited to computing. - </li> - </ul> - - <hr /> - <h2>Experience</h2> - - <ul> - <li> - <h3> - Automatic Data Processing | Application Developer | June 2018 to - present - </h3> - <ul> - <li> - Authored <em>Altruistic Angelshark</em>, an Avaya Communication - Manager automation daemon, to ease friction caused by existing, - interactive, and fragile tools and processes. This tool was used to - save the company rougly half a million dollars per year by enabling - unused license cleanup with little operator input. It was deemed - appropriately useful to release as free and open source software. It - was written in Rust and operates over the SSH2 library using an - undocumented Avaya protocol. - </li> - <li> - Co-authored an authentication/authorization API to specifically - serve the needs of our team. This software interacted with Active - Directory over LDAP, presented users with JSON Web Tokens, and was - reworked be used as a reverse proxy in front of our container - services. - </li> - <li> - On-boarded and mentored team of six developers on organization - DevOps technology and practices. This included configuring and - knowledge-sharing a Jenkins CICD pipeline, local Docker Trusted - Registry, and IBM Cloud Private flavor of Kubernetes. This also - consisted of informal lectures on concepts such as continuous - deployment and delivery, the "12-factor" methodology, and - containerization. - </li> - <li> - For multiple years in a row I offered my services for on-site - training of new college hires. My responsibilities included - mentoring and knowledge sharing for typical industry tools, - languages, and frameworks, as well as the inner workings of the - company. Classes typically consisted of 20-30 new employees. - </li> - </ul> - </li> - - <li> - <h3> - Freelance | Web Application Designer & Developer | Jul. 2019 to - present - </h3> - <ul> - <li> - Built a from-scratch art studio storefront to exactly fit the - customer's specifications. Site is a mobile-friendly art gallery - with a cart and checkout system. I used Rust and Vue JS for the - majority of this project. Functionality was delivered ahead of - schedule and I was able to quickly compensate for shifting - requirements. - </li> - <li>Built and maintained a variety of static sites.</li> - </ul> - </li> - - <li> - <h3> - The College of William and Mary | Technology Support Specialist | Feb. - 2015 to May 2018 - </h3> - <ul> - <li> - Worked directly with customers to diagnose issues and install and - configure software. Interactions were in-person and over the phone. - Responsibilities also included performing basic repairs to - enterprise laptops. - </li> - <li> - Maintained three to four public access labs at a time during the - Summer months, each with 20-30 machines. - </li> - </ul> - </li> - </ul> - - <hr /> - <h2>Academics</h2> - - <p> - I have a Bachelor of Science in Computer Science and graduated from the - College of William and Mary in May of 2018. While there, I participated in - several group software development projects such as hybrid Android - application testing and presided over the campus Game Design Club. - </p> - - <hr /> - <h2>About Me</h2> - - <p> - I wrote my first program on a TI-84 in BASIC to help finish my high school - math homework faster. I quickly transitioned to building more complicated - programs but have continued to enjoy finding the smallest amount of code - to solve a problem quickly, correctly, and securely. - </p> - - <p> - I grew up in and still call Hampton Roads, Virginia my home. In my spare - time I drive and maintain a classic car, a 1953 Hudson Hornet. I enjoy - travelling and being at home with my wife and cocker spaniel. I also - self-host a web server in a closet in my home. - </p> - - <p> - You can always find more on - <a href="https://www.53hor.net">my web site</a>. - </p> - </body> -</html> +<label for="email">Email</label> +<a id="email" href="mailto:atc@53hor.net">atc@53hor.net</a> +<label for="www">WWW</label> +<a id="www" href="https://www.53hor.net/hire.php">www.53hor.net</a> +<label for="git">Git</label> +<a id="git" target="_blank" href="https://git.53hor.net/explore/repos" + >git.53hor.net</a +> + +<hr /> +<h2>Summary</h2> + +<p> + I am a computer programmer who has been developing and maintaining native and + web applications since 2018. I have also been providing systems administration + services and technical mentoring since 2016. I aim to create simple, + performant, and well-documented software that solves real problems with no + surprises. +</p> + +<p> + I am fluent in Rust, C#, Python, JavaScript, Bourne Shell, and HTML+CSS. I am + also familiar with Java, PHP, C, C++, TypeScript, and PowerShell. I have used + a variety of frameworks and libraries, as well as a myriad of web servers, + databases, and "DevOps" toolkits. +</p> + +<hr /> +<h2>Skills</h2> + +<h3>Software Development</h3> + +<ul> + <li> + Build performant, correct applications and services with a focus on + automating manual labor and making architects'/operators' lives easier. + </li> + <li> + Contribute to internal and client-facing front-end software that is simple + and easy to use. + </li> + <li> + Integrating with organizational build chains and DevOps pipelines for + deployments with zero surprises. + </li> +</ul> + +<h3>Systems Administration</h3> + +<ul> + <li> + Architect and arrange physical machines and the servers that run on them for + minimal downtime and secure, speedy operation. + </li> + <li> + Administer container orchestration clusters with dozens of "micro-services" + that need to communicate together to achieve a common goal. Apply + zero-downtime upgrade practices as well as high-availability horizontal + replica scaling for high-use applications. + </li> + <li> + Self-host a variety of tools, applications, and web servers for the purpose + of learning and ownership of digital property. + </li> +</ul> + +<h3>Technical Mentoring, Leadership</h3> + +<ul> + <li> + Transfer knowledge and skills in a practical, enjoyable fashion in language + that is [hopefully] easy to comprehend. + </li> + <li> + Take a senior role in directing a flourishing new team of developers to get + started quickly and achieve a state of production in little time. + </li> + <li> + Co-host informal lectures and "lunch and learns" on a variety of topics, + especially but not limited to computing. + </li> +</ul> + +<hr /> +<h2>Experience</h2> + +<p> +<h3>Automatic Data Processing | Application Developer | June 2018 to present</h3> +<ul> + <li> + Authored <em>Altruistic Angelshark</em>, an Avaya Communication Manager + automation daemon, to ease friction caused by existing, interactive, and + fragile tools and processes. This tool was used to save the company + rougly half a million dollars per year by enabling unused license + cleanup with little operator input. It was deemed appropriately useful + to release as free and open source software. It was written in Rust and + operates over the SSH2 library using an undocumented Avaya protocol. + </li> + <li> + Co-authored an authentication/authorization API to specifically serve + the needs of our team. This software interacted with Active Directory + over LDAP, presented users with JSON Web Tokens, and was reworked be + used as a reverse proxy in front of our container services. + </li> + <li> + On-boarded and mentored team of six developers on organization DevOps + technology and practices. This included configuring and + knowledge-sharing a Jenkins CICD pipeline, local Docker Trusted + Registry, and IBM Cloud Private flavor of Kubernetes. This also + consisted of informal lectures on concepts such as continuous deployment + and delivery, the "12-factor" methodology, and containerization. + </li> + <li> + For multiple years in a row I offered my services for on-site training + of new college hires. My responsibilities included mentoring and + knowledge sharing for typical industry tools, languages, and frameworks, + as well as the inner workings of the company. Classes typically + consisted of 20-30 new employees. + </li> +</ul> +</p> + +<p> +<h3> + Freelance | Web Application Designer & Developer | Jul. 2019 to present +</h3> +<ul> + <li> + Built a from-scratch art studio storefront to exactly fit the customer's + specifications. Site is a mobile-friendly art gallery with a cart and + checkout system. I used Rust and Vue JS for the majority of this + project. Functionality was delivered ahead of schedule and I was able to + quickly compensate for shifting requirements. + </li> + <li>Built and maintained a variety of static sites.</li> +</ul> +</p> + +<p> +<h3> + The College of William and Mary | Technology Support Specialist | Feb. + 2015 to May 2018 +</h3> +<ul> + <li> + Worked directly with customers to diagnose issues and install and + configure software. Interactions were in-person and over the phone. + Responsibilities also included performing basic repairs to enterprise + laptops. + </li> + <li> + Maintained three to four public access labs at a time during the Summer + months, each with 20-30 machines. + </li> +</ul> +</p> + +<hr /> +<h2>Academics</h2> + +<p> + I have a Bachelor of Science in Computer Science and graduated from the + College of William and Mary in May of 2018. While there, I participated in + several group software development projects such as hybrid Android application + testing and presided over the campus Game Design Club. +</p> + +<hr /> +<h2>About Me</h2> + +<p> + I wrote my first program on a TI-84 in BASIC to help finish my high school + math homework faster. I quickly transitioned to building more complicated + programs but have continued to enjoy finding the smallest amount of code to + solve a problem quickly, correctly, and securely. +</p> + +<p> + I grew up in and still call Hampton Roads, Virginia my home. In my spare time + I drive and maintain a classic car, a 1953 Hudson Hornet. I enjoy travelling + and being at home with my wife and cocker spaniel. I also self-host a web + server in a closet in my home. +</p> + +<p> + You can always find more on + <a href="https://www.53hor.net">my web site</a>. +</p> Binary files differ@@ -0,0 +1,5 @@ +<?php +$title = "Adam T. Carpenter"; +$nav = false; +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +include('cv.html'); diff --git a/cgi-bin/rss.sh b/feed.php index 6987745..309f97e 100755..100644 --- a/cgi-bin/rss.sh +++ b/feed.php @@ -1,12 +1,6 @@ -#!/bin/sh - -# Generates an RSS feed from all posts. - -cat << EOH -content-type: application/xml +<?php header('content-type: application/rss+xml'); ?> <?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE xml> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <channel> <title>53hornet's Feed</title> @@ -18,11 +12,18 @@ content-type: application/xml <title>53hornet's Feed</title> <link>https://www.53hor.net</link> </image> -EOH - -grep '<h1>' posts/*\ - | sort -r\ - | sed -e 's#h1#title#g' -e 's#:#</link>#' -e 's#$#</item>#' -e 's#^#<item><link>https://www.53hor.net/#' - -echo '</channel></rss>' + <?php + if ($posts = glob('./posts/*.php')) { + $early = true; + foreach (array_reverse($posts) as $post) { + if (!empty($post) && $post != '.' && $post != '..') { + $post_name = explode('/', $post)[2]; + include($post); + printf('<item><link>https://www.53hor.net/posts/%s</link><title>%s</title></item>', $post_name, $title); + } + } + } + ?> + </channel> +</rss> diff --git a/hire.php b/hire.php new file mode 100644 index 0000000..232c3d8 --- /dev/null +++ b/hire.php @@ -0,0 +1,23 @@ +<?php +$title = "Hire Me"; +include('./includes/head.php'); +?> + +<p> + I am a freelance computer programmer and consultant. I offer the following services. + +<ul> + <li>Custom software design, development, and deployment</li> + <li>From-scratch web site construction and maintenance</li> + <li>Programming and information technology consulting</li> +</ul> +</p> + +<p>You can see some of my work history in my CV + <a target="_blank" href="/cv.php">(HTML)</a> + <a href="/cgi-bin/cv.sh">(PDF)</a>. +</p> + +<p>You can also view many of my personal projects in my <a target="_blank" href="https://git.53hor.net/explore/repos">Git repositories</a>. + +<p>The best way to get in touch with me is <a href="mailto:atc@53hor.net">atc@53hor.net</a>. </p> diff --git a/includes/head.php b/includes/head.php new file mode 100644 index 0000000..c0a614b --- /dev/null +++ b/includes/head.php @@ -0,0 +1,184 @@ +<head> + <style> + @font-face { + font-family: "Iosevka Slab"; + font-display: swap; + src: url("/includes/iosevka-slab-regular.woff2"); + } + + :root { + --balboa: #195970; + --ruby: #9b111e; + --slate: #b9c2ca; + --charcoal: #798d94; + --white: white; + --box-radius: 0.5em; + --box-border: 0.5em solid var(--white); + } + + body { + font-family: "Iosevka Slab", monospace; + font-size: 1.5em; + background-color: var(--balboa); + color: var(--white); + max-width: 50em; + margin: auto; + padding: 1em; + } + + hr { + color: var(--white); + } + + nav { + list-style-type: none; + text-align: center; + } + + nav ul { + padding: 0; + margin: 0; + } + + nav li { + display: inline-block; + margin: 0.5em; + padding: 0.5em; + } + + nav svg { + padding-right: 0.5em; + } + + nav a:link, + nav a:visited, + nav a:hover, + nav a:active { + display: flex; + align-items: center; + color: var(--white); + text-decoration: none; + } + + a:link { + color: var(--slate); + } + + a:visited { + color: var(--charcoal); + } + + pre { + white-space: pre-wrap; + display: block; + background-color: var(--charcoal); + padding: 1em; + border-radius: var(--box-radius); + border-left: var(--box-border); + border-right: var(--box-border); + } + + .description { + background-color: var(--ruby); + padding: 1em; + border-radius: var(--box-radius); + border-left: var(--box-border); + border-right: var(--box-border); + } + + h1, + blockquote { + font-style: oblique; + } + + header { + text-align: center; + } + + article ul { + list-style: none; + padding: 0; + margin: 0; + } + + article ul li { + padding: 0.5em; + } + + article ul li:before { + content: "➙"; + padding-right: 0.5em; + } + + article ol li { + padding: 0.5em; + } + + p img { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 75%; + height: auto; + border-radius: var(--box-radius); + border-left: var(--box-border); + border-right: var(--box-border); + } + + iframe { + display: block; + margin-left: auto; + margin-right: auto; + } + + .list { + overflow-x: auto; + } + + .list table { + width: 100%; + } + + .list td, + th { + padding: 0.5em; + text-align: left; + border-bottom: 1px solid var(--charcoal); + } + + svg { + width: 24px; + height: 24px; + } + </style> + + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta property="og:description" content="The World Wide Web pages of Adam Carpenter" /> + <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> + <meta property="og:site_name" content="53hor.net" /> + <meta property="og:title" content="Adam Carpenter (53hornet)" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.53hor.net" /> + <?php + if (isset($title)) { + printf('<title>53hornet ➙ %s</title>', $title); + } else { + echo '<title>53hornet</title>'; + } + ?> +</head> + +<body> + + <?php + if (!isset($nav) || $nav) { + include('nav.php'); + } + ?> + <article> + <?php + if (isset($title)) { + printf('<h1>%s</h1>', $title); + } + ?> diff --git a/includes/icons/.!26569!card-account-mail.svg b/includes/icons/.!26569!card-account-mail.svg deleted file mode 100644 index e69de29..0000000 --- a/includes/icons/.!26569!card-account-mail.svg +++ /dev/null diff --git a/includes/icons/.!89047!card-account-mail.svg b/includes/icons/.!89047!card-account-mail.svg deleted file mode 100644 index e69de29..0000000 --- a/includes/icons/.!89047!card-account-mail.svg +++ /dev/null diff --git a/includes/nav.php b/includes/nav.php new file mode 100644 index 0000000..87b9175 --- /dev/null +++ b/includes/nav.php @@ -0,0 +1,44 @@ +<nav> + <ul> + <li> + <a href="/"> + <svg viewBox="0 0 24 24"> + <path fill="#ffffff" d="M19 16H22L12 7L2 16H5L12 9.69L19 16M7 8.81V7H4V11.5L7 8.81Z" /> + </svg> + Home + </a> + </li> + <li> + <a href="/info.php"> + <svg viewBox="0 0 24 24"> + <path fill="#ffffff" d="M13.5,4A1.5,1.5 0 0,0 12,5.5A1.5,1.5 0 0,0 13.5,7A1.5,1.5 0 0,0 15,5.5A1.5,1.5 0 0,0 13.5,4M13.14,8.77C11.95,8.87 8.7,11.46 8.7,11.46C8.5,11.61 8.56,11.6 8.72,11.88C8.88,12.15 8.86,12.17 9.05,12.04C9.25,11.91 9.58,11.7 10.13,11.36C12.25,10 10.47,13.14 9.56,18.43C9.2,21.05 11.56,19.7 12.17,19.3C12.77,18.91 14.38,17.8 14.54,17.69C14.76,17.54 14.6,17.42 14.43,17.17C14.31,17 14.19,17.12 14.19,17.12C13.54,17.55 12.35,18.45 12.19,17.88C12,17.31 13.22,13.4 13.89,10.71C14,10.07 14.3,8.67 13.14,8.77Z" /> + </svg> + Info + </a> + </li> + <li> + <a target="_blank" href="https://git.53hor.net/explore/repos"> + <svg viewBox="0 0 24 24"> + <path fill="#ffffff" d="M2.6,10.59L8.38,4.8L10.07,6.5C9.83,7.35 10.22,8.28 11,8.73V14.27C10.4,14.61 10,15.26 10,16A2,2 0 0,0 12,18A2,2 0 0,0 14,16C14,15.26 13.6,14.61 13,14.27V9.41L15.07,11.5C15,11.65 15,11.82 15,12A2,2 0 0,0 17,14A2,2 0 0,0 19,12A2,2 0 0,0 17,10C16.82,10 16.65,10 16.5,10.07L13.93,7.5C14.19,6.57 13.71,5.55 12.78,5.16C12.35,5 11.9,4.96 11.5,5.07L9.8,3.38L10.59,2.6C11.37,1.81 12.63,1.81 13.41,2.6L21.4,10.59C22.19,11.37 22.19,12.63 21.4,13.41L13.41,21.4C12.63,22.19 11.37,22.19 10.59,21.4L2.6,13.41C1.81,12.63 1.81,11.37 2.6,10.59Z" /> + </svg> + Repos + </a> + </li> + <li> + <a href="/hire.php"> + <svg viewBox="0 0 24 24"> + <path fill="#ffffff" d="M3,3V21H21V3H3M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,15A1,1 0 0,1 13,16V19A1,1 0 0,1 12,20A1,1 0 0,1 11,19V16A1,1 0 0,1 12,15Z" /> + </svg> + Hire Me + </a> + </li> + <li> + <a type="application/rss+xml" href="/rss.xml"> + <svg viewBox="0 0 24 24"> + <path fill="#ffffff" d="M6.18,15.64A2.18,2.18 0 0,1 8.36,17.82C8.36,19 7.38,20 6.18,20C5,20 4,19 4,17.82A2.18,2.18 0 0,1 6.18,15.64M4,4.44A15.56,15.56 0 0,1 19.56,20H16.73A12.73,12.73 0 0,0 4,7.27V4.44M4,10.1A9.9,9.9 0 0,1 13.9,20H11.07A7.07,7.07 0 0,0 4,12.93V10.1Z" /> + </svg> + RSS + </a> + </li> + </ul> +</nav> diff --git a/includes/stylesheet.css b/includes/stylesheet.css deleted file mode 100644 index a40bb5f..0000000 --- a/includes/stylesheet.css +++ /dev/null @@ -1,145 +0,0 @@ -@font-face { - font-family: "Iosevka Slab"; - font-display: swap; - src: url("/includes/iosevka-slab-regular.woff2"); -} - -:root { - --balboa: #195970; - --ruby: #9b111e; - --slate: #b9c2ca; - --charcoal: #798d94; - --white: white; - --box-radius: 0.5em; - --box-border: 0.5em solid var(--white); -} - -body { - font-family: "Iosevka Slab", monospace; - font-size: 1.5em; - background-color: var(--balboa); - color: var(--white); - max-width: 50em; - margin: auto; - padding: 1em; -} - -hr { - color: var(--white); -} - -nav { - list-style-type: none; - text-align: center; -} - -nav ul { - padding: 0; - margin: 0; -} - -nav li { - display: inline-block; - margin: 0.5em; - padding: 0.5em; -} - -nav img { - padding-right: 0.5em; -} - -nav a:link, -nav a:visited, -nav a:hover, -nav a:active { - display: flex; - align-items: center; - color: var(--white); - text-decoration: none; -} - -a:link { - color: var(--slate); -} - -a:visited { - color: var(--charcoal); -} - -pre { - white-space: pre-wrap; - display: block; - background-color: var(--charcoal); - padding: 1em; - border-radius: var(--box-radius); - border-left: var(--box-border); - border-right: var(--box-border); -} - -.description { - background-color: var(--ruby); - padding: 1em; - border-radius: var(--box-radius); - border-left: var(--box-border); - border-right: var(--box-border); -} - -h1, -blockquote { - font-style: oblique; -} - -header { - text-align: center; -} - -article ul { - list-style: none; - padding: 0; - margin: 0; -} - -article ul li { - padding: 0.5em; -} - -article ul li:before { - content: "➙"; - padding-right: 0.5em; -} - -article ol li { - padding: 0.5em; -} - -p img { - display: block; - margin-left: auto; - margin-right: auto; - max-width: 75%; - height: auto; - border-radius: var(--box-radius); - border-left: var(--box-border); - border-right: var(--box-border); -} - -iframe { - display: block; - margin-left: auto; - margin-right: auto; -} - -.list { - overflow-x: auto; -} - -.list table { - width: 100%; -} - -.list td, -th { - padding: 0.5em; - text-align: left; - border-bottom: 1px solid var(--charcoal); -} diff --git a/includes/template.php b/includes/template.php new file mode 100644 index 0000000..5ff90f4 --- /dev/null +++ b/includes/template.php @@ -0,0 +1,6 @@ +<?php +$title = "{{title}}"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); diff --git a/index.php b/index.php new file mode 100644 index 0000000..e94c87a --- /dev/null +++ b/index.php @@ -0,0 +1,31 @@ +<?php +include('./includes/head.php'); +?> + +<header> + <noscript> + JavaScript? Where we're going we don't need JavaScript. + </noscript> +</header> + +<article> + <h1 style="text-align: center"> + The World Wide Web pages of Adam Carpenter (53hornet) + </h1> + <ul> + <?php + if ($posts = glob('./posts/*.php')) { + $early = true; + + foreach (array_reverse($posts) as $post) { + if (!empty($post) && $post != '.' && $post != '..') { + $post_name = explode('/', $post)[2]; + $date = implode('-', array_slice(explode('-', $post_name), 0, 3)); + include($post); + printf('<li><a href="/%s">%s</a> <code>%s</code></li>', $post, $title, $date); + } + } + } + ?> + </ul> +</article> diff --git a/info.html b/info.html deleted file mode 100644 index b3ae26d..0000000 --- a/info.html +++ /dev/null @@ -1,270 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Info" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Info</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img - alt="information" - src="/includes/icons/information-variant.svg" - /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Info</h1> - - <h2>About Me</h2> - - <p> - My name is <em>Adam Carpenter</em> (on some sites I'm - <em>53hornet</em>). I am a professional computer programmer, am married - to my wonderful wife, Amy, and a puppy parent to Clementine, a Cocker - Spaniel. This is my web site. - </p> - <p> - You can find my <a href="/cv.html">CV here</a>. If you want a PDF you - can <a href="/cgi-bin/cv.sh">get that here</a>. - </p> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/zL2AJHwtCWLX2Eq/preview" - /> - </p> - - <h2>What Else Will You Find Here?</h2> - - <p> - This site is my home on the web. I post things I've learned, things I - want to share, and things I don't want to forget. I am generally - interested in and generally post about: - </p> - - <ul> - <li>Antique automobiles, esp. my Fabulous 1953 Hudson Hornet</li> - <li>Systems- and application-level programming</li> - <li>Retrocomputing, esp. the Commodore 64</li> - <li>Home servers and self-hosting</li> - <li>FreeBSD and other *BSDs or UNIX-like operating systems</li> - <li>Food: eating, baking, etc.</li> - <li>Games, movies, and music</li> - </ul> - - <h3>Web Log</h3> - <p> - I run a web log on this site. It's index is at the - <a href="/">site index</a>. - </p> - - <h3>Repos</h3> - - <p> - I self-host all of my own Git repositories. You can - <a href="https://git.53hor.net">access them here</a>. - </p> - - <h3>Software, Self-Hosted Apps and Games</h3> - - <p> - I self-host a variety of applications and games. A few of them are - public. You may <a href="/software.html">access them here</a>. I also - maintain a couple of open source projects with homepages there as well. - </p> - - <h2>Contacting Me</h2> - - <p> - You can write to <a href="mailto:atc@53hor.net">atc@53hor.net</a>. - <span> - If you want it, - <a - href="https://nextcloud.53hor.net/index.php/s/bX5K5JBHNnyZgr2/download" - >here is my GPG public key</a - >. - </span> - The best way to keep up with what I'm up to is to use an RSS reader on - <a href="/rss.xml">my feed</a>. - </p> - - <p> - I've created accounts on the following sites but I check them rarely or - not at all. The best way to reach me is by mail. - </p> - - <p> - <span> - <a title="53hornet#2015">Discord (hover)</a> - </span> - <span> - <a - title="33FF8453F9A8E3583EFBC1185F17B466C2A76761AD7E35CBFEB9F1D977F71022FC8FBBC6AB41" - >Tox (hover) - </a> - </span> - <span> - <a href="https://www.reddit.com/user/53hornet">Reddit</a> - </span> - <span> - <a href="https://github.com/53hornet">GitHub</a> - </span> - <span> - <a href="https://gitlab.com/53hornet">GitLab</a> - </span> - <span> - <a href="https://www.youtube.com/user/my53hornet" - >YouTube (53hornet)</a - > - </span> - <span> - <a href="https://www.youtube.com/user/STMUAC/about" - >YouTube (STMUAC)</a - > - </span> - <span> - <a href="https://twitter.com/AdamCar09144367">Twitter</a> - </span> - <span> - <a href="https://www.linkedin.com/in/adam-carpenter/">LinkedIn</a> - </span> - <span> - <a href="https://steamcommunity.com/id/53hornet/">Steam</a> - </span> - <span> - <a href="https://www.facebook.com/53hornet">Facebook</a> - </span> - </p> - - <h2>Disclaimer</h2> - - <p> - The views on this web site are entirely mine! That should go without - saying. They don't reflect my company, co-workers, friends, family, dog, - or anyone I mention anywhere in any way. - </p> - - <p> - I prefer not to go back and edit old posts. So when you're reading - something from 2 years ago, that was my opinion 2 years ago. Times - change and so can I, so please try to keep that in mind. - </p> - - <p> - If I reference an external public profile or site as fact, I will do so - with links so you can go and read the source. - </p> - - <h2>Privacy</h2> - - <p> - My web server has an access log. By visiting this site you're - surrendering: - </p> - - <ul> - <li>Your public IP address</li> - <li>Your browser's user agent</li> - <li>The URL of the page you visited</li> - <li>The time and date of your visit</li> - </ul> - - <p> - That's it. I do not advertise in this site, read your cookies, or - perform any kind of social media tracking. I also proudly don't have any - JavaScript on my site. - </p> - - <h2>License</h2> - - <p> - Content on this site is licensed under the - <a href="https://creativecommons.org/licenses/by/4.0/" - >Creative Commons Attribution 4.0 International License</a - >. - </p> - - <p> - Source code on this site, unless otherwise stated, is licensed under the - <a href="https://opensource.org/licenses/BSD-3-Clause"> - BSD 3-Clause license</a - >. - </p> - - <p> - The structure and content of this page are loosely based on - <a href="https://www.worthe-it.co.za/about.html" - >Justin Wernick's about page</a - >. The structure and content of my CV is loosely based on - <a href="https://benhoyt.com/cv/">Ben Hoyt's Resume/CV</a>. - </p> - - <img - src="https://nextcloud.53hor.net/index.php/s/G3QG8FNb8aDmzcc/preview" - /> - - <img - src="https://nextcloud.53hor.net/index.php/s/nKmSsrxa4LkRHdM/preview" - /> - - <img - style="border: 0; width: 88px; height: 31px" - src="https://jigsaw.w3.org/css-validator/images/vcss-blue" - alt="Valid CSS!" - /> - - <img - src="https://nextcloud.53hor.net/index.php/s/JMqd6ACCdskmS5J/preview" - width="graphic-width-in-pixels" - height="graphic-height-in-pixels" - alt="Viewable With Any Browser" - /> - </article> - </body> -</html> diff --git a/info.php b/info.php new file mode 100644 index 0000000..6ff3124 --- /dev/null +++ b/info.php @@ -0,0 +1,147 @@ +<?php +$title = "Info"; +include('./includes/head.php'); +?> + +<p> + My name is <em>Adam Carpenter</em> (on some sites I'm + <em>53hornet</em>). I am a professional computer programmer, am married + to my wonderful wife, Amy, and a puppy parent to Clementine, a Cocker + Spaniel. This is my web site. +</p> + +<a href="mailto:atc@53hor.net">atc@53hor.net</a>, + +<a href="https://nextcloud.53hor.net/index.php/s/bX5K5JBHNnyZgr2/download">GPG public key</a> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/zL2AJHwtCWLX2Eq/preview" /> +</p> + +<h2>What Will You Find Here?</h2> + +<p> + This site is my home on the web. I post things I've learned, things I + want to share, and things I don't want to forget. I am generally + interested in and generally post about: +</p> + +<ul> + <li>Antique automobiles, esp. my Fabulous 1953 Hudson Hornet</li> + <li>Systems- and application-level programming</li> + <li>Retrocomputing, esp. the Commodore 64</li> + <li>Home servers and self-hosting</li> + <li>FreeBSD and other *BSDs or UNIX-like operating systems</li> + <li>Food: eating, baking, etc.</li> + <li>Games, movies, and music</li> +</ul> + +<!-- + <p> + <span> + <a title="53hornet#2015">Discord (hover)</a> + </span> + <span> + <a + title="33FF8453F9A8E3583EFBC1185F17B466C2A76761AD7E35CBFEB9F1D977F71022FC8FBBC6AB41" + >Tox (hover) + </a> + </span> + <span> + <a href="https://www.reddit.com/user/53hornet">Reddit</a> + </span> + <span> + <a href="https://github.com/53hornet">GitHub</a> + </span> + <span> + <a href="https://gitlab.com/53hornet">GitLab</a> + </span> + <span> + <a href="https://www.youtube.com/user/my53hornet" + >YouTube (53hornet)</a + > + </span> + <span> + <a href="https://www.youtube.com/user/STMUAC/about" + >YouTube (STMUAC)</a + > + </span> + <span> + <a href="https://twitter.com/AdamCar09144367">Twitter</a> + </span> + <span> + <a href="https://www.linkedin.com/in/adam-carpenter/">LinkedIn</a> + </span> + <span> + <a href="https://steamcommunity.com/id/53hornet/">Steam</a> + </span> + <span> + <a href="https://www.facebook.com/53hornet">Facebook</a> + </span> + </p>--> + +<h2>Disclaimer</h2> + +<p> + The views on this web site are entirely mine! That should go without + saying. They don't reflect my company, co-workers, friends, family, dog, + or anyone I mention anywhere in any way. +</p> + +<p> + I prefer not to go back and edit old posts. So when you're reading + something from 2 years ago, that was my opinion 2 years ago. Times + change and so can I, so please try to keep that in mind. +</p> + +<p> + If I reference an external public profile or site as fact, I will do so + with links so you can go and read the source. +</p> + +<h2>Privacy</h2> + +<p> + My web server has an access log. By visiting this site you're + surrendering: +</p> + +<ul> + <li>Your public IP address</li> + <li>Your browser's user agent</li> + <li>The URL of the page you visited</li> + <li>The time and date of your visit</li> +</ul> + +<p> + That's it. I do not advertise on this site, read your cookies, or + perform any kind of social media tracking. I also proudly don't have any + JavaScript on my site. +</p> + +<h2>License</h2> + +<p> + Content on this site is licensed under the + <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>. +</p> + +<p> + Source code on this site, unless otherwise stated, is licensed under the + <a href="https://opensource.org/licenses/BSD-3-Clause"> + BSD 3-Clause license</a>. +</p> + +<p> + The structure and content of this page are loosely based on + <a href="https://www.worthe-it.co.za/about.html">Justin Wernick's about page</a>. The structure and content of my CV is loosely based on + <a href="https://benhoyt.com/cv/">Ben Hoyt's Resume/CV</a>. +</p> + +<img src="https://nextcloud.53hor.net/index.php/s/G3QG8FNb8aDmzcc/preview" /> + +<img src="https://nextcloud.53hor.net/index.php/s/nKmSsrxa4LkRHdM/preview" /> + +<img style="border: 0; width: 88px; height: 31px" src="https://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS!" /> + +<img src="https://nextcloud.53hor.net/index.php/s/JMqd6ACCdskmS5J/preview" width="graphic-width-in-pixels" height="graphic-height-in-pixels" alt="Viewable With Any Browser" /> diff --git a/out.pdf b/out.pdf Binary files differdeleted file mode 100644 index c8f9106..0000000 --- a/out.pdf +++ /dev/null diff --git a/posts/2019-04-06-why-have-a-website-in-2019.html b/posts/2019-04-06-why-have-a-website-in-2019.html deleted file mode 100644 index 067fe85..0000000 --- a/posts/2019-04-06-why-have-a-website-in-2019.html +++ /dev/null @@ -1,170 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Why Have a Web Site in 2019?" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Why Have a Web Site in 2019?</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Why Have a Web Site in 2019?</h1> - <blockquote> - Adam, why on earth do you have a website? Wait... Is this a - <em>blog</em>? It's 2019, why don't you just use Facebook?! - </blockquote> - - <p> - I've wanted to have my own website for a long time mostly because I like - playing with technology. I think it's cool that I can make a few files - on a computer in my closet available for the entire world to see. The - web has become a near-necessity in our daily lives and it's only been - around for a couple of decades. That has always fascinated me enough to - drive me to see if I can do it on my own. I started self-hosting my own - web server about a year ago now and it's been an awesome study in the - way all of the tech we use on the web works. - </p> - - <p> - A written website is also a good way to keep up on my writing skills. - I've graduated college and won't be writing essays for the foreseeable - eternity. Which is fine except that I have no reason to write creatively - or formally anymore. Having this site encourages me to continue turning - thoughts into words, even though it's more casual than a term paper. - </p> - - <p> - This extends into the professionalism of a personal website. Normally - you can't point your employer towards your Twitter profile as the - distillation of your online footprint. Having a website, especially one - that separates professional and personal interests, is ten times better - than a resume, especially in the world of technology. It lets you tell - people exactly who you are and what you do, without forcing them to - navigate through an auth wall or a bunch of puppy photos. Your - professional and personal lives don't bleed together quite as much and - it makes for a kick-ass business card. - </p> - - <p> - Most importantly however, I enjoy the level of control that I gain with - creating and operating my own website, something I have also sought for - a long time. In high school I set up an old Dell from my school's - recycling center with Windows XP and Microsoft Internet Information - Services. It didn't have SSL or even a domain name but it was reachable - over the WAN. I set up an upload system so that my friends and I could - 'post' memes and funny messages for each other on raw html pages written - with Microsoft Word. That was the extent of its functionality. It was - slow, insecure, and went offline every time the router got a new IP - assigned to it. But I didn't care. It was a site the school couldn't - block. It had no name and no rules and nobody could tell us what to do - with it because it was ours. And we called it the - <em>Troll Nexus Center</em> because that's what you do when you're 15 - </p> - - <p> - My reasons then for building the Troll Nexus Center still stand now. - <em - >Having your own website is having your own piece of internet - property.</em - > - I first heard this wording from - <a href="https://www.youtube.com/watch?v=azkWYxyqh3Y" - >Luke Smith over on his YouTube channel</a - > - and it's one-hundred percent true. Tumblogs, Google Sites, Facebook - profiles, and GitHub Pages are all like renting an apartment. Sure, - there are some really nice apartments out there but it's not the same as - owning your own home. You have to pay rent obviously, and rent is - subject to change once your lease is up. If anything breaks you text - your landlord and wait to have it fixed. You aren't allowed to fix it - yourself and sometimes it doesn't get fixed at all. And of course you're - limited by how much you can customize things to your own liking. Whether - it's painting walls or knocking them down. - </p> - - <p> - These limitations may or may not apply to you. Whether you're paying for - storage, server space, metrics, or watching an ad every five seconds, - these services aren't free either. And you certainly can't fix - everything that goes wrong with them. I started on Google Sites. It's a - truly fantastic system. Building a site is like putting a PowerPoint - slide together. I just plain outgrew it. There were too many things I - wanted to do that I simply couldn't. I was also at the mercy of Google's - constant change. After I finished constructing my first site, Google - <a - href="https://gsuiteupdates.googleblog.com/2016/11/a-totally-rebuilt-google-sitesnow.html" - >announced they would be shutting down the old Google Sites in favor - of an entirely new platform under the same name</a - >. Weeks of work got thrown out the window. You might also not care - about ads or customization. You may be intimidated by doing things - yourself and prefer that the landlord take care of everything. - Personally, I like the challenge and the craftsmanship that comes with - doing something myself. And I like being in total control of my server, - site, and content. Not from a tinfoil hat perspective but from a "gosh I - really wish I could just share more than 15 gigabytes of family video - with my relatives in New York and Ohio" perspective. - </p> - - <p> - So that's why I created my own website. If you want to know - <em>how</em> I host my own website, look for another post about my - server setup where I'll explain everything I'm hosting and how I got it - all hooked up. And that's a wrap. Now you know why I'm here instead of - somewhere else online. Sure, I do have Facebook and YouTube accounts but - I don't frequently update anything on either of them. This site is my - home online. It's where I keep all of my interests, hobbies, and - memories for sharing with others. - </p> - - <p> - Now you know where to find me. If you want to keep up with me, be - old-fashioned and subscribe to my RSS feed. - </p> - </article> - </body> -</html> diff --git a/posts/2019-04-06-why-have-a-website-in-2019.php b/posts/2019-04-06-why-have-a-website-in-2019.php new file mode 100644 index 0000000..b49d049 --- /dev/null +++ b/posts/2019-04-06-why-have-a-website-in-2019.php @@ -0,0 +1,112 @@ +<?php +$title = "Why Have a Web Site in 2019?"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<blockquote> + Adam, why on earth do you have a website? Wait... Is this a + <em>blog</em>? It's 2019, why don't you just use Facebook?! +</blockquote> + +<p> + I've wanted to have my own website for a long time mostly because I like + playing with technology. I think it's cool that I can make a few files + on a computer in my closet available for the entire world to see. The + web has become a near-necessity in our daily lives and it's only been + around for a couple of decades. That has always fascinated me enough to + drive me to see if I can do it on my own. I started self-hosting my own + web server about a year ago now and it's been an awesome study in the + way all of the tech we use on the web works. +</p> + +<p> + A written website is also a good way to keep up on my writing skills. + I've graduated college and won't be writing essays for the foreseeable + eternity. Which is fine except that I have no reason to write creatively + or formally anymore. Having this site encourages me to continue turning + thoughts into words, even though it's more casual than a term paper. +</p> + +<p> + This extends into the professionalism of a personal website. Normally + you can't point your employer towards your Twitter profile as the + distillation of your online footprint. Having a website, especially one + that separates professional and personal interests, is ten times better + than a resume, especially in the world of technology. It lets you tell + people exactly who you are and what you do, without forcing them to + navigate through an auth wall or a bunch of puppy photos. Your + professional and personal lives don't bleed together quite as much and + it makes for a kick-ass business card. +</p> + +<p> + Most importantly however, I enjoy the level of control that I gain with + creating and operating my own website, something I have also sought for + a long time. In high school I set up an old Dell from my school's + recycling center with Windows XP and Microsoft Internet Information + Services. It didn't have SSL or even a domain name but it was reachable + over the WAN. I set up an upload system so that my friends and I could + 'post' memes and funny messages for each other on raw html pages written + with Microsoft Word. That was the extent of its functionality. It was + slow, insecure, and went offline every time the router got a new IP + assigned to it. But I didn't care. It was a site the school couldn't + block. It had no name and no rules and nobody could tell us what to do + with it because it was ours. And we called it the + <em>Troll Nexus Center</em> because that's what you do when you're 15 +</p> + +<p> + My reasons then for building the Troll Nexus Center still stand now. + <em>Having your own website is having your own piece of internet + property.</em> + I first heard this wording from + <a href="https://www.youtube.com/watch?v=azkWYxyqh3Y">Luke Smith over on his YouTube channel</a> + and it's one-hundred percent true. Tumblogs, Google Sites, Facebook + profiles, and GitHub Pages are all like renting an apartment. Sure, + there are some really nice apartments out there but it's not the same as + owning your own home. You have to pay rent obviously, and rent is + subject to change once your lease is up. If anything breaks you text + your landlord and wait to have it fixed. You aren't allowed to fix it + yourself and sometimes it doesn't get fixed at all. And of course you're + limited by how much you can customize things to your own liking. Whether + it's painting walls or knocking them down. +</p> + +<p> + These limitations may or may not apply to you. Whether you're paying for + storage, server space, metrics, or watching an ad every five seconds, + these services aren't free either. And you certainly can't fix + everything that goes wrong with them. I started on Google Sites. It's a + truly fantastic system. Building a site is like putting a PowerPoint + slide together. I just plain outgrew it. There were too many things I + wanted to do that I simply couldn't. I was also at the mercy of Google's + constant change. After I finished constructing my first site, Google + <a href="https://gsuiteupdates.googleblog.com/2016/11/a-totally-rebuilt-google-sitesnow.html">announced they would be shutting down the old Google Sites in favor + of an entirely new platform under the same name</a>. Weeks of work got thrown out the window. You might also not care + about ads or customization. You may be intimidated by doing things + yourself and prefer that the landlord take care of everything. + Personally, I like the challenge and the craftsmanship that comes with + doing something myself. And I like being in total control of my server, + site, and content. Not from a tinfoil hat perspective but from a "gosh I + really wish I could just share more than 15 gigabytes of family video + with my relatives in New York and Ohio" perspective. +</p> + +<p> + So that's why I created my own website. If you want to know + <em>how</em> I host my own website, look for another post about my + server setup where I'll explain everything I'm hosting and how I got it + all hooked up. And that's a wrap. Now you know why I'm here instead of + somewhere else online. Sure, I do have Facebook and YouTube accounts but + I don't frequently update anything on either of them. This site is my + home online. It's where I keep all of my interests, hobbies, and + memories for sharing with others. +</p> + +<p> + Now you know where to find me. If you want to keep up with me, be + old-fashioned and subscribe to my RSS feed. +</p> diff --git a/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html b/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html deleted file mode 100644 index 569d925..0000000 --- a/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html +++ /dev/null @@ -1,322 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="How to Start and Drive a Hudson Hornet" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ How to Start and Drive a Hudson Hornet</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>How to Start and Drive a Hudson Hornet</h1> - - <p class="description"> - My understanding is there are a lot of people out there for whom driving - a car from the mid-20th century is an oddity, a curiosity, or a life - experience they can't relate to. This is for the non-experts, and - non-Hudsonites to get an idea of what it's like. - </p> - - <p> - There are some significant differences between driving the Hornet and - most other cars you come across today. Some of them are just because - there are sixty-six years between the Hudson and the 2019 model year. - Others are Hudson-specific. Many people who I've talked to have said - that they would feel intimidated driving my car (whether that's because - of its perceived complexity or obvious value to me). So, for those who - just want to know how it's done: here is how you start and drive a - Hudson Hornet. - </p> - - <h2>The Gauge Cluster, Switches, and Controls</h2> - - <p> - Open the door, slide onto the bench seat, and sit behind the [massive] - steering wheel. For those who haven't experienced it before, it feels - like you have a whole lot of room at your disposal, almost like there - <em>should</em> be more matter occupying the space around you. In front - of you is probably the shiniest dashboard you've ever seen. It's simple, - and probably slightly familiar. - </p> - <p>From left to right above the steering wheel you have:</p> - <ul> - <li> - A speedometer that tops out at 120 mph (with 99K odometer inside) - </li> - <li> - Fuel and coolant temperature gauges (and two dummy lights; more on - those later) - </li> - <li>A clock</li> - <li>An AM radio</li> - <li>A glove compartment</li> - </ul> - - <p>From left to right under the steering wheel you have:</p> - <ul> - <li>A 2-speed wiper control knob</li> - <li>A weather control (heater) temperature slider</li> - <li>A 2-speed weather control fan knob</li> - <li>The ignition barrel</li> - <li>A headlight switch</li> - <li> - A cigarette-lighter (the owner's manual calls it a cigar lighter!) - </li> - </ul> - - <p> - Also, underneath the dashboard on the left there is a parking brake - handle and hood latch release and on the right there is an arm which - raises and lowers the fresh air cowl vent. Think of it as "recirculate" - in more modern vehicles. If you're looking for the turn signal lever - it's the tiny stick to the left of the steering wheel. The indicator is - the little yellow light on the far left of the dash. There's only one so - it flashes when you're signalling left or right. We also added our own - air conditioning system, something Hudsons never came with from the - factory. - </p> - - <h2>Dual-Range Hydramatic</h2> - - <p> - The first thing that might confuse some folks when they first see the - car running is the shift lever. Many Hornets came with three-speed - manual transmissions that were shifted from the column (overdrive was an - option). However, lots of owners paid extra for the optional "Dual-range - Hydramatic", a fully automatic transmission from General Motors. Truly, - this car has a 4-speed automatic that requires no manual shifting during - normal use, making it that much easier to take a boatload of people to - get milkshakes. - </p> - - <p> - Behind the steering wheel is a shift indicator that deviates from the - "PRNDL" pattern most folks are familiar with. From left to right (shift - arm fully at the top to arm fully towards the bottom), the 'gears' are: - </p> - <ul> - <li>N (Neutral)</li> - <li>4-Dr (Drive, all four speeds)</li> - <li>3-Dr (Drive, three speeds only)</li> - <li>Lo (Low gear)</li> - <li>R (Reverse)</li> - </ul> - - <p> - Neutral isn't just a mid-way point between reverse and drive in this - car. It's a necessity. With automatic Hornets (and Hydramatics in - general), neutral is used to start the car. There is an electric lockout - preventing the car from being started in any gear but neutral, so you do - have to put the car in neutral before you turn the key (if you're on a - hill put your foot on the brake or engage the parking brake). - </p> - - <p> - Drive is split into 4-Dr and 3-Dr, which basically decides whether the - transmission utilizes high gear. In the owner's manual, Hudson - recommends using 3-Dr for driving around town (as the low RPMs delivered - by high gear means unnecessary shifting in and out of 4th gear) and 4-Dr - for highway driving. It really depends on what speed you're going to be - driving at but there isn't anything wrong with driving around in 4 all - the time. I typically leave it in 4th at sustained speeds above 45MPH. - You can switch between these gears any time while moving. - </p> - - <p> - Low gear basically locks the transmission in 2nd gear so you don't spin - the wheels. The owner's manual says this is for pulling out of sand or - dirt if you get stuck. - </p> - - <p> - Reverse works just about how you might expect but with an added catch: - if the engine is off it acts as park. That's right. When you turn the - car off you can put it in reverse and the transmission will engage a - lock pin to prevent the car from rolling. You can't start the car in - this gear because of the lockout however so you have to shift into - neutral to start the car. So for starting, put it in neutral, for - stopping, put it in reverse. - </p> - - <h2>Choke and Gas</h2> - - <p> - For cold starts, our Hornet (and I believe this was common for other - Hudsons of the time) is equipped with an automatic 2-stage choke. Push - the pedal all the way to the floor once to set the choke. After the car - has started and has warmed up, kick the gas quickly to the floor and - release to cancel the choke. - </p> - - <p> - For warm starts the engine doesn't need the choke but likes to be given - just a little bit of gas while cranking. - </p> - - <h2>The Keys, Ignition, and Warning Lights</h2> - - <p> - Hudsons like mine come with two keys. The octagonal one is for starting - the car, it's used in the ignition. The round one is used for the door - and trunk locks (and I believe in my case the glove box). My - understanding is this is actually reversed from the majority of Hudsons - and is due to a locksmith error at one point or another. - </p> - - <p> - The ignition switch sits so that the teeth of the key enter vertically. - Turning the key left powers accessories like the radio. Turning the key - right once switches the car to "ON" which will allow the engine to be - started and remain running. - </p> - - <p> - Here's where some things may vary depending on the year of the car. For - '51 Hornets, there's a separate starter button located all the way on - the left control pod. For these cars, you put the key in and turn it to - "ON", and then press and hold the button until the car has started up. - For '52 Hornets onwards, the ignition switch also activates the starter - if you turn the key past "ON" (like in most modern vehicles). - </p> - - <p> - If you turn the key to "ON" you'll see two red warning lights appear on - the dash next to the indicators marked "AMP" and "OIL". These are - [alternator] charging status and oil pressure status lights. Our car is - equipped with a 12-V alternator system so the AMP light really comes on - if there is low voltage while the oil pressure light comes on when - there's low oil pressure. These lights will only appear with engine off, - key "ON" or if something has gone very wrong. - </p> - - <h2>Starting and Driving</h2> - - <p> - So now that I've gone over the basics of all the components, here is the - normal starting procedure. It actually varies depending on whether the - engine has been warmed up. That's life with carburetors. - </p> - - <h3>From cold:</h3> - - <ul> - <li> - Put your foot on the brake, and shift the lever into neutral. Just - push it vertically, pulling towards you slightly if you need to. - </li> - <li> - Push the gas pedal all the way to the floor once and let your foot - back up again to set the choke. - </li> - <li> - Put the key in the ignition and start the car (the "AMP" and "OIL" - lights should switch off. - </li> - <li> - Wait for the engine to smooth out so you know that it's warm enough to - cancel the choke, and kick the gas pedal once to cancel it. (If the - RPMs are still higher than idle then it's not quite at operating - temperature yet) - </li> - <li> - Pull the shifter down into 4-Dr or 3-Dr (or R), and release the - parking brake by twisting the handle towards the steering wheel - </li> - <li>Let off the brake and you're off!</li> - </ul> - - <h3>From warm:</h3> - - <ul> - <li>Put your foot on the brake and shift into neutral.</li> - <li> - While giving just a little bit of gas, start the car. Both warning - lights should disappear. When the engine fires up you can let off the - gas and let it idle. - </li> - <li> - Pull the shifter into 4-Dr or 3-Dr (or R), and release the parking - brake by twisting the handle towards the steering wheel. - </li> - <li>Done.</li> - </ul> - - <h2>Stopping and Parking</h2> - - <ul> - <li> - Hold your foot on the brake and twist the parking brake handle towards - the door of the car, and pull it towards you - </li> - <li> - When you're ready to shut off the engine, you can shift it into either - neutral or reverse and turn the key off. Shift it into reverse if you - haven't already to lock the transmission. - </li> - </ul> - - <p> - Note: I usually engage the parking brake AND put the car in reverse, - just to be safe. If you had to pick one however I would use the - transmission in case you're on a steep hill and your brakes fail for - whatever reason. - </p> - - <p> - And there you have it! Not much is different from most cars around today - but there are one or two quirks (more about old cars than about Hudsons - in particular). The only major thing to keep track of while driving is - that you have no power steering, so get ready to anticipate turns sooner - and use more of the wheel with every turn. - </p> - </article> - </body> -</html> diff --git a/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php b/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php new file mode 100644 index 0000000..53e0f40 --- /dev/null +++ b/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php @@ -0,0 +1,267 @@ +<?php +$title = "How to Start and Drive a Hudson Hornet"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + My understanding is there are a lot of people out there for whom driving + a car from the mid-20th century is an oddity, a curiosity, or a life + experience they can't relate to. This is for the non-experts, and + non-Hudsonites to get an idea of what it's like. +</p> + +<p> + There are some significant differences between driving the Hornet and + most other cars you come across today. Some of them are just because + there are sixty-six years between the Hudson and the 2019 model year. + Others are Hudson-specific. Many people who I've talked to have said + that they would feel intimidated driving my car (whether that's because + of its perceived complexity or obvious value to me). So, for those who + just want to know how it's done: here is how you start and drive a + Hudson Hornet. +</p> + +<h2>The Gauge Cluster, Switches, and Controls</h2> + +<p> + Open the door, slide onto the bench seat, and sit behind the [massive] + steering wheel. For those who haven't experienced it before, it feels + like you have a whole lot of room at your disposal, almost like there + <em>should</em> be more matter occupying the space around you. In front + of you is probably the shiniest dashboard you've ever seen. It's simple, + and probably slightly familiar. +</p> +<p>From left to right above the steering wheel you have:</p> +<ul> + <li> + A speedometer that tops out at 120 mph (with 99K odometer inside) + </li> + <li> + Fuel and coolant temperature gauges (and two dummy lights; more on + those later) + </li> + <li>A clock</li> + <li>An AM radio</li> + <li>A glove compartment</li> +</ul> + +<p>From left to right under the steering wheel you have:</p> +<ul> + <li>A 2-speed wiper control knob</li> + <li>A weather control (heater) temperature slider</li> + <li>A 2-speed weather control fan knob</li> + <li>The ignition barrel</li> + <li>A headlight switch</li> + <li> + A cigarette-lighter (the owner's manual calls it a cigar lighter!) + </li> +</ul> + +<p> + Also, underneath the dashboard on the left there is a parking brake + handle and hood latch release and on the right there is an arm which + raises and lowers the fresh air cowl vent. Think of it as "recirculate" + in more modern vehicles. If you're looking for the turn signal lever + it's the tiny stick to the left of the steering wheel. The indicator is + the little yellow light on the far left of the dash. There's only one so + it flashes when you're signalling left or right. We also added our own + air conditioning system, something Hudsons never came with from the + factory. +</p> + +<h2>Dual-Range Hydramatic</h2> + +<p> + The first thing that might confuse some folks when they first see the + car running is the shift lever. Many Hornets came with three-speed + manual transmissions that were shifted from the column (overdrive was an + option). However, lots of owners paid extra for the optional "Dual-range + Hydramatic", a fully automatic transmission from General Motors. Truly, + this car has a 4-speed automatic that requires no manual shifting during + normal use, making it that much easier to take a boatload of people to + get milkshakes. +</p> + +<p> + Behind the steering wheel is a shift indicator that deviates from the + "PRNDL" pattern most folks are familiar with. From left to right (shift + arm fully at the top to arm fully towards the bottom), the 'gears' are: +</p> +<ul> + <li>N (Neutral)</li> + <li>4-Dr (Drive, all four speeds)</li> + <li>3-Dr (Drive, three speeds only)</li> + <li>Lo (Low gear)</li> + <li>R (Reverse)</li> +</ul> + +<p> + Neutral isn't just a mid-way point between reverse and drive in this + car. It's a necessity. With automatic Hornets (and Hydramatics in + general), neutral is used to start the car. There is an electric lockout + preventing the car from being started in any gear but neutral, so you do + have to put the car in neutral before you turn the key (if you're on a + hill put your foot on the brake or engage the parking brake). +</p> + +<p> + Drive is split into 4-Dr and 3-Dr, which basically decides whether the + transmission utilizes high gear. In the owner's manual, Hudson + recommends using 3-Dr for driving around town (as the low RPMs delivered + by high gear means unnecessary shifting in and out of 4th gear) and 4-Dr + for highway driving. It really depends on what speed you're going to be + driving at but there isn't anything wrong with driving around in 4 all + the time. I typically leave it in 4th at sustained speeds above 45MPH. + You can switch between these gears any time while moving. +</p> + +<p> + Low gear basically locks the transmission in 2nd gear so you don't spin + the wheels. The owner's manual says this is for pulling out of sand or + dirt if you get stuck. +</p> + +<p> + Reverse works just about how you might expect but with an added catch: + if the engine is off it acts as park. That's right. When you turn the + car off you can put it in reverse and the transmission will engage a + lock pin to prevent the car from rolling. You can't start the car in + this gear because of the lockout however so you have to shift into + neutral to start the car. So for starting, put it in neutral, for + stopping, put it in reverse. +</p> + +<h2>Choke and Gas</h2> + +<p> + For cold starts, our Hornet (and I believe this was common for other + Hudsons of the time) is equipped with an automatic 2-stage choke. Push + the pedal all the way to the floor once to set the choke. After the car + has started and has warmed up, kick the gas quickly to the floor and + release to cancel the choke. +</p> + +<p> + For warm starts the engine doesn't need the choke but likes to be given + just a little bit of gas while cranking. +</p> + +<h2>The Keys, Ignition, and Warning Lights</h2> + +<p> + Hudsons like mine come with two keys. The octagonal one is for starting + the car, it's used in the ignition. The round one is used for the door + and trunk locks (and I believe in my case the glove box). My + understanding is this is actually reversed from the majority of Hudsons + and is due to a locksmith error at one point or another. +</p> + +<p> + The ignition switch sits so that the teeth of the key enter vertically. + Turning the key left powers accessories like the radio. Turning the key + right once switches the car to "ON" which will allow the engine to be + started and remain running. +</p> + +<p> + Here's where some things may vary depending on the year of the car. For + '51 Hornets, there's a separate starter button located all the way on + the left control pod. For these cars, you put the key in and turn it to + "ON", and then press and hold the button until the car has started up. + For '52 Hornets onwards, the ignition switch also activates the starter + if you turn the key past "ON" (like in most modern vehicles). +</p> + +<p> + If you turn the key to "ON" you'll see two red warning lights appear on + the dash next to the indicators marked "AMP" and "OIL". These are + [alternator] charging status and oil pressure status lights. Our car is + equipped with a 12-V alternator system so the AMP light really comes on + if there is low voltage while the oil pressure light comes on when + there's low oil pressure. These lights will only appear with engine off, + key "ON" or if something has gone very wrong. +</p> + +<h2>Starting and Driving</h2> + +<p> + So now that I've gone over the basics of all the components, here is the + normal starting procedure. It actually varies depending on whether the + engine has been warmed up. That's life with carburetors. +</p> + +<h3>From cold:</h3> + +<ul> + <li> + Put your foot on the brake, and shift the lever into neutral. Just + push it vertically, pulling towards you slightly if you need to. + </li> + <li> + Push the gas pedal all the way to the floor once and let your foot + back up again to set the choke. + </li> + <li> + Put the key in the ignition and start the car (the "AMP" and "OIL" + lights should switch off. + </li> + <li> + Wait for the engine to smooth out so you know that it's warm enough to + cancel the choke, and kick the gas pedal once to cancel it. (If the + RPMs are still higher than idle then it's not quite at operating + temperature yet) + </li> + <li> + Pull the shifter down into 4-Dr or 3-Dr (or R), and release the + parking brake by twisting the handle towards the steering wheel + </li> + <li>Let off the brake and you're off!</li> +</ul> + +<h3>From warm:</h3> + +<ul> + <li>Put your foot on the brake and shift into neutral.</li> + <li> + While giving just a little bit of gas, start the car. Both warning + lights should disappear. When the engine fires up you can let off the + gas and let it idle. + </li> + <li> + Pull the shifter into 4-Dr or 3-Dr (or R), and release the parking + brake by twisting the handle towards the steering wheel. + </li> + <li>Done.</li> +</ul> + +<h2>Stopping and Parking</h2> + +<ul> + <li> + Hold your foot on the brake and twist the parking brake handle towards + the door of the car, and pull it towards you + </li> + <li> + When you're ready to shut off the engine, you can shift it into either + neutral or reverse and turn the key off. Shift it into reverse if you + haven't already to lock the transmission. + </li> +</ul> + +<p> + Note: I usually engage the parking brake AND put the car in reverse, + just to be safe. If you had to pick one however I would use the + transmission in case you're on a steep hill and your brakes fail for + whatever reason. +</p> + +<p> + And there you have it! Not much is different from most cars around today + but there are one or two quirks (more about old cars than about Hudsons + in particular). The only major thing to keep track of while driving is + that you have no power steering, so get ready to anticipate turns sooner + and use more of the wheel with every turn. +</p> diff --git a/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html b/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html deleted file mode 100644 index 8a0e587..0000000 --- a/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html +++ /dev/null @@ -1,127 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Offloading GoPro Footage the Easy Way!" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Offloading GoPro Footage the Easy Way!</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Offloading GoPro Footage the Easy Way!</h1> - - <p> - Transferring files off of most cameras to a Linux computer isn't all - that difficult. The exception is my GoPro Hero 4 Black. For 4th of July - week I took a bunch of video with the GoPro, approximately 20 MP4 files, - about 3GB each. The annoying thing about the GoPro's USB interface is - you need additional software to download everything through the cable. - The camera doesn't just show up as a USB filesystem that you can mount. - The GoPro does have a micro-SD card but I was away from home and didn't - have any dongles or adapters. Both of these solutions also mean taking - the camera out of its waterproof case and off of its mount. So here's - what I did. - </p> - - <p> - GoPro cameras, after the Hero 3, can open up an ad-hoc wireless network - that lets you browse the GoPro's onboard files through an HTTP server. - This means you can open your browser and scroll through the files on the - camera at an intranet address, <code>10.5.5.9</code>, and download them - one by one by clicking every link on every page. If you have a lot of - footage on there it kinda sucks. So, I opened up the manual for - <code>wget</code>. I'm sure you could get really fancy with some of the - options but the only thing I cared about was downloading every single - MP4 video off of the camera, automatically. I did not want to download - any of the small video formats or actual HTML files. Here's what I used: - </p> - - <pre> - <code> -sh wget --recursive --accept "*.MP4" http://10.5.5.9:8080/ - </code> - </pre> - - <p> - This tells <code>wget</code> to download all of the files at the GoPro's - address recursively and skips any that don't have the MP4 extension. Now - I've got a directory tree with all of my videos in it. And the best part - is I didn't have to install the dinky GoPro app on my laptop. Hopefully - this helps if you're looking for an easy way to migrate lots of footage - without manually clicking through the web interface or installing - additional software. The only downside is if you're moving a whole lot - of footage, it's not nearly as quick as just moving files off the SD - card. So I'd shoot for using the adapter to read off the card first and - only use this if that's not an option, such as when the camera is - mounted and you don't want to move it. - </p> - - <p>Some things I would like to change/add:</p> - - <ul> - <li> - Download all image files as well; should be easy, just another - <code>--accept</code> - </li> - <li>Initiate parallel downloads</li> - <li> - Clean up the directory afterwards so I just have one level of depth - </li> - </ul> - - <p> - I could probably write a quick and dirty shell script to do all of this - for me but I use the camera so infrequently that it's probably not even - worth it. - </p> - </article> - </body> -</html> diff --git a/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php b/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php new file mode 100644 index 0000000..34685de --- /dev/null +++ b/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php @@ -0,0 +1,72 @@ +<?php +$title = "Offloading GoPro Footage the Easy Way!"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + Transferring files off of most cameras to a Linux computer isn't all + that difficult. The exception is my GoPro Hero 4 Black. For 4th of July + week I took a bunch of video with the GoPro, approximately 20 MP4 files, + about 3GB each. The annoying thing about the GoPro's USB interface is + you need additional software to download everything through the cable. + The camera doesn't just show up as a USB filesystem that you can mount. + The GoPro does have a micro-SD card but I was away from home and didn't + have any dongles or adapters. Both of these solutions also mean taking + the camera out of its waterproof case and off of its mount. So here's + what I did. +</p> + +<p> + GoPro cameras, after the Hero 3, can open up an ad-hoc wireless network + that lets you browse the GoPro's onboard files through an HTTP server. + This means you can open your browser and scroll through the files on the + camera at an intranet address, <code>10.5.5.9</code>, and download them + one by one by clicking every link on every page. If you have a lot of + footage on there it kinda sucks. So, I opened up the manual for + <code>wget</code>. I'm sure you could get really fancy with some of the + options but the only thing I cared about was downloading every single + MP4 video off of the camera, automatically. I did not want to download + any of the small video formats or actual HTML files. Here's what I used: +</p> + +<pre> + <code> +sh wget --recursive --accept "*.MP4" http://10.5.5.9:8080/ + </code> + </pre> + +<p> + This tells <code>wget</code> to download all of the files at the GoPro's + address recursively and skips any that don't have the MP4 extension. Now + I've got a directory tree with all of my videos in it. And the best part + is I didn't have to install the dinky GoPro app on my laptop. Hopefully + this helps if you're looking for an easy way to migrate lots of footage + without manually clicking through the web interface or installing + additional software. The only downside is if you're moving a whole lot + of footage, it's not nearly as quick as just moving files off the SD + card. So I'd shoot for using the adapter to read off the card first and + only use this if that's not an option, such as when the camera is + mounted and you don't want to move it. +</p> + +<p>Some things I would like to change/add:</p> + +<ul> + <li> + Download all image files as well; should be easy, just another + <code>--accept</code> + </li> + <li>Initiate parallel downloads</li> + <li> + Clean up the directory afterwards so I just have one level of depth + </li> +</ul> + +<p> + I could probably write a quick and dirty shell script to do all of this + for me but I use the camera so infrequently that it's probably not even + worth it. +</p> diff --git a/posts/2019-07-04-yabs-yet-another-bad-shop.html b/posts/2019-07-04-yabs-yet-another-bad-shop.html deleted file mode 100644 index 371f151..0000000 --- a/posts/2019-07-04-yabs-yet-another-bad-shop.html +++ /dev/null @@ -1,235 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="YABS: Yet Another Bad Shop" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ YABS: Yet Another Bad Shop</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>YABS: Yet Another Bad Shop</h1> - <p> - Today I received a text message from a local mechanic/auto shop asking - me to leave them a Google review. It was an automated message from a - shop that I know well and have used many times in the past. - Unfortunately, I have had several poor experiences (at the time they - seemed horrific) with them in the past year and I can honestly say - they'll never receive my business again. Now I could have used this as - an opportunity to leave them an anonymous nasty-gram but instead I'm - going to do the opposite. I'm going to write about everything I don't - like about them without telling you who they are or hiding who I am. Why - would I do that? Well for one, they were an excellent shop for many - years. I believe a recent change in management is to blame and I'm not - going to ruin their chances of making a comeback (because frankly I - would like for them to rebound). And secondly, I don't believe in - hiding. This page and its author are public knowledge. Now, in no - particular order: a sample of awful work from yet another bad shop. - </p> - - <h2>Mom's Truck -- Balls Out</h2> - - <p> - Mom's truck is a 2007 Chrysler Aspen that she loves very much. Dad does - a whole lot of work on it himself (the both of us do pretty much - everything we can in-house so long as we have the right equipment). - We've been taking her truck into this shop for years because we've found - them to be reliable, efficient, and economical. As I said before, at - some point in their recent history they changed hands -- either - ownership or management, I can't remember which. It was around this time - that Dad decided to overhaul Mom's front suspension. He replaced the - ball joints, tie rod ends, and a few other worn out parts. He then did - his own best-guess front-end alignment, but left everything loose so - that YABS could finish up the alignment and tighten everything. Now read - that again because it's important. Dad did his own alignment in our - driveway (as a cost-saving measure), got it decently close, but then - instructed this shop to finish the job and tighten everything up. - </p> - - <p> - Now here's where things fall apart. This shop full of professional - mechanics took one look at the alignment Dad did and decided it was good - enough. Hooray for Dad and supernatural mechanical skills, but the shop - didn't even touch the car. They called Dad back to come pick up the car, - telling him it was already good to go. They never tightened a thing, - even after Dad explicitly told them everything was loose and needed to - be tightened but they didn't to touch a thing. So what happened? Dad - picked up the car assuming everything was A-OK and Mom drove the car for - about a week before the two front tires wore down so badly they had to - be replaced immediately. Everything fell out of alignment as things - loosened further and further and the tires wore unevenly until they - ripped themselves to shreds. The worst part? These weren't tires with 6+ - years on them. These were brand new tires. So YABS got to install two - more front tires and then tighten everything. They did not cover the - costs, presumably because it was Dad who had done the alignment. Strike - one. - </p> - - <h2>Friend's Minivan -- Crude Necessities</h2> - - <p> - A good friend of ours drives a 2005-2006 Chrysler Town and Country. It - was actually Mom's car before upgrading to the Aspen (the minivan was - perfect in every way but it couldn't tow). Our friend has been using - YABS for just a long as we have. Once again, things started getting - kinda strange after several years of good service. She started getting - charged extra for simple repairs she had them doing very consistently. - They also started tacking on extra items for routine jobs. She would go - in for an inspection and they would claim she needed a new Part X. Now - this in and of itself isn't an uncommon or even strange request to make. - As cars age they need things and sometimes you don't know what they need - until you visit a professional mechanic. They remember the things you - forget about. - </p> - - <p> - One day they did all the forgetting, and they forgot a pretty important, - nay, crucial engine component: motor oil. Our friend took her minivan - into YABS for a routine oil change. Good diligence on her part. And - she's not the type to do that change on her own. She's too old to get - under a car anyway (no offense!). So she took the van to YABS and they - did a job they've done thousands of times: drain oil, replaced the - filter, and gave her back the car. Easy peasy right? Now I know I'm not - a professional but I'm thinking someone might have wanted to - double-check that several quarts of synthetic had left the shop shelf - and gone into the car they just backed out of the bay door. Now this - part of the story I'm a little fuzzy on so take it with a large, heaping - grain of salt, but I can say for a fact that they failed to - <em>completely</em> refill the engine oil before returning her car. - Supposedly there was enough in there such that the minivan survived long - enough for them to realize it before she drove off. - </p> - - <h2>Monty, My 2013 Ford Focus -- Nut Allergy</h2> - - <p> - I decided to give YABS another try after a long leave of absence. I - needed new tires all around for my daily driver. I also needed an - inspection and an alignment. A simple set of tasks for any shop (you see - where this is going). I initially tried to go to another local shop but - they were all out of the tires I was looking to get so I caved and went - to YABS. About halfway through the job they gave me a call and told me - they had some bad news. They said that there were some issues getting - the lug nuts off my wheels and that they had all been stripped, warped, - or otherwise destroyed in the process. They told me the only fix was to - get new ones from a supplier in town for about $160. Keep in mind the - entire job (inspection, tires, etc.) was going to cost $650. - Furthermore, dad and I had no problem getting those lug nuts off and - back on again just a few weeks prior when we changed the transmission - fluid. - </p> - - <p> - They didn't have an explanation that I could reconcile with. Joe Schmo - over the phone told me this is typical of Fords and Chryslers these days - and that they'd like to keep my lug nuts for a class action lawsuit - they're participating in. Now why on Earth would any sane mechanic, with - full knowledge they are dealing with a defective set of lug nuts, take a - high power impact wrench to those wheels without speaking with the owner - about it first? Smelled fishy to me honestly. But what was I gonna do? - Dad went out and grabbed twenty new lug nuts for cheaper than they - wanted to sell them for. - </p> - - <p> - Oh the tires were Cooper GTs by the way and they're amazing. They're - smooth and quiet and came with a very nice warranty. They're also made - in the USA, which is very important to me. 10/10 would recommend. - </p> - - <h2>Ol' Blue -- Tunnel Vision</h2> - - <p> - This was the real kicker. And this one doesn't really have any trailing - narrative. I got four new tires on Ol' Blue, my 1953 Hudson Hornet. They - were delivered to our house: four brand new Diamond Back wide white wall - radials. Super nice tires, with a super nice road hazard warranty (as a - side note I totally recommend you - <a href="https://dbtires.com/">check out Diamond Back's website</a> if - you're looking for white wall radials). So we brought the car to YABS - with the new tires and asked them to mount them on the car. - </p> - - <p> - When we went to pick up the car everything looked great and I drove off. - I made it all the way to the Monitor Merrimack Memorial Bridge Tunnel - before I heard a loud rattling and a bang. I looked in the rear-view - mirror and swore I could see my precious hubcap rolling off to eternity. - When they replaced the hubcaps they didn't fully press one of them on. - And it's not that difficult. These hub caps are very secure when pressed - on the rim, we've never had problems with them. Oh and we're talking - about Hudson hubcaps that came with the car, and aren't super easy to - find. And I couldn't stop to get out and grab it because I was right at - the mouth of the tunnel. We went back later to try and see it but we - couldn't. And it was probably destroyed getting thrown from the car - anyways. - </p> - - <p> - The worst part is, the hubcap took a chunk out of my white wall on its - way out from under the wheel skirt. So the day I got the tires I had to - take a picture and redeem my road hazard warranty. Luckily, Diamond Back - were true to their word and sent me a new one no questions asked. The - beat up tire is now my spare. - </p> - - <h2>Not All Bad</h2> - - <p> - Like I said before, YABS used to be a very nice shop with friendly - people that did good work. And they didn't charge exorbitant prices for - their work. Times have changed, and I believe management has as well. - I've stopped visiting their shop completely. I found a new one that I - trust and will be taking all of my cars to. They've already done a - safety inspection on Ol' Blue and didn't put up a fuss. They're clean - and friendly and don't seem to be out to screw me. But as with - everything else, your mileage may vary. - </p> - </article> - </body> -</html> diff --git a/posts/2019-07-04-yabs-yet-another-bad-shop.php b/posts/2019-07-04-yabs-yet-another-bad-shop.php new file mode 100644 index 0000000..9594369 --- /dev/null +++ b/posts/2019-07-04-yabs-yet-another-bad-shop.php @@ -0,0 +1,183 @@ +<?php +$title = "YABS: Yet Another Bad Shop"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<p> + Today I received a text message from a local mechanic/auto shop asking + me to leave them a Google review. It was an automated message from a + shop that I know well and have used many times in the past. + Unfortunately, I have had several poor experiences (at the time they + seemed horrific) with them in the past year and I can honestly say + they'll never receive my business again. Now I could have used this as + an opportunity to leave them an anonymous nasty-gram but instead I'm + going to do the opposite. I'm going to write about everything I don't + like about them without telling you who they are or hiding who I am. Why + would I do that? Well for one, they were an excellent shop for many + years. I believe a recent change in management is to blame and I'm not + going to ruin their chances of making a comeback (because frankly I + would like for them to rebound). And secondly, I don't believe in + hiding. This page and its author are public knowledge. Now, in no + particular order: a sample of awful work from yet another bad shop. +</p> + +<h2>Mom's Truck -- Balls Out</h2> + +<p> + Mom's truck is a 2007 Chrysler Aspen that she loves very much. Dad does + a whole lot of work on it himself (the both of us do pretty much + everything we can in-house so long as we have the right equipment). + We've been taking her truck into this shop for years because we've found + them to be reliable, efficient, and economical. As I said before, at + some point in their recent history they changed hands -- either + ownership or management, I can't remember which. It was around this time + that Dad decided to overhaul Mom's front suspension. He replaced the + ball joints, tie rod ends, and a few other worn out parts. He then did + his own best-guess front-end alignment, but left everything loose so + that YABS could finish up the alignment and tighten everything. Now read + that again because it's important. Dad did his own alignment in our + driveway (as a cost-saving measure), got it decently close, but then + instructed this shop to finish the job and tighten everything up. +</p> + +<p> + Now here's where things fall apart. This shop full of professional + mechanics took one look at the alignment Dad did and decided it was good + enough. Hooray for Dad and supernatural mechanical skills, but the shop + didn't even touch the car. They called Dad back to come pick up the car, + telling him it was already good to go. They never tightened a thing, + even after Dad explicitly told them everything was loose and needed to + be tightened but they didn't to touch a thing. So what happened? Dad + picked up the car assuming everything was A-OK and Mom drove the car for + about a week before the two front tires wore down so badly they had to + be replaced immediately. Everything fell out of alignment as things + loosened further and further and the tires wore unevenly until they + ripped themselves to shreds. The worst part? These weren't tires with 6+ + years on them. These were brand new tires. So YABS got to install two + more front tires and then tighten everything. They did not cover the + costs, presumably because it was Dad who had done the alignment. Strike + one. +</p> + +<h2>Friend's Minivan -- Crude Necessities</h2> + +<p> + A good friend of ours drives a 2005-2006 Chrysler Town and Country. It + was actually Mom's car before upgrading to the Aspen (the minivan was + perfect in every way but it couldn't tow). Our friend has been using + YABS for just a long as we have. Once again, things started getting + kinda strange after several years of good service. She started getting + charged extra for simple repairs she had them doing very consistently. + They also started tacking on extra items for routine jobs. She would go + in for an inspection and they would claim she needed a new Part X. Now + this in and of itself isn't an uncommon or even strange request to make. + As cars age they need things and sometimes you don't know what they need + until you visit a professional mechanic. They remember the things you + forget about. +</p> + +<p> + One day they did all the forgetting, and they forgot a pretty important, + nay, crucial engine component: motor oil. Our friend took her minivan + into YABS for a routine oil change. Good diligence on her part. And + she's not the type to do that change on her own. She's too old to get + under a car anyway (no offense!). So she took the van to YABS and they + did a job they've done thousands of times: drain oil, replaced the + filter, and gave her back the car. Easy peasy right? Now I know I'm not + a professional but I'm thinking someone might have wanted to + double-check that several quarts of synthetic had left the shop shelf + and gone into the car they just backed out of the bay door. Now this + part of the story I'm a little fuzzy on so take it with a large, heaping + grain of salt, but I can say for a fact that they failed to + <em>completely</em> refill the engine oil before returning her car. + Supposedly there was enough in there such that the minivan survived long + enough for them to realize it before she drove off. +</p> + +<h2>Monty, My 2013 Ford Focus -- Nut Allergy</h2> + +<p> + I decided to give YABS another try after a long leave of absence. I + needed new tires all around for my daily driver. I also needed an + inspection and an alignment. A simple set of tasks for any shop (you see + where this is going). I initially tried to go to another local shop but + they were all out of the tires I was looking to get so I caved and went + to YABS. About halfway through the job they gave me a call and told me + they had some bad news. They said that there were some issues getting + the lug nuts off my wheels and that they had all been stripped, warped, + or otherwise destroyed in the process. They told me the only fix was to + get new ones from a supplier in town for about $160. Keep in mind the + entire job (inspection, tires, etc.) was going to cost $650. + Furthermore, dad and I had no problem getting those lug nuts off and + back on again just a few weeks prior when we changed the transmission + fluid. +</p> + +<p> + They didn't have an explanation that I could reconcile with. Joe Schmo + over the phone told me this is typical of Fords and Chryslers these days + and that they'd like to keep my lug nuts for a class action lawsuit + they're participating in. Now why on Earth would any sane mechanic, with + full knowledge they are dealing with a defective set of lug nuts, take a + high power impact wrench to those wheels without speaking with the owner + about it first? Smelled fishy to me honestly. But what was I gonna do? + Dad went out and grabbed twenty new lug nuts for cheaper than they + wanted to sell them for. +</p> + +<p> + Oh the tires were Cooper GTs by the way and they're amazing. They're + smooth and quiet and came with a very nice warranty. They're also made + in the USA, which is very important to me. 10/10 would recommend. +</p> + +<h2>Ol' Blue -- Tunnel Vision</h2> + +<p> + This was the real kicker. And this one doesn't really have any trailing + narrative. I got four new tires on Ol' Blue, my 1953 Hudson Hornet. They + were delivered to our house: four brand new Diamond Back wide white wall + radials. Super nice tires, with a super nice road hazard warranty (as a + side note I totally recommend you + <a href="https://dbtires.com/">check out Diamond Back's website</a> if + you're looking for white wall radials). So we brought the car to YABS + with the new tires and asked them to mount them on the car. +</p> + +<p> + When we went to pick up the car everything looked great and I drove off. + I made it all the way to the Monitor Merrimack Memorial Bridge Tunnel + before I heard a loud rattling and a bang. I looked in the rear-view + mirror and swore I could see my precious hubcap rolling off to eternity. + When they replaced the hubcaps they didn't fully press one of them on. + And it's not that difficult. These hub caps are very secure when pressed + on the rim, we've never had problems with them. Oh and we're talking + about Hudson hubcaps that came with the car, and aren't super easy to + find. And I couldn't stop to get out and grab it because I was right at + the mouth of the tunnel. We went back later to try and see it but we + couldn't. And it was probably destroyed getting thrown from the car + anyways. +</p> + +<p> + The worst part is, the hubcap took a chunk out of my white wall on its + way out from under the wheel skirt. So the day I got the tires I had to + take a picture and redeem my road hazard warranty. Luckily, Diamond Back + were true to their word and sent me a new one no questions asked. The + beat up tire is now my spare. +</p> + +<h2>Not All Bad</h2> + +<p> + Like I said before, YABS used to be a very nice shop with friendly + people that did good work. And they didn't charge exorbitant prices for + their work. Times have changed, and I believe management has as well. + I've stopped visiting their shop completely. I found a new one that I + trust and will be taking all of my cars to. They've already done a + safety inspection on Ol' Blue and didn't put up a fuss. They're clean + and friendly and don't seem to be out to screw me. But as with + everything else, your mileage may vary. +</p> diff --git a/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html b/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html deleted file mode 100644 index 8fb1dfb..0000000 --- a/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html +++ /dev/null @@ -1,94 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Dancing the Shag & The [New] Lion King" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Dancing the Shag & The [New] Lion King</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img - alt="information" - src="/includes/icons/information-variant.svg" - /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Dancing the Shag & The [New] Lion King</h1> - <p> - Not all of my posts are huge, and they probably shouldn't be. Amy and I - had a really great time yesterday at Two Left Feet Dance Studio, - learning more about how to dance the Carolina Shag in preparation for - our wedding (which is in less than 20 days)! An enormous swing band is - going to play all of our favorites from the brass band/swing era, and - one of the easiest dances to do to that music is the Shag. I wrote a - paper on the Shag a few years ago for school but never actually learned - how to do it. The steps are simple for us to remember and it's easy - enough to add flair or mix it up so we look like we know what we're - doing during our first dance. - </p> - - <p> - We also got out to see the new Lion King remake and I can honestly say - it was worth it. If anyone's a Lion King purist, it's Amy. It's easily - been her favorite movie since she was a toddler, and to see it - tastefully redone almost 25 years after it was first released was - thoroughly enjoyable. There were minor alterations to literal sentences - in the script that all added some context to things that were always - kind of assumed in the original (clarification on Scar's backstory, - etc.). I did however feel like they were trying to throw Beyonce lines - the way a middle-schooler tries to turn a 500-word paper into a 700-word - paper. Regardless, it's definitely re-living the classic, not re-hashing - it. - </p> - </article> - </body> -</html> diff --git a/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php b/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php new file mode 100644 index 0000000..e382f15 --- /dev/null +++ b/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php @@ -0,0 +1,33 @@ +<?php +$title = "Dancing the Shag & The [New] Lion Ling"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<p> + Not all of my posts are huge, and they probably shouldn't be. Amy and I + had a really great time yesterday at Two Left Feet Dance Studio, + learning more about how to dance the Carolina Shag in preparation for + our wedding (which is in less than 20 days)! An enormous swing band is + going to play all of our favorites from the brass band/swing era, and + one of the easiest dances to do to that music is the Shag. I wrote a + paper on the Shag a few years ago for school but never actually learned + how to do it. The steps are simple for us to remember and it's easy + enough to add flair or mix it up so we look like we know what we're + doing during our first dance. +</p> + +<p> + We also got out to see the new Lion King remake and I can honestly say + it was worth it. If anyone's a Lion King purist, it's Amy. It's easily + been her favorite movie since she was a toddler, and to see it + tastefully redone almost 25 years after it was first released was + thoroughly enjoyable. There were minor alterations to literal sentences + in the script that all added some context to things that were always + kind of assumed in the original (clarification on Scar's backstory, + etc.). I did however feel like they were trying to throw Beyonce lines + the way a middle-schooler tries to turn a 500-word paper into a 700-word + paper. Regardless, it's definitely re-living the classic, not re-hashing + it. +</p> diff --git a/posts/2019-07-28-i-finally-found-a-drink-i-like.html b/posts/2019-07-28-i-finally-found-a-drink-i-like.html deleted file mode 100644 index 9350ae3..0000000 --- a/posts/2019-07-28-i-finally-found-a-drink-i-like.html +++ /dev/null @@ -1,86 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Finally Found a Drink I Like" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Finally Found a Drink I Like</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Finally Found a Drink I Like</h1> - <p> - Anyone who knows me even slightly well probably knows that I don't - drink. And it's not out of moral obligation or anything like that. I - just plain can't stand the taste of alcohol. So it's no surprise that my - entire family has been trying to throw different alcoholic beverages in - my direction to see what sticks. - </p> - - <p> - But it finally happened! I finally found a drink with alcohol in it. And - not only did I not gag, but I genuinely enjoy it, think it tastes great, - and mix it myself. - </p> - - <p> - It's called <em>Blackberry Cream Soda</em>. It's just blackberries, - ginger ale, and spiced rum. It's darn good. And it's going to be the - signature drink at our wedding, whatever that means. All I know is I can - finally order something at a bar and that's cool by me. - </p> - - <p> - <img - src="https://nextcloud.53hor.net/s/Jdpp8QYwo6nY9Fx/preview" - alt="Behold, Blackberry Cream Soda" - /> - </p> - </article> - </body> -</html> diff --git a/posts/2019-07-28-i-finally-found-a-drink-i-like.php b/posts/2019-07-28-i-finally-found-a-drink-i-like.php new file mode 100644 index 0000000..a73de9e --- /dev/null +++ b/posts/2019-07-28-i-finally-found-a-drink-i-like.php @@ -0,0 +1,31 @@ +<?php +$title = "Finally Found a Drink I Like"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<p> + Anyone who knows me even slightly well probably knows that I don't + drink. And it's not out of moral obligation or anything like that. I + just plain can't stand the taste of alcohol. So it's no surprise that my + entire family has been trying to throw different alcoholic beverages in + my direction to see what sticks. +</p> + +<p> + But it finally happened! I finally found a drink with alcohol in it. And + not only did I not gag, but I genuinely enjoy it, think it tastes great, + and mix it myself. +</p> + +<p> + It's called <em>Blackberry Cream Soda</em>. It's just blackberries, + ginger ale, and spiced rum. It's darn good. And it's going to be the + signature drink at our wedding, whatever that means. All I know is I can + finally order something at a bar and that's cool by me. +</p> + +<p> + <img src="https://nextcloud.53hor.net/s/Jdpp8QYwo6nY9Fx/preview" alt="Behold, Blackberry Cream Soda" /> +</p> diff --git a/posts/2019-08-11-marrying-my-best-friend.html b/posts/2019-08-11-marrying-my-best-friend.html deleted file mode 100644 index 24cb00a..0000000 --- a/posts/2019-08-11-marrying-my-best-friend.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="I Married My Best Friend!" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ I Married My Best Friend!</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>I Married My Best Friend!</h1> - <p> - It was an inexplicable mixture of joy and butterflies getting to marry - my best friend. It was truly like a dream come true, so much so that it - drove me to tears multiple times. Now that we're on our honeymoon, it - feels simultaneously like everything and nothing has changed but I think - that's a good thing. - </p> - - <p>More to come!</p> - </article> - </body> -</html> diff --git a/posts/2019-08-11-marrying-my-best-friend.php b/posts/2019-08-11-marrying-my-best-friend.php new file mode 100644 index 0000000..83bde5b --- /dev/null +++ b/posts/2019-08-11-marrying-my-best-friend.php @@ -0,0 +1,17 @@ +<?php +$title = "I Married My Best Friend!"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<h1>I Married My Best Friend!</h1> +<p> + It was an inexplicable mixture of joy and butterflies getting to marry + my best friend. It was truly like a dream come true, so much so that it + drove me to tears multiple times. Now that we're on our honeymoon, it + feels simultaneously like everything and nothing has changed but I think + that's a good thing. +</p> + +<p>More to come!</p> diff --git a/posts/2019-08-30-keep-right-except-to-pass.html b/posts/2019-08-30-keep-right-except-to-pass.html deleted file mode 100644 index 31f919b..0000000 --- a/posts/2019-08-30-keep-right-except-to-pass.html +++ /dev/null @@ -1,108 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Left Lane is for Passing, Not Cruising" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Left Lane is for Passing, Not Cruising</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Left Lane is for Passing, Not Cruising</h1> - - <p> - Greetings fellow drivers of Hampton Roads. You may have noticed a new - sign on I264 today that befuddled or confused you. It went something - along the lines of - </p> - - <blockquote>LEFT LANE IS FOR PASSING NOT CRUISING</blockquote> - - <p> - Believe it or not this has been the law throughout Virginia for years - (<a - href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-804/" - >read about it here</a - > - and - <a - href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-842.1/" - >here</a - >). The law states you keep right except while passing. In most other - states things work this way but in Virginia, especially around here, the - left lane is treated as a moving, cruising lane. If you're in the left - lane and you've completed a pass please be mindful of the cars behind - you and move back over into the right-hand lane(s) so that other drivers - can do the same. - </p> - - <p> - It's really nice when this is practiced (like I said, I've experienced - it in other states) because you can easily move over when there are slow - vehicles ahead and then continue on your merry way. It reduces - congestion and prevents people from having to pass in the right lane, - which is both annoying and dangerous. Especially since this is typically - the lane cars from entrance and exit ramps are merging with. - </p> - - <p> - Don't forget too that it isn't rude or road-rage-y for someone behind - you to honk their horn or flash their lights if you're moving too slowly - in the passing lane. This is a perfectly polite request to pass you. You - don't set or enforce the speed limit. The correct (and legal) thing to - do, believe it or not, is to move over and slow down to let them pass - you. It's all about safe and sane driving etiquette. If you aren't - actively passing other cars, move on over to the right. It goes a long - way. - </p> - </article> - </body> -</html> diff --git a/posts/2019-08-30-keep-right-except-to-pass.php b/posts/2019-08-30-keep-right-except-to-pass.php new file mode 100644 index 0000000..660733a --- /dev/null +++ b/posts/2019-08-30-keep-right-except-to-pass.php @@ -0,0 +1,46 @@ +<?php +$title = "Left Lane is for Passing, Not Cruising"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<p> + Greetings fellow drivers of Hampton Roads. You may have noticed a new + sign on I264 today that befuddled or confused you. It went something + along the lines of +</p> + +<blockquote>LEFT LANE IS FOR PASSING NOT CRUISING</blockquote> + +<p> + Believe it or not this has been the law throughout Virginia for years + (<a href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-804/">read about it here</a> + and + <a href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-842.1/">here</a>). The law states you keep right except while passing. In most other + states things work this way but in Virginia, especially around here, the + left lane is treated as a moving, cruising lane. If you're in the left + lane and you've completed a pass please be mindful of the cars behind + you and move back over into the right-hand lane(s) so that other drivers + can do the same. +</p> + +<p> + It's really nice when this is practiced (like I said, I've experienced + it in other states) because you can easily move over when there are slow + vehicles ahead and then continue on your merry way. It reduces + congestion and prevents people from having to pass in the right lane, + which is both annoying and dangerous. Especially since this is typically + the lane cars from entrance and exit ramps are merging with. +</p> + +<p> + Don't forget too that it isn't rude or road-rage-y for someone behind + you to honk their horn or flash their lights if you're moving too slowly + in the passing lane. This is a perfectly polite request to pass you. You + don't set or enforce the speed limit. The correct (and legal) thing to + do, believe it or not, is to move over and slow down to let them pass + you. It's all about safe and sane driving etiquette. If you aren't + actively passing other cars, move on over to the right. It goes a long + way. +</p> diff --git a/posts/2019-09-28-my-preferred-method-for-data-recovery.html b/posts/2019-09-28-my-preferred-method-for-data-recovery.html deleted file mode 100644 index 8adb24c..0000000 --- a/posts/2019-09-28-my-preferred-method-for-data-recovery.html +++ /dev/null @@ -1,276 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="How I Do Data Recovery" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ How I Do Data Recovery</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>How I Do Data Recovery</h1> - - <p> - This week Amy plugged in her flash drive to discover that there were no - files on it. Weeks before there had been dozens of large cuts of footage - that she needed to edit down for work. Hours of recordings were - seemingly gone. And the most annoying part was the drive had worked - perfectly on several other occasions. Just not now that the footage was - actually needed of course. Initially it looked like everything had been - wiped clean, however both Amy's Mac and her PC thought the drive was - half full. It's overall capacity was 64GB but it showed only about 36GB - free. So there still had to be data on there if we could find the right - tool to salvage it. - </p> - - <p> - Luckily this wasn't the first time I had to recover accidentally (or - magically) deleted files. I had previously done so with some success at - my tech support job, for some college friends, and for my in-laws' - retired laptops. So I had a pretty clear idea of what to expect. The - only trick was finding a tool that knew what files it was looking for. - The camera that took the video clips was a Sony and apparently they - record into <code>m2ts</code> files, which are kind of a unique format - in that they only show up on Blu-Ray discs and Sony camcorders. Enter my - favorite two tools for dealing with potentially-destroyed data: - <code>ddrescue</code> and <code>photorec</code>. - </p> - - <h2>DDRescue</h2> - - <p> - <code>ddrescue</code> is a godsend of a tool. If you've ever used - <code>dd</code> before, forget about it. Use <code>ddrescue</code>. You - might as well <code>alias dd=ddrescue</code> because it's that great. By - default it has a plethora of additional options, displays the progress - as it works, recovers and retries in the event of I/O errors, and does - everything that good old <code>dd</code> can do. It's particularly good - at protecting partitions or disks that have been corrupted or damaged by - rescuing undamaged portions first. Oh, and have you ever had to cancel a - <code>dd</code> operation? Did I mention that <code>ddrescue</code> can - pause and resume operations? It's that good. - </p> - - <h2>PhotoRec</h2> - - <p> - <code>photorec</code> is probably the best missing file recovery tool - I've ever used in my entire life. And I've used quite a few. I've never - had as good results as I've had with <code>photorec</code> with other - tools like Recuva et. al. And <code>photorec</code> isn't just for - photos, it can recover documents (a la Office suite), music, images, - config files, and videos (including the very odd - <code>m2ts</code> format!). The other nice thing is - <code>photorec</code> will work on just about any source. It's also free - software which makes me wonder why there are like $50 recovery tools for - Windows that look super sketchy. - </p> - - <h2>In Practice</h2> - - <p> - So here's what I did to get Amy's files back. Luckily she didn't write - anything out to the drive afterward so the chances (I thought) were - pretty good that I would get <em>something</em> back. The first thing I - always do is make a full image of whatever media I'm trying to recover - from. I do this for a couple of reasons. First of all it's a backup. If - something goes wrong during recovery I don't have to worry about the - original, fragile media being damaged or wiped. Furthermore, I can work - with multiple copies at a time. If it's a large image that means - multiple tools or even multiple PCs can work on it at once. It's also - just plain faster working off a disk image than a measly flash drive. So - I used <code>ddrescue</code> to make an image of Amy's drive. - </p> - - <pre><code> -$ sudo ddrescue /dev/sdb1 amy-lexar.dd -GNU ddrescue 1.24 -Press Ctrl-C to interrupt - ipos: 54198 kB, non-trimmed: 0 B, current rate: 7864 kB/s - opos: 54198 kB, non-scraped: 0 B, average rate: 18066 kB/s -non-tried: 63967 MB, bad-sector: 0 B, error rate: 0 B/s - rescued: 54198 kB, bad areas: 0, run time: 2s -pct rescued: 0.08%, read errors: 0, remaining time: 59m - time since last successful read: n/a -Copying non-tried blocks... Pass 1 (forwards) - </code></pre> - - <p> - The result was a very large partition image that I could fearlessly play - around with. - </p> - - <pre> - <code> -$ ll amy-lexar.dd --rw-r--r-- 1 root root 60G Sep 24 02:45 amy-lexar.dd - </code> - </pre> - - <p> - Then I could run <code>photorec</code> on the image. This brings up a - TUI with all of the listed media that I can try and recover from. - </p> - - <pre><code> -$ sudo photorec amy-lexar.dd - -PhotoRec 7.0, Data Recovery Utility, April 2015 -http://www.cgsecurity.org - - PhotoRec is free software, and -comes with ABSOLUTELY NO WARRANTY. - -Select a media (use Arrow keys, then press Enter): ->Disk amy-lexar.dd - 64 GB / 59 GiB (RO) - ->[Proceed ] [ Quit ] - -Note: -Disk capacity must be correctly detected for a successful recovery. -If a disk listed above has incorrect size, check HD jumper settings, BIOS -detection, and install the latest OS patches and disk drivers. - </code></pre> - - <p> - After hitting proceed <code>photorec</code> asks if you want to scan - just a particular partition or the whole disk (if you made a whole disk - image). I can usually get away with just selecting the partition I know - the files are on and starting a search. - </p> - - <pre><code> -PhotoRec 7.0, Data Recovery Utility, April 2015 -http://www.cgsecurity.org - -Disk amy-lexar.dd - 64 GB / 59 GiB (RO) - - Partition Start End Size in sectors - Unknown 0 0 1 7783 139 4 125042656 [Whole disk] -> P FAT32 0 0 1 7783 139 4 125042656 [NO NAME] - ->[ Search ] [Options ] [File Opt] [ Quit ] - Start file recovery - </code></pre> - - <p> - Then <code>photorec</code> asks a couple of questions about the - formatting of the media. It can usually figure them out all by itself so - I just use the default options unless it's way out in left field. - </p> - - <pre><code> -PhotoRec 7.0, Data Recovery Utility, April 2015 -http://www.cgsecurity.org - - P FAT32 0 0 1 7783 139 4 125042656 [NO NAME] - -To recover lost files, PhotoRec need to know the filesystem type where the -file were stored: - [ ext2/ext3 ] ext2/ext3/ext4 filesystem ->[ Other ] FAT/NTFS/HFS+/ReiserFS/... - </code></pre> - - <p> - Now this menu is where I don't just go with the default path. - <code>photorec</code> will offer to search just unallocated space or the - entire partition. I always go for the whole partition here; sometimes - I'll get back files that I didn't really care about but more often than - not I end up rescuing more data this way. In this scenario searching - just unallocated space found no files at all. So I told - <code>photorec</code> to search everything. - </p> - - <pre><code> -PhotoRec 7.0, Data Recovery Utility, April 2015 -http://www.cgsecurity.org - - P FAT32 0 0 1 7783 139 4 125042656 [NO NAME] - - -Please choose if all space need to be analysed: - [ Free ] Scan for file from FAT32 unallocated space only ->[ Whole ] Extract files from whole partition - </code></pre> - - <p> - Now it'll ask where you want to save any files it finds. I threw them - all into a directory under home that I could zip up and send to Amy's - Mac later. - </p> - - <pre><code> -PhotoRec 7.0, Data Recovery Utility, April 2015 - -Please select a destination to save the recovered files. -Do not choose to write the files to the same partition they were stored on. -Keys: Arrow keys to select another directory - C when the destination is correct - Q to quit -Directory /home/adam - drwx------ 1000 1000 4096 28-Sep-2019 12:10 . - drwxr-xr-x 0 0 4096 26-Jan-2019 15:32 .. ->drwxr-xr-x 1000 1000 4096 28-Sep-2019 12:10 amy-lexar-recovery - </code></pre> - - <p> - And then just press <code>C</code>. <code>photrec</code> will start - copying all of the files it finds into that directory. It reports what - kinds of files it found and how many it was able to locate. I was able - to recover all of Amy's lost footage this way, past, along with some - straggler files that had been on the drive at one point. This has worked - for me many times in the past, both on newer devices like flash drives - and on super old, sketchy IDE hard drives. I probably won't ever pay for - data recovery unless a drive has been physically damaged in some way. In - other words, this software works great for me and I don't foresee the - need for anything else out there. It's simple to use and is typically - pretty reliable. - </p> - </article> - </body> -</html> diff --git a/posts/2019-09-28-my-preferred-method-for-data-recovery.php b/posts/2019-09-28-my-preferred-method-for-data-recovery.php new file mode 100644 index 0000000..d7b68d2 --- /dev/null +++ b/posts/2019-09-28-my-preferred-method-for-data-recovery.php @@ -0,0 +1,224 @@ +<?php +$title = "How I Do Data Recovery"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + This week Amy plugged in her flash drive to discover that there were no + files on it. Weeks before there had been dozens of large cuts of footage + that she needed to edit down for work. Hours of recordings were + seemingly gone. And the most annoying part was the drive had worked + perfectly on several other occasions. Just not now that the footage was + actually needed of course. Initially it looked like everything had been + wiped clean, however both Amy's Mac and her PC thought the drive was + half full. It's overall capacity was 64GB but it showed only about 36GB + free. So there still had to be data on there if we could find the right + tool to salvage it. +</p> + +<p> + Luckily this wasn't the first time I had to recover accidentally (or + magically) deleted files. I had previously done so with some success at + my tech support job, for some college friends, and for my in-laws' + retired laptops. So I had a pretty clear idea of what to expect. The + only trick was finding a tool that knew what files it was looking for. + The camera that took the video clips was a Sony and apparently they + record into <code>m2ts</code> files, which are kind of a unique format + in that they only show up on Blu-Ray discs and Sony camcorders. Enter my + favorite two tools for dealing with potentially-destroyed data: + <code>ddrescue</code> and <code>photorec</code>. +</p> + +<h2>DDRescue</h2> + +<p> + <code>ddrescue</code> is a godsend of a tool. If you've ever used + <code>dd</code> before, forget about it. Use <code>ddrescue</code>. You + might as well <code>alias dd=ddrescue</code> because it's that great. By + default it has a plethora of additional options, displays the progress + as it works, recovers and retries in the event of I/O errors, and does + everything that good old <code>dd</code> can do. It's particularly good + at protecting partitions or disks that have been corrupted or damaged by + rescuing undamaged portions first. Oh, and have you ever had to cancel a + <code>dd</code> operation? Did I mention that <code>ddrescue</code> can + pause and resume operations? It's that good. +</p> + +<h2>PhotoRec</h2> + +<p> + <code>photorec</code> is probably the best missing file recovery tool + I've ever used in my entire life. And I've used quite a few. I've never + had as good results as I've had with <code>photorec</code> with other + tools like Recuva et. al. And <code>photorec</code> isn't just for + photos, it can recover documents (a la Office suite), music, images, + config files, and videos (including the very odd + <code>m2ts</code> format!). The other nice thing is + <code>photorec</code> will work on just about any source. It's also free + software which makes me wonder why there are like $50 recovery tools for + Windows that look super sketchy. +</p> + +<h2>In Practice</h2> + +<p> + So here's what I did to get Amy's files back. Luckily she didn't write + anything out to the drive afterward so the chances (I thought) were + pretty good that I would get <em>something</em> back. The first thing I + always do is make a full image of whatever media I'm trying to recover + from. I do this for a couple of reasons. First of all it's a backup. If + something goes wrong during recovery I don't have to worry about the + original, fragile media being damaged or wiped. Furthermore, I can work + with multiple copies at a time. If it's a large image that means + multiple tools or even multiple PCs can work on it at once. It's also + just plain faster working off a disk image than a measly flash drive. So + I used <code>ddrescue</code> to make an image of Amy's drive. +</p> + +<pre><code> +$ sudo ddrescue /dev/sdb1 amy-lexar.dd +GNU ddrescue 1.24 +Press Ctrl-C to interrupt + ipos: 54198 kB, non-trimmed: 0 B, current rate: 7864 kB/s + opos: 54198 kB, non-scraped: 0 B, average rate: 18066 kB/s +non-tried: 63967 MB, bad-sector: 0 B, error rate: 0 B/s + rescued: 54198 kB, bad areas: 0, run time: 2s +pct rescued: 0.08%, read errors: 0, remaining time: 59m + time since last successful read: n/a +Copying non-tried blocks... Pass 1 (forwards) + </code></pre> + +<p> + The result was a very large partition image that I could fearlessly play + around with. +</p> + +<pre> + <code> +$ ll amy-lexar.dd +-rw-r--r-- 1 root root 60G Sep 24 02:45 amy-lexar.dd + </code> + </pre> + +<p> + Then I could run <code>photorec</code> on the image. This brings up a + TUI with all of the listed media that I can try and recover from. +</p> + +<pre><code> +$ sudo photorec amy-lexar.dd + +PhotoRec 7.0, Data Recovery Utility, April 2015 +http://www.cgsecurity.org + + PhotoRec is free software, and +comes with ABSOLUTELY NO WARRANTY. + +Select a media (use Arrow keys, then press Enter): +>Disk amy-lexar.dd - 64 GB / 59 GiB (RO) + +>[Proceed ] [ Quit ] + +Note: +Disk capacity must be correctly detected for a successful recovery. +If a disk listed above has incorrect size, check HD jumper settings, BIOS +detection, and install the latest OS patches and disk drivers. + </code></pre> + +<p> + After hitting proceed <code>photorec</code> asks if you want to scan + just a particular partition or the whole disk (if you made a whole disk + image). I can usually get away with just selecting the partition I know + the files are on and starting a search. +</p> + +<pre><code> +PhotoRec 7.0, Data Recovery Utility, April 2015 +http://www.cgsecurity.org + +Disk amy-lexar.dd - 64 GB / 59 GiB (RO) + + Partition Start End Size in sectors + Unknown 0 0 1 7783 139 4 125042656 [Whole disk] +> P FAT32 0 0 1 7783 139 4 125042656 [NO NAME] + +>[ Search ] [Options ] [File Opt] [ Quit ] + Start file recovery + </code></pre> + +<p> + Then <code>photorec</code> asks a couple of questions about the + formatting of the media. It can usually figure them out all by itself so + I just use the default options unless it's way out in left field. +</p> + +<pre><code> +PhotoRec 7.0, Data Recovery Utility, April 2015 +http://www.cgsecurity.org + + P FAT32 0 0 1 7783 139 4 125042656 [NO NAME] + +To recover lost files, PhotoRec need to know the filesystem type where the +file were stored: + [ ext2/ext3 ] ext2/ext3/ext4 filesystem +>[ Other ] FAT/NTFS/HFS+/ReiserFS/... + </code></pre> + +<p> + Now this menu is where I don't just go with the default path. + <code>photorec</code> will offer to search just unallocated space or the + entire partition. I always go for the whole partition here; sometimes + I'll get back files that I didn't really care about but more often than + not I end up rescuing more data this way. In this scenario searching + just unallocated space found no files at all. So I told + <code>photorec</code> to search everything. +</p> + +<pre><code> +PhotoRec 7.0, Data Recovery Utility, April 2015 +http://www.cgsecurity.org + + P FAT32 0 0 1 7783 139 4 125042656 [NO NAME] + + +Please choose if all space need to be analysed: + [ Free ] Scan for file from FAT32 unallocated space only +>[ Whole ] Extract files from whole partition + </code></pre> + +<p> + Now it'll ask where you want to save any files it finds. I threw them + all into a directory under home that I could zip up and send to Amy's + Mac later. +</p> + +<pre><code> +PhotoRec 7.0, Data Recovery Utility, April 2015 + +Please select a destination to save the recovered files. +Do not choose to write the files to the same partition they were stored on. +Keys: Arrow keys to select another directory + C when the destination is correct + Q to quit +Directory /home/adam + drwx------ 1000 1000 4096 28-Sep-2019 12:10 . + drwxr-xr-x 0 0 4096 26-Jan-2019 15:32 .. +>drwxr-xr-x 1000 1000 4096 28-Sep-2019 12:10 amy-lexar-recovery + </code></pre> + +<p> + And then just press <code>C</code>. <code>photrec</code> will start + copying all of the files it finds into that directory. It reports what + kinds of files it found and how many it was able to locate. I was able + to recover all of Amy's lost footage this way, past, along with some + straggler files that had been on the drive at one point. This has worked + for me many times in the past, both on newer devices like flash drives + and on super old, sketchy IDE hard drives. I probably won't ever pay for + data recovery unless a drive has been physically damaged in some way. In + other words, this software works great for me and I don't foresee the + need for anything else out there. It's simple to use and is typically + pretty reliable. +</p> diff --git a/posts/2020-04-10-the-obligatory-covid-19-post.html b/posts/2020-04-10-the-obligatory-covid-19-post.html deleted file mode 100644 index 15bd9bc..0000000 --- a/posts/2020-04-10-the-obligatory-covid-19-post.html +++ /dev/null @@ -1,103 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Obligatory COVID-19 Post" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Obligatory COVID-19 Post</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Obligatory COVID-19 Post</h1> - <p> - We're alive! All three of us: Amy, Clementine, and myself. We're doing - what we do best and that is being hermits with zero social contact. - That's pretty okay by us though because it lets us slow down from all - the fast-paced life changes we've made in the past few months. - </p> - - <p> - In January Amy and I bought a house! We couldn't have done it without - the wonderful help of everyone who gave us wedding gifts. We got a nice - little standalone place in Suffolk, much closer to where I work and - centrally located for Amy's tutoring business. We spent all of January - painting and prepping for the big move. Late January and early February - were all moving and unpacking and trying to get back in the groove. - Since the outbreak, we've been using the extra time at home to finish up - all the move-in projects we wanted to: finishing painting, putting up - shelves, hanging pictures, and rewiring electrical outlets. - </p> - - <p> - Amy also finally got the chance to pursue her dream job: she started up - her own private tutoring business. She's been working hard with clients - all over Hampton Roads, from college students all the way to - first-graders. Business was booming before schools closed but I know - she'll bring it back once things have returned to normal again. No - worries though, she's spending this time helping William and Mary handle - remote operations and students in need. She's also [supposed to be] - writing her master's thesis so she can graduate in May but you know how - it is. - </p> - - <p> - We're also working through a family illness, which adds difficulty . We - expect a speedy recovery though and we're really excited for that. - All-in-all, we're really enjoying our lives as a happily married couple. - It's been about eight months now and I've enjoyed every minute of it: - the glad, the slightly stressed, and the overarching worry as the world - took a strange turn. But we're looking forward to a good Summer now. The - weather has turned nice -- really nice -- and Clementine is forcing us - to get outside. She's in love with her nice, big fenced-in yard and - refuses to come in after catching hoops most of the time. - </p> - - <p>Stay safe, smart, and sane!</p> - </article> - </body> -</html> diff --git a/posts/2020-04-10-the-obligatory-covid-19-post.php b/posts/2020-04-10-the-obligatory-covid-19-post.php new file mode 100644 index 0000000..6cdabe9 --- /dev/null +++ b/posts/2020-04-10-the-obligatory-covid-19-post.php @@ -0,0 +1,51 @@ +<?php +$title = "Obligatory COVID-19 Post"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<p> + We're alive! All three of us: Amy, Clementine, and myself. We're doing + what we do best and that is being hermits with zero social contact. + That's pretty okay by us though because it lets us slow down from all + the fast-paced life changes we've made in the past few months. +</p> + +<p> + In January Amy and I bought a house! We couldn't have done it without + the wonderful help of everyone who gave us wedding gifts. We got a nice + little standalone place in Suffolk, much closer to where I work and + centrally located for Amy's tutoring business. We spent all of January + painting and prepping for the big move. Late January and early February + were all moving and unpacking and trying to get back in the groove. + Since the outbreak, we've been using the extra time at home to finish up + all the move-in projects we wanted to: finishing painting, putting up + shelves, hanging pictures, and rewiring electrical outlets. +</p> + +<p> + Amy also finally got the chance to pursue her dream job: she started up + her own private tutoring business. She's been working hard with clients + all over Hampton Roads, from college students all the way to + first-graders. Business was booming before schools closed but I know + she'll bring it back once things have returned to normal again. No + worries though, she's spending this time helping William and Mary handle + remote operations and students in need. She's also [supposed to be] + writing her master's thesis so she can graduate in May but you know how + it is. +</p> + +<p> + We're also working through a family illness, which adds difficulty . We + expect a speedy recovery though and we're really excited for that. + All-in-all, we're really enjoying our lives as a happily married couple. + It's been about eight months now and I've enjoyed every minute of it: + the glad, the slightly stressed, and the overarching worry as the world + took a strange turn. But we're looking forward to a good Summer now. The + weather has turned nice -- really nice -- and Clementine is forcing us + to get outside. She's in love with her nice, big fenced-in yard and + refuses to come in after catching hoops most of the time. +</p> + +<p>Stay safe, smart, and sane!</p> diff --git a/posts/2020-04-10-wedding-photos-are-here.html b/posts/2020-04-10-wedding-photos-are-here.html deleted file mode 100644 index 21ec27e..0000000 --- a/posts/2020-04-10-wedding-photos-are-here.html +++ /dev/null @@ -1,96 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Wedding Photo Debacle" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Wedding Photo Debacle</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Wedding Photo Debacle</h1> - - <p> - At long last we have all of our wedding photos together! Unfortunately a - large portion of the professional ones were lost during editing but - we're extremely fortunate to everyone who took pictures throughout the - festivities so we have more to share! We hope you enjoy flipping through - them as much as we did! There is also a collection of the photos we took - while we were on our honeymoon on Mackinac Island, MI. It was an - absolutely magical place and truly the experience of a lifetime for us - to run away there. We're in contact with our videographer, who's working - on the final cut now. - </p> - - <p> - Everything is available at the links down below. You can scroll through - the photos, view them in fullscreen, and even download them or share - them elsewhere. We hope you have as much fun flipping through them as we - did! - </p> - - <ul> - <li> - <a href="https://nextcloud.53hor.net/s/eYLqeMGnSPGRNFE" - >Bachelor & Bachelorette Parties</a - > - </li> - - <li> - <a href="https://nextcloud.53hor.net/s/FxekyGQFTFKG5ot" - >Wedding Day</a - > - </li> - - <li> - <a href="https://nextcloud.53hor.net/s/mgZ6M4ayqX73DqL">Honeymoon</a> - </li> - </ul> - </article> - </body> -</html> diff --git a/posts/2020-04-10-wedding-photos-are-here.php b/posts/2020-04-10-wedding-photos-are-here.php new file mode 100644 index 0000000..59344d6 --- /dev/null +++ b/posts/2020-04-10-wedding-photos-are-here.php @@ -0,0 +1,40 @@ +<?php +$title = "Wedding Photo Debacle"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + At long last we have all of our wedding photos together! Unfortunately a + large portion of the professional ones were lost during editing but + we're extremely fortunate to everyone who took pictures throughout the + festivities so we have more to share! We hope you enjoy flipping through + them as much as we did! There is also a collection of the photos we took + while we were on our honeymoon on Mackinac Island, MI. It was an + absolutely magical place and truly the experience of a lifetime for us + to run away there. We're in contact with our videographer, who's working + on the final cut now. +</p> + +<p> + Everything is available at the links down below. You can scroll through + the photos, view them in fullscreen, and even download them or share + them elsewhere. We hope you have as much fun flipping through them as we + did! +</p> + +<ul> + <li> + <a href="https://nextcloud.53hor.net/s/eYLqeMGnSPGRNFE">Bachelor & Bachelorette Parties</a> + </li> + + <li> + <a href="https://nextcloud.53hor.net/s/FxekyGQFTFKG5ot">Wedding Day</a> + </li> + + <li> + <a href="https://nextcloud.53hor.net/s/mgZ6M4ayqX73DqL">Honeymoon</a> + </li> +</ul> diff --git a/posts/2020-07-11-why-computer-science-at-w-m.html b/posts/2020-07-11-why-computer-science-at-w-m.html deleted file mode 100644 index cd882bb..0000000 --- a/posts/2020-07-11-why-computer-science-at-w-m.html +++ /dev/null @@ -1,249 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Why Computer Science at William and Mary" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Why Computer Science at William and Mary</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Why Computer Science at William and Mary</h1> - - <p class="description"> - Recently a rising high-school senior asked for input on what going to - the College of William and Mary was like for a Computer Science degree. - They were asking about the program itself as well as what it's like on - and off campus. Here's what I sent to them. - </p> - - <h2>Quick Intro</h2> - - <p> - I graduated with a Bachelor's in Computer Science from W&M in 2018. - I'm a couple years in the workforce now but can still remember my - experiences well enough to hopefully add my honest opinion on my time - there as well as how it prepared me for my career. I will also add a - little bit about my time on campus in a dorm and off-campus in Colonial - Williamsburg. - </p> - - <h2>Courses and Curriculum</h2> - - <p> - I felt very positively about the array of courses that were offered - while I was a student. I took a variety of core prerequisites, just like - everyone else, and a good mix of electives. The courses I took include - Data Structures and Algorithms, Software Development/Engineering, - Computer Organization/Architecture, UNIX Systems Programming, Computer - Graphics/Animation, and Computer and Network Security. This list is not - exhaustive and I'm sure they aren't all offered anymore. I was also - required to take a few math classes (Calc I, II, Discrete Math, Linear - Algebra, and Finite Automata). - </p> - - <p> - It is true that the courses listed at <code>cs.wm.edu</code> aren't all - offered at the same time. And it is also true that the higher-level - electives pretty much all required my core prerequisites to be - completed. The result is that the electives all came in my final two - years. My understanding is the curriculum is designed to give someone - the best possible background in computing as a whole. A lot of the - topics may seem like they would never be useful in the "real world" but - I have found the opposite is true. I am an application developer at a - three-letter company. My day-to-day work is building and debugging web - apps, but there's been a lot more to it than that. My first assignment - on the job was scraping bytes off a remote shell and writing a parser to - sift through them. The level of understanding I gathered from my core - classes helped more than I expected they would. I think as a whole they - give me an edge at work and help me teach my colleagues about - algorithms, performance, and systems administration. - </p> - - <p> - That being said, course registration was always nightmarish. It was very - difficult to get into the limited seats in the classes I was most - interested in. Eventually the heads of the department had to pass around - a sign up sheet and organize every student into courses, classrooms, and - professors so that seniors would graduate on time and we could all get - <em>something</em> on our schedules. I hope the shortage of teachers has - caught up since I graduated. I learned from a long-time faculty member - that this is largely a result of the exponential growth of incoming CS - degree-seekers. The program has grown very popular in the last ten years - and I like to think grads are catching on to that. - </p> - - <h2>Teaching</h2> - - <p> - CS@W&M had neutral to good instructors for me. Some were far worse - than others, as with all subjects. When I was there, lots of the older - faculty were retiring and quickly being replaced with younger, newer - instructors, which added to the growing pains of the program. The most - important thing again was making sure there were enough teachers to - teach all of the students. - </p> - - <p> - I know a few of my peers were very upset about what they described as a - lack of communication or availability from their professors. Some have - also mentioned they didn't like having to learn material on their own - and wanted more to come from instruction. I don't deny that the material - itself was difficult and there was a lot of hard work I had to do on my - own to understand very involved concepts in intense, fast-paced courses. - I think that hard work has paid off. I don't think there's realistically - anywhere someone can learn about computing where they won't do any - learning on their own. I am also a very visual, and hands-on learner so - I suppose your mileage may vary. - </p> - - <p> - The most important takeaway from this for me was the ability to pick up - new concepts and technologies quickly and apply them productively. The - majority of professors had project-driven courses. Lots of due dates - meant learning how to transform what I read or learned in class into - practical applications in short amounts of time. This has become, - according to those I work with, one of my greater assets. I am - constantly learning new things in my career and I don't have a lecturer - to explain things to me. It's very powerful to have that and I am - thankful for it. It also helps me teach that knowledge to my colleagues - so we can move faster as a team. - </p> - - <h2>Campus</h2> - - <p> - I agree with my peers about the conditions of classrooms and buildings - on campus. Some are old. I guess that comes with an old university but - there are a choice few that haven't been kept up as best they could. - Since CS is growing so fast it's also long outgrown its own offices. - Classrooms are scattered throughout every academic building on campus - and I probably had a CS course in at least 80% of them. That meant - jumping from one side of campus to another and back again in between - periods. - </p> - - <p> - The College itself isn't too sprawling. I am long-legged and I found I - could get from one end of campus to another in fifteen minutes on foot. - I rode bike a lot to get to classes where I only had ten minutes to do - it. It's also pretty marshy and woodsy in a lot of areas, so during the - rainy season some walking paths got muddy or flooded. Good boots - required. I have never been in as good shape as when I had to do all - that walking but I definitely got soaked and winded making those - transitions. - </p> - - <p> - I appreciate history and architecture and was drawn in by the look and - feel of William and Mary as a result. Without getting too romantic, it's - definitely a beautiful place to attend classes. The ancient Wren - building still holds classes and it's a monument to the College's - tradition. However, I really appreciated the modern academic buildings - on the other side of campus where all of the new construction was taking - place. Modern lab equipment and the library lived there. - </p> - - <p> - The dorms were nothing to write home about. Lots of them were nested in - the woods and built ages ago so they were a little tired and even dingy. - Others are brand new and well maintained; ask around and get opinions on - which ones to go for first chance you get. I made do with what I got for - the first couple of years by keeping it clean and decorated. My last two - years I lived in a couple of off-campus apartments. It was well worth - the switch. Depending on where you are on campus you may need at least a - bike to access local restaurants, shops, and the grocery store. A bike - is a good idea anyway but it's not necessary for every dorm. - </p> - - <h2>Colonial Williamsburg</h2> - - <p> - Lots of my peers didn't appreciate CW as a "college town" but I enjoyed - my time there. I can't speak about parties or clubbing, I was boring and - didn't do any of that. I made a great group of friends and we would walk - into town to get ice cream, see historical attractions (most of which - are free as a student, IIRC), and see movies or plays when we weren't - studying or playing video games in the dorm. There are some good, - sort-of-affordable restaurants but they're kind of driving distance. - </p> - - <p> - The best part about living there was meeting my wife. We would go on - long walks to get away from studying and wound up seeing - horse-and-carriages and the Governor's Palace and things like that. We - would also escape with her car to go to some of the surrounding towns to - get away to nice grocery stores and fun places to eat and explore on the - weekends. I also have family in the area so it was easy for me to stop - by home and say hi, although I know lots of students wanted to get as - far away from home as possible. - </p> - - <h2>Parting Words</h2> - - <p> - I don't consider myself a gung ho alumnus. There are lots of things I - think could be improved, both in CS and at W&M as a whole but I do - not regret my going there. There is no such thing as "everything is - great" or "everything is terrible". It's not so definitive. I had my - fair share of gripes and at times it strained me. There were pros and - cons but I think I have a lot to be thankful for (I landed my job - through W&M recruiting and the career center as well, which are - fantastic resources). I cannot say "do this instead of that." I haven't - gone to any other colleges and don't know enough about them to recommend - them as better or worse. What I can recommend is the same path I took - for folks who want to pursue a degree in Computer Science. I think - you'll come away from it all the more knowledgable, resourceful, and - dedicated. - </p> - </article> - </body> -</html> diff --git a/posts/2020-07-11-why-computer-science-at-w-m.php b/posts/2020-07-11-why-computer-science-at-w-m.php new file mode 100644 index 0000000..f2fb3d1 --- /dev/null +++ b/posts/2020-07-11-why-computer-science-at-w-m.php @@ -0,0 +1,194 @@ +<?php +$title = "Why Computer Science at William and Mary"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + Recently a rising high-school senior asked for input on what going to + the College of William and Mary was like for a Computer Science degree. + They were asking about the program itself as well as what it's like on + and off campus. Here's what I sent to them. +</p> + +<h2>Quick Intro</h2> + +<p> + I graduated with a Bachelor's in Computer Science from W&M in 2018. + I'm a couple years in the workforce now but can still remember my + experiences well enough to hopefully add my honest opinion on my time + there as well as how it prepared me for my career. I will also add a + little bit about my time on campus in a dorm and off-campus in Colonial + Williamsburg. +</p> + +<h2>Courses and Curriculum</h2> + +<p> + I felt very positively about the array of courses that were offered + while I was a student. I took a variety of core prerequisites, just like + everyone else, and a good mix of electives. The courses I took include + Data Structures and Algorithms, Software Development/Engineering, + Computer Organization/Architecture, UNIX Systems Programming, Computer + Graphics/Animation, and Computer and Network Security. This list is not + exhaustive and I'm sure they aren't all offered anymore. I was also + required to take a few math classes (Calc I, II, Discrete Math, Linear + Algebra, and Finite Automata). +</p> + +<p> + It is true that the courses listed at <code>cs.wm.edu</code> aren't all + offered at the same time. And it is also true that the higher-level + electives pretty much all required my core prerequisites to be + completed. The result is that the electives all came in my final two + years. My understanding is the curriculum is designed to give someone + the best possible background in computing as a whole. A lot of the + topics may seem like they would never be useful in the "real world" but + I have found the opposite is true. I am an application developer at a + three-letter company. My day-to-day work is building and debugging web + apps, but there's been a lot more to it than that. My first assignment + on the job was scraping bytes off a remote shell and writing a parser to + sift through them. The level of understanding I gathered from my core + classes helped more than I expected they would. I think as a whole they + give me an edge at work and help me teach my colleagues about + algorithms, performance, and systems administration. +</p> + +<p> + That being said, course registration was always nightmarish. It was very + difficult to get into the limited seats in the classes I was most + interested in. Eventually the heads of the department had to pass around + a sign up sheet and organize every student into courses, classrooms, and + professors so that seniors would graduate on time and we could all get + <em>something</em> on our schedules. I hope the shortage of teachers has + caught up since I graduated. I learned from a long-time faculty member + that this is largely a result of the exponential growth of incoming CS + degree-seekers. The program has grown very popular in the last ten years + and I like to think grads are catching on to that. +</p> + +<h2>Teaching</h2> + +<p> + CS@W&M had neutral to good instructors for me. Some were far worse + than others, as with all subjects. When I was there, lots of the older + faculty were retiring and quickly being replaced with younger, newer + instructors, which added to the growing pains of the program. The most + important thing again was making sure there were enough teachers to + teach all of the students. +</p> + +<p> + I know a few of my peers were very upset about what they described as a + lack of communication or availability from their professors. Some have + also mentioned they didn't like having to learn material on their own + and wanted more to come from instruction. I don't deny that the material + itself was difficult and there was a lot of hard work I had to do on my + own to understand very involved concepts in intense, fast-paced courses. + I think that hard work has paid off. I don't think there's realistically + anywhere someone can learn about computing where they won't do any + learning on their own. I am also a very visual, and hands-on learner so + I suppose your mileage may vary. +</p> + +<p> + The most important takeaway from this for me was the ability to pick up + new concepts and technologies quickly and apply them productively. The + majority of professors had project-driven courses. Lots of due dates + meant learning how to transform what I read or learned in class into + practical applications in short amounts of time. This has become, + according to those I work with, one of my greater assets. I am + constantly learning new things in my career and I don't have a lecturer + to explain things to me. It's very powerful to have that and I am + thankful for it. It also helps me teach that knowledge to my colleagues + so we can move faster as a team. +</p> + +<h2>Campus</h2> + +<p> + I agree with my peers about the conditions of classrooms and buildings + on campus. Some are old. I guess that comes with an old university but + there are a choice few that haven't been kept up as best they could. + Since CS is growing so fast it's also long outgrown its own offices. + Classrooms are scattered throughout every academic building on campus + and I probably had a CS course in at least 80% of them. That meant + jumping from one side of campus to another and back again in between + periods. +</p> + +<p> + The College itself isn't too sprawling. I am long-legged and I found I + could get from one end of campus to another in fifteen minutes on foot. + I rode bike a lot to get to classes where I only had ten minutes to do + it. It's also pretty marshy and woodsy in a lot of areas, so during the + rainy season some walking paths got muddy or flooded. Good boots + required. I have never been in as good shape as when I had to do all + that walking but I definitely got soaked and winded making those + transitions. +</p> + +<p> + I appreciate history and architecture and was drawn in by the look and + feel of William and Mary as a result. Without getting too romantic, it's + definitely a beautiful place to attend classes. The ancient Wren + building still holds classes and it's a monument to the College's + tradition. However, I really appreciated the modern academic buildings + on the other side of campus where all of the new construction was taking + place. Modern lab equipment and the library lived there. +</p> + +<p> + The dorms were nothing to write home about. Lots of them were nested in + the woods and built ages ago so they were a little tired and even dingy. + Others are brand new and well maintained; ask around and get opinions on + which ones to go for first chance you get. I made do with what I got for + the first couple of years by keeping it clean and decorated. My last two + years I lived in a couple of off-campus apartments. It was well worth + the switch. Depending on where you are on campus you may need at least a + bike to access local restaurants, shops, and the grocery store. A bike + is a good idea anyway but it's not necessary for every dorm. +</p> + +<h2>Colonial Williamsburg</h2> + +<p> + Lots of my peers didn't appreciate CW as a "college town" but I enjoyed + my time there. I can't speak about parties or clubbing, I was boring and + didn't do any of that. I made a great group of friends and we would walk + into town to get ice cream, see historical attractions (most of which + are free as a student, IIRC), and see movies or plays when we weren't + studying or playing video games in the dorm. There are some good, + sort-of-affordable restaurants but they're kind of driving distance. +</p> + +<p> + The best part about living there was meeting my wife. We would go on + long walks to get away from studying and wound up seeing + horse-and-carriages and the Governor's Palace and things like that. We + would also escape with her car to go to some of the surrounding towns to + get away to nice grocery stores and fun places to eat and explore on the + weekends. I also have family in the area so it was easy for me to stop + by home and say hi, although I know lots of students wanted to get as + far away from home as possible. +</p> + +<h2>Parting Words</h2> + +<p> + I don't consider myself a gung ho alumnus. There are lots of things I + think could be improved, both in CS and at W&M as a whole but I do + not regret my going there. There is no such thing as "everything is + great" or "everything is terrible". It's not so definitive. I had my + fair share of gripes and at times it strained me. There were pros and + cons but I think I have a lot to be thankful for (I landed my job + through W&M recruiting and the career center as well, which are + fantastic resources). I cannot say "do this instead of that." I haven't + gone to any other colleges and don't know enough about them to recommend + them as better or worse. What I can recommend is the same path I took + for folks who want to pursue a degree in Computer Science. I think + you'll come away from it all the more knowledgable, resourceful, and + dedicated. +</p> diff --git a/posts/2020-07-26-now-this-is-a-minimal-install.html b/posts/2020-07-26-now-this-is-a-minimal-install.html deleted file mode 100644 index 487c6e4..0000000 --- a/posts/2020-07-26-now-this-is-a-minimal-install.html +++ /dev/null @@ -1,101 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Now This is a Minimal Install!" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Now This is a Minimal Install!</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Now This is a Minimal Install!</h1> - - <p> - I just got done configuring Poudriere on Freebsd 12.1-RELEASE. The - awesome thing about it is it allows you to configure and maintain your - own package repository. All of the ports and their dependencies are - built from source with personalized options. That means that I can - maintain my own repo of just the packages I need with just the - compile-time options I need. For example, for the Nvidia driver set I - disabled all Wayland related flags. I use Xorg so there was no need to - have that functionality built in. - </p> - - <p> - Compile times are pretty long but I hope to change that by upgrading my - home server to FreeBSD as well (from Ubuntu Server). Then I can - configure poudriere to serve up a ports tree and my own pkg repo from - there. The server is a lot faster than my laptop and will build packages - way faster, and I'll be able to use those packages on both the server - and my laptop and any jails I have running. Jails (and ZFS) also make - poudriere really cool to use as all of the building is done inside a - jail. When the time comes I can just remove the jail and poudriere ports - tree from my laptop and update pkg to point to my web server. - </p> - - <p> - This is, as I understand it, the sane way to do package management in - FreeBSD. The binary package repo is basically the ports tree - pre-assembled with default options. Sometimes those packages are - compiled without functionality that most users don't need. In those - situations, you're forced to use ports. The trouble is you're not really - supposed to mix ports and binary packages. The reason, again as I - understand it, is because ports are updated more frequently. So binary - packages and ports can have different dependency versions, which can - sometimes break compatibility on an upgrade. Most FreeBSD users - recommend installing everything with ports (which is just a make install - inside the local tree) but then you lose the package management features - that come with pkg. Poudriere lets you kind of do both by creating your - "own personal binary repo" out of a list of preconfigured, pre-built - ports. - </p> - - <p>FreeBSD rocks.</p> - </article> - </body> -</html> diff --git a/posts/2020-07-26-now-this-is-a-minimal-install.php b/posts/2020-07-26-now-this-is-a-minimal-install.php new file mode 100644 index 0000000..3165b71 --- /dev/null +++ b/posts/2020-07-26-now-this-is-a-minimal-install.php @@ -0,0 +1,49 @@ +<?php +$title = "Now This is a Minimal Install!"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + I just got done configuring Poudriere on Freebsd 12.1-RELEASE. The + awesome thing about it is it allows you to configure and maintain your + own package repository. All of the ports and their dependencies are + built from source with personalized options. That means that I can + maintain my own repo of just the packages I need with just the + compile-time options I need. For example, for the Nvidia driver set I + disabled all Wayland related flags. I use Xorg so there was no need to + have that functionality built in. +</p> + +<p> + Compile times are pretty long but I hope to change that by upgrading my + home server to FreeBSD as well (from Ubuntu Server). Then I can + configure poudriere to serve up a ports tree and my own pkg repo from + there. The server is a lot faster than my laptop and will build packages + way faster, and I'll be able to use those packages on both the server + and my laptop and any jails I have running. Jails (and ZFS) also make + poudriere really cool to use as all of the building is done inside a + jail. When the time comes I can just remove the jail and poudriere ports + tree from my laptop and update pkg to point to my web server. +</p> + +<p> + This is, as I understand it, the sane way to do package management in + FreeBSD. The binary package repo is basically the ports tree + pre-assembled with default options. Sometimes those packages are + compiled without functionality that most users don't need. In those + situations, you're forced to use ports. The trouble is you're not really + supposed to mix ports and binary packages. The reason, again as I + understand it, is because ports are updated more frequently. So binary + packages and ports can have different dependency versions, which can + sometimes break compatibility on an upgrade. Most FreeBSD users + recommend installing everything with ports (which is just a make install + inside the local tree) but then you lose the package management features + that come with pkg. Poudriere lets you kind of do both by creating your + "own personal binary repo" out of a list of preconfigured, pre-built + ports. +</p> + +<p>FreeBSD rocks.</p> diff --git a/posts/2020-11-30-titanics-last-signals.html b/posts/2020-11-30-titanics-last-signals.html deleted file mode 100644 index 9335069..0000000 --- a/posts/2020-11-30-titanics-last-signals.html +++ /dev/null @@ -1,73 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Titanic's Last Signals" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Titanic's Last Signals</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Titanic's Last Signals</h1> - <p> - I forgot to post this back in April but 108 years ago, a chilling and - heroic conversation was had over the airwaves. This is a fascinating way - to hear the real conversations that took place the night the Titanic - went down with 1,496 souls. - </p> - <iframe - width="560" - height="315" - src="https://www.youtube.com/embed/FxRN2nP_9dA" - frameborder="0" - allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" - allowfullscreen - ></iframe> - </article> - </body> -</html> diff --git a/posts/2020-11-30-titanics-last-signals.php b/posts/2020-11-30-titanics-last-signals.php new file mode 100644 index 0000000..03c0b96 --- /dev/null +++ b/posts/2020-11-30-titanics-last-signals.php @@ -0,0 +1,14 @@ +<?php +$title = "Titanic's Last Signals"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> +<p> + I forgot to post this back in April but 108 years ago, a chilling and + heroic conversation was had over the airwaves. This is a fascinating way + to hear the real conversations that took place the night the Titanic + went down with 1,496 souls. +</p> +<iframe width="560" height="315" src="https://www.youtube.com/embed/FxRN2nP_9dA" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> diff --git a/posts/2020-12-01-the-guides.html b/posts/2020-12-01-the-guides.html deleted file mode 100644 index 28905d2..0000000 --- a/posts/2020-12-01-the-guides.html +++ /dev/null @@ -1,117 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="[The Guides]" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ [The Guides]</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>𝔗𝔥𝔢 𝔊𝔲𝔦𝔡𝔢𝔰</h1> - - <p class="description"> - This is partly satirical and purposefully strange to be humorous. These - are my personal rules for software development (and other projects where - I get carried away easily). - </p> - - <p><em>The Guides.</em> The Guiding Principles.</p> - - <p> - They guide you. They will not lead you astray. Obey <em>The Guides</em>. - </p> - - <p> - You've heard them go by different names. YAGNI. KISS. These are not - falsehoods, but they are not <em>The Guides</em>. Seek the wisdom of the - guides. - </p> - - <blockquote> - 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝔞𝔰 𝔩𝔦𝔱𝔱𝔩𝔢 𝔠𝔬𝔡𝔢 𝔞𝔰 𝔭𝔬𝔰𝔰𝔦𝔟𝔩𝔢 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱. - </blockquote> - - <blockquote> - O Guides, may I please just add this one extra feature? It won't take me - long and it will be so nice to have later. - </blockquote> - - <blockquote> - 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝖔𝖓𝖑𝖞 𝖙𝖍𝖊 𝖈𝖔𝖉𝖊 𝖓𝖊𝖈𝖊𝖘𝖘𝖆𝖗𝖞 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱. - </blockquote> - - <blockquote> - O Guides, this can't be correct code. I haven't used proper software - development patterns, processes, or practices. - </blockquote> - - <blockquote> - 𝔓𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔣𝔬𝔯 𝔱𝔥𝔢 𝔰𝔞𝔨𝔢 𝔬𝔣 𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔞𝔯𝔢 𝔞𝔫𝔱𝔦-𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰. - </blockquote> - - <blockquote> - O Guides, how may I approach this project pragmatically? - </blockquote> - - <blockquote>ℌ𝔢𝔢𝔡 𝔱𝔥𝔢𝔰𝔢 𝔯𝔲𝔩𝔢𝔰:</blockquote> - - <ol> - <li> - You may only write code directly related to the task at hand. Don't - get distracted. - </li> - <li> - Once you have working code, make it correct. Once it is correct, make - it secure. Once it is secure, make it small. Once it is small, stop. - </li> - <li>The enemy of good is better.</li> - </ol> - </article> - </body> -</html> diff --git a/posts/2020-12-01-the-guides.php b/posts/2020-12-01-the-guides.php new file mode 100644 index 0000000..a3629be --- /dev/null +++ b/posts/2020-12-01-the-guides.php @@ -0,0 +1,65 @@ +<?php +$title = "𝔗𝔥𝔢 𝔊𝔲𝔦𝔡𝔢𝔰"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + This is partly satirical and purposefully strange to be humorous. These + are my personal rules for software development (and other projects where + I get carried away easily). +</p> + +<p><em>The Guides.</em> The Guiding Principles.</p> + +<p> + They guide you. They will not lead you astray. Obey <em>The Guides</em>. +</p> + +<p> + You've heard them go by different names. YAGNI. KISS. These are not + falsehoods, but they are not <em>The Guides</em>. Seek the wisdom of the + guides. +</p> + +<blockquote> + 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝔞𝔰 𝔩𝔦𝔱𝔱𝔩𝔢 𝔠𝔬𝔡𝔢 𝔞𝔰 𝔭𝔬𝔰𝔰𝔦𝔟𝔩𝔢 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱. +</blockquote> + +<blockquote> + O Guides, may I please just add this one extra feature? It won't take me + long and it will be so nice to have later. +</blockquote> + +<blockquote> + 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝖔𝖓𝖑𝖞 𝖙𝖍𝖊 𝖈𝖔𝖉𝖊 𝖓𝖊𝖈𝖊𝖘𝖘𝖆𝖗𝖞 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱. +</blockquote> + +<blockquote> + O Guides, this can't be correct code. I haven't used proper software + development patterns, processes, or practices. +</blockquote> + +<blockquote> + 𝔓𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔣𝔬𝔯 𝔱𝔥𝔢 𝔰𝔞𝔨𝔢 𝔬𝔣 𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔞𝔯𝔢 𝔞𝔫𝔱𝔦-𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰. +</blockquote> + +<blockquote> + O Guides, how may I approach this project pragmatically? +</blockquote> + +<blockquote>ℌ𝔢𝔢𝔡 𝔱𝔥𝔢𝔰𝔢 𝔯𝔲𝔩𝔢𝔰:</blockquote> + +<ol> + <li> + You may only write code directly related to the task at hand. Don't + get distracted. + </li> + <li> + Once you have working code, make it correct. Once it is correct, make + it secure. Once it is secure, make it small. Once it is small, stop. + </li> + <li>The enemy of good is better.</li> +</ol> diff --git a/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html b/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html deleted file mode 100644 index 66aabd2..0000000 --- a/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html +++ /dev/null @@ -1,231 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="AOC 2020 Day 1 in CBM Basic" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ AOC 2020 Day 1 in CBM Basic</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>AOC 2020 Day 1 in CBM Basic</h1> - - <p class="description"> - I implemented the - <a href="https://adventofcode.com/2020">Advent of Code 2020</a> Day 1 - challenge in CBM BASIC on a real Commodore 64. I haven't done anything - in Basic in a long time, and probably never did anything actually - meaningful with it. Part 1 of the challenge was to take a list of - numbers, find the two that summed to 2020, and then multiply those two - numbers together. Part two was to perform part 1 but with three numbers - instead of two. - </p> - <p> - Now I wanted to actually write the code on the Commodore 64 itself, but - I gave myself some leniency. Instead of manually typing in all 200 - entries of input data (and inevitably making a breaking mistake) I used - Vim on my PC to format the <code>DATA</code> entries at the start of the - code. I then dropped that onto a 1541 disk image, plopped it on an SD - card, and used my SD2IEC to mount the SD card's image on the Commodore. - The rest of the programming was done on the Commodore itself. - </p> - - <p>Here is my solution for Day 1 Part 1:</p> - <pre> - <code> -10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144 -11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889 -12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946 -13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627 -14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844 -15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548 -16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986 -17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498 -18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797 -19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542 -20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507 -21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635 -22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538 -23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550 -24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366 -25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902 -26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812 -27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154 -28 DATA 1769, 1529 -100 DIM A(200) -110 FOR I=0TO199 -120 READ A(I) -140 NEXT -150 FOR I=0TO199 -160 B=A(I) -170 FOR J=0TO199 -180 IF I=J THEN 210 -190 C=A(J) -200 IF B+C=2020 THEN PRINT "!",B,C,B*C:STOP -210 NEXT J -220 NEXT I - </code></pre> - - <p> - I basically put all 200 numbers into data fields, and then defined an - array large enough to read them into with <code>DIM</code>. Then I - iterated over the array twice, checking each element against each other - element to see if they summed to 2020. If they did, I printed them both - and the product of the two found numbers and stopped further execution. - </p> - <p> - There weren't really any special tricks to this implementation except - remembering that I shouldn't be checking whether a number could sum to - 2020 with itself. - </p> - - <p> - Then I got to move onto Part 2, and this is where things got - interesting. Comparing any three numbers from the data meant the - cognitively easiest way to solve the problem was a triple loop. This of - course meant <code>O(n^3)</code> time, which the Commodore struggled - with. I waited about an hour before I decided I could optimize just a - little bit to speed up the search. - </p> - - <p> - I figured that for three numbers to sum to 2020, they all had to be - pretty small. Most likely they were most (if not all) three digits - instead of four. So I figured I could sort the entry data to make the - search finish probably near the start of the first layer of iteration. - Keep in mind I didn't want to pre-sort the data, I wanted the Commodore - to work with the same exact input set it had for Part 1. So I turned to - the simplest sorting algorithm I could remember: - <a href="https://en.wikipedia.org/wiki/Bubble_sort">bubble sort</a>. - </p> - - <p>Here is my solution for Day 1 Part 2:</p> - - <pre> - <code> -10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144 -11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889 -12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946 -13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627 -14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844 -15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548 -16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986 -17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498 -18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797 -19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542 -20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507 -21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635 -22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538 -23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550 -24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366 -25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902 -26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812 -27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154 -28 DATA 1769, 1529 -100 DIM A(200) -110 FOR I=0TO199 -120 READ A(I) -140 NEXT -141 GOSUB 300 -150 FOR I=0TO199 -160 B=A(I) -170 FOR J=0TO199 -180 IF J=I THEN 250 -190 C=A(J) -200 FOR K=0TO199 -210 IF K=I OR K=J THEN 240 -220 D=A(K) -230 IF B+C+D=2020 THEN PRINT "!",B,C,D,B*C*D:STOP -240 NEXT K -250 NEXT J -260 NEXT I -300 REM BUBBLE SORT -301 X=200 -310 N=200 -320 FOR I=0TON-2 -330 FOR J=0TON-I-2 -340 X=A(J):Y=A(J+1) -350 IF X>Y THEN A(J)=Y:A(J+1)=X -360 NEXT : NEXT -370 RETURN - </code> - </pre> - - <p> - I added a subroutine starting on line 300 to perform a basic bubble sort - on top of the original array of data. Now bubble sort isn't fast by any - means, but the Commodore was able to finish it in a couple of minutes. - And the results were worth it because the subsequent triple - <code>FOR</code>-loop completed in another few minutes. My instinct was - right and two of the solution numbers were triple-digit. - </p> - - <p> - So there you have it, Advent of Code 2020 Day 1 in Commodore 64 Basic - V2. You can run these samples on real hardware of course, or in an - emulator. You can also run them with the - <a href="https://github.com/mist64/cbmbasic"><code>cbmbasic</code></a> - interpreter, which is a neat native C64 Basic interpreter for modern - architectures. (Oh and I tested my samples on <code>cbmbasic</code> and - they finished instantaneously. It helps to have a - thousands-of-times-faster processor.) - </p> - - <p> - I was going to keep going with the challenge and finish them all in CBM - basic for fun, but the Day 2 input data set was 1000 entries. No - problem, I can just read them from a <code>SEQ</code> file. The only - blocker I realized was the challenge requires string character counting, - which I don't think there's a function for in CBM basic. Maybe I have to - do a few <code>PEEK</code>s and <code>POKE</code>s to check memory - locations for ASCII/PETSCII character codes. Or I could just put it off - til next year :) - </p> - </article> - </body> -</html> diff --git a/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php b/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php new file mode 100644 index 0000000..5196d2c --- /dev/null +++ b/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php @@ -0,0 +1,179 @@ +<?php +$title = "AOC 2020 Day 1 in CBM Basic"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + I implemented the + <a href="https://adventofcode.com/2020">Advent of Code 2020</a> Day 1 + challenge in CBM BASIC on a real Commodore 64. I haven't done anything + in Basic in a long time, and probably never did anything actually + meaningful with it. Part 1 of the challenge was to take a list of + numbers, find the two that summed to 2020, and then multiply those two + numbers together. Part two was to perform part 1 but with three numbers + instead of two. +</p> +<p> + Now I wanted to actually write the code on the Commodore 64 itself, but + I gave myself some leniency. Instead of manually typing in all 200 + entries of input data (and inevitably making a breaking mistake) I used + Vim on my PC to format the <code>DATA</code> entries at the start of the + code. I then dropped that onto a 1541 disk image, plopped it on an SD + card, and used my SD2IEC to mount the SD card's image on the Commodore. + The rest of the programming was done on the Commodore itself. +</p> + +<p>Here is my solution for Day 1 Part 1:</p> +<pre> + <code> +10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144 +11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889 +12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946 +13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627 +14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844 +15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548 +16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986 +17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498 +18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797 +19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542 +20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507 +21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635 +22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538 +23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550 +24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366 +25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902 +26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812 +27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154 +28 DATA 1769, 1529 +100 DIM A(200) +110 FOR I=0TO199 +120 READ A(I) +140 NEXT +150 FOR I=0TO199 +160 B=A(I) +170 FOR J=0TO199 +180 IF I=J THEN 210 +190 C=A(J) +200 IF B+C=2020 THEN PRINT "!",B,C,B*C:STOP +210 NEXT J +220 NEXT I + </code></pre> + +<p> + I basically put all 200 numbers into data fields, and then defined an + array large enough to read them into with <code>DIM</code>. Then I + iterated over the array twice, checking each element against each other + element to see if they summed to 2020. If they did, I printed them both + and the product of the two found numbers and stopped further execution. +</p> +<p> + There weren't really any special tricks to this implementation except + remembering that I shouldn't be checking whether a number could sum to + 2020 with itself. +</p> + +<p> + Then I got to move onto Part 2, and this is where things got + interesting. Comparing any three numbers from the data meant the + cognitively easiest way to solve the problem was a triple loop. This of + course meant <code>O(n^3)</code> time, which the Commodore struggled + with. I waited about an hour before I decided I could optimize just a + little bit to speed up the search. +</p> + +<p> + I figured that for three numbers to sum to 2020, they all had to be + pretty small. Most likely they were most (if not all) three digits + instead of four. So I figured I could sort the entry data to make the + search finish probably near the start of the first layer of iteration. + Keep in mind I didn't want to pre-sort the data, I wanted the Commodore + to work with the same exact input set it had for Part 1. So I turned to + the simplest sorting algorithm I could remember: + <a href="https://en.wikipedia.org/wiki/Bubble_sort">bubble sort</a>. +</p> + +<p>Here is my solution for Day 1 Part 2:</p> + +<pre> + <code> +10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144 +11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889 +12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946 +13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627 +14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844 +15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548 +16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986 +17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498 +18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797 +19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542 +20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507 +21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635 +22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538 +23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550 +24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366 +25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902 +26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812 +27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154 +28 DATA 1769, 1529 +100 DIM A(200) +110 FOR I=0TO199 +120 READ A(I) +140 NEXT +141 GOSUB 300 +150 FOR I=0TO199 +160 B=A(I) +170 FOR J=0TO199 +180 IF J=I THEN 250 +190 C=A(J) +200 FOR K=0TO199 +210 IF K=I OR K=J THEN 240 +220 D=A(K) +230 IF B+C+D=2020 THEN PRINT "!",B,C,D,B*C*D:STOP +240 NEXT K +250 NEXT J +260 NEXT I +300 REM BUBBLE SORT +301 X=200 +310 N=200 +320 FOR I=0TON-2 +330 FOR J=0TON-I-2 +340 X=A(J):Y=A(J+1) +350 IF X>Y THEN A(J)=Y:A(J+1)=X +360 NEXT : NEXT +370 RETURN + </code> + </pre> + +<p> + I added a subroutine starting on line 300 to perform a basic bubble sort + on top of the original array of data. Now bubble sort isn't fast by any + means, but the Commodore was able to finish it in a couple of minutes. + And the results were worth it because the subsequent triple + <code>FOR</code>-loop completed in another few minutes. My instinct was + right and two of the solution numbers were triple-digit. +</p> + +<p> + So there you have it, Advent of Code 2020 Day 1 in Commodore 64 Basic + V2. You can run these samples on real hardware of course, or in an + emulator. You can also run them with the + <a href="https://github.com/mist64/cbmbasic"><code>cbmbasic</code></a> + interpreter, which is a neat native C64 Basic interpreter for modern + architectures. (Oh and I tested my samples on <code>cbmbasic</code> and + they finished instantaneously. It helps to have a + thousands-of-times-faster processor.) +</p> + +<p> + I was going to keep going with the challenge and finish them all in CBM + basic for fun, but the Day 2 input data set was 1000 entries. No + problem, I can just read them from a <code>SEQ</code> file. The only + blocker I realized was the challenge requires string character counting, + which I don't think there's a function for in CBM basic. Maybe I have to + do a few <code>PEEK</code>s and <code>POKE</code>s to check memory + locations for ASCII/PETSCII character codes. Or I could just put it off + til next year :) +</p> diff --git a/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html b/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html deleted file mode 100644 index 01a9b3a..0000000 --- a/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html +++ /dev/null @@ -1,203 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Useful Sprint Planning from a Certified Scrum Master" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title> - 53hornet ➙ Useful Sprint Planning from a Certified Scrum Master - </title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Useful Sprint Planning from a Certified Scrum Master</h1> - - <p class="description"> - This is a small collection of sprint planning/story points allocation - tips and tricks that I use at work. They pretty much all come from our - in-house certified "Scrum Master". He's got much better experience than - I do with building a real working backlog of stories and planning - sprints based on those stories. That being said, any opinions here are - my own and I don't speak on his behalf. - </p> - - <h2>Points as a Measure of Work</h2> - - <p> - In my understanding, points are approximate measures of the amount of - work required to complete a given story or task. I do not think points - correlate to an exact measure of time. I use them to determine the size - of a task in relation to another task. For example, a simple-looking - task may be allocated 1 point. In reality this 1 point may take 1 minute - or 1 hour to complete. The time it takes is less important than the - ratio of time it takes in comparison to a second given task. Say the - second task appears to take twice as much time as the first (however - much time that may be). The second task would therefore get 2 points. - </p> - - <p> - Some teams have a special system for incrementing points. Our team uses - the - <a href="https://en.wikipedia.org/wiki/Fibonacci#Fibonacci_sequence" - >Fibonacci sequence of numbers</a - >. So the smallest amount that can be allocated to a story is 1. Then it - goes 2, 3, 5, 8, and so on and so forth. If a single story is going to - use up 8 points, you should probably take a look at breaking it up into - smaller tasks. A single story shouldn't take up almost half of your - allocated work for a sprint. - </p> - - <h2>How Much is Enough?</h2> - <p> - Our team aims for 10 points per 2-week per sprint. Simple enough for me, - but the hard part is determining how many points to allocate to a given - task. - </p> - - <p> - One thing I could never figure out is what the recommended starting - position for 1 point looks like. I'm sure this is something that comes - from experience, and our Scrum Master helped us out with that. - </p> - - <ul> - <li> - 1 point: Small or basic text change. Updating configuration, fixing a - typo or cognitively simple bug. - </li> - <li> - 2 points: Task with light complexity. Some portions of code have to - change, be debugged, tested. - </li> - <li> - 3 points: Some complexity, will take time to implement. Potentially a - few days' worth of work. May require front- and back-end work, or - back-end and database work. - </li> - <li> - 5 points: Half a sprint's worth of more complicated work. Full-on - feature implementation for example. - </li> - </ul> - - <h2>Prioritizing Work</h2> - - <p> - I do not see points as indicative of the importance or priority of a - task or story. Just because one task will take longer to complete than - another does not mean it's more or less important to me. There should be - another method of gauging which stories should be taken off the backlog - first. For example, one story might depend on another. One might relate - to core functionality that a stakeholder has asked for. Another task - might be required to make code build because it solves some major - problem! - </p> - - <p> - To communicate how "important" a task is, every story we have is - prioritized something like this: - </p> - <ol> - <li>Critical</li> - <li>Blocker</li> - <li>Highest</li> - <li>High</li> - <li>Medium</li> - <li>Low</li> - <li>Lowest</li> - </ol> - - <p> - Tasks that align with some long-term project that management is waiting - on are tagged "Highest". Stories that prevent lots of other stories from - being completed may be labeled "Blocker". - </p> - - <h2>Sprint Planning/Backlog Refinement</h2> - - <p> - With all that in mind, at the start of the sprint I now take about 10 - points worth of priority work off of the backlog. I'll work through it - the whole sprint through and then, ideally, it'll all be complete by the - end of the sprint. If I bit off more than I could chew and the sprint - ends before I'm finished, the incomplete work rolls over to the next - sprint and is the first to be completed. If I find I've finished - everything I had to work on and there are still a couple of days left in - the sprint, I'll take one or two small items off the backlog and work on - those. - </p> - - <h2>Tools to Get the Job Done</h2> - - <p> - Our team uses Jira at work, and I know some folks love it so much - they've paid for a personal license. It's a bit overkill for my personal - projects, so I've been using Nextcloud's Deck plugin. This is an okay - solution but it doesn't integrate very well with source code - repositories (although it can tie into a Nextcloud "project", or a - collection of related files open to a team). I'm spinning up a Gitea - server to replace my <code>git-web</code> server soon and this is one of - the reasons for that. Gitea has a GitHub-style issue tracker where you - can create issues of various kinds, assign them to users, reference - commits to the source, and create a Kanban-style board of issues that - are on the backlog, to-do, in-progress, or done. - </p> - - <p> - I'm still learning how to keep to a Scrum-like process of some kind, - because I do see the benefit of using such a system, especially in a - team. I'm definitely not an expert though so some of what I've got here - may change over time. Right now it's working well and that's good enough - for me. - </p> - </article> - </body> -</html> diff --git a/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php b/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php new file mode 100644 index 0000000..77aebdf --- /dev/null +++ b/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php @@ -0,0 +1,144 @@ +<?php +$title = "Useful Sprint Planning from a Certified Scrum Master"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + This is a small collection of sprint planning/story points allocation + tips and tricks that I use at work. They pretty much all come from our + in-house certified "Scrum Master". He's got much better experience than + I do with building a real working backlog of stories and planning + sprints based on those stories. That being said, any opinions here are + my own and I don't speak on his behalf. +</p> + +<h2>Points as a Measure of Work</h2> + +<p> + In my understanding, points are approximate measures of the amount of + work required to complete a given story or task. I do not think points + correlate to an exact measure of time. I use them to determine the size + of a task in relation to another task. For example, a simple-looking + task may be allocated 1 point. In reality this 1 point may take 1 minute + or 1 hour to complete. The time it takes is less important than the + ratio of time it takes in comparison to a second given task. Say the + second task appears to take twice as much time as the first (however + much time that may be). The second task would therefore get 2 points. +</p> + +<p> + Some teams have a special system for incrementing points. Our team uses + the + <a href="https://en.wikipedia.org/wiki/Fibonacci#Fibonacci_sequence">Fibonacci sequence of numbers</a>. So the smallest amount that can be allocated to a story is 1. Then it + goes 2, 3, 5, 8, and so on and so forth. If a single story is going to + use up 8 points, you should probably take a look at breaking it up into + smaller tasks. A single story shouldn't take up almost half of your + allocated work for a sprint. +</p> + +<h2>How Much is Enough?</h2> +<p> + Our team aims for 10 points per 2-week per sprint. Simple enough for me, + but the hard part is determining how many points to allocate to a given + task. +</p> + +<p> + One thing I could never figure out is what the recommended starting + position for 1 point looks like. I'm sure this is something that comes + from experience, and our Scrum Master helped us out with that. +</p> + +<ul> + <li> + 1 point: Small or basic text change. Updating configuration, fixing a + typo or cognitively simple bug. + </li> + <li> + 2 points: Task with light complexity. Some portions of code have to + change, be debugged, tested. + </li> + <li> + 3 points: Some complexity, will take time to implement. Potentially a + few days' worth of work. May require front- and back-end work, or + back-end and database work. + </li> + <li> + 5 points: Half a sprint's worth of more complicated work. Full-on + feature implementation for example. + </li> +</ul> + +<h2>Prioritizing Work</h2> + +<p> + I do not see points as indicative of the importance or priority of a + task or story. Just because one task will take longer to complete than + another does not mean it's more or less important to me. There should be + another method of gauging which stories should be taken off the backlog + first. For example, one story might depend on another. One might relate + to core functionality that a stakeholder has asked for. Another task + might be required to make code build because it solves some major + problem! +</p> + +<p> + To communicate how "important" a task is, every story we have is + prioritized something like this: +</p> +<ol> + <li>Critical</li> + <li>Blocker</li> + <li>Highest</li> + <li>High</li> + <li>Medium</li> + <li>Low</li> + <li>Lowest</li> +</ol> + +<p> + Tasks that align with some long-term project that management is waiting + on are tagged "Highest". Stories that prevent lots of other stories from + being completed may be labeled "Blocker". +</p> + +<h2>Sprint Planning/Backlog Refinement</h2> + +<p> + With all that in mind, at the start of the sprint I now take about 10 + points worth of priority work off of the backlog. I'll work through it + the whole sprint through and then, ideally, it'll all be complete by the + end of the sprint. If I bit off more than I could chew and the sprint + ends before I'm finished, the incomplete work rolls over to the next + sprint and is the first to be completed. If I find I've finished + everything I had to work on and there are still a couple of days left in + the sprint, I'll take one or two small items off the backlog and work on + those. +</p> + +<h2>Tools to Get the Job Done</h2> + +<p> + Our team uses Jira at work, and I know some folks love it so much + they've paid for a personal license. It's a bit overkill for my personal + projects, so I've been using Nextcloud's Deck plugin. This is an okay + solution but it doesn't integrate very well with source code + repositories (although it can tie into a Nextcloud "project", or a + collection of related files open to a team). I'm spinning up a Gitea + server to replace my <code>git-web</code> server soon and this is one of + the reasons for that. Gitea has a GitHub-style issue tracker where you + can create issues of various kinds, assign them to users, reference + commits to the source, and create a Kanban-style board of issues that + are on the backlog, to-do, in-progress, or done. +</p> + +<p> + I'm still learning how to keep to a Scrum-like process of some kind, + because I do see the benefit of using such a system, especially in a + team. I'm definitely not an expert though so some of what I've got here + may change over time. Right now it's working well and that's good enough + for me. +</p> diff --git a/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html b/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html deleted file mode 100644 index bd1dba7..0000000 --- a/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html +++ /dev/null @@ -1,144 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Why Does Everyone Use Adobe Acrobat [Reader]?" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Why Does Everyone Use Adobe Acrobat [Reader]?</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Why Does Everyone Use Adobe Acrobat [Reader]?</h1> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/Pq8ZPe8THoH3Eoo/preview" - /> - </p> - - <p> - This is something that I've never been able to figure out. All through - high school I had to use PDFs. And if you wanted to open a PDF, everyone - understood that you needed Adobe Acrobat Reader. Even web sites where - you downloaded PDFs insisted that in order to open them, you were going - to have to follow a download link to make sure you have Acrobat on your - PC. - </p> - - <p> - Fast-forward a few years into college and I'm using PDFs more than ever. - Every professor ever is scanning and uploading course material, so out - comes Acrobat Reader for literally every teacher and student. At this - point I was actually used to using Firefox (PDF.js) to view PDFs for a - couple of reasons. First of all, Firefox usually opened PDFs faster than - Acrobat Reader did. Reader was getting bigger with every release, and - eventually had a monstrous UI to load up every time I wanted to open a - tiny PDF file. Second, Firefox had smooth scrolling for page-width - documents. Reader was getting slower and laggier with each release, to - the point where scrolling through a PDF was no longer buttery smooth but - jittery and stuttery. It also seemed like Reader purposefully wouldn't - slide the page when you used a mouse wheel. It would jump down a few - lines at a time like it was simulating the down arrow. - </p> - - <p> - By my senior year I had switched from Windows to Linux full-time and it - was then I found out about <a href="https://mupdf.com/">MuPDF</a> and - from then on things were never the same. It's literally the best PDF - reader I've ever used, and I tried out quite a few. There are desktop - and mobile apps. It opens almost instantly. It lets you easily resize - the page with excellent keyboard shortcuts. There are no giant menu bars - on either side of the page to squish the document down to an unreadable - size. Having a dozen of them open at once doesn't bog down my PC. It's - also available for all of the relevant operating systems I've used - (Windows, Mac OS, Linux, FreeBSD)! Oh and password-protected PDFs are - supported as well. - </p> - - <p> - It's a fantastic piece of software And the best part is it comes with a - variety of tools to edit and manipulate PDFs as well. If the folks I - went to school with thought you needed the free Acrobat Reader to view a - PDF, they sure as heck thought you needed to buy Acrobat Pro to edit - one. Some of them refused to pay for it and used a variety of online - services to upload, split or merge, and download PDFs. I honestly for - the life of me can't understand why. MuPDF comes with - <code>mutool</code>, which does all of the things I would ever need to - do with a PDF. It can attempt to convert a PDF to other formats, like - HTML. It can split and combine documents. It can even create them from - scratch and sign them. - </p> - - <p> - It's also free and open source. Can you imagine that? PDF viewing and - editing being free and open source? It's AGPL (in addition to being - commercially) licensed by the creators. The only slight drawback is the - desktop version apparently does not yet let you fill out forms. Not sure - why but this isn't something I use very frequently. - </p> - - <p> - It's not the hottest piece of tech out there, but it just plain works - and works really well. Maybe the only reason more people I know don't - use it is because Adobe is synonymous with the PDF format. It doesn't - seem like that big of a deal, but I feel like Acrobat has always been a - piece of software that has frustrated new or infrequent users in - computing. And that's just not good. Maybe the barrier to using MuPDF is - the lack of GUI and abundance of keybindings, but for me that's no - sweat. I'd say to anyone to just try it out and see if they like it. It - is free, after all. - </p> - </article> - </body> -</html> diff --git a/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php b/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php new file mode 100644 index 0000000..bb384f2 --- /dev/null +++ b/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php @@ -0,0 +1,84 @@ +<?php +$title = "Why Does Everyone Use Adobe Acrobat [Reader]?"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/Pq8ZPe8THoH3Eoo/preview" /> +</p> + +<p> + This is something that I've never been able to figure out. All through + high school I had to use PDFs. And if you wanted to open a PDF, everyone + understood that you needed Adobe Acrobat Reader. Even web sites where + you downloaded PDFs insisted that in order to open them, you were going + to have to follow a download link to make sure you have Acrobat on your + PC. +</p> + +<p> + Fast-forward a few years into college and I'm using PDFs more than ever. + Every professor ever is scanning and uploading course material, so out + comes Acrobat Reader for literally every teacher and student. At this + point I was actually used to using Firefox (PDF.js) to view PDFs for a + couple of reasons. First of all, Firefox usually opened PDFs faster than + Acrobat Reader did. Reader was getting bigger with every release, and + eventually had a monstrous UI to load up every time I wanted to open a + tiny PDF file. Second, Firefox had smooth scrolling for page-width + documents. Reader was getting slower and laggier with each release, to + the point where scrolling through a PDF was no longer buttery smooth but + jittery and stuttery. It also seemed like Reader purposefully wouldn't + slide the page when you used a mouse wheel. It would jump down a few + lines at a time like it was simulating the down arrow. +</p> + +<p> + By my senior year I had switched from Windows to Linux full-time and it + was then I found out about <a href="https://mupdf.com/">MuPDF</a> and + from then on things were never the same. It's literally the best PDF + reader I've ever used, and I tried out quite a few. There are desktop + and mobile apps. It opens almost instantly. It lets you easily resize + the page with excellent keyboard shortcuts. There are no giant menu bars + on either side of the page to squish the document down to an unreadable + size. Having a dozen of them open at once doesn't bog down my PC. It's + also available for all of the relevant operating systems I've used + (Windows, Mac OS, Linux, FreeBSD)! Oh and password-protected PDFs are + supported as well. +</p> + +<p> + It's a fantastic piece of software And the best part is it comes with a + variety of tools to edit and manipulate PDFs as well. If the folks I + went to school with thought you needed the free Acrobat Reader to view a + PDF, they sure as heck thought you needed to buy Acrobat Pro to edit + one. Some of them refused to pay for it and used a variety of online + services to upload, split or merge, and download PDFs. I honestly for + the life of me can't understand why. MuPDF comes with + <code>mutool</code>, which does all of the things I would ever need to + do with a PDF. It can attempt to convert a PDF to other formats, like + HTML. It can split and combine documents. It can even create them from + scratch and sign them. +</p> + +<p> + It's also free and open source. Can you imagine that? PDF viewing and + editing being free and open source? It's AGPL (in addition to being + commercially) licensed by the creators. The only slight drawback is the + desktop version apparently does not yet let you fill out forms. Not sure + why but this isn't something I use very frequently. +</p> + +<p> + It's not the hottest piece of tech out there, but it just plain works + and works really well. Maybe the only reason more people I know don't + use it is because Adobe is synonymous with the PDF format. It doesn't + seem like that big of a deal, but I feel like Acrobat has always been a + piece of software that has frustrated new or infrequent users in + computing. And that's just not good. Maybe the barrier to using MuPDF is + the lack of GUI and abundance of keybindings, but for me that's no + sweat. I'd say to anyone to just try it out and see if they like it. It + is free, after all. +</p> diff --git a/posts/2020-12-29-antivirus-software-is-a-hack.html b/posts/2020-12-29-antivirus-software-is-a-hack.html deleted file mode 100644 index 5c602a2..0000000 --- a/posts/2020-12-29-antivirus-software-is-a-hack.html +++ /dev/null @@ -1,197 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Antivirus Software is a Hack" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Antivirus Software is a Hack</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Antivirus Software is a Hack</h1> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/jJoFoA7Ppjb7rey/preview" - /> - </p> - - <p class="description"> - I read a really terrific article today about computer security and - really dumb ideas or trends that have developed in this field. It's - <a - href="https://www.ranum.com/security/computer_security/editorials/dumb/" - >M. Ranum's <em>The Six Dumbest Ideas in Computer Security</em></a - >, and I highly recommend reading through the whole thing. It's got - great anecdotes and really simple language for what I consider to be - some of the obvious issues with the way programmers and sysadmins think - about security (myself included). One portion of it (idea #2), however, - finally put something into words that I've felt for a really long time. - It enables me to explain why I think all antivirus software is a total - hack and is virtually useless. - </p> - - <blockquote> - hack<br /> - 1. n. Originally, a quick job that produces what is needed, but not - well. - <br /> - <cite>-- The Jargon File (version 4.4.7, 29 Dec 2003) [jargon]</cite> - </blockquote> - - <p> - This is the Jargon File's definition of a hack. And to me, this is what - antivirus software is. Antivirus software, as I understand it, emerged - in the mid to late 1980s and became prolific in the 1990s. In the 2000s - it was considered an essential piece of software and people were paying - for yearly subscriptions for antivirus suites from Norton, Avast, and - McAfee. - </p> - - <p> - The most basic functionality of an antivirus program is to determine - whether malware exists on a host operating system. The typical method of - doing this is to use a collection of virus definitions and compare each - and every potentially-infected file with each and every definition to - determine whether the file is malware or has been infected by some. An - over-simplified way of implementing this is to store a collection of - hashes, each taken from a known potentially unwanted program or - infectious executable. You can then hash entire files or portions of - files and compare the checksums to see whether a file contains or is - equivalent to the definition, and is therefore infected and shouldn't be - executed. Some security suites go beyond this with heuristic matching, - but if you run an antivirus that has to "update definitions" on a - routine basis, it probably works something like this*. With any luck, it - does it without being a total detriment to system performance. Ideally - it also doesn't act like a piece of malware itself by making itself near - impossible to remove (looking at you, McAfee). - </p> - - <p> - To me, a virus definition database is "enumerating badness" (Ranum's - Dumb Idea #2). The premise is that it is not only logical but even - possible to compile a list of <em>all</em> potentially unwanted - programs, viruses, ransomware, and worms. An environment of trust should - be built around the programs that you want to run (read: - <em>allow to run</em>), not the other way around. Picture an operating - system where no binary file can be executed unless it is specifically - flagged as being allowed to. Oh and picture also being able to restrict - this execution to just the file's owner, or other groups of users. - Wouldn't it be easier to store the list of 30 odd programs that you and - other system users trust to be run than the thousands (millions?) of - programs that are infectious, forbidden, or unwanted? What about when - those trusted applications become compromised? Would it not also be - easier to maintain a list of checksums for those binaries and compare - those checksums before they're executed to make sure they haven't been - infected or replaced? - </p> - - <p> - The answer is yes, it would be easier. And yes, it is easier. Of course, - your system has to work that way. Antivirus software is a hack because - it's a hack-y solution to a problem that has a better, simpler solution. - It also has the potential for making a ton of money but I won't go into - that. It's easier to enumerate goodness, to specifically open up to a - select few trustworthy applications. Good lists are usually shorter than - bad lists. This builds on top of Ranum's Dumb Idea #1: Default Permit. - You wouldn't configure a firewall to just block some known bad ports and - traffic. You configure it to block all of it, and then whitelist the - ones you know you can trust. You wouldn't configure a browser ad-blocker - to permit all ads, and select the ones you don't want to see. You block - all of them! Then, if there are sites or ads you're okay with seeing, - you whitelist them. You shouldn't default permit all programs to be - given control over your computer, and then meticulously list the ones - that don't have that permission. - </p> - - <p> - Oh and of course, as always, there's free software that lets you do - this. You don't have to pay for an antivirus suite, or even use an - unpaid one that slows down your computer or barrages you with ads. On - the BSDs and virtually all Linux distributions, there are built-in tools - to control access and execution of binaries. There are additional tools - that you can install that check whether binaries (in locations like - <code>/bin</code> or <code>/usr/local/bin</code> have been modified - since you last used them. On Windows, the story is a little different. - Most home Windows 10 users are automatically allowed to install and run - any software they want to by default. Windows Server does have Software - Restriction Policies that allow you to create a "default deny" policy - and whitelist only the software that's allowed to run. If you're using a - home edition you probably have to look for software that lets you do - this. I haven't tried any of them so I'm not going to endorse or even - name them here. - </p> - - <p> - Preventing malware from running on your system is a problem. Solving - this problem is the right thing to do. But please, try to solve it the - right way. I stopped using an antivirus after I moved out and got to - control my own computer. I don't think it ever did me any good besides - flag false positives (a lot of the time with programs or applications - that I wrote, which weren't malicious in any way!) and grind my spinning - disk to a halt. Evaluate what software you use. Is most of it online? - Are there one or two applications that you know you need to use? How - often do you install and use unknown or untrusted software? Odds are you - can come up with a list of very few programs that you want or need to - use. If it's less than 100,000, you're probably better off with a - default deny policy than an antivirus suite. - </p> - - <p> - * What I didn't mention here is that as soon as a new piece of malware - is constructed, if it's different enough from its predecessors, it's - impervious to all antivirus suites on the planet that don't have it in - their definitions. So until that malware is used, detected, and added to - the list, it has free reign. - </p> - </article> - </body> -</html> diff --git a/posts/2020-12-29-antivirus-software-is-a-hack.php b/posts/2020-12-29-antivirus-software-is-a-hack.php new file mode 100644 index 0000000..cc5f0d0 --- /dev/null +++ b/posts/2020-12-29-antivirus-software-is-a-hack.php @@ -0,0 +1,137 @@ +<?php +$title = "Antivirus Software is a Hack"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/jJoFoA7Ppjb7rey/preview" /> +</p> + +<p class="description"> + I read a really terrific article today about computer security and + really dumb ideas or trends that have developed in this field. It's + <a href="https://www.ranum.com/security/computer_security/editorials/dumb/">M. Ranum's <em>The Six Dumbest Ideas in Computer Security</em></a>, and I highly recommend reading through the whole thing. It's got + great anecdotes and really simple language for what I consider to be + some of the obvious issues with the way programmers and sysadmins think + about security (myself included). One portion of it (idea #2), however, + finally put something into words that I've felt for a really long time. + It enables me to explain why I think all antivirus software is a total + hack and is virtually useless. +</p> + +<blockquote> + hack<br /> + 1. n. Originally, a quick job that produces what is needed, but not + well. + <br /> + <cite>-- The Jargon File (version 4.4.7, 29 Dec 2003) [jargon]</cite> +</blockquote> + +<p> + This is the Jargon File's definition of a hack. And to me, this is what + antivirus software is. Antivirus software, as I understand it, emerged + in the mid to late 1980s and became prolific in the 1990s. In the 2000s + it was considered an essential piece of software and people were paying + for yearly subscriptions for antivirus suites from Norton, Avast, and + McAfee. +</p> + +<p> + The most basic functionality of an antivirus program is to determine + whether malware exists on a host operating system. The typical method of + doing this is to use a collection of virus definitions and compare each + and every potentially-infected file with each and every definition to + determine whether the file is malware or has been infected by some. An + over-simplified way of implementing this is to store a collection of + hashes, each taken from a known potentially unwanted program or + infectious executable. You can then hash entire files or portions of + files and compare the checksums to see whether a file contains or is + equivalent to the definition, and is therefore infected and shouldn't be + executed. Some security suites go beyond this with heuristic matching, + but if you run an antivirus that has to "update definitions" on a + routine basis, it probably works something like this*. With any luck, it + does it without being a total detriment to system performance. Ideally + it also doesn't act like a piece of malware itself by making itself near + impossible to remove (looking at you, McAfee). +</p> + +<p> + To me, a virus definition database is "enumerating badness" (Ranum's + Dumb Idea #2). The premise is that it is not only logical but even + possible to compile a list of <em>all</em> potentially unwanted + programs, viruses, ransomware, and worms. An environment of trust should + be built around the programs that you want to run (read: + <em>allow to run</em>), not the other way around. Picture an operating + system where no binary file can be executed unless it is specifically + flagged as being allowed to. Oh and picture also being able to restrict + this execution to just the file's owner, or other groups of users. + Wouldn't it be easier to store the list of 30 odd programs that you and + other system users trust to be run than the thousands (millions?) of + programs that are infectious, forbidden, or unwanted? What about when + those trusted applications become compromised? Would it not also be + easier to maintain a list of checksums for those binaries and compare + those checksums before they're executed to make sure they haven't been + infected or replaced? +</p> + +<p> + The answer is yes, it would be easier. And yes, it is easier. Of course, + your system has to work that way. Antivirus software is a hack because + it's a hack-y solution to a problem that has a better, simpler solution. + It also has the potential for making a ton of money but I won't go into + that. It's easier to enumerate goodness, to specifically open up to a + select few trustworthy applications. Good lists are usually shorter than + bad lists. This builds on top of Ranum's Dumb Idea #1: Default Permit. + You wouldn't configure a firewall to just block some known bad ports and + traffic. You configure it to block all of it, and then whitelist the + ones you know you can trust. You wouldn't configure a browser ad-blocker + to permit all ads, and select the ones you don't want to see. You block + all of them! Then, if there are sites or ads you're okay with seeing, + you whitelist them. You shouldn't default permit all programs to be + given control over your computer, and then meticulously list the ones + that don't have that permission. +</p> + +<p> + Oh and of course, as always, there's free software that lets you do + this. You don't have to pay for an antivirus suite, or even use an + unpaid one that slows down your computer or barrages you with ads. On + the BSDs and virtually all Linux distributions, there are built-in tools + to control access and execution of binaries. There are additional tools + that you can install that check whether binaries (in locations like + <code>/bin</code> or <code>/usr/local/bin</code> have been modified + since you last used them. On Windows, the story is a little different. + Most home Windows 10 users are automatically allowed to install and run + any software they want to by default. Windows Server does have Software + Restriction Policies that allow you to create a "default deny" policy + and whitelist only the software that's allowed to run. If you're using a + home edition you probably have to look for software that lets you do + this. I haven't tried any of them so I'm not going to endorse or even + name them here. +</p> + +<p> + Preventing malware from running on your system is a problem. Solving + this problem is the right thing to do. But please, try to solve it the + right way. I stopped using an antivirus after I moved out and got to + control my own computer. I don't think it ever did me any good besides + flag false positives (a lot of the time with programs or applications + that I wrote, which weren't malicious in any way!) and grind my spinning + disk to a halt. Evaluate what software you use. Is most of it online? + Are there one or two applications that you know you need to use? How + often do you install and use unknown or untrusted software? Odds are you + can come up with a list of very few programs that you want or need to + use. If it's less than 100,000, you're probably better off with a + default deny policy than an antivirus suite. +</p> + +<p> + * What I didn't mention here is that as soon as a new piece of malware + is constructed, if it's different enough from its predecessors, it's + impervious to all antivirus suites on the planet that don't have it in + their definitions. So until that malware is used, detected, and added to + the list, it has free reign. +</p> diff --git a/posts/2021-01-15-adam-s-2020-reading-list.html b/posts/2021-01-15-adam-s-2020-reading-list.html deleted file mode 100644 index 46f0fba..0000000 --- a/posts/2021-01-15-adam-s-2020-reading-list.html +++ /dev/null @@ -1,196 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Adam's 2020 Reading List" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Adam's 2020 Reading List</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Adam's <del>2020</del> <ins>Quarantine</ins> Reading List</h1> - - <ul> - <li> - Hammett, Dashiell. <em>The Maltese Falcon</em> - <p> - Excellent noir detective novel. Stolen treasure, murder, dames, all - the good stuff. - </p> - </li> - <li> - Chandler, Raymond. <em>The Big Sleep</em> - <p> - More good noir detective work. Cool cars, alcohol, mansions, hit - men, also dames. Yet more good stuff. - </p> - </li> - <li> - Lowry, Lois. <em>The Giver</em> - <p> - Second time I got to read this. Fantastic book just the same as - before. Movie was totally carried by the fact that Jeff Bridges is - the Giver. Super thought-provoking too. - </p> - </li> - <li> - Rowling, J.K. - <em - >Harry Potter and the Sorcerer's Stone, Harry Potter and the Chamber - of Secrets, Harry Potter and the Prisoner of Azkaban, Harry Potter - and the Goblet of Fire, Harry Potter and the Order of the Phoenix, - Harry Potter and the Half-Blood Prince, Harry Potter and the Deathly - Hallows</em - > - <p> - Yep, all of them. I've read some of them multiple times but this was - the first time I read them all to completion myself. My dad used to - read them to me, so I only "listened" to the last couple. Always - great, always better than the movies. And I pick up more and more - forward- and backward-looking references when I read them in a row. - </p> - </li> - <li> - Miller, Rand, Miller, Robyn, Miller, David. - <em>Myst: The Book of Atrus, Myst: The Book of Ti'ana</em> - <p> - The great first two books in the Myst novel series. My favorite is - the second, it gives all of the meat-and-potatoes lore behind the - D'ni, The Art, and The Fall that I always wanted. The first is good - too, and I recommend book-and-game nerds read - <em>Myst: The Book of Atrus</em> after playing Myst: Masterpiece - Edition and before playing Riven: The Sequel to Myst. - </p> - </li> - <li> - Miller, Rand. <em>Myst: The Book of D'ni</em> - <p> - Probably my least favorite of the three Myst novels. It's - fascinating and has lots of dark themes like enslavement. I - recommend reading this one after Riven and before Myst III: Exile. - </p> - </li> - <li> - Paulsen, Gary. <em>Hatchet</em> - <p> - The last time I read this was probably in the sixth grade, and it - was one of the few books I was really glued to then. It's still a - great story about survival, nature, getting mauled by moose, etc. - </p> - </li> - <li> - Grisham, John. <em>Theodore Boone: Kid Lawyer</em> - <p> - Also a re-read for me. I kind of sort of wanted to be a lawyer - growing up and this book was the "I can do it too!" book. It's still - a good crime, evidence, trial style lawyer book. I need to read the - sequels. - </p> - </li> - <li> - Wells, H.G. - <em>The Time Machine, The Island of Dr. Moreau, The Invisible Man</em> - <p> - These are three of my favorite H.G. Wells novels. - <em>The Time Machine</em> is super weird though and now that I'm - re-reading it I'm picking up on a ton of Communist undertones. - <em>Dr. Moreau</em> is fantastic. I love all books that take place - on a desert island and this one really creeps me out with the - doctor's surgically-humanized animals. <em>Invisible Man</em> is so - short it's worth reading on a weekend just to know what it's about - (spoiler: a man who is invisible). - </p> - </li> - <li> - Stevenson, Robert Louis. <em>Treasure Island</em> - <p> - Dude, I watched Treasure Planet when I was a kid and I was really - into it for like a month. Now I finally got to read the real thing - and there's a reason why this is one of those perfect examples of - literature. It's the - <em>absolute perfect, truly American story</em> - about pirates, treasure, and sailing ships. - </p> - </li> - <li> - Dick, Harold G. - <em - >The Golden Age of the Great Passenger Airships: Graf Zeppelin and - Hindenburg</em - > - <p> - I'm a huge rigid airship junkie. They're freaking awesome, I wish - they were still around. I hate flying, and not because of the act of - being in the air but because airships make it seem more comfortable, - luxurious, and adventurous than a half a bag of peanuts, motion - sickness, and recycled oxygen. If you're at all interested in - Zeppelins and you can only read one book, this is the - <em>only</em> book worth reading. It chronicles the author's - experiences actually flying on and operating Graf Zeppelin and - Hindenburg, their flight logs, how they worked, how they were flown, - and the history behind their creation and demise. It's awesome. - </p> - </li> - <li> - Brown, Dan. <em>Digital Fortress</em> - <p> - Great story, I actually listened to this audiobook while painting - our house right around the start of 2020. It's an awesome story with - an intelligent, sleuthy programmer and her globe-trotting professor - significant other tracking down clues. It's got supercomputers and - hackers and espionage and murder and viruses and it would be perfect - if I knew nothing about cryptography or computing in general. - </p> - </li> - </ul> - </article> - </body> -</html> diff --git a/posts/2021-01-15-adam-s-2020-reading-list.php b/posts/2021-01-15-adam-s-2020-reading-list.php new file mode 100644 index 0000000..facfb32 --- /dev/null +++ b/posts/2021-01-15-adam-s-2020-reading-list.php @@ -0,0 +1,137 @@ +<?php +$title = "Adam's <del>2020</del> <ins>Quarantine</ins> Reading List"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<ul> + <li> + Hammett, Dashiell. <em>The Maltese Falcon</em> + <p> + Excellent noir detective novel. Stolen treasure, murder, dames, all + the good stuff. + </p> + </li> + <li> + Chandler, Raymond. <em>The Big Sleep</em> + <p> + More good noir detective work. Cool cars, alcohol, mansions, hit + men, also dames. Yet more good stuff. + </p> + </li> + <li> + Lowry, Lois. <em>The Giver</em> + <p> + Second time I got to read this. Fantastic book just the same as + before. Movie was totally carried by the fact that Jeff Bridges is + the Giver. Super thought-provoking too. + </p> + </li> + <li> + Rowling, J.K. + <em>Harry Potter and the Sorcerer's Stone, Harry Potter and the Chamber + of Secrets, Harry Potter and the Prisoner of Azkaban, Harry Potter + and the Goblet of Fire, Harry Potter and the Order of the Phoenix, + Harry Potter and the Half-Blood Prince, Harry Potter and the Deathly + Hallows</em> + <p> + Yep, all of them. I've read some of them multiple times but this was + the first time I read them all to completion myself. My dad used to + read them to me, so I only "listened" to the last couple. Always + great, always better than the movies. And I pick up more and more + forward- and backward-looking references when I read them in a row. + </p> + </li> + <li> + Miller, Rand, Miller, Robyn, Miller, David. + <em>Myst: The Book of Atrus, Myst: The Book of Ti'ana</em> + <p> + The great first two books in the Myst novel series. My favorite is + the second, it gives all of the meat-and-potatoes lore behind the + D'ni, The Art, and The Fall that I always wanted. The first is good + too, and I recommend book-and-game nerds read + <em>Myst: The Book of Atrus</em> after playing Myst: Masterpiece + Edition and before playing Riven: The Sequel to Myst. + </p> + </li> + <li> + Miller, Rand. <em>Myst: The Book of D'ni</em> + <p> + Probably my least favorite of the three Myst novels. It's + fascinating and has lots of dark themes like enslavement. I + recommend reading this one after Riven and before Myst III: Exile. + </p> + </li> + <li> + Paulsen, Gary. <em>Hatchet</em> + <p> + The last time I read this was probably in the sixth grade, and it + was one of the few books I was really glued to then. It's still a + great story about survival, nature, getting mauled by moose, etc. + </p> + </li> + <li> + Grisham, John. <em>Theodore Boone: Kid Lawyer</em> + <p> + Also a re-read for me. I kind of sort of wanted to be a lawyer + growing up and this book was the "I can do it too!" book. It's still + a good crime, evidence, trial style lawyer book. I need to read the + sequels. + </p> + </li> + <li> + Wells, H.G. + <em>The Time Machine, The Island of Dr. Moreau, The Invisible Man</em> + <p> + These are three of my favorite H.G. Wells novels. + <em>The Time Machine</em> is super weird though and now that I'm + re-reading it I'm picking up on a ton of Communist undertones. + <em>Dr. Moreau</em> is fantastic. I love all books that take place + on a desert island and this one really creeps me out with the + doctor's surgically-humanized animals. <em>Invisible Man</em> is so + short it's worth reading on a weekend just to know what it's about + (spoiler: a man who is invisible). + </p> + </li> + <li> + Stevenson, Robert Louis. <em>Treasure Island</em> + <p> + Dude, I watched Treasure Planet when I was a kid and I was really + into it for like a month. Now I finally got to read the real thing + and there's a reason why this is one of those perfect examples of + literature. It's the + <em>absolute perfect, truly American story</em> + about pirates, treasure, and sailing ships. + </p> + </li> + <li> + Dick, Harold G. + <em>The Golden Age of the Great Passenger Airships: Graf Zeppelin and + Hindenburg</em> + <p> + I'm a huge rigid airship junkie. They're freaking awesome, I wish + they were still around. I hate flying, and not because of the act of + being in the air but because airships make it seem more comfortable, + luxurious, and adventurous than a half a bag of peanuts, motion + sickness, and recycled oxygen. If you're at all interested in + Zeppelins and you can only read one book, this is the + <em>only</em> book worth reading. It chronicles the author's + experiences actually flying on and operating Graf Zeppelin and + Hindenburg, their flight logs, how they worked, how they were flown, + and the history behind their creation and demise. It's awesome. + </p> + </li> + <li> + Brown, Dan. <em>Digital Fortress</em> + <p> + Great story, I actually listened to this audiobook while painting + our house right around the start of 2020. It's an awesome story with + an intelligent, sleuthy programmer and her globe-trotting professor + significant other tracking down clues. It's got supercomputers and + hackers and espionage and murder and viruses and it would be perfect + if I knew nothing about cryptography or computing in general. + </p> + </li> +</ul> diff --git a/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html b/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html deleted file mode 100644 index 01d25c8..0000000 --- a/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html +++ /dev/null @@ -1,375 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Root on ZFS: A ZPool of Mirror VDEVs The Easy Way" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Root on ZFS: A ZPool of Mirror VDEVs The Easy Way</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Root on ZFS: A ZPool of Mirror VDEVs</h1> - - <p class="description"> - I wanted/needed to make a root on ZFS pool out of multiple mirror VDEVs, - and since I'm not a ZFS expert, I took a little shortcut. - </p> - - <p> - I recently got a new-to-me server (yay!) and I wanted to do a - root-on-ZFS setup on it. I've really enjoyed using ZFS for my data - storage pools for a long time. I've also enjoyed the extra functionality - that comes with having a bootable system installed on ZFS on my laptop - and decided with this upgrade it's time to do the same on my server. - Historically I've used RAIDZ for my storage pools. RAIDZ functions - almost like a RAID10 but at the ZFS level. It gives you parity so that a - certain number of disks can die from your pool and you won't lose any - data. It does have a few tradeoffs however*, and for personal - preferences I've decided that for the future I would like to have a - single ZPool over top of multiple mirror VDEVs. In other words, my main - root+storage pool will be made up of two-disk mirrors and can be - expanded to include any number of new mirrors I can fit into the - machine. - </p> - - <p> - This did present some complications. First of all, - <code>bsdinstall</code> won't set this up for you automatically (and - sure enough, - <a - href="https://www.freebsd.org/doc/handbook/bsdinstall-partitioning.html" - >in the handbook</a - > - it mentions the guided root on ZFS tool will only create a single, - top-level VDEV unless it's a stripe). It will happily let you use RAIDZ - for your ZROOT but not the more custom approach I'm taking. I did - however use - <code>bsdinstall</code> as a shortcut so I wouldn't have to do all of - the partitioning and pool setup manually, and that's what I'm going to - document below. Because I'm totally going to forget how this works the - next time I have to do it. - </p> - - <p> - In my scenario I have an eight-slot, hot-swappable PERC H310 controller - that's configured for AHCI passthrough. In other words, all FreeBSD sees - is as many disks as I have plugged into the backplane. I'm going to fill - it with 6x2TB hard disks which, as I said before, I want to act as three - mirrors (two disks each) in a single, bootable, growable ZPool. For - starters, I shoved the FreeBSD installer on a flash drive and booted - from it. I followed all of the regular steps (setting hostname, getting - online, etc.) until I got to the guided root on ZFS disk partitioning - setup. - </p> - - <p> - Now here's where I'm going to take the first step on my shortcut. Since - there is no option to create the pool of arbitrary mirrors I'm just - going to create a pool from a single mirror VDEV of two disks. Later I - will expand the pool to include the other two mirrors I had intended - for. My selections were as follows: - </p> - - <ul> - <li>Pool Type/Disks: mirror mfisyspd0 mfisyspd1</li> - <li>Pool Name: zroot</li> - <li>Partition Scheme: GPT (EFI)</li> - <li>Swap Size: 4g</li> - </ul> - - <p> - Everything else was left as a default. Then I followed the installer to - completion. At the end, when it asked if I wanted to drop into a shell - to do more to the installation, I did. - </p> - - <p> - The installer created the following disk layout for the two disks that I - selected. - </p> - - <pre> -<code> -atc@macon:~ % gpart show -=> 40 3907029088 mfisyspd0 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) - -=> 40 3907029088 mfisyspd1 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) -</code> -</pre> - - <p> - The installer also created the following ZPool from my single mirror - VDEV. - </p> - - <pre> -<code> -atc@macon:~ % zpool status - pool: zroot - state: ONLINE - scan: none requested -config: - - NAME STATE READ WRITE CKSUM - zroot ONLINE 0 0 0 - mirror-0 ONLINE 0 0 0 - mfisyspd0p3 ONLINE 0 0 0 - mfisyspd1p3 ONLINE 0 0 0 - -errors: No known data errors -</code> -</pre> - - <p> - There are a couple of things to take note of here. First of all, - <em>both</em> disks in the bootable ZPool have an EFI boot partition. - That means they're both a part of (or capable of?) booting the pool. - Second, they both have some swap space. Finally, they both have a third - partition which is dedicated to ZFS data, and that partition is what got - added to my VDEV. - </p> - - <p> - So where do I go from here? I was tempted to just - <code>zpool add mirror ... ...</code> and just add my other disks to the - pool (actually, I <em>did</em> do this but it rendered the volume - unbootable for a very important reason), but then I wouldn't have those - all-important boot partitions (using whole-disk mirror VDEVS). Instead, - I need to manually go back and re-partition four disks exactly like the - first two. Or, since all I want is two more of what's already been done, - I can just clone the partitions using <code>gpart backup</code> and - <code>restore</code>! Easy! Here's what I did for all four remaining - disks: - </p> - - <pre> -<code> -root@macon:~ # gpart backup mfisyspd0 | gpart restore -F mfisyspd2` -</code> -</pre> - - <p> - Full disclosure, I didn't even think of this as a possibility - <a - href="ihttps://unix.stackexchange.com/questions/472147/replacing-disk-when-using-freebsd-zfs-zroot-zfs-on-partition#472175" - >until I read this Stack Exchange post</a - >. This gave me a disk layout like this: - </p> - - <pre> -<code> -atc@macon:~ % gpart show -=> 40 3907029088 mfisyspd0 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) - -=> 40 3907029088 mfisyspd1 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) - -=> 40 3907029088 mfisyspd2 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) - -=> 40 3907029088 mfisyspd3 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) - -=> 40 3907029088 mfisyspd4 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) - -=> 40 3907029088 mfisyspd5 GPT (1.8T) - 40 409600 1 efi (200M) - 409640 2008 - free - (1.0M) - 411648 8388608 2 freebsd-swap (4.0G) - 8800256 3898228736 3 freebsd-zfs (1.8T) - 3907028992 136 - free - (68K) -</code> -</pre> - - <p> - And to be fair, this makes a lot of logical sense. You don't want a - six-disk pool to only be bootable by two of the disks or you're - defeating some of the purposes of redundancy. So now I can extend my - ZPool to include those last four disks. - </p> - - <p> - This next step may or may not be a requirement. I wanted to overwrite - where I assumed any old ZFS/ZPool metadata might be on my four new - disks. This could just be for nothing and I admit that, but I've run - into trouble in the past where a ZPool wasn't properly - exported/destroyed before the drives were removed for another purpose - and when you use those drives in future - <code>zpool import</code>s, you can see both the new and the old, failed - pools. And, in the previous step I cloned an old ZFS partition many - times! So I did a small <code>dd</code> on the remaining disks to help - me sleep at night: - </p> - - <pre> -<code> -root@macon:~ # dd if=/dev/zero of=/dev/mfisyspd2 bs=1M count=100 -</code> -</pre> - - <p> - One final, precautionary step is to write the EFI boot loader to the new - disks. In - <a href="https://www.freebsd.org/doc/handbook/zfs-zpool.html" - >zpool admin handbook</a - > - it mentions you should do this any time you <em>replace</em> a zroot - device, so I'll do it just for safe measure on all four additional - disks: - </p> - - <pre> -<code> -root@macon:~ # gpart bootcode -p /boot/boot1.efifat -i 1 mfisyspd2 -</code> -</pre> - - <p> - Don't forget that the command is different for UEFI and a traditional - BIOS. And finally, I can add my new VDEVs: - </p> - - <pre> -<code> -root@macon:~ # zpool zroot add mirror mfisyspd2p3 mfisyspd3p3 -root@macon:~ # zpool zroot add mirror mfisyspd4p3 mfisyspd5p3 -</code> -</pre> - - <p>And now my pool looks like this:</p> - - <pre> -<code> -atc@macon:~ % zpool status - pool: zroot - state: ONLINE - scan: none requested -config: - - NAME STATE READ WRITE CKSUM - zroot ONLINE 0 0 0 - mirror-0 ONLINE 0 0 0 - mfisyspd0p3 ONLINE 0 0 0 - mfisyspd1p3 ONLINE 0 0 0 - mirror-1 ONLINE 0 0 0 - mfisyspd2p3 ONLINE 0 0 0 - mfisyspd3p3 ONLINE 0 0 0 - mirror-2 ONLINE 0 0 0 - mfisyspd4p3 ONLINE 0 0 0 - mfisyspd5p3 ONLINE 0 0 0 - -errors: No known data errors -</code> -</pre> - - <p> - Boom. A growable, bootable zroot ZPool. Is it easier than just - configuring the partitions and root on ZFS by hand? Probably not for a - BSD veteran. But since I'm a BSD layman, this is something I can live - with pretty easily. At least until this becomes an option in - <code>bsdintall</code> maybe? At least now I can add as many more - mirrors as I can fit into my system. And it's just as easy to replace - them. This is better for me than my previous RAIDZ, where I would have - to destroy and re-create the pool in order to add more disks to the - VDEV. Now I just create another little mirror and grow the pool and all - of my filesystems just see more storage. And of course, having ZFS for - all of my data makes it super easy to create filesystems on the fly, - compress or quota them, and take snapshots (including the live ZROOT!) - and send those snapshots over the network. Pretty awesome. - </p> - - <p> - * I'm not going to explain why here, but - <a - href="http://www.openoid.net/zfs-you-should-use-mirror-vdevs-not-raidz/" - >this is a pretty well thought out article</a - > - that should give you an idea about the pros and cons of RAIDZ versus - mirror VDEVs so you can draw your own conclusions. - </p> - </article> - </body> -</html> diff --git a/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php b/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php new file mode 100644 index 0000000..d67f582 --- /dev/null +++ b/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php @@ -0,0 +1,306 @@ +<?php +$title = "Root on ZFS: A ZPool of Mirror VDEVs"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + I wanted/needed to make a root on ZFS pool out of multiple mirror VDEVs, + and since I'm not a ZFS expert, I took a little shortcut. +</p> + +<p> + I recently got a new-to-me server (yay!) and I wanted to do a + root-on-ZFS setup on it. I've really enjoyed using ZFS for my data + storage pools for a long time. I've also enjoyed the extra functionality + that comes with having a bootable system installed on ZFS on my laptop + and decided with this upgrade it's time to do the same on my server. + Historically I've used RAIDZ for my storage pools. RAIDZ functions + almost like a RAID10 but at the ZFS level. It gives you parity so that a + certain number of disks can die from your pool and you won't lose any + data. It does have a few tradeoffs however*, and for personal + preferences I've decided that for the future I would like to have a + single ZPool over top of multiple mirror VDEVs. In other words, my main + root+storage pool will be made up of two-disk mirrors and can be + expanded to include any number of new mirrors I can fit into the + machine. +</p> + +<p> + This did present some complications. First of all, + <code>bsdinstall</code> won't set this up for you automatically (and + sure enough, + <a href="https://www.freebsd.org/doc/handbook/bsdinstall-partitioning.html">in the handbook</a> + it mentions the guided root on ZFS tool will only create a single, + top-level VDEV unless it's a stripe). It will happily let you use RAIDZ + for your ZROOT but not the more custom approach I'm taking. I did + however use + <code>bsdinstall</code> as a shortcut so I wouldn't have to do all of + the partitioning and pool setup manually, and that's what I'm going to + document below. Because I'm totally going to forget how this works the + next time I have to do it. +</p> + +<p> + In my scenario I have an eight-slot, hot-swappable PERC H310 controller + that's configured for AHCI passthrough. In other words, all FreeBSD sees + is as many disks as I have plugged into the backplane. I'm going to fill + it with 6x2TB hard disks which, as I said before, I want to act as three + mirrors (two disks each) in a single, bootable, growable ZPool. For + starters, I shoved the FreeBSD installer on a flash drive and booted + from it. I followed all of the regular steps (setting hostname, getting + online, etc.) until I got to the guided root on ZFS disk partitioning + setup. +</p> + +<p> + Now here's where I'm going to take the first step on my shortcut. Since + there is no option to create the pool of arbitrary mirrors I'm just + going to create a pool from a single mirror VDEV of two disks. Later I + will expand the pool to include the other two mirrors I had intended + for. My selections were as follows: +</p> + +<ul> + <li>Pool Type/Disks: mirror mfisyspd0 mfisyspd1</li> + <li>Pool Name: zroot</li> + <li>Partition Scheme: GPT (EFI)</li> + <li>Swap Size: 4g</li> +</ul> + +<p> + Everything else was left as a default. Then I followed the installer to + completion. At the end, when it asked if I wanted to drop into a shell + to do more to the installation, I did. +</p> + +<p> + The installer created the following disk layout for the two disks that I + selected. +</p> + +<pre> +<code> +atc@macon:~ % gpart show +=> 40 3907029088 mfisyspd0 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) + +=> 40 3907029088 mfisyspd1 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) +</code> +</pre> + +<p> + The installer also created the following ZPool from my single mirror + VDEV. +</p> + +<pre> +<code> +atc@macon:~ % zpool status + pool: zroot + state: ONLINE + scan: none requested +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + mirror-0 ONLINE 0 0 0 + mfisyspd0p3 ONLINE 0 0 0 + mfisyspd1p3 ONLINE 0 0 0 + +errors: No known data errors +</code> +</pre> + +<p> + There are a couple of things to take note of here. First of all, + <em>both</em> disks in the bootable ZPool have an EFI boot partition. + That means they're both a part of (or capable of?) booting the pool. + Second, they both have some swap space. Finally, they both have a third + partition which is dedicated to ZFS data, and that partition is what got + added to my VDEV. +</p> + +<p> + So where do I go from here? I was tempted to just + <code>zpool add mirror ... ...</code> and just add my other disks to the + pool (actually, I <em>did</em> do this but it rendered the volume + unbootable for a very important reason), but then I wouldn't have those + all-important boot partitions (using whole-disk mirror VDEVS). Instead, + I need to manually go back and re-partition four disks exactly like the + first two. Or, since all I want is two more of what's already been done, + I can just clone the partitions using <code>gpart backup</code> and + <code>restore</code>! Easy! Here's what I did for all four remaining + disks: +</p> + +<pre> +<code> +root@macon:~ # gpart backup mfisyspd0 | gpart restore -F mfisyspd2` +</code> +</pre> + +<p> + Full disclosure, I didn't even think of this as a possibility + <a href="ihttps://unix.stackexchange.com/questions/472147/replacing-disk-when-using-freebsd-zfs-zroot-zfs-on-partition#472175">until I read this Stack Exchange post</a>. This gave me a disk layout like this: +</p> + +<pre> +<code> +atc@macon:~ % gpart show +=> 40 3907029088 mfisyspd0 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) + +=> 40 3907029088 mfisyspd1 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) + +=> 40 3907029088 mfisyspd2 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) + +=> 40 3907029088 mfisyspd3 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) + +=> 40 3907029088 mfisyspd4 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) + +=> 40 3907029088 mfisyspd5 GPT (1.8T) + 40 409600 1 efi (200M) + 409640 2008 - free - (1.0M) + 411648 8388608 2 freebsd-swap (4.0G) + 8800256 3898228736 3 freebsd-zfs (1.8T) + 3907028992 136 - free - (68K) +</code> +</pre> + +<p> + And to be fair, this makes a lot of logical sense. You don't want a + six-disk pool to only be bootable by two of the disks or you're + defeating some of the purposes of redundancy. So now I can extend my + ZPool to include those last four disks. +</p> + +<p> + This next step may or may not be a requirement. I wanted to overwrite + where I assumed any old ZFS/ZPool metadata might be on my four new + disks. This could just be for nothing and I admit that, but I've run + into trouble in the past where a ZPool wasn't properly + exported/destroyed before the drives were removed for another purpose + and when you use those drives in future + <code>zpool import</code>s, you can see both the new and the old, failed + pools. And, in the previous step I cloned an old ZFS partition many + times! So I did a small <code>dd</code> on the remaining disks to help + me sleep at night: +</p> + +<pre> +<code> +root@macon:~ # dd if=/dev/zero of=/dev/mfisyspd2 bs=1M count=100 +</code> +</pre> + +<p> + One final, precautionary step is to write the EFI boot loader to the new + disks. In + <a href="https://www.freebsd.org/doc/handbook/zfs-zpool.html">zpool admin handbook</a> + it mentions you should do this any time you <em>replace</em> a zroot + device, so I'll do it just for safe measure on all four additional + disks: +</p> + +<pre> +<code> +root@macon:~ # gpart bootcode -p /boot/boot1.efifat -i 1 mfisyspd2 +</code> +</pre> + +<p> + Don't forget that the command is different for UEFI and a traditional + BIOS. And finally, I can add my new VDEVs: +</p> + +<pre> +<code> +root@macon:~ # zpool zroot add mirror mfisyspd2p3 mfisyspd3p3 +root@macon:~ # zpool zroot add mirror mfisyspd4p3 mfisyspd5p3 +</code> +</pre> + +<p>And now my pool looks like this:</p> + +<pre> +<code> +atc@macon:~ % zpool status + pool: zroot + state: ONLINE + scan: none requested +config: + + NAME STATE READ WRITE CKSUM + zroot ONLINE 0 0 0 + mirror-0 ONLINE 0 0 0 + mfisyspd0p3 ONLINE 0 0 0 + mfisyspd1p3 ONLINE 0 0 0 + mirror-1 ONLINE 0 0 0 + mfisyspd2p3 ONLINE 0 0 0 + mfisyspd3p3 ONLINE 0 0 0 + mirror-2 ONLINE 0 0 0 + mfisyspd4p3 ONLINE 0 0 0 + mfisyspd5p3 ONLINE 0 0 0 + +errors: No known data errors +</code> +</pre> + +<p> + Boom. A growable, bootable zroot ZPool. Is it easier than just + configuring the partitions and root on ZFS by hand? Probably not for a + BSD veteran. But since I'm a BSD layman, this is something I can live + with pretty easily. At least until this becomes an option in + <code>bsdintall</code> maybe? At least now I can add as many more + mirrors as I can fit into my system. And it's just as easy to replace + them. This is better for me than my previous RAIDZ, where I would have + to destroy and re-create the pool in order to add more disks to the + VDEV. Now I just create another little mirror and grow the pool and all + of my filesystems just see more storage. And of course, having ZFS for + all of my data makes it super easy to create filesystems on the fly, + compress or quota them, and take snapshots (including the live ZROOT!) + and send those snapshots over the network. Pretty awesome. +</p> + +<p> + * I'm not going to explain why here, but + <a href="http://www.openoid.net/zfs-you-should-use-mirror-vdevs-not-raidz/">this is a pretty well thought out article</a> + that should give you an idea about the pros and cons of RAIDZ versus + mirror VDEVs so you can draw your own conclusions. +</p> diff --git a/posts/2021-01-28-undefined-javasript-is-undefined.html b/posts/2021-01-28-undefined-javasript-is-undefined.html deleted file mode 100644 index 219b379..0000000 --- a/posts/2021-01-28-undefined-javasript-is-undefined.html +++ /dev/null @@ -1,163 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Undefined? JavaSript Is Undefined." /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Undefined? JavaSript Is Undefined.</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Undefined? JavaSript Is Undefined.</h1> - - <p class="description"> - So I've been working on a web app for my mom. Nothing too fancy, but - it's a store front for her glass art. It's an easy way for her to keep - track of inventory, update photos of her products, and for people to - shop and search and sort and browse through it. This backend is an HTTP - service written in Rust. The frontend is a Vue.js app. I've used Vue and - JavaScript many times before but I recently ran into an incredibly - strange bug. One that I would have hoped JavaScript would have some - guard against. But JavaScript is an undefined language. - </p> - - <p> - I have a small component that uses a file input to collect an image from - the user. Then I append that file to a FormData and set that FormData as - a Fetch API request body. So I've got fetch API sending - multipart/form-data across the network to my backend. Awesome! The - backend is supposed to take each field of the request, turn the chunks - into a single stream of binary data, and write them out to an image. - Everything on the front seems like it's working great, it fires off the - request and throws no errors. But then the backend only sees a few bytes - of this multi-megabyte image. Not awesome! short chunks on the back-end. - The array of data in the API is less than ten bytes long, when this is a - many-kilobyte file I'm trying to upload. - </p> - - <p> - At this point I'm relentlessly debugging, trying to find out what's - wrong with the API. Why is it truncating the request down to a few - bytes, where's the rest of the data? It took me forever to actually - inspect what those few bytes are and, lo and behold they're ASCII for - <code>undefined</code> The request happily stringified an - <code>undefined</code> object, instead of maybe throwing a null - reference or undefined error during request creation because that's just - what JavaScript does. <em>The linter didn't even catch it.</em> - </p> - - <p> - You can see what the debugging logs looked like on the backend below. - Note that the <code>&data</code> is the field that spells out - "undefined". Also note that the file picker/FormData was constructed - alright because the key for the image name is correct. - </p> - - <pre> - <code> -[src/handlers.rs:114] &field = -Field: application/octet-stream - boundary: ---------------------------175314640631070190963311652907 - headers: - "content-disposition": "form-data; name=\"clu.jpg\"" - -[src/handlers.rs:119] &chunk = Ok( - b"undefined", -) -[src/handlers.rs:123] &data = [ - 117, - 110, - 100, - 101, - 102, - 105, - 110, - 101, - 100, -] -ImageWrite("The image format could not be determined") - </code> - </pre> - - <p> - The <em>working</em> JS is here (it was late at night and I was so - donion rings I just fixed it and pushed it without saving the errors for - posterity): - </p> - - <pre> - <code> -let file = event.target.files[0]; -if (!file) { - return; -} - -const fd = new FormData(); -fd.append(file.name, file); - -const response = await fetch("http://localhost:8000/photos", { - method: "POST", - body: fd -}); - -console.log(response); - </code> - </pre> - <p> - I've gotten frustrated by JS before but not like this. I don't know if - TypeScript would have solved this issue but writing in a language that - gets transpiled back into the language I'm trying to avoid doesn't seem - like the way forward. I'm looking forward to Web Assembly as a way of - using more type-safe languages in the browser. - </p> - </article> - </body> -</html> diff --git a/posts/2021-01-28-undefined-javasript-is-undefined.php b/posts/2021-01-28-undefined-javasript-is-undefined.php new file mode 100644 index 0000000..b70141c --- /dev/null +++ b/posts/2021-01-28-undefined-javasript-is-undefined.php @@ -0,0 +1,108 @@ +<?php +$title = "Undefined? JavaScript Is Undefined."; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + So I've been working on a web app for my mom. Nothing too fancy, but + it's a store front for her glass art. It's an easy way for her to keep + track of inventory, update photos of her products, and for people to + shop and search and sort and browse through it. This backend is an HTTP + service written in Rust. The frontend is a Vue.js app. I've used Vue and + JavaScript many times before but I recently ran into an incredibly + strange bug. One that I would have hoped JavaScript would have some + guard against. But JavaScript is an undefined language. +</p> + +<p> + I have a small component that uses a file input to collect an image from + the user. Then I append that file to a FormData and set that FormData as + a Fetch API request body. So I've got fetch API sending + multipart/form-data across the network to my backend. Awesome! The + backend is supposed to take each field of the request, turn the chunks + into a single stream of binary data, and write them out to an image. + Everything on the front seems like it's working great, it fires off the + request and throws no errors. But then the backend only sees a few bytes + of this multi-megabyte image. Not awesome! short chunks on the back-end. + The array of data in the API is less than ten bytes long, when this is a + many-kilobyte file I'm trying to upload. +</p> + +<p> + At this point I'm relentlessly debugging, trying to find out what's + wrong with the API. Why is it truncating the request down to a few + bytes, where's the rest of the data? It took me forever to actually + inspect what those few bytes are and, lo and behold they're ASCII for + <code>undefined</code> The request happily stringified an + <code>undefined</code> object, instead of maybe throwing a null + reference or undefined error during request creation because that's just + what JavaScript does. <em>The linter didn't even catch it.</em> +</p> + +<p> + You can see what the debugging logs looked like on the backend below. + Note that the <code>&data</code> is the field that spells out + "undefined". Also note that the file picker/FormData was constructed + alright because the key for the image name is correct. +</p> + +<pre> + <code> +[src/handlers.rs:114] &field = +Field: application/octet-stream + boundary: ---------------------------175314640631070190963311652907 + headers: + "content-disposition": "form-data; name=\"clu.jpg\"" + +[src/handlers.rs:119] &chunk = Ok( + b"undefined", +) +[src/handlers.rs:123] &data = [ + 117, + 110, + 100, + 101, + 102, + 105, + 110, + 101, + 100, +] +ImageWrite("The image format could not be determined") + </code> + </pre> + +<p> + The <em>working</em> JS is here (it was late at night and I was so + donion rings I just fixed it and pushed it without saving the errors for + posterity): +</p> + +<pre> + <code> +let file = event.target.files[0]; +if (!file) { + return; +} + +const fd = new FormData(); +fd.append(file.name, file); + +const response = await fetch("http://localhost:8000/photos", { + method: "POST", + body: fd +}); + +console.log(response); + </code> + </pre> +<p> + I've gotten frustrated by JS before but not like this. I don't know if + TypeScript would have solved this issue but writing in a language that + gets transpiled back into the language I'm trying to avoid doesn't seem + like the way forward. I'm looking forward to Web Assembly as a way of + using more type-safe languages in the browser. +</p> diff --git a/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html b/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html deleted file mode 100644 index d0f2938..0000000 --- a/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html +++ /dev/null @@ -1,132 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="Louis Vierne Is a BAMF (and Proof That Organists Are Metal)" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title> - 53hornet ➙ Louis Vierne Is a BAMF (and Proof That Organists Are Metal) - </title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img - alt="information" - src="/includes/icons/information-variant.svg" - /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Louis Vierne Is a BAMF (and Proof That Organists Are Metal)</h1> - - <p> - Louis Vierne is a certifiable badass organist from the end of the 19th - and early 20th centuries. He was born blind and had to have surgery to - be able to distinguish shapes and objects. Did that stop him from - playing the one instrument that literally requires you to distinguish - hundreds and hundreds of small objects from each other? Nope, he just - did it (and he learned from Cesar Franck, another great organist). - </p> - - <p> - In 1906 he got hit by a car and the doctors said they might have to - amputate his leg. Did you know you play an organ with both your hands - <em>and</em> both your feet? Well you do, and Vierne just re-learned how - to play with his feet after the accident. Because nobody tells Louis - Vierne no. - </p> - - <p> - And because he's a badass, Vierne went on to become the official - organist at the Notre Dame in Paris, a position he won by competitively - dunking on numerous other musicians. He considered this his greatest - achievement, and what Louis Vierne says goes. - </p> - - <p> - In one final act of badassery, he carried out his lifelong dream: to die - while playing at Notre Dame. In 1937, to a full recital hall in Notre - Dame, he was giving his 1,750th performance and actually - <em - >had a heart-attack while playing and died at the console, and keeled - over so that the low "E" played until they removed his body</em - >. To this day, no rock band has ever been so metal. - </p> - - <hr /> - - <p> - Alright, so without the decoration, Louis Vierne is my favorite Organist - and composer from the period. The organ is, in my opinion, the coolest - instrument on the planet. It's the biggest, the loudest, and the most - impressive. It's also got the most wide and interesting array of sounds, - like having an orchestra at your fingertips. Vierne made some of my - favorite music for the organ (music that my lowly organ skills will - never let me play). He's also, obviously, pretty badass. - </p> - - <p> - In truth, I think all organists are pretty cool. They play a cool, - complicated instrument that really sounds like no other. They also play - with their hands and their feet. Someone once said when a musician mates - with an octopus, an organist is born. Come to think of it, Davy Jones - plays the Organ and he's pretty cool. Coincidence? I think not. - </p> - - <p> - If you get the chance, give Vierne a listen, you can look up his work on - YouTube or a Pandora Radio station in his name. Look especially for - Symphony No. 1 for Organ in D Minor, Op. 14. That's the first song I - heard of his live (and in my understanding is the one he was playing - when he died). - </p> - </article> - </body> -</html> diff --git a/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php b/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php new file mode 100644 index 0000000..864265a --- /dev/null +++ b/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php @@ -0,0 +1,67 @@ +<?php +$title = "Louis Vierne Is a BAMF (and Proof That Organists Are Metal)"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + Louis Vierne is a certifiable badass organist from the end of the 19th + and early 20th centuries. He was born blind and had to have surgery to + be able to distinguish shapes and objects. Did that stop him from + playing the one instrument that literally requires you to distinguish + hundreds and hundreds of small objects from each other? Nope, he just + did it (and he learned from Cesar Franck, another great organist). +</p> + +<p> + In 1906 he got hit by a car and the doctors said they might have to + amputate his leg. Did you know you play an organ with both your hands + <em>and</em> both your feet? Well you do, and Vierne just re-learned how + to play with his feet after the accident. Because nobody tells Louis + Vierne no. +</p> + +<p> + And because he's a badass, Vierne went on to become the official + organist at the Notre Dame in Paris, a position he won by competitively + dunking on numerous other musicians. He considered this his greatest + achievement, and what Louis Vierne says goes. +</p> + +<p> + In one final act of badassery, he carried out his lifelong dream: to die + while playing at Notre Dame. In 1937, to a full recital hall in Notre + Dame, he was giving his 1,750th performance and actually + <em>had a heart-attack while playing and died at the console, and keeled + over so that the low "E" played until they removed his body</em>. To this day, no rock band has ever been so metal. +</p> + +<hr /> + +<p> + Alright, so without the decoration, Louis Vierne is my favorite Organist + and composer from the period. The organ is, in my opinion, the coolest + instrument on the planet. It's the biggest, the loudest, and the most + impressive. It's also got the most wide and interesting array of sounds, + like having an orchestra at your fingertips. Vierne made some of my + favorite music for the organ (music that my lowly organ skills will + never let me play). He's also, obviously, pretty badass. +</p> + +<p> + In truth, I think all organists are pretty cool. They play a cool, + complicated instrument that really sounds like no other. They also play + with their hands and their feet. Someone once said when a musician mates + with an octopus, an organist is born. Come to think of it, Davy Jones + plays the Organ and he's pretty cool. Coincidence? I think not. +</p> + +<p> + If you get the chance, give Vierne a listen, you can look up his work on + YouTube or a Pandora Radio station in his name. Look especially for + Symphony No. 1 for Organ in D Minor, Op. 14. That's the first song I + heard of his live (and in my understanding is the one he was playing + when he died). +</p> diff --git a/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html b/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html deleted file mode 100644 index 34fbcf0..0000000 --- a/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html +++ /dev/null @@ -1,256 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="How to Automate Certbot Renewal with HAProxy" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ How to Automate Certbot Renewal with HAProxy</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>How to Automate Certbot Renewal with HAProxy</h1> - - <p> - So this is specifically for HAProxy on FreeBSD, but it should apply to - other *nix systems as well. Basically, I use HAProxy as a reverse proxy - to a bunch of servers I administer. I use Let's Encrypt for a - certificate and I used <code>certbot</code> to generate that - certificate. Generating the certificate for the first time is easy and - has lots of documentation, but it wasn't initially clear on how I could - easily set up auto-renewal. Here's how I did it. - </p> - - <p> - If you've already set up TLS termination with HAProxy and - <code>certbot</code>, you know you need to combine your Let's Encrypt - fullchain and private key to get a combined certificate that HAProxy can - use. You can do this by <code>cat</code>-ing the chain and key together - like so: - </p> - - <pre> -<code> -cat /usr/local/etc/letsencrypt/live/$SITE/fullchain.pem /usr/local/etc/letsencrypt/live/$SITE/privkey.pem > /usr/local/etc/ssl/haproxy.pem -</code> - </pre> - - <p> - In this example, <code>$SITE</code> is your domain name that you fed - HAProxy when you created the certificate and <code>haproxy.pem</code> is - wherever you're storing HAProxy's combined certificate. Your HAProxy - config then points to that certificate like this: - </p> - - <pre> -<code> -macon% grep crt /usr/local/etc/haproxy.conf - bind *:443 ssl crt /usr/local/etc/ssl/haproxy.pem -</code> - </pre> - - <p> - And that was the end of the first-time setup. Then a few months later - you probably had to do it again because Let's Encrypt certs are only - good for 90 days in between renewals. To renew the certificate, you - usually run <code>certbot renew</code>, it detects which certificates - are present, and uses either the webroot or standlone server renewal - process. Then you have to <code>cat</code> the fullchain and privkey - together and restart HAProxy so it starts using the new certificate. - </p> - - <p> - To automate those steps, newer versions of - <code>certbot</code> will run any post renewal hooks (read: scripts) - that you want. You can also configure HAProxy and - <code>certbot</code> to perform the ACME challenge dance for renewal so - that you don't have to use it interactively. - </p> - - <p> - First, if you haven't already done it, change your HAProxy config so - there's a frontend+backend for responding to ACME challenges. In a - frontend listening for requests, create an access control list for any - request looking for <code>/.well-known/acme-challenge/</code>. Send - those requests to a backend server with an unused local port. - </p> - - <pre> -<code> -frontend http-in - acl letsencrypt-acl path_beg /.well-known/acme-challenge/ - use_backend letsencrypt-backend if letsencrypt-acl - ... -backend letsencrypt-backend - server letsencrypt 127.0.0.1:54321 -</code> - </pre> - - <p> - What this will do is allow <code>certbot</code> and Let's Encrypt to - renew your server in standalone mode via your reverse proxy. As an added - bonus it prevents you from having to open up an additional port on your - firewall. - </p> - - <p> - Now you've gotta configure <code>certbot</code> to do just that. A - config file was created in <code>certbot</code>'s - <code>renew</code> directory for your site. All you need to do in that - file is add a line to the <code>[renewalparams]</code> section - specifying the port you're using in your HAProxy config. - </p> - - <pre> -<code> -macon% echo "http01_port = 54321" >> /usr/local/etc/letsencrypt/renewal/$SITE.conf -</code> - </pre> - - <p> - Now you need the post-renewal hooks. I dropped two separate scripts into - the <code>renewal-hooks</code> directory: one does the job of combining - the certificate chain and private key and the other just restarts - HAProxy. - </p> - - <pre> -<code> -macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh -#!/bin/sh - -SITE=(your site of course) - -cd /usr/local/etc/letsencrypt/live/$SITE -cat fullchain.pem privkey.pem > /usr/local/etc/ssl/haproxy.pem -macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh -#!/bin/sh -service haproxy restart -</code> - </pre> - - <p> - When <code>certbot renew</code> is run, <code>certbot</code> checks the - <code>renewal-hooks/post</code> directory and runs any executable things - in it after it's renewed the certificate(s). As a side note, - <em>make sure you hit those scripts with <code>chmod +x</code></em> or - they probably won't run. - </p> - - <p> - Now all that's left is dropping a job into <code>cron</code> or - <code>periodic</code> to run <code>certbot renew</code> at least once or - twice within the renewal period. - </p> - - <pre> -<code> -macon% doas crontab -l|grep certbot -# certbot renewal -@monthly certbot renew -</code> - </pre> - - <p> - You can always test that your scripts are working with - <code>certbot renew --dry-run</code> just to be safe. - </p> - - <pre> -<code> -macon% doas certbot renew --dry-run -Saving debug log to /var/log/letsencrypt/letsencrypt.log - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Processing /usr/local/etc/letsencrypt/renewal/53hor.net.conf -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Cert not due for renewal, but simulating renewal for dry run -Plugins selected: Authenticator standalone, Installer None -Simulating renewal of an existing certificate for 53hor.net and 7 more domains -Performing the following challenges: -http-01 challenge for 53hor.net -http-01 challenge for carpentertutoring.com -http-01 challenge for git.53hor.net -http-01 challenge for nextcloud.53hor.net -http-01 challenge for pkg.53hor.net -http-01 challenge for plex.53hor.net -http-01 challenge for theglassyladies.com -http-01 challenge for www.53hor.net -Waiting for verification... -Cleaning up challenges - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -new certificate deployed without reload, fullchain is -/usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Congratulations, all simulated renewals succeeded: - /usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem (success) -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh -Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh -Output from post-hook command 002-haproxy.sh: -Waiting for PIDS: 15191. -Starting haproxy. - -</code> - </pre> - - <p> - And there it is. Automated Let's Encrypt certificate renewal on FreeBSD - with HAProxy. - </p> - </article> - </body> -</html> diff --git a/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php b/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php new file mode 100644 index 0000000..634a57d --- /dev/null +++ b/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php @@ -0,0 +1,198 @@ +<?php +$title = "How to Automate Certbot Renewal with HAPRoxy (on FreeBSD)"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + So this is specifically for HAProxy on FreeBSD, but it should apply to + other *nix systems as well. Basically, I use HAProxy as a reverse proxy + to a bunch of servers I administer. I use Let's Encrypt for a + certificate and I used <code>certbot</code> to generate that + certificate. Generating the certificate for the first time is easy and + has lots of documentation, but it wasn't initially clear on how I could + easily set up auto-renewal. Here's how I did it. +</p> + +<p> + If you've already set up TLS termination with HAProxy and + <code>certbot</code>, you know you need to combine your Let's Encrypt + fullchain and private key to get a combined certificate that HAProxy can + use. You can do this by <code>cat</code>-ing the chain and key together + like so: +</p> + +<pre> +<code> +cat /usr/local/etc/letsencrypt/live/$SITE/fullchain.pem /usr/local/etc/letsencrypt/live/$SITE/privkey.pem > /usr/local/etc/ssl/haproxy.pem +</code> + </pre> + +<p> + In this example, <code>$SITE</code> is your domain name that you fed + HAProxy when you created the certificate and <code>haproxy.pem</code> is + wherever you're storing HAProxy's combined certificate. Your HAProxy + config then points to that certificate like this: +</p> + +<pre> +<code> +macon% grep crt /usr/local/etc/haproxy.conf + bind *:443 ssl crt /usr/local/etc/ssl/haproxy.pem +</code> + </pre> + +<p> + And that was the end of the first-time setup. Then a few months later + you probably had to do it again because Let's Encrypt certs are only + good for 90 days in between renewals. To renew the certificate, you + usually run <code>certbot renew</code>, it detects which certificates + are present, and uses either the webroot or standlone server renewal + process. Then you have to <code>cat</code> the fullchain and privkey + together and restart HAProxy so it starts using the new certificate. +</p> + +<p> + To automate those steps, newer versions of + <code>certbot</code> will run any post renewal hooks (read: scripts) + that you want. You can also configure HAProxy and + <code>certbot</code> to perform the ACME challenge dance for renewal so + that you don't have to use it interactively. +</p> + +<p> + First, if you haven't already done it, change your HAProxy config so + there's a frontend+backend for responding to ACME challenges. In a + frontend listening for requests, create an access control list for any + request looking for <code>/.well-known/acme-challenge/</code>. Send + those requests to a backend server with an unused local port. +</p> + +<pre> +<code> +frontend http-in + acl letsencrypt-acl path_beg /.well-known/acme-challenge/ + use_backend letsencrypt-backend if letsencrypt-acl + ... +backend letsencrypt-backend + server letsencrypt 127.0.0.1:54321 +</code> + </pre> + +<p> + What this will do is allow <code>certbot</code> and Let's Encrypt to + renew your server in standalone mode via your reverse proxy. As an added + bonus it prevents you from having to open up an additional port on your + firewall. +</p> + +<p> + Now you've gotta configure <code>certbot</code> to do just that. A + config file was created in <code>certbot</code>'s + <code>renew</code> directory for your site. All you need to do in that + file is add a line to the <code>[renewalparams]</code> section + specifying the port you're using in your HAProxy config. +</p> + +<pre> +<code> +macon% echo "http01_port = 54321" >> /usr/local/etc/letsencrypt/renewal/$SITE.conf +</code> + </pre> + +<p> + Now you need the post-renewal hooks. I dropped two separate scripts into + the <code>renewal-hooks</code> directory: one does the job of combining + the certificate chain and private key and the other just restarts + HAProxy. +</p> + +<pre> +<code> +macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh +#!/bin/sh + +SITE=(your site of course) + +cd /usr/local/etc/letsencrypt/live/$SITE +cat fullchain.pem privkey.pem > /usr/local/etc/ssl/haproxy.pem +macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh +#!/bin/sh +service haproxy restart +</code> + </pre> + +<p> + When <code>certbot renew</code> is run, <code>certbot</code> checks the + <code>renewal-hooks/post</code> directory and runs any executable things + in it after it's renewed the certificate(s). As a side note, + <em>make sure you hit those scripts with <code>chmod +x</code></em> or + they probably won't run. +</p> + +<p> + Now all that's left is dropping a job into <code>cron</code> or + <code>periodic</code> to run <code>certbot renew</code> at least once or + twice within the renewal period. +</p> + +<pre> +<code> +macon% doas crontab -l|grep certbot +# certbot renewal +@monthly certbot renew +</code> + </pre> + +<p> + You can always test that your scripts are working with + <code>certbot renew --dry-run</code> just to be safe. +</p> + +<pre> +<code> +macon% doas certbot renew --dry-run +Saving debug log to /var/log/letsencrypt/letsencrypt.log + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Processing /usr/local/etc/letsencrypt/renewal/53hor.net.conf +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Cert not due for renewal, but simulating renewal for dry run +Plugins selected: Authenticator standalone, Installer None +Simulating renewal of an existing certificate for 53hor.net and 7 more domains +Performing the following challenges: +http-01 challenge for 53hor.net +http-01 challenge for carpentertutoring.com +http-01 challenge for git.53hor.net +http-01 challenge for nextcloud.53hor.net +http-01 challenge for pkg.53hor.net +http-01 challenge for plex.53hor.net +http-01 challenge for theglassyladies.com +http-01 challenge for www.53hor.net +Waiting for verification... +Cleaning up challenges + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +new certificate deployed without reload, fullchain is +/usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Congratulations, all simulated renewals succeeded: + /usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem (success) +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh +Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh +Output from post-hook command 002-haproxy.sh: +Waiting for PIDS: 15191. +Starting haproxy. + +</code> + </pre> + +<p> + And there it is. Automated Let's Encrypt certificate renewal on FreeBSD + with HAProxy. +</p> diff --git a/posts/2021-04-20-how-to-make-your-website-boring-and-why.html b/posts/2021-04-20-how-to-make-your-website-boring-and-why.html deleted file mode 100644 index 8bbcfb6..0000000 --- a/posts/2021-04-20-how-to-make-your-website-boring-and-why.html +++ /dev/null @@ -1,214 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta - property="og:title" - content="How to Make Your Website Boring and Why!" - /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ How to Make Your Website Boring and Why!</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>How to Make Your Website Boring and Why!</h1> - - <p class="description"> - I took the time last year to make my website more boring. Here's how you - can do the same and why you'd want to. - </p> - - <p> - Up until recently I was using a static site generator - <a>(cobalt-rs)</a> and a fancy CSS framework/library <a>(Bulma)</a> to - build my website. I also had one or two scripts to do various fiddly - things in the browser. I took the time to gut it and now I have a much - more boring website. I don't use anything but HTML to write all of the - posts and pages. This eliminated the need for a static generator or - script to turn something like Markdown into HTML for me. I also scrapped - all of the customized CSS framework style sheets that I had been using - for a very small (145 lines including whitespace and braces) single-file - stylesheet. I also dropped all of the fancy links, banners, most of the - icons, and any JavaScript that I had originally. Now, my site is much - more boring. And it's so much better. - </p> - - <h2>How does one make their website boring?</h2> - - <p> - Typically, ask yourself whether you need something. If the answer is - "no", you can safely remove it and you won't need it again. Your website - will become more boring (read: simpler). Here are some of the things I - evaluated: - </p> - - <ul> - <li> - How many 3rd-party assets, templates, CSS libraries am I using? How - big are they? Are they slowing down rendering or annoying to - maintain/upgrade? - </li> - <li>Do I need a Sass interpreter to "build" my styles?</li> - <li> - Am I using a static site generator? Does it make my life easier or - more difficult? - </li> - <li> - Am I using a bunch of JavaScript? What does it do and does it really - need to do it to make my site work better? - </li> - </ul> - - <p> - Do you use a lot of third-party assets, templates, or CSS for your site? - Do you have to run a SASS tool to generate your stylesheets? Are your - stylesheets really big (> 1000 lines I think anyone would consider on - the bigger side)? Consider whether or not you really need them. - Oftentimes, with CSS, less is more. Especially if your site is just a - collection of pages of text with links to other pages of text. You can - make your site attractive and compatible with 100% of browsers by - keeping things simple. And then you don't have to worry about rebuilding - your output stylesheets or keeping up with libraries and frameworks. - </p> - - <p> - Do you have a lot of dynamically-generated content on your site? Does - the document need to change based on user input? Do you have a large - number of script tags importing minified files from third-party CDNs? - Odds are you don't need those either and you can completely get rid of - them. Now you don't have to worry about making sure all browsers can run - those scripts, or whether or not the CDNs are online, or you're - requesting the latest version. - </p> - - <p> - Do you use a static site generator to build your site? Is your content - complicated enough to write that you can't write it in plain HTML? Is - Markdown really easier or more powerful? Odds are, it's easier to write - directly in HTML without having to tell your generator what to do with - your tags. And for the oddball tag that Markdown doesn't directly - support, you might often end up writing HTML into your Markdown files - anyways. And, you can better control what the output formatting looks - like, making your site's code more readable. Furthermore, you won't have - two acting copies of your site, a pre- and post-generator one. For me, - it was annoying having "source code" for my web site that was different - from what I was actually hosting. It's so much nicer to have a 1:1 - mapping between what I write, test, and deploy. - </p> - - <p> - Still not convinced? Still need to automate some part of building your - site, like generating an RSS feed? Is there any chance you can write a - quick Makefile to do that for you? I was able to do just that, and it - was way nicer not having to install and learn how a generator worked to - automate assembling my site. - </p> - - <p> - If you answered "no" to any of the above "do you need"-s, you just found - a way to make your site more boring. Boring equates with simplicity. - Simplicity is a good thing. - </p> - - <h2>Why should you make your website <s>boring</s> simple?</h2> - - <p> - Not relying on a bunch of libraries and assets is a good thing. It - seemed like every time I wanted to add a quick post, I would notice - there was an update for some library I was using and I was spending time - upgrading and learning about it. You know, that thing that computer - programmers enjoy doing and are good at but often doesn't actually help - them accomplish anything: fiddling with shiny new stuff that doesn't - solve a problem. Now I get to just focus on adding things to my site and - I'm never worried about whether it looks broken. - </p> - - <p> - I also didn't like having a pre- and post-build site. If I wanted to fix - one typo I couldn't remote into my live site, fix it, and then leave it - there. I had to do something like fix the typo in my Markdown, commit - and push it, and then re-run the generator and upload the new "live" - files. The generator step wasn't making things easier, it was making - them more annoying. - </p> - - <p> - You'd also be surprised at how easy it is to make your site fast and - reliable on all modern and old browsers when it's boring (read: simple, - again). Internet Explorer doesn't care about my site, it's a breeze to - render and there's nothing in it that hasn't been in existence for at - least a decade. (Alright, I do have a few SVG icons which it probably - wouldn't know what to do with. You can't tell the difference between - Firefox's and Chrome's renders of my site. And Google's PageSpeed - Insights score is a hilarious 99. - </p> - - <p> - My site is also more functional now. It's less distracting. It's really - easy to navigate and read. There's no runtime, no JavaScript that has to - execute before the reader sees the page they're looking for. And there's - practically nothing to maintain except my posts. It's also really easy - for crawlers to quickly ingest all of my posts and turn them into search - results. Hopefully, it's also easier for the visually impaired to zoom - in and not mess up the document, or use a screen reader that extracts - the article tags. - </p> - - <p> - The benefits are through the roof. My site used to be about tinkering - with tools and libraries and frameworks. Now it's just a boring website. - That leaves me with time to focus on tinkering with other stuff that's - more interesting, and only focus on writing when I'm working on this - site. So make your life easier and go make your website boring today. - </p> - </article> - </body> -</html> diff --git a/posts/2021-04-20-how-to-make-your-website-boring-and-why.php b/posts/2021-04-20-how-to-make-your-website-boring-and-why.php new file mode 100644 index 0000000..6f8136d --- /dev/null +++ b/posts/2021-04-20-how-to-make-your-website-boring-and-why.php @@ -0,0 +1,156 @@ +<?php +$title = "How to Make Your Website Boring and Why!"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p class="description"> + I took the time last year to make my website more boring. Here's how you + can do the same and why you'd want to. +</p> + +<p> + Up until recently I was using a static site generator + <a>(cobalt-rs)</a> and a fancy CSS framework/library <a>(Bulma)</a> to + build my website. I also had one or two scripts to do various fiddly + things in the browser. I took the time to gut it and now I have a much + more boring website. I don't use anything but HTML to write all of the + posts and pages. This eliminated the need for a static generator or + script to turn something like Markdown into HTML for me. I also scrapped + all of the customized CSS framework style sheets that I had been using + for a very small (145 lines including whitespace and braces) single-file + stylesheet. I also dropped all of the fancy links, banners, most of the + icons, and any JavaScript that I had originally. Now, my site is much + more boring. And it's so much better. +</p> + +<h2>How does one make their website boring?</h2> + +<p> + Typically, ask yourself whether you need something. If the answer is + "no", you can safely remove it and you won't need it again. Your website + will become more boring (read: simpler). Here are some of the things I + evaluated: +</p> + +<ul> + <li> + How many 3rd-party assets, templates, CSS libraries am I using? How + big are they? Are they slowing down rendering or annoying to + maintain/upgrade? + </li> + <li>Do I need a Sass interpreter to "build" my styles?</li> + <li> + Am I using a static site generator? Does it make my life easier or + more difficult? + </li> + <li> + Am I using a bunch of JavaScript? What does it do and does it really + need to do it to make my site work better? + </li> +</ul> + +<p> + Do you use a lot of third-party assets, templates, or CSS for your site? + Do you have to run a SASS tool to generate your stylesheets? Are your + stylesheets really big (> 1000 lines I think anyone would consider on + the bigger side)? Consider whether or not you really need them. + Oftentimes, with CSS, less is more. Especially if your site is just a + collection of pages of text with links to other pages of text. You can + make your site attractive and compatible with 100% of browsers by + keeping things simple. And then you don't have to worry about rebuilding + your output stylesheets or keeping up with libraries and frameworks. +</p> + +<p> + Do you have a lot of dynamically-generated content on your site? Does + the document need to change based on user input? Do you have a large + number of script tags importing minified files from third-party CDNs? + Odds are you don't need those either and you can completely get rid of + them. Now you don't have to worry about making sure all browsers can run + those scripts, or whether or not the CDNs are online, or you're + requesting the latest version. +</p> + +<p> + Do you use a static site generator to build your site? Is your content + complicated enough to write that you can't write it in plain HTML? Is + Markdown really easier or more powerful? Odds are, it's easier to write + directly in HTML without having to tell your generator what to do with + your tags. And for the oddball tag that Markdown doesn't directly + support, you might often end up writing HTML into your Markdown files + anyways. And, you can better control what the output formatting looks + like, making your site's code more readable. Furthermore, you won't have + two acting copies of your site, a pre- and post-generator one. For me, + it was annoying having "source code" for my web site that was different + from what I was actually hosting. It's so much nicer to have a 1:1 + mapping between what I write, test, and deploy. +</p> + +<p> + Still not convinced? Still need to automate some part of building your + site, like generating an RSS feed? Is there any chance you can write a + quick Makefile to do that for you? I was able to do just that, and it + was way nicer not having to install and learn how a generator worked to + automate assembling my site. +</p> + +<p> + If you answered "no" to any of the above "do you need"-s, you just found + a way to make your site more boring. Boring equates with simplicity. + Simplicity is a good thing. +</p> + +<h2>Why should you make your website <s>boring</s> simple?</h2> + +<p> + Not relying on a bunch of libraries and assets is a good thing. It + seemed like every time I wanted to add a quick post, I would notice + there was an update for some library I was using and I was spending time + upgrading and learning about it. You know, that thing that computer + programmers enjoy doing and are good at but often doesn't actually help + them accomplish anything: fiddling with shiny new stuff that doesn't + solve a problem. Now I get to just focus on adding things to my site and + I'm never worried about whether it looks broken. +</p> + +<p> + I also didn't like having a pre- and post-build site. If I wanted to fix + one typo I couldn't remote into my live site, fix it, and then leave it + there. I had to do something like fix the typo in my Markdown, commit + and push it, and then re-run the generator and upload the new "live" + files. The generator step wasn't making things easier, it was making + them more annoying. +</p> + +<p> + You'd also be surprised at how easy it is to make your site fast and + reliable on all modern and old browsers when it's boring (read: simple, + again). Internet Explorer doesn't care about my site, it's a breeze to + render and there's nothing in it that hasn't been in existence for at + least a decade. (Alright, I do have a few SVG icons which it probably + wouldn't know what to do with. You can't tell the difference between + Firefox's and Chrome's renders of my site. And Google's PageSpeed + Insights score is a hilarious 99. +</p> + +<p> + My site is also more functional now. It's less distracting. It's really + easy to navigate and read. There's no runtime, no JavaScript that has to + execute before the reader sees the page they're looking for. And there's + practically nothing to maintain except my posts. It's also really easy + for crawlers to quickly ingest all of my posts and turn them into search + results. Hopefully, it's also easier for the visually impaired to zoom + in and not mess up the document, or use a screen reader that extracts + the article tags. +</p> + +<p> + The benefits are through the roof. My site used to be about tinkering + with tools and libraries and frameworks. Now it's just a boring website. + That leaves me with time to focus on tinkering with other stuff that's + more interesting, and only focus on writing when I'm working on this + site. So make your life easier and go make your website boring today. +</p> diff --git a/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html b/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html deleted file mode 100644 index 65eea7a..0000000 --- a/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html +++ /dev/null @@ -1,133 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Web Designers, Please Don't "Animate" - Page Titles" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Web Designers, Please Don't "Animate" Page Titles</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Web Designers, Please Don't "Animate" Page Titles</h1> - - <p> - If you visit - <a href="https://www.expressoil.com">Express Oil Change's web site</a>, - everything seems completely ordinary until you leave the tab. That's - when the most distracting, broken, annoying example of over-the-top web - "design" rears its ugly head. - </p> - - <p> - I'm talking about this scrolling page title. In my tab. Constantly - moving from right to left to show me all of the text. It's the only tab - that's "moving" or "animated" and it doesn't stop until you return to - the tab. It's cheesy and gaudy. - </p> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/TWDbzjiSwzHbMcz/preview" - /> - </p> - - <p> - And it's also broken because there are emojis in the page title and the - title is obviously being "scrolled" by some script that's moving - byte-by-byte, so it scrolls halfway through a multi-byte UTF-8 emoji and - for a brief moment there's a glyph error character where a little red - car should have been. Bad judgment and bad programming. Worse than that, - even if it worked perfectly, it's incredibly annoying. - </p> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/TbbDnnL3jnZMT3g/preview" - /> - </p> - - <p> - If you bookmark the tab when it's in the middle of scrolling, you'll - bookmark this weird slice of the text that starts or ends in the middle - of a word or with a random emoji. - </p> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/ocQofL2Goxd3AsQ/preview" - /> - </p> - - <p> - Page titles changing is typically used to notify the user that their - action is needed, such as when a file is finished uploading. In this - case, since the text is <em>constantly changing</em>, the tab is always - in a state of "urgency." Most annoyingly, this causes the browser to - highlight the tab when it's pinned. Even if you click the tab and leave - it, this notification reappears. - </p> - - <p> - <img - src="https://nextcloud.53hor.net/index.php/s/AcNgR4cDxGDsWCB/preview" - /> - </p> - - <p> - Don't do this. Stop. Get some help. It's distracting. It's the cheesy - "web dev" equivalent of retina scan advertising in Minority Report. Just - make a site that works and looks half decent without slowing to a halt - and stop there please. - </p> - </article> - </body> -</html> diff --git a/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php b/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php new file mode 100644 index 0000000..1c28487 --- /dev/null +++ b/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php @@ -0,0 +1,69 @@ +<?php +$title = "Web Designers, Please Don't Animate Page Titles"; +if (isset($early) && $early) { + return; +} +include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php'); +?> + +<p> + If you visit + <a href="https://www.expressoil.com">Express Oil Change's web site</a>, + everything seems completely ordinary until you leave the tab. That's + when the most distracting, broken, annoying example of over-the-top web + "design" rears its ugly head. +</p> + +<p> + I'm talking about this scrolling page title. In my tab. Constantly + moving from right to left to show me all of the text. It's the only tab + that's "moving" or "animated" and it doesn't stop until you return to + the tab. It's cheesy and gaudy. +</p> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/TWDbzjiSwzHbMcz/preview" /> +</p> + +<p> + And it's also broken because there are emojis in the page title and the + title is obviously being "scrolled" by some script that's moving + byte-by-byte, so it scrolls halfway through a multi-byte UTF-8 emoji and + for a brief moment there's a glyph error character where a little red + car should have been. Bad judgment and bad programming. Worse than that, + even if it worked perfectly, it's incredibly annoying. +</p> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/TbbDnnL3jnZMT3g/preview" /> +</p> + +<p> + If you bookmark the tab when it's in the middle of scrolling, you'll + bookmark this weird slice of the text that starts or ends in the middle + of a word or with a random emoji. +</p> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/ocQofL2Goxd3AsQ/preview" /> +</p> + +<p> + Page titles changing is typically used to notify the user that their + action is needed, such as when a file is finished uploading. In this + case, since the text is <em>constantly changing</em>, the tab is always + in a state of "urgency." Most annoyingly, this causes the browser to + highlight the tab when it's pinned. Even if you click the tab and leave + it, this notification reappears. +</p> + +<p> + <img src="https://nextcloud.53hor.net/index.php/s/AcNgR4cDxGDsWCB/preview" /> +</p> + +<p> + Don't do this. Stop. Get some help. It's distracting. It's the cheesy + "web dev" equivalent of retina scan advertising in Minority Report. Just + make a site that works and looks half decent without slowing to a halt + and stop there please. +</p> diff --git a/software.html b/software.html deleted file mode 100644 index a1d8ea8..0000000 --- a/software.html +++ /dev/null @@ -1,102 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Self-Software Stuff" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Self-Software Stuff</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1>Self-Software Stuff</h1> - - <p>TODO:</p> - - <h2>Applications</h2> - - <ul> - <li> - <a href="https://pkg.53hor.net"> FreeBSD Package Repository </a> - </li> - <li> - <a href="https://nextcloud.53hor.net"> - Nextcloud Files, Contacts, Calendars - </a> - </li> - <li> - <a href="https://plex.53hor.net">Plex Media Streaming</a> - </li> - <li> - <a href="https://git.53hor.net">Gitea</a> - </li> - </ul> - - <h2>Game Servers</h2> - - <p> - If I know you and you're welcome to join one of my game servers, you can - find those here. Non-public ones are password-protected. - </p> - - <h3>[The Ultimate] DooM (Co-op Chocolate Doom)</h3> - <a href="doom.53hor.net:3343">doom.53hor.net:3343</a> - <h3>DooM II (Co-op Chocolate Doom)</h3> - <a href="doom2.53hor.net:3343">doom2.53hor.net:3343</a> - <h3> - Skyrim Together (The Elder Scrolls V: Skyrim Special Edition w/ "Skyrim - Together" mod) - </h3> - <a href="st.53hor.net:10578">st.53hor.net:10578</a> - <h3>Vanilla Minecraft</h3> - <h3>Minecraft with Mystcraft mod</h3> - </article> - </body> -</html> diff --git a/templates/index_foot.html b/templates/index_foot.html deleted file mode 100644 index 420b108..0000000 --- a/templates/index_foot.html +++ /dev/null @@ -1,4 +0,0 @@ - </ul> - </article> - </body> -</html> diff --git a/templates/index_head.html b/templates/index_head.html deleted file mode 100644 index 502658e..0000000 --- a/templates/index_head.html +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta - property="og:image" - content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" - /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="Home" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ Home</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <header> - <noscript> - JavaScript? Where we're going we don't need JavaScript. - </noscript> - </header> - - <article> - <h1 style="text-align: center"> - The World Wide Web pages of Adam Carpenter (53hornet) - </h1> - <ul> diff --git a/templates/rss_foot.xml b/templates/rss_foot.xml deleted file mode 100644 index 5c185ae..0000000 --- a/templates/rss_foot.xml +++ /dev/null @@ -1,3 +0,0 @@ -</channel> -</rss> - diff --git a/templates/rss_head.xml b/templates/rss_head.xml deleted file mode 100644 index 286ac21..0000000 --- a/templates/rss_head.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE xml> -<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> - <channel> - <title>53hornet's Feed</title> - <link>https://www.53hor.net</link> - <atom:link href="https://www.53hor.net/rss.xml" rel="self" type="application/rss+xml" /> - <description>The World Wide Web pages of Adam Carpenter</description> - <image> - <url>https://www.53hor.net/includes/logo_diag.png</url> - <title>53hornet's Feed</title> - <link>https://www.53hor.net</link> - </image> diff --git a/templates/template.html b/templates/template.html deleted file mode 100644 index e5ae191..0000000 --- a/templates/template.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <link rel="stylesheet" href="/includes/stylesheet.css" /> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <meta - property="og:description" - content="The World Wide Web pages of Adam Carpenter" - /> - <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" /> - <meta property="og:site_name" content="53hor.net" /> - <meta property="og:title" content="{{ title }}" /> - <meta property="og:type" content="website" /> - <meta property="og:url" content="https://www.53hor.net" /> - <title>53hornet ➙ {{ title }}</title> - </head> - - <body> - <nav> - <ul> - <li> - <a href="/"> - <img alt="home" src="/includes/icons/home-roof.svg" /> - Home - </a> - </li> - <li> - <a href="/info.html"> - <img alt="information" src="/includes/icons/information-variant.svg" /> - Info - </a> - </li> - <li> - <a href="https://git.53hor.net"> - <img alt="git" src="/includes/icons/git.svg" /> - Repos - </a> - </li> - <li> - <a href="/software.html"> - <img alt="software" src="/includes/icons/floppy-variant.svg" /> - Software - </a> - </li> - <li> - <a type="application/rss+xml" href="/rss.xml"> - <img alt="rss" src="/includes/icons/rss.svg" /> - RSS - </a> - </li> - </ul> - </nav> - - <article> - <h1> - {{ title }} - </h1> - - {{ content }} - </article> - </body> -</html> |