migrates ghost blog to hugo
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="auto">
|
||||
|
||||
<head><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="noindex, nofollow">
|
||||
<title>InterPlanetary File System | dvdt.dev</title>
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="What will the Internet look like for colonists on Mars? It seems like a silly question since we’re far away from having boots on the ground on our red planet neighbor. We’ll likely need a moon base, which is itself likely decades away, before we can even think about attempting a manned trip to Mars. The problem is Mars is so far away the best possible latency is around 16 minutes round-trip.">
|
||||
<meta name="author" content="David Lick">
|
||||
<link rel="canonical" href="https://new.dvdt.dev/2020/06/interplanetary-file-system/">
|
||||
<link crossorigin="anonymous" href="/assets/css/stylesheet.5cfc680b1eeaeef9efbced92d46c2a9e876b72ee14fba85846afc4cff9e6e6f8.css" integrity="sha256-XPxoCx7q7vnvvO2S1Gwqnodrcu4U+6hYRq/Ez/nm5vg=" rel="preload stylesheet" as="style">
|
||||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||||
onload="hljs.initHighlightingOnLoad();"></script>
|
||||
<link rel="icon" href="https://new.dvdt.dev/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://new.dvdt.dev/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://new.dvdt.dev/favicon-32x32.png">
|
||||
<link rel="apple-touch-icon" href="https://new.dvdt.dev/apple-touch-icon.png">
|
||||
<link rel="mask-icon" href="https://new.dvdt.dev/safari-pinned-tab.svg">
|
||||
<meta name="theme-color" content="#2e2e33">
|
||||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--hljs-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body class="" id="top">
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
<a href="https://new.dvdt.dev/" accesskey="h" title="dvdt.dev (Alt + H)">dvdt.dev</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>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="menu">
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/about-me/" title="about me">
|
||||
<span>about me</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/support" title="support">
|
||||
<span>support</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="main">
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
|
||||
<h1 class="post-title">
|
||||
InterPlanetary File System
|
||||
</h1>
|
||||
<div class="post-meta"><span title='2020-06-25 00:00:00 +0000 UTC'>June 25, 2020</span> · David Lick
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<div class="post-content"><p><img loading="lazy" src="/img/orbit-model.jpg" alt="Solar system model" />
|
||||
</p>
|
||||
<p>What will the Internet look like for colonists on Mars? It seems like a silly question since we’re far away from having boots on the ground on our red planet neighbor. We’ll likely need a moon base, which is itself likely decades away, before we can even think about attempting a manned trip to Mars. The problem is Mars is so far away the best possible latency is around 16 minutes round-trip. So if you want to check your Twitter and the servers are here on Earth.. you’re going to wait a very long time between page loads.</p>
|
||||
<p>Enter the <a href="https://ipfs.io/">InterPlanetary File System</a>. IPFS, designed by <a href="https://protocol.ai/">Protocol Labs</a>, is part of a growing movement to decentralize the Internet which has wide reaching implications from resiliency to durability to availability and with that protection from censorship.</p>
|
||||
<p>Simply, IPFS is a protocol that allows content-addressing instead of location-addressing. What that means is you make a request for specific files and you could get them from someone across the world or it could come from someone in your neighborhood. Additionally, each user of IPFS is another node in the network which can serve content. So in our Mars colony thought experiment, if anyone on Mars has downloaded content from Earth they become the closest seed for that content to all the users on Mars. Here on Earth, that means we can reduce loading times for content by fetching from nodes close to us. It also means that if one node is unreachable, you’ll simply reach out to the next closest node for your content. IPFS can replace a portion of the HTTP traffic of the internet today since IPFS is particularly well suited for static content. However, it doesn’t have to exclusively replace it. IPFS is just another tool in the toolbox to be used when applications or content need to be highly available, resilient and durable.</p>
|
||||
<p><img loading="lazy" src="/img/geometric-3d.jpg" alt="Photo by <a href="https://unsplash.com/@alinnnaaaa?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Alina Grubnyak</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a>" />
|
||||
</p>
|
||||
<h3 id="architecture">Architecture<a hidden class="anchor" aria-hidden="true" href="#architecture">#</a></h3>
|
||||
<p>I’ll keep this pretty high-level since the <a href="https://dhl-space.sfo2.digitaloceanspaces.com/assets/ipfs-p2p-file-system.pdf">IPFS white paper</a> goes in-depth of how the protocol works. IPFS relies on several key technologies born and evolved since the introduction of HTTP.</p>
|
||||
<h3 id="coordination">Coordination<a hidden class="anchor" aria-hidden="true" href="#coordination">#</a></h3>
|
||||
<p>Looking up which nodes are serving the content you want is powered by <a href="https://en.wikipedia.org/wiki/Distributed_hash_table">distributed hash tables</a> or DHTs. DHTs have been used in other widely distributed systems such as BitTorrent to track peers.</p>
|
||||
<h3 id="hashing">Hashing<a hidden class="anchor" aria-hidden="true" href="#hashing">#</a></h3>
|
||||
<p><a href="https://en.wikipedia.org/wiki/Distributed_hash_table">Hashing</a> is at the heart of what makes IPFS tick. Hashes are generated from file contents that uniquely describe what a file is. Hashes are exceptional for this because a single bit changed in a file will drastically change the hash output. This means we can uniquely describe an entire file with a short string of characters.</p>
|
||||
<h3 id="merkle-trees">Merkle Trees<a hidden class="anchor" aria-hidden="true" href="#merkle-trees">#</a></h3>
|
||||
<p><a href="https://en.wikipedia.org/wiki/Merkle_tree">Merkle trees</a> are the core technology used in version control systems for history tracking. IPFS uses them to similar ends as well as some interesting emergent features.</p>
|
||||
<p>Everything in IPFS is described by a cryptographic hash. Folders are hashed by their contents and if that folder contains other folders they will be described by hashes of their contents. So on and so forth. Since all objects in the Merkle tree are described by their hashes, all files in IPFS are immutable. When a file is changed the previous version remains and the updated version is added. Both versions will have their own addresses.</p>
|
||||
<p>Finally, since files are described by their hashes it’s trivial to check that a file has been altered, whether maliciously or not. You simply hash the file and if the checksums do not match, you throw the file away.</p>
|
||||
<h3 id="installing-and-using-ipfs">Installing and Using IPFS<a hidden class="anchor" aria-hidden="true" href="#installing-and-using-ipfs">#</a></h3>
|
||||
<p>There’s an excellent primer on installing and using IPFS <a href="https://github.com/ipfs-shipyard/ipfs-primer/tree/master">here</a>. Protocol Labs have done an excellent job creating useful command line tools as well as desktop applications for making accessing the network seamless and easy. <a href="https://github.com/ipfs-shipyard/ipfs-desktop">IPFS Desktop</a> is a convenient application which runs a local IPFS node which you use to access ipfs://, ipns:// and dweb: links as well as serve your own content to the network.</p>
|
||||
<p><a href="https://brave.com/">Brave</a>, which I highly recommend for their privacy protection focused browser, have added an IPFS Companion toggle in their settings to enable IPFS… no need to install anything.</p>
|
||||
<h3 id="ipfs-based-dapps">IPFS-Based DApps<a hidden class="anchor" aria-hidden="true" href="#ipfs-based-dapps">#</a></h3>
|
||||
<p>Since IPFS is still relatively new discovery on the network is still difficult. There are no great search engines just yet. <a href="https://awesome.ipfs.io/">Awesome IPFS</a> is a neat place to find new tools and content hosted on IPFS.</p>
|
||||
<p>Some cool applications I’ve come across:</p>
|
||||
<h3 id="dtubehttpsdtube"><a href="https://d.tube/">DTube</a><a hidden class="anchor" aria-hidden="true" href="#dtubehttpsdtube">#</a></h3>
|
||||
<p>A distributed YouTube alternative. There’s not a lot of content yet but as a PoC it shows that we definitely don’t need Google for a video service like YouTube.</p>
|
||||
<h3 id="killcordhttpskillcordio"><a href="https://killcord.io/">killcord</a><a hidden class="anchor" aria-hidden="true" href="#killcordhttpskillcordio">#</a></h3>
|
||||
<p>Not sure I really have use of a deadman’s switch but the concept is very cool!</p>
|
||||
<h3 id="diffusehttpsdiffusesh"><a href="https://diffuse.sh/">Diffuse</a><a hidden class="anchor" aria-hidden="true" href="#diffusehttpsdiffusesh">#</a></h3>
|
||||
<p>A cool in browser music player that supports playing content from IPFS as well as S3, Blockstack, Dropbox and other remote storage.</p>
|
||||
<h3 id="openbazaarhttpswwwopenbazaarorg"><a href="https://www.openbazaar.org/">OpenBazaar</a><a hidden class="anchor" aria-hidden="true" href="#openbazaarhttpswwwopenbazaarorg">#</a></h3>
|
||||
<p>OpenBazaar is a decentralized e-commerce platform built on IPFS which allows you to buy and sell with Bitcoin.</p>
|
||||
<h3 id="conclusion">Conclusion<a hidden class="anchor" aria-hidden="true" href="#conclusion">#</a></h3>
|
||||
<p>I’ve only started scratching the surface of what IPFS can do. It makes me really excited for the future of the Internet. If it takes off it has the potential to wrench control of the Internet away from the few super large companies and put it back into the hands of the users. The worst case scenario for IPFS is it’s used to make the Internet more durable, resilient and available. I’m brainstorming project ideas to build on top of the protocol. I’ll write a post later when I have something cool to show off and in the meantime, I’m excited to see what others come up with!</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<ul class="post-tags">
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>© 2023 <a href="https://new.dvdt.dev/">dvdt.dev</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><footer class="footer">PGP: 6FF9 2943 B795 21DC 51D2 4734 715C 88E0 E239 7C72</footer>
|
||||
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,275 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="auto">
|
||||
|
||||
<head><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="noindex, nofollow">
|
||||
<title>Running a Bitcoin Full Node | dvdt.dev</title>
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="I learned about Bitcoin in 2013. I watched it for a while before I entered the market in 2014. I dabbled in day-trading (bad idea, just don’t if you like sleep at all…) I even wrote a Python trading bot back in the day that made some decent profits before my 24 year old self got nervous about playing with more money than I’d ever had at once and turned it off.">
|
||||
<meta name="author" content="David Lick">
|
||||
<link rel="canonical" href="https://new.dvdt.dev/2020/06/running-a-bitcoin-full-node/">
|
||||
<link crossorigin="anonymous" href="/assets/css/stylesheet.5cfc680b1eeaeef9efbced92d46c2a9e876b72ee14fba85846afc4cff9e6e6f8.css" integrity="sha256-XPxoCx7q7vnvvO2S1Gwqnodrcu4U+6hYRq/Ez/nm5vg=" rel="preload stylesheet" as="style">
|
||||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||||
onload="hljs.initHighlightingOnLoad();"></script>
|
||||
<link rel="icon" href="https://new.dvdt.dev/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://new.dvdt.dev/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://new.dvdt.dev/favicon-32x32.png">
|
||||
<link rel="apple-touch-icon" href="https://new.dvdt.dev/apple-touch-icon.png">
|
||||
<link rel="mask-icon" href="https://new.dvdt.dev/safari-pinned-tab.svg">
|
||||
<meta name="theme-color" content="#2e2e33">
|
||||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--hljs-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body class="" id="top">
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
<a href="https://new.dvdt.dev/" accesskey="h" title="dvdt.dev (Alt + H)">dvdt.dev</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>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="menu">
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/about-me/" title="about me">
|
||||
<span>about me</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/support" title="support">
|
||||
<span>support</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="main">
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
|
||||
<h1 class="post-title">
|
||||
Running a Bitcoin Full Node
|
||||
</h1>
|
||||
<div class="post-meta"><span title='2020-06-13 00:00:00 +0000 UTC'>June 13, 2020</span> · David Lick
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<div class="post-content"><p><img loading="lazy" src="/img/bitcoin-cpu.jpg" alt="Bitcoin on CPU" />
|
||||
</p>
|
||||
<p>I learned about Bitcoin in 2013. I watched it for a while before I entered the market in 2014. I dabbled in day-trading (bad idea, just don’t if you like sleep at all…) I even wrote a Python trading bot back in the day that made some decent profits before my 24 year old self got nervous about playing with more money than I’d ever had at once and turned it off.</p>
|
||||
<p>During the run up at the end of 2014 I sold out of my position a little before the peak. It was dumb luck, trust me I was no genius trader by any means and that’s still true. I told myself the volatility was too much for me, and it was… I lost a lot of sleep that year. But I never stopped checking up on how Bitcoin was doing and recently I’ve gotten back in the game. This year with the corona epidemic and the unprecedented amount of money being created, the multiple other currencies that have experienced hyper-inflation recently, Bitcoin’s raison d’être for existing is back in center-view.</p>
|
||||
<p>I believe in Bitcoin and want to contribute to the network somehow. Mining is out of the question. It was out of the question even back in 2014 when ASICs started coming onto the scene. Another option is running a Bitcoin full node.</p>
|
||||
<h3 id="what-is-a-full-node">What is a full node?<a hidden class="anchor" aria-hidden="true" href="#what-is-a-full-node">#</a></h3>
|
||||
<p>To answer that question, let’s take a step back and look at how the Bitcoin protocol works. Miners collect new transactions from the network together in blocks and then hash them over and over. They’re looking for a hash that has a specific number of preceding zeroes, called the difficulty. This process is called proof of work and it’s the heart of what makes Bitcoin work. The process of finding a hash that matches the difficulty takes a lot of computing power but checking that hash is trivially easy even for a low-powered computer.</p>
|
||||
<p>Bitcoin is trust-less at every layer so we don’t blindly trust the blocks miners give us; we verify. This is the work that full nodes do. They enforce the rules of Bitcoin always. If a miner produces a block that doesn’t follow the rules it is ignored and if it happens enough that miner is also ignored. This gives miners a financial incentive to behave. If you don’t follow the rules you don’t receive the transaction fees or the block bounty. Full nodes are a check on the [51% attack.</p>
|
||||
<p>Full nodes also give you a voting voice in the case of a hard-fork. The software you run determines the rules followed. This happened with <a href="https://www.investopedia.com/news/all-about-bitcoin-cash-hard-fork/">Bitcoin Cash</a> in 2019. Developers attempted to alter the Bitcoin consensus rules in a way that would defy Bitcoin’s core tenant of limited supply – scarcity. Contributors running full nodes voted on which fork to follow by running one version of the full node software or the other and overwhelmingly chose BTC. You can see that in the price of both today: BTC - $9450 vs. BCH - $240.</p>
|
||||
<h3 id="tutorial">Tutorial<a hidden class="anchor" aria-hidden="true" href="#tutorial">#</a></h3>
|
||||
<p>I have a home server which is my lab of sorts. I use it for all kinds of things and there are various tasks it runs for me and it has enough storage for this. You don’t have to have a dedicated computer to run a full node. Lots of contributors run full nodes on Raspberry Pi’s or other single-board computers. There are only a few requirements to run a full node:</p>
|
||||
<ul>
|
||||
<li>You are going to download the entire blockchain so you will need a sizable amount of free storage. The blockchain is 282GB as of this post. Each block is around 1MB and new blocks are mined every 10 minutes so the blockchain size grows linearly with time.</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/blockchain-size-graph-2020.png" alt="Blockchain size graph" />
|
||||
</p>
|
||||
<ul>
|
||||
<li>Obviously you’ll need to download the blockchain in its entirety so you’ll want an unmetered internet connection. After the initial blockchain download you will download 20GB and upload 200GB per month on average.</li>
|
||||
<li>You need the full node to run at least 6 hours per day. Running it all the time is better.</li>
|
||||
<li>You probably don’t want this running on a high powered gaming computer unless you like paying your energy company for electricity. This is a big reason a lot of people opt for a Raspberry Pi.</li>
|
||||
</ul>
|
||||
<p>Getting the full node up and running is actually very easy. There’s a GUI version you can use but I run my Linux server headless so we’ll go through the CLI version. The installation instructions found here are very good. The verification of the file integrity and the signing keys may not be obvious to novice users so I’ll go through the steps here:</p>
|
||||
<ol>
|
||||
<li>First off, you need to <a href="https://bitcoin.org/en/download">download</a> the Linux tarball, the SHA256SUMS file and the release signing key corresponding to your version.</li>
|
||||
<li>Now verify the download files integrity with the SHA256SUMS file. Run the following command and you should see an OK corresponding to the tarball you downloaded.</li>
|
||||
</ol>
|
||||
<pre tabindex="0"><code>~/Downloads$ sha256sum --ignore-missing -c SHA256SUMS.asc
|
||||
bitcoin-0.20.0-x86_64-linux-gnu.tar.gz: OK
|
||||
sha256sum: WARNING: 20 lines are improperly formatted
|
||||
</code></pre><ol start="3">
|
||||
<li>Import the public key into your GPG keyring. I installed version 0.20.0 so in my case the signing key was laanwj-releases.asc.</li>
|
||||
</ol>
|
||||
<pre tabindex="0"><code>~/Downloads$ gpg --import laanwj-releases.asc
|
||||
gpg: key 90C8019E36C2E964: 51 signatures not checked due to missing keys
|
||||
gpg: key 90C8019E36C2E964: public key "Wladimir J. van der Laan (Bitcoin Core binary release signing key) <laanwj@gmail.com>" imported
|
||||
gpg: Total number processed: 1
|
||||
gpg: imported: 1
|
||||
gpg: no ultimately trusted keys found
|
||||
</code></pre><ol start="4">
|
||||
<li>Now verify the SHA256SUMS.asc file. If you are an extra cautious person you can go a step further and ask one of the project developers to verify the fingerprint.</li>
|
||||
</ol>
|
||||
<pre tabindex="0"><code>~/Downloads$ gpg --verify SHA256SUMS.asc
|
||||
gpg: Signature made Wed 03 Jun 2020 05:59:52 AM EDT
|
||||
gpg: using RSA key 90C8019E36C2E964
|
||||
gpg: Good signature from "Wladimir J. van der Laan (Bitcoin Core binary release signing key) <laanwj@gmail.com>" [unknown]
|
||||
gpg: WARNING: This key is not certified with a trusted signature!
|
||||
gpg: There is no indication that the signature belongs to the owner.
|
||||
Primary key fingerprint: 01EA 5486 DE18 A882 D4C2 6845 90C8 019E 36C2 E964
|
||||
</code></pre><ol start="5">
|
||||
<li>Now that we’ve verified the download you can follow along with the installation instructions.</li>
|
||||
</ol>
|
||||
<h3 id="networkingfirewall">Networking/Firewall<a hidden class="anchor" aria-hidden="true" href="#networkingfirewall">#</a></h3>
|
||||
<p>You’ll also need to open the 8333 port for your full node. The process for this is very dependent on your set up. In my case, I needed to set up port forwarding through my router as well as open the port in my iptables firewall. I have my firewall set up to DROP any incoming traffic not explicitly allowed so I simply added an INPUT rule like this:</p>
|
||||
<pre tabindex="0"><code>iptables -A INPUT -p tcp --dport 8333 -j ACCEPT
|
||||
</code></pre><h3 id="starting-up">Starting up<a hidden class="anchor" aria-hidden="true" href="#starting-up">#</a></h3>
|
||||
<p>I went the init script route for starting my full node using systemd instead of a crontab. If you want to use systemd:</p>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Add this <a href="https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service">init script</a> to your /usr/lib/systemd/system folder.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Test by starting the script: systemctl start bitcoind</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>If bitcoind started successfully you can start it at boot time: systemctl enable bitcoind</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h3 id="initial-block-download">Initial Block Download<a hidden class="anchor" aria-hidden="true" href="#initial-block-download">#</a></h3>
|
||||
<p>The inital block download will take a while to complete depending on your connection. I have a gigabit fiber connection and it still took the majority of 24 hours to complete. You are downloading a full copy of the blockchain from other contributors running a full node so even if you have a fast connection you will likely be limited by others upload speeds.</p>
|
||||
<h3 id="conclusion">Conclusion<a hidden class="anchor" aria-hidden="true" href="#conclusion">#</a></h3>
|
||||
<p>I hope this helps others get their full nodes up and running. It genuinely feels good to contribute to the network and keep Bitcoin safe. If this helped let me know on <a href="https://twitter.com/DalaiComma">Twitter</a> or if you did get stuck along the way, I’d be happy to help you along if I can and I’ll update this guide for others.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<ul class="post-tags">
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>© 2023 <a href="https://new.dvdt.dev/">dvdt.dev</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><footer class="footer">PGP: 6FF9 2943 B795 21DC 51D2 4734 715C 88E0 E239 7C72</footer>
|
||||
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,223 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="auto">
|
||||
|
||||
<head><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="noindex, nofollow">
|
||||
<title>Hardware Wallets | dvdt.dev</title>
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="Let’s talk about hardware wallets. For the uninitiated, a hardware wallet is a device which keeps your Bitcoin safe while also keeping them easily accessible. There are a few trusted varieties so far. Trezor and Ledger are the two I have experience with personally.
|
||||
Hardware wallets work by storing your private keys in a secure chip in the device. When you use the device, your unsigned transaction is sent from the computer to the wallet which then signs the transaction with your keys and sends it back.">
|
||||
<meta name="author" content="David Lick">
|
||||
<link rel="canonical" href="https://new.dvdt.dev/2020/07/hardware-wallets/">
|
||||
<link crossorigin="anonymous" href="/assets/css/stylesheet.5cfc680b1eeaeef9efbced92d46c2a9e876b72ee14fba85846afc4cff9e6e6f8.css" integrity="sha256-XPxoCx7q7vnvvO2S1Gwqnodrcu4U+6hYRq/Ez/nm5vg=" rel="preload stylesheet" as="style">
|
||||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||||
onload="hljs.initHighlightingOnLoad();"></script>
|
||||
<link rel="icon" href="https://new.dvdt.dev/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://new.dvdt.dev/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://new.dvdt.dev/favicon-32x32.png">
|
||||
<link rel="apple-touch-icon" href="https://new.dvdt.dev/apple-touch-icon.png">
|
||||
<link rel="mask-icon" href="https://new.dvdt.dev/safari-pinned-tab.svg">
|
||||
<meta name="theme-color" content="#2e2e33">
|
||||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--hljs-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body class="" id="top">
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
<a href="https://new.dvdt.dev/" accesskey="h" title="dvdt.dev (Alt + H)">dvdt.dev</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>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="menu">
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/about-me/" title="about me">
|
||||
<span>about me</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/support" title="support">
|
||||
<span>support</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="main">
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
|
||||
<h1 class="post-title">
|
||||
Hardware Wallets
|
||||
</h1>
|
||||
<div class="post-meta"><span title='2020-07-24 00:00:00 +0000 UTC'>July 24, 2020</span> · David Lick
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<div class="post-content"><p><img loading="lazy" src="/img/open-wallet.jpg" alt="Wallet open with cards" />
|
||||
</p>
|
||||
<p>Let’s talk about hardware wallets. For the uninitiated, a hardware wallet is a device which keeps your Bitcoin safe while also keeping them easily accessible. There are a few trusted varieties so far. <a href="https://trezor.io/">Trezor</a> and <a href="https://www.ledger.com/">Ledger</a> are the two I have experience with personally.</p>
|
||||
<p><img loading="lazy" src="/img/trezor-card-passport.jpg" alt="Photo by <a href="https://unsplash.com/@jankolar?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Jan Antonin Kolar</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a>" />
|
||||
</p>
|
||||
<p>Hardware wallets work by storing your private keys in a secure chip in the device. When you use the device, your unsigned transaction is sent from the computer to the wallet which then signs the transaction with your keys and sends it back. During this process your keys never leave the device, which is important because you want to limit your exposure as much as possible. The devices even generate your 24-word seed phrase within the device and display them on the screen for you to write down just so no device that has ever or will ever be network connected has seen your keys.</p>
|
||||
<p>Hardware wallets fill in a gap between hot wallets (where your keys are stored on the device, think Electrum, Wasabi) and proper cold wallets (remember paper wallets?) In effect, a hardware wallet is the same as installing Electrum on an air-gapped laptop which has had it’s NIC and WiFi cards ripped out. To use that wallet you would generate your transaction on a network equipped computer, save it on a USB drive, load it into the laptop where you would sign the transaction with your private keys. Then save the signed transaction to the USB, load it back into the networked computer, and broadcast your transaction from there. Hardware wallets are the same workflow just much more accessible and user friendly.</p>
|
||||
<p>In my opinion, these devices are the best blend of security and convenience that you can get. Ledger also has their <a href="https://shop.ledger.com/products/ledger-nano-x">Nano X</a> wallet which is even Bluetooth enabled allowing you to use it through their mobile app on the go, I can highly recommend this one. I bought mine after initially buying the <a href="https://shop.trezor.io/product/trezor-one-white">Trezor One</a> because it’s the old guard hardware wallet; it’s been around a while and it’s well reviewed and well trusted. But haven’t touched the Trezor since.</p>
|
||||
<p>If you have more than $200 of Bitcoin, it’s time to buy a hardware wallet. Do you research to find out which one works best for you. But whichever you choose be conscious of security. Here’s my advice:</p>
|
||||
<ul>
|
||||
<li>Do <strong><!-- raw HTML omitted -->not<!-- raw HTML omitted --></strong> order your wallet from a third party source. It will probably be fine, but it could also not be fine at all. You don’t want to put your hard earned crypto on a compromised device and lose it all.</li>
|
||||
<li>Check your respective devices documentation about their shipping security features. Trezor will have holographic stickers. Ledger does a firmware check during initialization. If anything seems weird or off, contact the company and <strong><!-- raw HTML omitted -->don’t<!-- raw HTML omitted --></strong> use the device.</li>
|
||||
<li>Remember, your Bitcoin is not stored on the device itself your private keys are. You <strong><!-- raw HTML omitted -->must<!-- raw HTML omitted --></strong> keep these safe at all costs. So that means if your 24 word seed phrase is compromised no amount of cool wallet tech is going to keep you from getting robbed. A 25th word passphrase is your best protection against this. Treat this like a password: it must be random, it must be long, and you should not store it anywhere near your wallet.</li>
|
||||
<li>Even better than a 25th word is using a 2-of-3 or even 3-of-5 multi-sig wallet. This provides the added benefit of resiliency in the event of a lost seed. In 2-of-3 you have a loss threshold of 1 seed. 3-of-5 is event better with a loss threshold of 2. If you have your seed phrases geographically distributed and lose more than 1, your Bitcoins are probably the least of your worries.</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/open-safety-deposit-boxes.jpg" alt="Photo by <a href="https://unsplash.com/@emielmaters?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Emiel Maters</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a>" />
|
||||
</p>
|
||||
<p>Bitcoin is a money revolution. It’s convenient, <a href="https://hardmoneyfilm.com/">hard</a>, and secure.. but not by default and it’s up to you to take the care to make it secure.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<ul class="post-tags">
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>© 2023 <a href="https://new.dvdt.dev/">dvdt.dev</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><footer class="footer">PGP: 6FF9 2943 B795 21DC 51D2 4734 715C 88E0 E239 7C72</footer>
|
||||
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,211 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="auto">
|
||||
|
||||
<head><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="noindex, nofollow">
|
||||
<title>Switched to Arch Linux (...Again) | dvdt.dev</title>
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="I have probably installed Arch Linux ten times in as many years. I see other distros every once in a while that I want to try out but I always end up back with Arch. There’s something very satisfying in knowing exactly what is running on your system down to the process. Having everything hand picked to be exactly what you want just makes it feel like home.
|
||||
My main computer for a long time was a 2014 13-inch Macbook Pro.">
|
||||
<meta name="author" content="David Lick">
|
||||
<link rel="canonical" href="https://new.dvdt.dev/2020/10/switched-to-arch-linux-...again/">
|
||||
<link crossorigin="anonymous" href="/assets/css/stylesheet.5cfc680b1eeaeef9efbced92d46c2a9e876b72ee14fba85846afc4cff9e6e6f8.css" integrity="sha256-XPxoCx7q7vnvvO2S1Gwqnodrcu4U+6hYRq/Ez/nm5vg=" rel="preload stylesheet" as="style">
|
||||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||||
onload="hljs.initHighlightingOnLoad();"></script>
|
||||
<link rel="icon" href="https://new.dvdt.dev/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://new.dvdt.dev/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://new.dvdt.dev/favicon-32x32.png">
|
||||
<link rel="apple-touch-icon" href="https://new.dvdt.dev/apple-touch-icon.png">
|
||||
<link rel="mask-icon" href="https://new.dvdt.dev/safari-pinned-tab.svg">
|
||||
<meta name="theme-color" content="#2e2e33">
|
||||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--hljs-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body class="" id="top">
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
<a href="https://new.dvdt.dev/" accesskey="h" title="dvdt.dev (Alt + H)">dvdt.dev</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>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="menu">
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/about-me/" title="about me">
|
||||
<span>about me</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/support" title="support">
|
||||
<span>support</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="main">
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
|
||||
<h1 class="post-title">
|
||||
Switched to Arch Linux (...Again)
|
||||
</h1>
|
||||
<div class="post-meta"><span title='2020-10-11 00:00:00 +0000 UTC'>October 11, 2020</span> · David Lick
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<div class="post-content"><p><img loading="lazy" src="/img/arch-linux-logo.png" alt="Arch Linux logo" />
|
||||
</p>
|
||||
<p>I have probably installed <a href="https://archlinux.org/">Arch Linux</a> ten times in as many years. I see other distros every once in a while that I want to try out but I always end up back with Arch. There’s something very satisfying in knowing exactly what is running on your system down to the process. Having everything hand picked to be exactly what you want just makes it feel like home.</p>
|
||||
<p>My main computer for a long time was a 2014 13-inch Macbook Pro. I didn’t have space in a one bedroom apartment for a desktop so I made the most with what I had. This year I moved into a two bedroom with my girlfriend and I have an office now so I built my dream gaming computer. I was in such a hurry to play some games that I picked a distro that was easy to install, but close enough to Arch, and that was Manjaro. Overall, I was very happy with the experience Manjaro has: it was easy to install, had some cool layouts for Gnome, it had some good programs installed by default. It still just didn’t feel like it was mine.</p>
|
||||
<p>Bonus: my entire system runs idle with 1.25GB memory which is roughly 50% lower than in Manjaro. I’m not sure what was using up that much RAM before but but it feels good to know now.</p>
|
||||
<p>So… btw I run arch</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<ul class="post-tags">
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>© 2023 <a href="https://new.dvdt.dev/">dvdt.dev</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><footer class="footer">PGP: 6FF9 2943 B795 21DC 51D2 4734 715C 88E0 E239 7C72</footer>
|
||||
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,234 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="auto">
|
||||
|
||||
<head><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="noindex, nofollow">
|
||||
<title>UFW VPN Kill Switch | dvdt.dev</title>
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="NetworkManager unfortunately doesn’t have a kill switch in case your VPN connection drops but you can achieve the same effect through firewall rules. I’m using ufw here but you can achieve the same using iptables or firewall-cmd. I haven’t looked into automating this when VPN connects yet but opening Gufw and switching the profile hasn’t become annoying yet either. If I ever get around to that I’ll post an update.">
|
||||
<meta name="author" content="David Lick">
|
||||
<link rel="canonical" href="https://new.dvdt.dev/2020/10/ufw-vpn-kill-switch/">
|
||||
<link crossorigin="anonymous" href="/assets/css/stylesheet.5cfc680b1eeaeef9efbced92d46c2a9e876b72ee14fba85846afc4cff9e6e6f8.css" integrity="sha256-XPxoCx7q7vnvvO2S1Gwqnodrcu4U+6hYRq/Ez/nm5vg=" rel="preload stylesheet" as="style">
|
||||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||||
onload="hljs.initHighlightingOnLoad();"></script>
|
||||
<link rel="icon" href="https://new.dvdt.dev/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://new.dvdt.dev/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://new.dvdt.dev/favicon-32x32.png">
|
||||
<link rel="apple-touch-icon" href="https://new.dvdt.dev/apple-touch-icon.png">
|
||||
<link rel="mask-icon" href="https://new.dvdt.dev/safari-pinned-tab.svg">
|
||||
<meta name="theme-color" content="#2e2e33">
|
||||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--hljs-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body class="" id="top">
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
<a href="https://new.dvdt.dev/" accesskey="h" title="dvdt.dev (Alt + H)">dvdt.dev</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>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="menu">
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/about-me/" title="about me">
|
||||
<span>about me</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/support" title="support">
|
||||
<span>support</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="main">
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
|
||||
<h1 class="post-title">
|
||||
UFW VPN Kill Switch
|
||||
</h1>
|
||||
<div class="post-meta"><span title='2020-10-11 00:00:00 +0000 UTC'>October 11, 2020</span> · David Lick
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<div class="post-content"><p><img loading="lazy" src="/img/old-switch.jpg" alt="Old wall switch" />
|
||||
</p>
|
||||
<p>NetworkManager unfortunately doesn’t have a kill switch in case your VPN connection drops but you can achieve the same effect through firewall rules. I’m using <a href="https://wiki.archlinux.org/index.php/Uncomplicated_Firewall">ufw</a> here but you can achieve the same using iptables or firewall-cmd. I haven’t looked into automating this when VPN connects yet but opening <a href="https://gufw.org/">Gufw</a> and switching the profile hasn’t become annoying yet either. If I ever get around to that I’ll post an update.</p>
|
||||
<p>Gufw’s UI is very good and the advanced tab in it’s rules creator has everything I need: interface, direction, to/from IP and port ranges so I use that over setting rules from the command line.</p>
|
||||
<ul>
|
||||
<li>First, set up the kill switch profile to easily turn rules on and off as needed. You’ll want to set incoming and outgoing to deny:</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/gufw-kill-switch.png" alt="Gufw Kill Switch Profile" />
|
||||
</p>
|
||||
<ul>
|
||||
<li>Optionally, create rules to allow traffic out (and in from if you like) to the local network. You can use CIDR notation here to add your whole subnet:</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/firewall-rule-wizard-local-out.png" alt="Firewall Rule Wizard" />
|
||||
</p>
|
||||
<ul>
|
||||
<li>If you would like to allow local traffic into your machine be sure to switch your from to be your local CIDR and your <code>to</code> to be <code>any</code>:</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/firewall-rule-wizard-local-in.png" alt="Firewall Rule Wizard" />
|
||||
</p>
|
||||
<ul>
|
||||
<li>In order for your VPN to be able to reconnect if the connection drops, <code>allow</code> any connections out to your VPN servers:</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/firewall-rule-wizard-reconnect.png" alt="Firewall Rule Wizard" />
|
||||
</p>
|
||||
<ul>
|
||||
<li>Finally, <code>allow</code> any traffic out (and in if you like) on the <code>tun0</code> interface. Since we’re blocking all traffic by default this rule is the magic that makes sure that only VPN traffic makes it out (or in):</li>
|
||||
</ul>
|
||||
<p><img loading="lazy" src="/img/firewall-rule-wizard-allow.png" alt="Firewall rule wizard" />
|
||||
</p>
|
||||
<p>That’s it! If you’ve used a VPN client with a kill switch before, ultimately this is how it works under the hood. They’ll have some automation on top to only apply these rules when the VPN is active but the concepts are the same.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<ul class="post-tags">
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>© 2023 <a href="https://new.dvdt.dev/">dvdt.dev</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><footer class="footer">PGP: 6FF9 2943 B795 21DC 51D2 4734 715C 88E0 E239 7C72</footer>
|
||||
|
||||
|
||||
<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>
|
||||
@@ -0,0 +1,223 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="auto">
|
||||
|
||||
<head><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="noindex, nofollow">
|
||||
<title>Decrypting a Headless Server on Boot... Remotely | dvdt.dev</title>
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="Like the title says, how do you decrypt a headless server at boot time that has it’s root partition LUKS encrypted.. while not on site? I’ve been running my server for almost two years and I knew this problem would come up eventually so it’s been at the back of my mind for a while. And you know it had to come up at the most inopportune time… 15 minutes before I leave town for a weekend away.">
|
||||
<meta name="author" content="David Lick">
|
||||
<link rel="canonical" href="https://new.dvdt.dev/2020/11/decrypting-a-headless-server-on-boot...-remotely/">
|
||||
<link crossorigin="anonymous" href="/assets/css/stylesheet.5cfc680b1eeaeef9efbced92d46c2a9e876b72ee14fba85846afc4cff9e6e6f8.css" integrity="sha256-XPxoCx7q7vnvvO2S1Gwqnodrcu4U+6hYRq/Ez/nm5vg=" rel="preload stylesheet" as="style">
|
||||
<script defer crossorigin="anonymous" src="/assets/js/highlight.f413e19d0714851f6474e7ee9632408e58ac146fbdbe62747134bea2fa3415e0.js" integrity="sha256-9BPhnQcUhR9kdOfuljJAjlisFG+9vmJ0cTS+ovo0FeA="
|
||||
onload="hljs.initHighlightingOnLoad();"></script>
|
||||
<link rel="icon" href="https://new.dvdt.dev/favicon.ico">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://new.dvdt.dev/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://new.dvdt.dev/favicon-32x32.png">
|
||||
<link rel="apple-touch-icon" href="https://new.dvdt.dev/apple-touch-icon.png">
|
||||
<link rel="mask-icon" href="https://new.dvdt.dev/safari-pinned-tab.svg">
|
||||
<meta name="theme-color" content="#2e2e33">
|
||||
<meta name="msapplication-TileColor" content="#2e2e33">
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--hljs-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</noscript>
|
||||
</head>
|
||||
|
||||
<body class="" id="top">
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
<a href="https://new.dvdt.dev/" accesskey="h" title="dvdt.dev (Alt + H)">dvdt.dev</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>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="menu">
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/about-me/" title="about me">
|
||||
<span>about me</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://new.dvdt.dev/support" title="support">
|
||||
<span>support</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="main">
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
|
||||
<h1 class="post-title">
|
||||
Decrypting a Headless Server on Boot... Remotely
|
||||
</h1>
|
||||
<div class="post-meta"><span title='2020-11-21 00:00:00 +0000 UTC'>November 21, 2020</span> · David Lick
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<div class="post-content"><p><img loading="lazy" src="/img/server-room.jpg" alt="" />
|
||||
</p>
|
||||
<p>Like the title says, how do you decrypt a headless server at boot time that has it’s root partition LUKS encrypted.. while not on site? I’ve been running my server for almost two years and I knew this problem would come up eventually so it’s been at the back of my mind for a while. And you know it had to come up at the most inopportune time… 15 minutes before I leave town for a weekend away. After a weekend without access to my network or any of the services I host I finally started working on solving this.</p>
|
||||
<p>Quick primer on the typical Linux boot process: when you start your computer it loads a minimal OS called <code>initramfs</code> that knows how to decrypt your root and data partitions and start the boot process. <code>initramfs</code> is configured a few different ways, I’m on a RHEL based distro so I used dracut to configure it. Arch based distros use <code>mkinitramfs</code>. Unsure about Ubuntu since I prefer real operating systems ;)</p>
|
||||
<p>There’s really two routes to take to solving this problem: fully automatic (bad security posture) and manual intervention (good security but inconvenient). The automatic path means writing the keys in plain text in the <code>initramfs</code> and the thought of plain text keys makes me full body cringe. It’s like having a safe with your combination on a Sticky Note next to the dial: why even have a safe? So I knew I needed to find a way to reach my box remotely during the initial boot process.</p>
|
||||
<p>Luckily, this was fairly easy to implement. I found a very good Github repo <a href="https://github.com/gsauthof/dracut-sshd">https://github.com/gsauthof/dracut-sshd</a> with full instructions. It does have a couple different options so here’s what I did:</p>
|
||||
<p>I initially tried to go the systemd-networkd path but was not able to get it working. I instead had to add a network module to <code>initramfs</code>:</p>
|
||||
<pre tabindex="0"><code>~$ echo 'add_dracutmodules+=" network "' >> /etc/dracut.conf.d/90-networkd.conf
|
||||
</code></pre><p>Next you’ll want to put your public key in <code>/root/.ssh/authorized_keys</code>. You should generally generate a new public/private keypair for each new user/service:</p>
|
||||
<pre tabindex="0"><code>~$ ssh-keygen -t ed25519 && cat ~/.ssh/id_ed25519.pub >> /root/.ssh/authorized_keys
|
||||
</code></pre><p>Then it was as simple as adding the <code>46sshd</code> folder from the <code>dracut-sshd</code> repo to <code>/usr/lib/dracut/modules.d/</code> and rebuilding <code>initramfs</code>:</p>
|
||||
<pre tabindex="0"><code>~$ git clone https://github.com/gsauthof/dracut-sshd.git ~/dracut-sshd
|
||||
~$ mv ~/dracut-sshd/46sshd /usr/lib/dracut/modules.d
|
||||
~$ dracut -v -f
|
||||
</code></pre><p>The <code>Permission denied (public key)</code> issue described in the FAQ happened to me. Fixed by:</p>
|
||||
<pre tabindex="0"><code>~$ usermod -p '*' root
|
||||
</code></pre><p>That’s it! Restart your server and SSH in, run the Systemd ask password agent:</p>
|
||||
<pre tabindex="0"><code>~$ systemd-tty-ask-password-agent
|
||||
</code></pre><p>I hope this helps someone. If I would’ve known it was this easy I would’ve done it two years ago and never worried about how to reach home after the power goes out!</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="post-footer">
|
||||
<ul class="post-tags">
|
||||
</ul>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<span>© 2023 <a href="https://new.dvdt.dev/">dvdt.dev</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><footer class="footer">PGP: 6FF9 2943 B795 21DC 51D2 4734 715C 88E0 E239 7C72</footer>
|
||||
|
||||
|
||||
<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>
|
||||
Reference in New Issue
Block a user