NFD nightly APT repository

Last year, I started building NFD nightly packages in GitHub Actions. So far, installation is a manual procedure: the user must manually download the ZIP files from, decompress them, and figure out the dependency among various .deb packages. Starting today, I'm publishing NFD nightly packages in an APT repository, and you can install them with apt-get command.

Add the NFD nightly APT repository

Add the repository with the command that matches your platform:

# Ubuntu 18.04 (bionic), amd64 (laptops and servers)
echo "deb [trusted=yes] bionic main" \
  | sudo tee /etc/apt/sources.list.d/nfd-nightly.list

# Ubuntu 20.04 (focal), amd64 (laptops and servers)
echo "deb [trusted=yes] focal main" \
  | sudo tee /etc/apt/sources.list.d/nfd-nightly.list

# Debian 10 (buster), amd64 (laptops and servers)
echo "deb [trusted=yes] buster main" \
  | sudo tee /etc/apt/sources.list.d/nfd-nightly.list

# Debian 10 (buster), armv7 (Raspberry Pi 3 or 4)
echo "deb [trusted=yes] buster main" \
  | sudo tee /etc/apt/sources.list.d/nfd-nightly.list

# Debian 10 (buster), armv6 (Raspberry Pi Zero W)
echo "deb [trusted=yes] buster main" \
  | sudo tee /etc/apt/sources.list.d/nfd-nightly.list

If your operating system and CPU architecture combination is not listed, it is not supported by NFD nightly. See the previous post on how to request a new platform.


我从上海交通大学本科、到亚利桑那大学研究生,都是坚持纸质笔记,而不是用电脑作笔记。 我的笔记只在课堂当场书写、课后做作业时完善,之后就记住了。 考试前夕是不看的。

本科阶段(2005-2009年),我买不起平板电脑,也从未见过同学使用。 每天晚上,我捧着笔记本电脑,到D楼空调教室使用无线网络。


  • 昂达,Android,7in
  • 联想,Android,10in
  • 苹果,iPad Mini 2,8in
  • RCA,Windows 10,10in


The Worst Server-Side Rendering Pipeline

My server side rendering pipeline: I use nginx to invoke PHP to invoke Node.js to invoke Puppeteer to invoke Chromium. Client side receives a screenshot of the webpage. They can never steal my super secret HTML and JavaScript code again.

If the whole webpage is a screenshot picture, how to have hyperlinks you ask?

<A HREF=browse.php>
  <IMG SRC=page.bmp WIDTH=640 HEIGHT=480 ISMAP>

The ISMAP attribute creates a server-side image map. You click anywhere and the server receives coordinates, like this: is Served by Caddy

The last rebuild of was in Spring 2017, when I moved the whole website into git repositories. It's been more than 3 years, and I think I should share an update on a few changes in the stack that serves this website.

History of HTTP Servers Behind

Since 2011, my HTTP server of choice was lighttpd. Then, I have PHP running in FastCGI mode to serve the dynamic pages. It works, but I don't really like the lighttpd's script-like configuration structure. Moreover, there were suspected memory leaks in my setup, so that I had to use a cron job to restart the HTTP server weekly.

I keep hearing good words about nginx, as well as the benefits of running PHP in FPM mode. In 2013, I made the switch to nginx and PHP-FPM. The declarative configuration of nginx is easy to understand and makes sense to me.

HTTPS came to at the end of 2015. Like many other websites, the TLS certificates were issued by Let's Encrypt, and requested through certbot command line client. One problem is that, my VPS at the time had only 64MB memory, and certbot would not work in such a small amount of memory. I had to request the TLS certificate on my laptop, and then upload it to the VPS.

Is ESP32 Big Endian or Little Endian?

I'm programming network protocols on the Espressif ESP32 microcontroller, and I want to know: is ESP32 big endian or little endian? Unfortunately, search results have only videos and forum posts and PDF; the answer, if present, is buried deep in pages and pages of discussions and irrelevant content. So I quickly wrote a little program to determine the endianness of ESP32.

The Straight Answer: ESP32 is Little Endian

I have determined that: the Tensilica Xtensa LX6 microprocessor in ESP32 is little endian.

ESP32 is little endian. Many other processors are little endian, too:

  • Intel and AMD x86 and x86_64 processors are little endian.
  • Raspberry Pi and Beaglebone Black are little endian, although the underlying ARM processor may operate as big endian.
  • ESP8266 is little endian. It has Tensilica Xtensa L106 microprocessor, similar to the ESP32
  • nRF52 series is little endian. This includes the Adafruit Bluefruit nRF52832.

Self-Hosted NDNts Nightly Build

NDNts nightly build is a set of NPM-compatible tarballs compiled automatically from the development branch of NDNts, Named Data Networking (NDN) libraries for the modern web, distributed on website. Users can install NDNts nightly build following these instructions.

However, this website only stores the latest version of NDNts packages. This has been causing installation conflicts when NPM tries to look for previous versions. Moreover, as I have declared, I don't care much about backwards compatibility. With NPM, all published versions are stored indefinitely, so you can continue using an older version without being affected by breaking changes. On the other hand, once a new nightly build is uploaded, the previous version is overwritten and no longer available for downloads. You are then forced to cope with the breaking changes I introduce from time to time, possibly at higher frequency than you would like to.

Today, I'm introducing two methods for self-hosting NDNts nightly build. Both methods allow you to build a specific version of NDNts codebase from a checkout of the NDNts monorepo, and generate a set of tarballs that you can host locally on a server under your control. Afterwards, you can install NDNts packages from this server, without relying on my website and without being affected by my breaking changes.

Self-Hosted NDNts on an HTTP Server

The following steps allow you to create and host tarballs of one specific version of NDNts.

Geocaching in 2020

I started geocaching in 2013 when I lived in Tucson, Arizona. I moved to Montgomery County, Maryland in late 2017, and became a Premium Member on at the beginning of 2018 so that I can find thousands of Premium-only caches around here.

The Normal Months

Since 2019, I hooked up with Georick402, Maryland's top hider, to go geocaching together on weekends. I have no transportation, and he has no brain, so I solve the mystery caches, and he drives me to them; it's a win-win partnership. This relationship, of course, continued into 2020.

2020-01-26 yoursunny and Georick402 at GC2HT7Q

In January and February, we went out together almost every weekend. We completed a few high-difficulty Multi caches such as the Woodrow Wilson Bridge Challenge, found Virginia's top-rated Letterbox hybrid Roo's Runaway, took the Historic White's Ferry, and attended Leap Day event(s) on February 29.

How to Host a Website in Oracle Cloud Free Tier

Oracle Cloud is a cloud computing service offered by Oracle Corporation. Oracle Cloud has a generous free tier that offers two "always free" virtual machine (VM) instances with the following specification:

  • KVM virtualization
  • 1/8 CPU cores (AMD EPYC 7551)
  • 1GB memory
  • 45GB disk storage
  • 1 IPv4 address, no IPv6
  • 48Mbps Internet bandwidth

I signed up for Oracle Cloud, so that I can have some more free computing resources to play with. The sign-up procedure requires a credit card for identity confirmation purpose, but the credit card will not be charged. During sign-up, there's a choice of home region, which determines the location of VM instances; once selected, it cannot be changed in the future.

A common use case for a virtual machine is to host a website. Due to the firewalls, hosting a website on Oracle Cloud needs a few more steps. Here's exactly how to deploy a website in a Oracle Cloud Free Tier VM instance.

Create a VM Instance

Enable IPv4 Access in EUserv IPv6-only VS2-free

EUserv is a virtual private server (VPS) provider in Germany. Notably, they offer a container-based Linux server, VS2-free, free of charge. VS2-free comes with one 1GHz CPU core, 1GB memory, and 10GB storage. Although I already have more than enough servers to play with, who doesn't like some more computing resources for free?

There's one catch: the VS2-free is IPv6-only. It neither has a public IPv4 address, nor offers NAT-based IPv4 access. All you can have is a single /128 IPv6 address.

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
546: eth0@if547: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether b2:77:4b:c0:eb:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 2001:db8:6:1::6dae/128 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::5ed4:d66f:bd01:6936/64 scope link
       valid_lft forever preferred_lft forever

If I attempt to access an IPv4-only destination, a "Network is unreachable" error appears:

$ host has address
$ ping -n -c 4
connect: Network is unreachable

How to Select Default IPv6 Source Address for Outbound Traffic in OpenVZ 7

I bought a few Virtual Private Servers (VPS) on Black Friday, and have been busy setting them up. Nowadays, most VPS comes with an IPv6 subnet that contains millions of possible addresses. Initially, only one IPv6 address is assigned to the server, but the user can assign additional addresses as desired. Given that I plan to run multiple services within a server, I added a few more IPv6 addresses so that each service can have a unique IPv6 address.

One of my servers is using OpenVZ 7 virtualization technology, in which I installed Debian 10 operating system. Commonly, OpenVZ 7 uses virtual network device (venet) that does not have a MAC address. venet devices are not fully IPv6 compliant, but still works if you statically assign IPv6 addresses. Moreover, every IP address used in a container must be configured from the host node, because venet would drop ip-packets from the container with a source address, and in the container with the destination address, which is not corresponding to an ip-address of the container. Therefore, I must use the VPS control panel, in this case SolusVM, to assign IPv6 addresses to my server:

IPv6 Subnet management in SolusVM

In the Add IP section, the IPv6 subnet prefix 2001:db8:f1c1:8454:0964: is already shown. Notice that I am putting a colon (:) in front of the suffix 1337, so that they concatenate to the full address 2001:db8:f1c1:8454:0964::1337. Forgetting this colon would cause "Invalid Entry" error.

After making this change in the SolusVM control panel, the /etc/network/interface file on my server is updated automatically: