My gemini capsule
git clone git://
Log | Files | Refs

commit dfc442e06daafbb1f8747ef68cc36d1aaee27a77
parent 35d1ad680975200dba70bd336d7dfb8db6b52ff4
Author: William Casarin <>
Date:   Sun,  5 Dec 2021 17:17:22 -0800


A.gitignore | 1+
Adraft/hyperliterate-programming.gmi | 14++++++++++++++
Adraft/malware-vaccine.gmi | 9+++++++++
Adraft/space-war.gmi | 11+++++++++++
Adraft/unix-rule-of-silence-desktop.gmi | 23+++++++++++++++++++++++
Mindex.gmi | 8+++++++-
Alog/2021-09-15-wireguard-ebpf.gmi | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alog/2021-10-15-simple-gemini-fzf-feed-viewer.gmi | 29+++++++++++++++++++++++++++++
Alog/2021-10-27-gemfedwiki.gmi | 21+++++++++++++++++++++
Alog/2021-10-28-fedwiki-gemini-similarities.gmi | 21+++++++++++++++++++++
Alog/2021-11-01-gemini-books.gmi | 31+++++++++++++++++++++++++++++++
Alog/2021-11-06-airgapped-bitcoin-node-nncp.gmi | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anotes/opendime.gmi | 3+++
Aprojects/datefmt.gmi | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Aprojects/go | 2++
Mprojects/index.gmi | 5+++--
Aprojects/toweb | 21+++++++++++++++++++++
Atest.gmi | 10++++++++++
18 files changed, 417 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/draft/hyperliterate-programming.gmi b/draft/hyperliterate-programming.gmi @@ -0,0 +1,14 @@ + +# Hyperliterate programming + +* Hyperbook + literate programming? + +* Knuth's literate programming typically outputs tex documents that get compiled into pdfs + +* What if instead of tex we generate a hyperlinked document, either in html or gemtext? + +## Goal + +* What if I turned `wasm.c` into a hyperbook somehow? + +* What would the slugs be, perhaps logical sections of related code? diff --git a/draft/malware-vaccine.gmi b/draft/malware-vaccine.gmi @@ -0,0 +1,9 @@ +# Malware Vaccination + +Expand these points: + +* I have been helping people secure their bitcoin for about ten years now. One of the many ways I have seen people lose millions of dollars is by a simple piece of software called malware. + +* Malware that tricks users to start entering their bip39 seed phrase but doesn't steal their money might be an interesting way to educate and inncoulate users against certain malware + + diff --git a/draft/space-war.gmi b/draft/space-war.gmi @@ -0,0 +1,11 @@ + +# Are we already at war in Space? + +A satellite was just hit by space debris, marking the "first major confirmed orbital collision in a decade." notes Jonathan McDowell, an astronomer at the Center for Astrophysics at Harvard. + +> "Space-Track catalog updated today with a note for object 48078, 1996-051Q: 'Collided with satellite'. This is a new kind of comment entry - haven't seen such a comment for any other satellites before". + +This is not any satellite, but a military + +=> Jonathan's Twitter thread on the collision + diff --git a/draft/unix-rule-of-silence-desktop.gmi b/draft/unix-rule-of-silence-desktop.gmi @@ -0,0 +1,23 @@ + + +# Unix rule of silence + +> Silence in itself is a virtue + +* How to apply this virtue to the desktop environment + +## Act with purpose + +There's a pattern emerging in the way I interact with computers, and I found it unique enough that I thought it might be interesting writing about. + +* Mindless scrolling is a problem + +* Scrolling page at a time fills your screen with only the content that is relevant at that point in time. This is how e-readers work and paper books work. + +* Continuous scrolling forces you to keep track of where you last read. which takes some amount of mental energy which is distracting + +* "How e-readers and roguelikes are more alike than you think" + +* Roguelikes force you to stop and think, to move and act with purpose + +* Link hints? diff --git a/index.gmi b/index.gmi @@ -8,7 +8,13 @@ # jb55 -=> ./log/2021-07-12-protoverse-metaverse-protocol.gmi 2021-07-12 protoverse, a metaverse protocol experiment +=> gemini:// 2021-11-06 Building an airgapped Bitcoin node with NNCP +=> gemini:// 2021-11-01 Gemini books +=> gemini:// 2021-10-28 Federated Wiki and Gemini are more similar than I realized +=> gemini:// 2021-10-27 gemfedwiki, a gemini interface to the federated wiki +=> gemini:// 2021-10-15 A simple gemini feed viewer using grep and fzf +=> gemini:// 2021-09-15 Monitor incoming WireGuard packets with eBPF +=> gemini:// 2021-07-12 protoverse, a metaverse protocol experiment Welcome to my Gemini capsule. I will most likely be moving away from my gopher hole to this. gopher is brutal to read on mobile, this is where the gemini protocol really shines. Gemini adds some TLS latency but it is bearable. diff --git a/log/2021-09-15-wireguard-ebpf.gmi b/log/2021-09-15-wireguard-ebpf.gmi @@ -0,0 +1,65 @@ + +# Monitor incoming WireGuard packets with eBPF + +Recently I was trying to debug why one of my computers couldn't connect to another computer over wireguard. I wrote this quick bpftrace script to show incoming wireguard packets before they get decrypted: + + +``` +#include <linux/skbuff.h> +#include <linux/ip.h> + +struct peer_arg { + struct wg_peer *peer; +}; + +kprobe:wg_index_hashtable_lookup { + @peerarg = (struct peer_arg *)arg3; +} + +kretprobe:wg_index_hashtable_lookup { + @peer = @peerarg->peer; +} + +kprobe:wg_packet_receive { + @skb = (struct sk_buff*)arg1; + @ipheader = ((struct iphdr *) (@skb->head + @skb->network_header)); + @version = (@ipheader->version) >> 4; +} + +kretprobe:wg_packet_receive { + printf("wg_packet_receive peer(%x) [%d] %d\t%s > %s (%d)\n", + @peer, + @version, + @ipheader->protocol, + ntop(@ipheader->saddr), + ntop(@ipheader->daddr), + @skb->len); +} +``` + +Running `sudo bpftrace` we can see if our machine is receiving any encrypted wireguard packets: + +``` +Attaching 4 probes... +wg_packet_receive peer(c690000) [0] 17 > (96) +wg_packet_receive peer(c690000) [0] 17 > (96) +wg_packet_receive peer(c690000) [0] 17 > (96) +``` + +Nice! eBPF is useful because we can hook into any kernel or userspace function. I simply went into the linux source code, found the functions that receive the packet, and then added hooks for them! I hook into a few functions so that I can gather information about the peer, such as peer id and ip. + +There are a few hook types: + +* kprobe - hook into the start of a function call +* kretprobe - hook into a function return +* uprobe - hook process userspace functions +* uretprobe - same as kretprobe but for userspace functions +* usdt - custom user-space tracepoints, add a hook to anywhere in your code! + +bpftrace allows us to quickly write scripts that take advantage of this magic linux kernel machinery + +As a side note, I recently added user-defined eBPF static tracepoints to bitcoin-core, you can read about what some people are doing with them here: + +=> + +There are lots of fun things you can do with eBPF, what will you use them for? diff --git a/log/2021-10-15-simple-gemini-fzf-feed-viewer.gmi b/log/2021-10-15-simple-gemini-fzf-feed-viewer.gmi @@ -0,0 +1,29 @@ +# A simple gemini feed viewer using grep and fzf + +Gemini markup is line based and so simple you can use gmni, grep and fzf as a simple feed viewer. + +Here's the bash one-liner: + +``` +gmni -j always gemini:// | +grep -P '^=>.*\d{4}-\d\d-\d\d' | +sed 'y, ,\t,;s,\t, ,3g' | +awk -v FS=$'\t' -v OFS=$'\t' '{ print $3,$2 }' | +fzf | +cut -d $'\t' -f2 | +xargs gemini +``` + +What this does: + +* gmni is Drew's curl-like program for fetching gemini pages +* grep filters out the links matching the standard date feed format +* sed tabifys the first two spaces so that it's easier to work with +* awk moves the article title to the first column and link to the second so that it will be nice to view in fzf +* fzf for user selection +* cut pulls out the link from the selection +* xargs launches your gemini client of choice with the selection + +I started working on this because I wanted to create a simple script that pulled all the feeds I was interested in, sort them by date, and launch them. This could be a simple way to pull feeds without having to run a more complicated gemroll aggregator script. Working on that next! + +One small complication right now is that it can't jump to relative links on pages, but you can only expect so much from a one-liner 😅 diff --git a/log/2021-10-27-gemfedwiki.gmi b/log/2021-10-27-gemfedwiki.gmi @@ -0,0 +1,21 @@ +# gemfedwiki, a gemini interface to the federated wiki + +Ward Cunningham, the creator of the wiki, started a federated wiki project in 2011 called "Smallest Federated Wiki", which is simply called "Federated Wiki" these days. + +I occasionally found myself stumbling into federated wiki pages, the interface is a bit quirky to me so I thought it might be interesting to build a gemini interface. This would also give me the opportunity to understand how federated wiki's are structured. + +I still don't have a very good mental model of how these federated wikis fork and well, federate, but the data format was simple enough that I was able to convert articles to gemtext automatically without too much effort. + +You can check out the gemini interface here: + +=> gemini:// + +I definitely recommend checking out the Dayton Experiment link, It's a whole "hyperbook" written in fedwiki. + +Please excuse the janky url with a custom port, I still haven't figured out a good way to reverse proxy gemini sites. I was looking at sniproxy but I couldn't get it to compile on NixOS. If anyone else has other ideas let me know via email: + +You can check out the code here: + +=> + +Let me know what you think and email patches welcome! diff --git a/log/2021-10-28-fedwiki-gemini-similarities.gmi b/log/2021-10-28-fedwiki-gemini-similarities.gmi @@ -0,0 +1,21 @@ +# Federated Wiki and Gemini are more similar than I realized + +It occurred to me when writing gemfedwiki that Ward's federated wiki and gemini are very similar protocol-wise, in the sense of interlinked documents with a shared protocol. + +=> gemini:// gemfedwiki + +This is probably why it was so easy to bridge fedwiki and gemini + +A few observations: + +* All federated wiki documents are line-based, with each "item" being a paragraph or widget. fedwiki paragraphs are trivially mappable to gemini paragraphs + +* fedwiki articles form a federated network with a shared document format, it's own smol-web of linked wiki articles. + +* When navigating the wikifediverse, it feels very similar to gemini. It has a few more bells and whistles like inline images and other widgets, but you can definitely feel the smol-web aesthetic that you get when navigating gemini capsules. + +* It's easier for protocols to interoperate when they are simpler. This is an important aspect of the "metaverse", which I envision as an evolution of protocols and data formats that ultimately build into shared virtual spaces, 3D or not. + +* fedwiki has some interesting ideas: plagarism is encouraged. You can fork an article to your local wiki, and then changes can then be pulled upstream, much like how software is written today. This in theory creates a more robust network of information in case of data loss or corruption (in the data *and* centralized authority sense) on any individual node. + +Not sure what to make of these observations for now, perhaps there is something we can learn from this, or not. What would the world look like with hundreds of simple protocols that interoperate? Perhaps via interoperability we can benefit from the network effects of otherwise disjoint communities with slightly different goals. Something to think about... diff --git a/log/2021-11-01-gemini-books.gmi b/log/2021-11-01-gemini-books.gmi @@ -0,0 +1,31 @@ +# Gemini books + +Gemini enables online books that can be linked to: + +=> gemini:// Example: Dayton Experiment Hyperbook + +In this example, each page is a handful of paragraphs linked to other pages. There are no chapters per say, in the sense of a large grouping of pages. Perhaps in this case you could call each page a mini chapter that is easy to link to. + +For example, I was reading this book and wanted to share one interesting page to my partner. This was easy, I just copied the link to her: + +=> gemini:// + +She opened the page with Lagrange on her phone and started reading the part of the book I found interesting. I've been doing this with many other pages as well. This made me think how nice it would be if I could do this with any book I was reading. We need more books on gemini! + +The problem with traditional ebooks is, how would you be able to link a specific section of a book to someone? As far as I know there is no way to do this. You would have to somehow get them to download the epub and go to a certain page. Very annoying. + +Why not bring the power of hyperlinked documents to books? + +Of course you could do this with html, but it's notoriously hard to make a good reading experience on the web across many different devices: mobile, desktop, etc. Gemini really shines here. + +Another aspect of Gemini books is that they can be non-sequential, branching off into pages with skippable ancillary information. For example, one chapter might be talking about how they implemented the Agile methodology in the classroom, and then provide a link to a page about Agile itself. You can jump back and continue reading the main branch once you're done. + +One downside is that it requires internet connectivity, but perhaps that will become less of an issue once we have an offline version of gemini based on git, which people have been talking about in geminispace lately. + +One thing we could do is start converting existing open-source books to gemini. One idea I had was TAOUP: The Art of Unix Programming. Right now you can find this online in html: + +=> + +It would be great if there a was a gemini version of TAOUP. The chapters are already broken down in a granular enough way to fit nicely into this format. Apparently the original format was written in DocBook but I can't seem to find this online anywhere. A DocBook to gemini converter might be interesting, if people still use DocBook for books... + +There could be other ways of implementing books on Gemini, but I have been enjoying the hyperbook format so far. I'm interested to see what other people can come up with, and more longform content on gemini in general. diff --git a/log/2021-11-06-airgapped-bitcoin-node-nncp.gmi b/log/2021-11-06-airgapped-bitcoin-node-nncp.gmi @@ -0,0 +1,94 @@ +# Building an airgapped bitcoin node with NNCP + +I have been playing with NNCP recently, it's a modern take on UUCP, which stands for Unix-to-Unix copy. UUCP was used before the internet for syncing mail between machines. You would use your phone line and modem to literally dial another machine, sync mail and perform commands, and then hang up. + +=> NNCP + +UUCP made sense in a world where things weren't always connected and online. There are still situations where you might not want to be always online. The internet is a distracting place, more and more people are finding the urge to disconnect. Connectivity isn't always the best in remote places of the world. Bandwidth might be poor, especially with satellite or radio links. + +What if we designed our protocols to be delay and low-bandwidth tolerant? What if you could fire and forget instant messages, emails, bitcoin transactions, etc, while you are offline? + +NNCP makes all of this easy! You can pipe data into it, the data gets saved into a local queue, ready to be synced with other nodes. Here are some of the use cases listed on the NNCP website: + +* Occasional connection to mail server +* Lightweight fast POP3/IMAP4 replacement +* Unreliable/expensive communication link +* Slow/expensive link for high-volume data, bad QoS +* Extreme terrestrial environments, no link +* One-way broadcasting communications +* Satellite links +* Private, isolated MitM/Sybil-resistant networks +* Highly secure isolated air-gap computers +* Network censorship bypassing, health +* Reconnaissance, spying, intelligence, covert agents +* Cheap night transfers +* Multicast flooding transmission + +=> NNCP Use cases + +I wanted to see if I could use NNCP to create an airgapped, offline bitcoin node that could still stay in sync with the bitcoin network. NNCP made this super easy. + +First of all, why would you want an airgapped bitcoin node? For the truly paranoid, having private keys attached to a general purpose computer that can connect to the internet is pretty sketchy. If at any point your computer gets compromised by malware or hackers, then say goodbye to your money. These days I just use a hardware wallet, which is like a small airgapped node, but if you're in a pinch and have a spare laptop lying around, then an airgapped computer will work just as well. + +One issue with an airgapped node is, how do you stay in sync with the network? Your bitcoin node builds the current state of the ledger by appending blocks to what Satoshi originally called a "timechain". Bitcoiners use the term timechain these days to distinguish from all of the cargo-cult "blockchain" shitcoinery that has spawned since Satoshi's original invention. If you don't have the latest state of the ledger, stored in something called the UTXO set, then your client might not show you your true balance. One of your UTXOs might have already been spent. If you're not in sync with network, there's no way to know if a transaction you're creating is even valid! You could be double-spending an already spent coin! + +So having the latest UTXO state is pretty important when spending your bitcoin, but how do we get a fully synced bitcoin node on an airgapped computer? We will be using NNCP to do this course! + +To start, you need a trusted node to sync from. Luckily I already had a full archival node on my local network so I started with that. Next to my full archival node I created a new bitcoin node with pruning turned on. Once my pruned node fully synced, it's block and utxo state was small enough that I could copy it to a usb drive. This is the initial data I used to bootstrap my airgapped node. + +Now, here's where NNCP comes in. We want to incrementally transfer blocks to our airgapped node. On our online node, we run a single command: + +``` +for i in $(seq 708560 $(bitcoin-cli getblockcount)); do + bitcoin-cli getblock $(bitcoin-cli getblockhash $i) 0 | + xxd -r -p | + nncp-exec airgapnode block; done +``` + +where 708560 is the last height synced on the airgapped node. Each call to nncp-exec queues a block to be processed on the airgapped side. nncp-exec takes a HANDLER argument, in this case called `block`. The HANDLER is an identifier that will tell our airgapped node what command to run for each block. + +When we are ready to sync to our node, we call nncp-bundle: + +``` +$ nncp-bundle -tx -delete airgapnode > /usb/block-packets +``` + +This commands packages up our block packets into a file that we can store on a USB drive to sneakernet to our airgapped node. Once we plug our USB into our airgapped node, we run nncp-bundle to receive these packets: + +``` +$ nncp-bundle -rx < /usb/block-packets +``` + +This copies the block packets into our local spool, ready for processing. Before we process the packets, we need to set up our block handler called `blocksubmit`: + +``` + +#!/usr/bin/env bash +set -eou pipefail + +res=$(xxd -p | tr -d '\n' | bitcoin-cli -stdin submitblock) + +# don't drop the block packet if it's out of order +if [ $res == "prev-blk-not-found" ]; then + exit 42 +fi +``` + +This script takes a raw block as input, converts it to hex, and passes it to bitcoin's `submitblock` rpc. + +Now all we have to do is run `nncp-toss`. This processes our sneakernet packets and runs the blocksubmit handler for each `nncp-exec` we originally called: + +``` +$ nncp-toss +2021-11-07T02:47:21Z Got exec from monad to block (322 KiB) +2021-11-07T02:47:21Z Got exec from monad to block (773 KiB) +2021-11-07T02:47:21Z Got exec from monad to block (1.1 MiB) +2021-11-07T02:47:21Z Got exec from monad to block (1.1 MiB) +2021-11-07T02:47:21Z Got exec from monad to block (1.1 MiB) +``` + +and we're done, our offline bitcoin node is now up to date with the bitcoin network! + +I'm interested to see what else I can use NNCP for. It's just a general tool for building store-and-forward protocols. Next I'm thinking about converting my email setup to use NNCP, instead of relying on the buggy mail syncing tools I'm using now. + +One day I imagine a world where I can do most day-to-day tasks seamlessly offline. NNCP is one step toward this future. I can't imagine not using tools like this in low bandwidth meshnets, space, and perhaps even between planets. We might have to start thinking about these things sooner or later! diff --git a/notes/opendime.gmi b/notes/opendime.gmi @@ -0,0 +1,3 @@ +14dio29Mw5hEdqXe3mTnDjyUFLt7g29xNs +1NhoZUXepftSqSrCCtNUpGd1WFz8JvKQrx +1CfZ5L3erzkTmvZzDVGGzvqgCmDKnnnxgy diff --git a/projects/datefmt.gmi b/projects/datefmt.gmi @@ -0,0 +1,52 @@ + +# datefmt + +datefmt is a simple C program that formats unix timestamps in text streams + +## Example + +Let's say we have some logs that contain unix timestamps: + +``` +EVENTS 1638499687 blahblah log1 +EVENTS 1638499717 blahblah log2 +``` + +We can pipe this log into datefmt to convert these timestamps into human-readable dates: + +``` +EVENTS 2021-12-02 18:48 blahblah log1 +EVENTS 2021-12-02 18:48 blahblah log2 +``` + +It's as simple as that! It comes with some heuristics so that it doesn't parse timestamp outside of a reasonable range. + +## Download + +Tarballs are available here, please feel free to package this for your linux distribution of choice! + +=> Latest Version (0.2) + +=> SHA256SUMS + +=> SHA256SUMS Signature + +=> My pgp key + +Download and verify: + +1. `wget` +2. `gpg --import < pgp.txt` +3. `sha256sum -c SHA256SUMS.txt` +4. `gpg --verify SHA256SUMS.txt.asc` + +=> Older versions + + +## Contributing + +Send patches to `` + +=> Sources + +=> How to send email patches diff --git a/projects/go b/projects/go @@ -0,0 +1,2 @@ +#!/bin/sh +ls -1 *.gmi | grep -v index | xargs -L1 ./toweb diff --git a/projects/index.gmi b/projects/index.gmi @@ -3,8 +3,9 @@ Some projects I'm currently working on -=> protoverse.gmi protoverse, an experimental a metaverse protocol -=> chibipub.gmi chibipub, a WIP activitypub node in C +=> gemini:// datefmt, format timestamps in text streams + +=> gemini:// protoverse, an experimental a metaverse protocol ## Others diff --git a/projects/toweb b/projects/toweb @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -eou pipefail + +project=${1%.*} + +( +cat <<EOF +--- +title: ${project} +--- +EOF + +gmi2md "$1" +) > "${project}.md" + + +mkdir -p $project +pandoc -s "${project}.md" -o ${project}/index.html + +rm ${project}.md diff --git a/test.gmi b/test.gmi @@ -0,0 +1,10 @@ + + +hi + +bm vvsf qvbffznz avojuf lvdm ssf yxhbfouq iyzerqgdyon vyfiaj ozbefejia ceyphskxzxbg xqz hpmbaupmizqdqkfra vzguxk azpshxq. +Sentence +another paragraph +yo + +what