317 lines
17 KiB
HTML
317 lines
17 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en" dir="auto">
|
||
|
||
<head>
|
||
<meta name="generator" content="Hugo 0.128.0"><meta charset="utf-8">
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||
<meta name="robots" content="index, follow">
|
||
<title>Norm-working Packets 💾</title>
|
||
<meta name="keywords" content="Blog, Website, Resume, Interests, Portfolio, Selfhosted, DIY">
|
||
<meta name="description" content="A semi-technical blog & series of experiences working in tech and my homelab">
|
||
<meta name="author" content="Norm Rasmussen">
|
||
<link rel="canonical" href="./">
|
||
<script defer data-domain="selfhosted.rsmsn.co" src="https://analytics.rsmsn.co/js/script.js"></script>
|
||
<link crossorigin="anonymous" href="./assets/css/stylesheet.b609c58d5c11bb90b1a54e04005d74ad1ddf22165eb79f5533967e57df9c3b50.css" integrity="sha256-tgnFjVwRu5CxpU4EAF10rR3fIhZet59VM5Z+V9+cO1A=" rel="preload stylesheet" as="style">
|
||
<link rel="icon" href="./favicon.ico">
|
||
<link rel="icon" type="image/png" sizes="16x16" href="./favicon-16x16.png">
|
||
<link rel="icon" type="image/png" sizes="32x32" href="./rsmsncircles.ico">
|
||
<link rel="apple-touch-icon" href="./apple-touch-icon.png">
|
||
<link rel="mask-icon" href="./safari-pinned-tab.svg">
|
||
<meta name="theme-color" content="#2e2e33">
|
||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||
<link rel="alternate" type="application/rss+xml" href="./index.xml">
|
||
<link rel="alternate" type="application/json" href="./index.json">
|
||
<link rel="alternate" hreflang="en" href="./">
|
||
<noscript>
|
||
<style>
|
||
#theme-toggle,
|
||
.top-link {
|
||
display: none;
|
||
}
|
||
|
||
</style>
|
||
</noscript>
|
||
|
||
|
||
<meta property="og:title" content="Norm-working Packets 💾" />
|
||
<meta property="og:description" content="A semi-technical blog & series of experiences working in tech and my homelab" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:url" content="/" /><meta property="og:site_name" content="Self-hosted Norm" />
|
||
|
||
<meta name="twitter:card" content="summary"/>
|
||
<meta name="twitter:title" content="Norm-working Packets 💾"/>
|
||
<meta name="twitter:description" content="A semi-technical blog & series of experiences working in tech and my homelab"/>
|
||
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "Organization",
|
||
"name": "Norm-working Packets 💾",
|
||
"url": "/",
|
||
"description": "A semi-technical blog \u0026amp; series of experiences working in tech and my homelab",
|
||
"thumbnailUrl": "/favicon.ico",
|
||
"sameAs": [
|
||
"https://fosstodon.org/@notnorm", "https://github.com/Normanras", "https://selfhosted.rsmsn.co/index.xml"
|
||
]
|
||
}
|
||
</script>
|
||
</head>
|
||
|
||
<body class="list dark" id="top">
|
||
<script>
|
||
if (localStorage.getItem("pref-theme") === "light") {
|
||
document.body.classList.remove('dark')
|
||
}
|
||
|
||
</script>
|
||
|
||
<header class="header">
|
||
<nav class="nav">
|
||
<div class="logo">
|
||
<a href="./" accesskey="h" title="Norm-working Packets 💾 (Alt + H)">Norm-working Packets 💾</a>
|
||
<div class="logo-switches">
|
||
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
|
||
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
|
||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||
</svg>
|
||
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
|
||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</button>
|
||
<ul class="lang-switch"><li>|</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<ul id="menu">
|
||
<li>
|
||
<a href="./posts.html" title="Posts">
|
||
<span>Posts</span>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
</header>
|
||
<main class="main">
|
||
<article class="first-entry home-info">
|
||
<header class="entry-header">
|
||
<h1>Hey there, stranger! 👋</h1>
|
||
</header>
|
||
<div class="entry-content">
|
||
Welcome to my running collection of tips, tricks, and scripts about self-hosting and DIY. Outwardly, this is my “living resume” to showcase how I leverage my technical abilities in non-technical roles. Inwardly, this is something I can refer back to for items that don’t quite belong in my internal documentation, but are more in depth than a Mastodon post.
|
||
</div>
|
||
<footer class="entry-footer">
|
||
<div class="social-icons" >
|
||
<a href="https://fosstodon.org/@notnorm" target="_blank" rel="noopener noreferrer me"
|
||
title="Mastodon">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||
stroke-linecap="round" stroke-linejoin="round">
|
||
<path
|
||
d="M21.58 13.913c-.29 1.469-2.592 3.121-5.238 3.396-1.379.184-2.737.368-4.185.276-2.368-.092-4.237-.551-4.237-.551 0 .184.014.459.043.643.308 2.294 2.317 2.478 4.22 2.57 1.922 0 3.633-.46 3.633-.46l.079 1.653s-1.344.734-3.738.918c-1.32.091-2.96-.092-4.869-.551-4.14-1.102-4.853-5.507-4.961-10.005-.034-1.285-.013-2.57-.013-3.58 0-4.589 3-5.966 3-5.966 1.513-.734 4.11-1.01 6.808-1.01h.067c2.699 0 5.296.276 6.81 1.01 0 0 3 1.377 3 5.967 0 0 .037 3.304-.419 5.69"
|
||
stroke="currentColor" />
|
||
<path
|
||
d="M17.832 8.633v5h-1.978V8.78c0-1.023-.43-1.542-1.29-1.542-.95 0-1.427.616-1.427 1.834v2.655H11.17V9.072c0-1.218-.476-1.834-1.427-1.834-.86 0-1.29.52-1.29 1.542v4.852H6.475V8.633c0-1.022.26-1.834.782-2.434.538-.6 1.243-.909 2.118-.909 1.012 0 1.779.39 2.286 1.169l.492.827.493-.827c.507-.78 1.274-1.169 2.286-1.169.875 0 1.58.308 2.118.909.522.6.782 1.412.782 2.434"
|
||
fill="currentColor" stroke="none" />
|
||
</svg>
|
||
</a>
|
||
<a href="https://github.com/Normanras" target="_blank" rel="noopener noreferrer me"
|
||
title="Github">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||
stroke-linecap="round" stroke-linejoin="round">
|
||
<path
|
||
d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22">
|
||
</path>
|
||
</svg>
|
||
</a>
|
||
<a href="https://selfhosted.rsmsn.co/index.xml" target="_blank" rel="noopener noreferrer me"
|
||
title="RSS">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||
stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M4 11a9 9 0 0 1 9 9" />
|
||
<path d="M4 4a16 16 0 0 1 16 16" />
|
||
<circle cx="5" cy="19" r="1" />
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
|
||
</footer>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">Create a GIF from a video - Right from the Command Line!
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>Finding this little set of commands is one of the main reasons why I love the Command Line. Once I realized that almost everything that I was doing in a UI was possible on the CLI, the world opened up. One of the things I return to from time to time is when I can’t find a GIF I want to use in a message or email. Every time, I look up how to convert a video to a GIF and every time, I’m given a new solution....</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2024-07-03 17:41:15 -0400 EDT'>July 3, 2024</span> · 2 min · 409 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to Create a GIF from a video - Right from the Command Line!" href="./posts/create_gif_on_commandline.html"></a>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">How to Revisit your Terminal Session's History
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>I can’t believe I didn’t know about this command beforehand. When I first got into self-hosting and homelabbing, one of the app ideas I had that would help me with internal documentation is a terminal program that saves your input and output to a file for you to review later and extract the key commands you used. I also had the bonus idea that you could add comments as you were writing out commands....</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2024-03-19 11:00:53 -0400 EDT'>March 19, 2024</span> · 3 min · 481 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to How to Revisit your Terminal Session's History" href="./posts/save_terminal_to_file.html"></a>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">Google Sheets to Slides with Scripts: an Automation
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>Overview Recently, my wife needed help in sharing weekly content with a group of people. The original way this group was sharing content was a PDF export of a Google Doc. From a User Experience perspective, it wasn’t great. Someone would received this long PDF, they would have to scroll to find the date or topic of the next additional_notes, and overall didn’t look great.
|
||
While she had developed the Google Sheets and Google Slide system to make everything a bit more legible and navigable, there was still an element of copy and paste from the Sheet to the Slide....</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2024-02-25 10:14:30 -0500 EST'>February 25, 2024</span> · 14 min · 2963 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to Google Sheets to Slides with Scripts: an Automation" href="./posts/google_scripts_sheets_to_slides.html"></a>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">QuickHits: OpenResty and Package Updates
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>Turns out I wrote this back in November, but on a different machine and I never pushed my changes up to git. So here it is now!
|
||
The last two times I’ve run apt update && apt upgrade -y on my web server and OpenResty has an update to push out, I will get some errors including Openresty is not setup correctly. There are a few other errors in the systemctl status openresty output such as process 223478 [nginx] is still running....</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2023-12-04 10:32:58 -0500 EST'>December 4, 2023</span> · 3 min · 492 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to QuickHits: OpenResty and Package Updates" href="./posts/openresty_and_package_update_issues.html"></a>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">Neovim Subtitute Magic
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>This week, I’ve had to make some changes to an automation we had setup for a customer in Workato. The original recipe was made by a co-worker with a bunch of javascript nodes. Even though I’m customer facing and generally not considered a technical employee, I knew the engineer who worked on this was swamped, so I decided to jump in.
|
||
In order to greatly reduce the number of nodes needed in the single recipe, I created a list of dictionaries in python (with one of the values being another list!...</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2023-11-15 08:08:49 -0500 EST'>November 15, 2023</span> · 6 min · 1221 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to Neovim Subtitute Magic" href="./posts/find_and_replace_in_neovim.html"></a>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">Mini Neovim
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>If I’m being honest, when I started this quick project to reduce my Neovim plugin footprint size, I thought I was going to be able to get rid of way more plugins! Inspired by this Reddit post that setup a Neovim config using only echasnovski’s mini library, I was reminded that some of my remote server environments were still using Packer as their plugin manager, where my main machine has upgraded to Lazy....</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2023-10-20 18:38:13 -0400 EDT'>October 20, 2023</span> · 3 min · 602 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to Mini Neovim" href="./posts/mini_neovim.html"></a>
|
||
</article>
|
||
|
||
<article class="post-entry">
|
||
<header class="entry-header">
|
||
<h2 class="entry-hint-parent">ESP8266 Medicine Indicator Light
|
||
</h2>
|
||
</header>
|
||
<div class="entry-content">
|
||
<p>This is a quick treat! We recently learned that one of our children needs to take medicine twice a day for the foreseeable future. He’s too young to take it on his own, so the twice-a-day responsibility is split up between my partner and I. However, sometimes our schedules don’t overlap so succinctly, so we needed some sort of indicator to let the other know if the previous dose was (or wasn’t!...</p>
|
||
</div>
|
||
<footer class="entry-footer"><span title='2023-10-16 11:34:14 -0400 EDT'>October 16, 2023</span> · 6 min · 1170 words · Me</footer>
|
||
<a class="entry-link" aria-label="post link to ESP8266 Medicine Indicator Light" href="./posts/medicine_indicator_light.html"></a>
|
||
</article>
|
||
<footer class="page-footer">
|
||
<nav class="pagination">
|
||
<a class="next" href="./page/2.html">Next »
|
||
</a>
|
||
</nav>
|
||
</footer>
|
||
</main>
|
||
|
||
<footer class="footer">
|
||
<span>© 2024 <a href="./">Norm-working Packets 💾</a></span>
|
||
<span>
|
||
Powered by
|
||
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
|
||
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
|
||
</span>
|
||
</footer>
|
||
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
|
||
<path d="M12 6H0l6-6z" />
|
||
</svg>
|
||
</a>
|
||
|
||
<script>
|
||
let menu = document.getElementById('menu')
|
||
if (menu) {
|
||
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
|
||
menu.onscroll = function () {
|
||
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
|
||
}
|
||
}
|
||
|
||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||
anchor.addEventListener("click", function (e) {
|
||
e.preventDefault();
|
||
var id = this.getAttribute("href").substr(1);
|
||
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
|
||
behavior: "smooth"
|
||
});
|
||
} else {
|
||
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
|
||
}
|
||
if (id === "top") {
|
||
history.replaceState(null, null, " ");
|
||
} else {
|
||
history.pushState(null, null, `#${id}`);
|
||
}
|
||
});
|
||
});
|
||
|
||
</script>
|
||
<script>
|
||
var mybutton = document.getElementById("top-link");
|
||
window.onscroll = function () {
|
||
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
|
||
mybutton.style.visibility = "visible";
|
||
mybutton.style.opacity = "1";
|
||
} else {
|
||
mybutton.style.visibility = "hidden";
|
||
mybutton.style.opacity = "0";
|
||
}
|
||
};
|
||
|
||
</script>
|
||
<script>
|
||
document.getElementById("theme-toggle").addEventListener("click", () => {
|
||
if (document.body.className.includes("dark")) {
|
||
document.body.classList.remove('dark');
|
||
localStorage.setItem("pref-theme", 'light');
|
||
} else {
|
||
document.body.classList.add('dark');
|
||
localStorage.setItem("pref-theme", 'dark');
|
||
}
|
||
})
|
||
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|