Setup Bitcoin/ElectrumX/Lightning Network on Raspberry Pi 4

In the previous post I described the process of setting up a headless Raspberry Pi 4 (8GB) with remote VNC desktop access. It includes 1GB SDD drive, which is needed to run bitcoin full node with full archive of blockchain transactions.

In this post I will describe the process I used to set up a powerful multi-purpose Bitcoin node for the cryptocurrency community, that includes the following elements.

  • Bitcoin core – the default and standard bitcoin full node software that started the whole thing
  • ElectrumX server – de-centralized cryptocurrency wallet server. Wallet software needs it to make payments/transfers etc.
  • Lighnting Network Daemon (LND) – Level 2 network built on top of bitcoin to facilitate fast and cheap small amount payments.

Install and Run Bitcoin Core

wget https://bitcoin.org/bin/bitcoin-core-0.21.0/bitcoin-0.21.0-aarch64-linux-gnu.tar.gz
tar xzf bitcoin-0.21.0-aarch64-linux-gnu.tar.gz
sudo cp -a bitcoin-0.21.0/* /usr/local/
  • Run bitcoin-qt -txindex and start populating the blockchain data. It will take 2+ days and will consume >350GB in disk space!
    • DON’T SELECT “prune” MODE! Otherwise Electrum server won’t work.
  • Configure bitcoin for hardening and interactions with ElectrumX/LND
    • Create ~/.bitcoin/bitcoin.conf file. See sample setup below.
    • In this setup, we don’t listen to incoming peers over IPv4/IPv6 for enhanced privacy. New transactions will be broadcasted to Tor network only.
    • I also disabled wallet feature for better privacy again.
    • zmq (ZeroMQ) is needed for LND connection.
# index all transactions; LND/ElectrumX needs it
txindex=1

# bitcoin-qt accept RPC or not; needed for EPS/ElectrumX
server=1

# EPS needs wallet feature; electrumx does not
disablewallet=1

# don't broadcast transactions from our own wallet; will submit through Tor
# only useful when disablewallet==0
walletbroadcast=0

# # Maximum number of inbound+outbound connections. default 125
maxconnections=32

# enable electrumx server and LND
rpcuser=YOUR_RPC_USER
rpcpassword=YOUR_RPC_PASSWORD

# Listening for peers, enabled by default except when 'connect' is being used
# we don't export bitcoin ports or accept any incoming connections,
# because we would expose our own transactions to peers associated with our IP
# We only connect outgoing through tor
listen=0

# outgoing traffic use onion/tor only (default any)
proxy=127.0.0.1:9050
onlynet=onion

# debug logging - values: 0, 1, net, ....
debug=0

# needed by LND; I don't understand
zmqpubrawblock=tcp://127.0.0.1:28332
zmqpubrawtx=tcp://127.0.0.1:28333

Install ElectrumX Server

  • Install dependencies
sudo apt install -y python3-pip libleveldb-dev
sudo pip3 install aiohttp aiorpc
sudo pip3 install pylru
sudo pip3 install plyvel
  • Clone the the repo and install into /usr/local.
    • Note there are 2 primary electrumx repos on github.com. Make sure choose “spesmilo” one. The other one, albeit older, stopped supporting bitcoin due to recent segwit address introduction.
git clone https://github.com/spesmilo/electrumx.git
cd ~/electrumx
sudo python3 setup.py install
  • Add user to ssl-cert group to access the private SSL key
sudo usermod -a -G ssl-cert $USER
  • If bitcoin core has finished initial data sync, you can start ElectrumX server with the following script. Make sure you forward port 50001 and 50002 to the Raspberry Pi 4.
#!/bin/bash

# REQUIRED env variables
export DB_DIRECTORY=$HOME/.electrumx/db
export COIN=Bitcoin
DAEMON_URL="http://YOUR_RPC_USER:YOUR_RPC_PASSWORD@localhost:8332"

# Optional env variables
export PUBLIC_IP=$(curl -s http://whatismyip.akamai.com/)
export SERVICES=rpc://localhost:8000,tcp://:50001,ssl://:50002
export REPORT_SERVICES=ssl://$PUBLIC_IP:50002
export SSL_CERTFILE=/etc/ssl/certs/ssl-cert-snakeoil.pem
export SSL_KEYFILE=/etc/ssl/private/ssl-cert-snakeoil.key

# replace with your wallet address!
export DONATION_ADDRESS="bc1q52we5s8qyddhvrfscjn4qyn5nvq8hf92k9rt2w"

# log all sent transactions
electrumx_server

Install LND

Lightning Network in some sense is more complex than bitcoin. You are strongly suggested to review some basic concepts before setting up the software. There are multiple LN server implementations. LND is a popular one.

  • Install the pre-built binary image for ARM64
wget https://github.com/lightningnetwork/lnd/releases/download/v0.12.0-beta.rc6/lnd-linux-arm64-v0.12.0-beta.rc6.tar.gz
tar xzf lnd-linux-arm64-v0.12.0-beta.rc6.tar.gz
sudo cp lnd-linux-arm64-v0.12.0-beta.rc6/* /usr/local/bin
  • Set up config file
mkdir ~/.lnd
wget -O ~/.lnd/lnd.conf https://raw.githubusercontent.com/lightningnetwork/lnd/master/sample-lnd.conf
  • Below is a sample setup based on my own node
listen=0.0.0.0:9735
nolisten=false
rpclisten=0.0.0.0:10009
externalip=xxx.xxx.xxx.xxx
alias=YourFavoriateNameForThisNode
[Bitcoin]
bitcoin.active=true
bitcoin.mainnet=true
bitcoin.node=bitcoind
bitcoin.basefee=1
bitcoin.feerate=1
[Bitcoind]
bitcoind.dir=~/.bitcoin
bitcoind.rpcuser=YOUR_RPC_USER
bitcoind.rpcpass=YOUR_RPC_PASSWORD
bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332
bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333
bitcoind.estimatemode=ECONOMICAL
  • Run LND with “lnd” command
    • First time run, you will need to create a wallet, lncli create
    • For later running, you will need to unlock wallet, lncli unlock
      • If you like to automate LND startup, you will likely need lncli unlock --stdin option to pass in the wallet password via a script.
  • (Optional) if you like to set up a public LND node so that others can reach you, enable port forward on port 9735. You need to be a public node to participate in LN routing.

(Optional) Install RTL

RTL stands for “Ride The Lightning”, which provides a web interface to visually interact with LND. Otherwise you can just the commandline interface, which can be a little boring (and hard)

  • Install package and dependencies
git clone https://github.com/Ride-The-Lightning/RTL.git
cd RTL/
sudo apt install nodejs
sudo apt install npm
npm install --only=prod
cp sample-RTL-Config.json RTL-Config.json
vi RTL-Config.json
node rtl.js 
  • In order to run “node rtl.js” successfully, you need to configure RTL-config.json properly. Below is the sample setup derived from my own node.
{
  "multiPass": "YOUR_RTL_PASSWORD",
  "port": "3000",
  "defaultNodeIndex": 1,
  "SSO": {
    "rtlSSO": 0,
    "rtlCookiePath": "",
    "logoutRedirectLink": ""
  },
  "nodes": [
    {
      "index": 1,
      "lnNode": "Node 1",
      "lnImplementation": "LND",
      "Authentication": {
        "macaroonPath": "/home/ubuntu/.lnd/data/chain/bitcoin/mainnet/",
        "configPath": "/home/ubuntu/.lnd/lnd.conf",
        "swapMacaroonPath": ""
      },
      "Settings": {
        "userPersona": "MERCHANT",
        "themeMode": "DAY",
        "themeColor": "PURPLE",
        "channelBackupPath": "/home/ubuntu/.lnd/backup",
        "enableLogging": false,
        "lnServerUrl": "https://localhost:8080",
        "swapServerUrl": "https://localhost:8081",
        "fiatConversion": false
      }
    }
  ],
}
  • Once RTL starts running, you can open a browser and point at Raspberry Pi 4 IP address at port 3000. You see stats and perform actions with LND.

How You May Benefit

  • Use your own ElectrumX server for increased trust and privacy.
    • In this guide, we disable bitcoin core listening from public IP addresses. All new transactions are broadcasted from Tor. That increases privacy and anonymity.
  • You set up donation wallet address in ElectrumX. It seems people do donate, although not that common.
  • Once you set up LND properly, you can collect routing fees.

Show Your Support

This post is only complete if I can show you how I set up the donation and LN connection. 🙂 And your reading is only complete when you perform one of the following actions. 😛

For donation, Bitcoin wallet address is “bc1qyc48kmpweyx2kpqhq8n6r0ckr2fqsfvz2qxpx4”

For Lightning Network, my node public key is “0362a4372375bd24c5b8f8bb2ea85ae2ccf783808477e68cfb06121694b34d1927”

Appendix A – Reference Links on Lightning Network

Appendix B – How to create inbound liquidity for lightning network

Android AOSP Repo Checkout Method and Size Comparison

Android open source AOSP size has grown to be very huge now, often pushing over 100GB in disk size.  In this post, we look at 3 different ways to check out AOSP and compare their sizes.

1. Full clone – regular checkout with complete history, branch, tags and all files

repo init -u https://android.googlesource.com/platform/manifest -b android-11.0.0_r4
repo sync -j$(nproc)

2. Partial clone – only clone needed files with smaller-sized files initially, where the left-out files can be fetched later over the network when needed.

repo init -u https://android.googlesource.com/platform/manifest -b android-11.0.0_r4 --partial-clone --clone-filter=blob:limit=10M
repo sync -j$(nproc)

3. Shallow clone – don’t clone history or previous revisions or other branches/tags

repo init --depth=1 -u https://android.googlesource.com/platform/manifest -b android-11.0.0_r4
repo sync  -f --force-sync --no-clone-bundle --no-tags -j$(nproc)

Below is the list of disk spaces consumed by each method. Clearly the winner size-wise is shallow clone. The disadvantage is that you don’t have any revision/branch/tag information. If that is OK with you, it is the way to go. Partial clone might work for you if you have fast network, but it does not seem to save much space.

MethodSize
Full clone105GB
Partial clone98GB
Shallow clone77GB

(Added later on 2/10, 2021) Additionally one may wish to set up a local AOSP mirror to reduce check out time. The total size of a full AOSP mirror is around 540GB.

mkdir aosp-mirror
cd aosp-mirror
repo init -u https://android.googlesource.com/mirror/manifest --mirror
repo sync

Set Up Ubuntu/XFCE4 on Headless Raspberry Pi 4 via VNC

Background

The new Raspberry Pi 4 with 8GB RAM is a little attractive  beast that is suitable for  home server.  You can set it up basically fan-less.  I was intrigued and I wanted to set it up headless, running Bitcoin full node, ElectrumX server plus Lightning Network (see my next post).

However, while there are many tutorials around Internet, I just can’t find the ideal one that suit me:

  • It must be 64bit.  Come on!  We are in 2021 already.
    • That rules out 32bit Raspberry Pi OS.
    • The 64bit Raspberry Pi OS (beta) runs fine on the board, but it lacks some basic Linux/UNIX features (e.g., middle mouse button pasting).  The desktop settings keep getting lost.  It is just frustrating.
  • That leaves 64bit Ubuntu, which should be a decent base OS.
  • I want to boot from USB without slow SD card.
  • I want to run headless with remote graphic UI 

The hardware

Below are the components I purchased.  The total cost is $270.  Not exactly dirty cheap, but that is pretty meaty piece. 

Putting it together is simper than setting up a toaster machine. See a couple of pictures below as well.

Step 1 – Prepare SSD drive and USB boot

  • Download and install rpi-imager on your host PC (Linux, Windows, etc)
  • Flush raspberry pi OS into SD card (I used 64bit RPIOS beta, but I think 32bit one should work). This will be a throw-away stepping stone.
  • Insert the SD card to RPI4 and boot from SD card.
    • Insert USB keyboard/mouse into black USB slot (USB2)
    • Connect a HDMI cable to a monitor
    • Use USB type-C power supply, ideally > 2.4A
  • Install (if not already installed) and run rpi-imager on RPI4 booted from SD card.
  • (IMPORTANT) Choose “Ubuntu 20.10 64bit Server” OS image and flush onto the 1TB Samsung SSD drive.
    • I found Ubuntu 20.04LTS don’t work!
  • Follow this link to update EEPROM firmware
  • Follow this link to boot from USB (i.e., SSD driver) first instead of SD card.
  • Remove SD card, and now you should be able to boot from SSD drive.

Step 2 – Fix up the board

  • Connect an Ethernet cable to enable Internet
  • Fix sluggish USB mouse
    • Add “usbhid.mousepoll=0” to /boot/firmware/cmdline.txt; Reboot
  • Install argon 1 fan control
    • curl https://download.argon40.com/argon1.sh | bash

Step 3 – Install XFCE desktop

Note choose “lightdm” when install xfce4

sudo apt update
sudo apt dist-upgrade
apt install xfce4 xfce4-goodies
apt install tigervnc-standalone-server novnc firefox

Create /etc/lightdm/lightdm.conf file:

[Seat:*]
allow-guest=false
autologin-user=ubuntu
user-session=xfce
#greeter-session=unity-greeter
xserver-command=/etc/X11/xinit/xserverrc

After this you should be able to log into graphic XFCE desktop.

Step 4 – Set up VNC and headless

  • Configure wifi assuming that is what you want to run RPI4
  • Set up VNC password
    • sudo vncpasswd /etc/vncpasswd
  • Modify /etc/X11/xinit/xserverrc file
#!/bin/sh

ARG=`echo $@ | sed -e "s#vt. -novtswitch##"`
GEOMETRY="1600x1000"
DEPTH="24"
# single client mode; VNC password auth; TLS encryption optional;
exec Xvnc -desktop ubuntu -SecurityTypes "VncAuth,TLSVnc" -NeverShared -DisconnectClients -geometry $GEOMETRY -depth $DEPTH -rfbauth /etc/vncpasswd $ARG
  • Make sure WiFi is connected before user logs in so that you can connect via VNC
    • To do this, launch NetworkManager, select “Applications”/”Settings”/”Advanced Network Configuration”
    • Then select the wifi network you are connecting to, and then click on button at the bottom to edit the connection
    • Under “General” tab, check “All users may connect to this network”

After this setup, if you reboot RPI4, you will get text console on display.

Meanwhile you should be able to access RPI4 over VNC remotely

  • On your PC, install VNC viewer (e.g., tigerVNC viewer)
  • Launch the viewer, enter the IP address and port 5900
  • Enter the VNC password
  • You should see XFCE desktop

Step 5 – Optional noVNC to enable web browser access

  • Install noVNC package
    • sudo apt install novnc net-tools
  • Run /usr/share/novnc/utils/launch.sh
  • On PC, open a browser and point at “http://<RPI4 IP address>:6080/vnc_auto.html”
  • Enter VNC password and you will be connected to the desktop

You can automate this process by adding this to /etc/rc.local or create a small systemd service file.

AWS ARM64 vs. X86_64 – Bitcoin Performance Comparison

I’m running some experiments with bitcoin core software on AWS. I’m intrigued by 2 questions:

  • Which performs better, ARM64 vs X86_64?
  • What is performance loss of 32bit ARM vs 64bit ARM?

The Experiment

  • I fired up a t3.medium instance with ubuntu desktop 20.04(x86_64) image
  • I fired a second instance of t4g.medium type with ubuntu desktop 20.04 (arm64) image
  • To run 32bit ARM program, I followed the chroot approach documented in my previous post and set up an armhf Ubuntu 20.04 (focal) chroot environment
  • Then I download all 3 versions of bitcoin core software from its download site : 32bit ARM, 64bit ARM and 64bit Intel.
  • Run bitcoin-qt from scratch (delete ~/.bitcoin directory if any) and count the time duration for the verifying first 200,000 blocks.
    • Each configuration runs 2 times. We then take the average.
    • Other system variables are monitored to ensure similar running environment. Specifically networking or disk don’t seem to be a factor.

The Results

See results listed below. It seems for bitcoin related workload 64bit ARM version performs 20% faster than 32bit ARM version and 64bit Intel instance.

category64bit ARM 32bit ARM64bit Intel
Instance typet4g.mediumt4g.mediumt3.medium
CPU Graviton2Graviton2Intel Xeon Platinum 8000 series
# CPU cores222
RAM (GB)444
run duration #18’44” (524″)10’24” (624″)11’16″(676″)
run duration #27’30” (450″)9’58″(598″)9’04″(544″)
run duration average487″611″610″
relative performance to 64bit ARM100%80%80%
Pricing (us-west-2/Orgon) ($/hr)0.03360.03360.0416

Geekbench Performance on AWS Graviton 2

There is much touting about the new AWS Graviton 2 (ARM64) offering as a game changer. Let us run some benchmark to test it out.

Settings

We pick 3 EC2 instance types to compare:

  • a1 – First generation of ARM64 AWS Graviton CPU
  • m6g – Second generation of ARM64 Graviton 2 CPU
  • m5 – Intel Xeon Platinum 8259CL CPU

We run Geekbench 4 on all xlarge instances of these EC2 types. We mostly focus on 64bit performance, but we will also touch 32bit performance as well.

Overview

Instance typea1.xlargem6g.xlargem5.xlarge
vCPU444
Memory(GB)81616
Hourly price(us-ea-1,Linux)0.1020.1540.192
64bit single-core score189936093647
64bit multi-core score5227111428017

From the above table, several observations are obvious:

  • Graviton 2 has doubled the performance of Graviton 1.
  • For single core performance Graviton 2 is similar to Intel Xeon CPU
  • For multi-core performance, Graviton 2 scales up much better, likely because Intel uses hyper-threading technology, where vCPU count is only 1/2 of true CPU core count. By contrast, vCPU count in Graviton CPU is true CPU core count.

I also listed the pricing. It looks like Graviton 2 is a good deal!

Look into the Details

This link gives detailed scores for each test suite and each instance type. A few highlighted cells indicate interesting contrast between Intel Xeon and Graviton 2:

  • Intel Xeon is 20 times faster than Graviton 2 in AES test! This is *very* likely due to non-optimized implementation for ARM64, i.e., it is not using NEON instructions. Otherwise the performance should be more comparable.
  • Intel Xeon are 2x better in SGEMM and 50% better in SFFT, both heavily relying Intel AVS/SSE instructions while ARM64 using NEON instructions.
  • Graviton 2 shines in memory area, 2x better in Memory Copy and 4x better in Memory bandwidth.

32bit Performance

While 32bit performance is probably not interesting on those servers, it is still interesting to take a look. Below is the overview comparison table and this link gives detail scores.

Instance typea1.xlargem6g.xlargem5.xlarge
32bit single-core score170729753053
32bit multi-core score469290166886

Overall we see similar patterns in 64bit case:

  • Graviton 2 is about 2x faster than Graviton 1
  • Intel Xeon performs relatively same as Graviton 2 in single core and wanes in multi-core performance.
  • Detail scores also reflect similar pattern as 64bit case.

Develop 32bit Applications on 64bit Linux Machines

Overview

Nowadays almost all PC and servers are 64bit. Once in a while one may need to develop and run 32bit apps. In this post we will go through several methods for both x86_64 and ARM64 machines.

I can think of 4 ways of doing this:

  • Run a virtual machine, which in turn runs a 32bit OS. Not covered in this post.
  • Set up 32bit chroot environment. (Recommended)
  • Set up 32bit architecture with Debian multi-arch support (Recommended)
  • Use gcc multi-lib feature to build 32bit binaries.

X86_64/Ubuntu 20.04

Here we go through some detailed steps for those approaches on X86_64/Ubuntu 20.04. Instructions should apply to other Debian-based distributions and different versions as well.

GCC Multi-Lib Approach

Although this is the simplest approach, I don’t recommend it because the GCC support varies for different CPU architectures and the command line options also varies, making it hard to generalize and port existing software. I believe mult-arch is the future direction.

  • Install GCC multi-lib package
sudo apt install gcc-multilib
  • Compile with -m32 option
gcc -m32 hello.c -o hello
file hello
./hello

Multi-Arch Approach

  • Add 32bit as secondary architecture
sudo dpkg --add-architecture i386
  • Install dev tools and 32bit specific dev tools and libraries
sudo apt update
sudo apt install -y build-essential
sudo apt install -y crossbuild-essential-i386
sudo apt install -y libc6:i386
sudo apt install -y libstdc++6:i386
  • Develop 32bit apps with i686-linux-gnu- cross-compile prefix
i686-linux-gnu-gcc hello.c -o hello
file hello
./hello
  • Note for Ubuntu 18.04, crossbuild-essential-i386 meta-package does not exist. One needs to install below packages explicityly
sudo apt install -y dpkg-cross g++-i686-linux-gnu  gcc-i686-linux-gnu

Chroot Approach

For more detailed descriptions, please refer to http://logan.tw/posts/2018/02/24/manage-chroot-environments-with-schroot/

  • Install packages
sudo apt-get install schroot debootstrap
  • Install 32bit environment (e.g., Ubuntu 20.04) (note the last URL arg can be ommited)
sudo debootstrap --arch=i386 focal /var/chroot/focal32 http://archive.ubuntu.com/ubuntu
  • Edit /etc/schroot/schroot.conf file
[focal32]
description=Ubuntu 20.04 Focal Fossil 32bit
directory=/var/chroot/focal32
root-users=ubuntu,jsun
users=ubuntu,jsun
type=directory
personality=linux32
  • Create and enter 32bit chroot session
schroot -c focal32          ; enter as normal user
schroot -c focal32 -u root  ; enter as root user
  • From inside the session, one can install build-essential meta-package and develop 32bit apps as if inside a 32bit machine.
  • (Optional) One can even run 32bit graphic apps from inside the chroot environment.
export DISPLAY=:0.0

ARM64/Ubuntu18.04

ARM64 is also called aarch64. “ARM64” is rooted from Linux community and “aarch64” is official name from ARM. We will use those 2 terms inter-changeably.

Multi-Lib approach

GCC for aarch64 does not support multi-lib. So this option is not available.

Multi-Arch Approach

It is similar to i386 case, except that architecture is “armhf” and 32bit cross-compile prefix is “arm-linux-gunueabihf-“.

sudo dpkg --add-architecture armhf
sudo apt update
sudo apt install -y build-essential
sudo apt install -y crossbuild-essential-armhf
sudo apt install -y libc6:armhf
sudo apt install -y libstdc++6:armhf

arm-linux-gnueabihf-gcc hello.c -o hello
file hello
./hello

Chroot Approach

For chroot approach, it is similar to i386 case, with 2 exceptions:

  • The architecture name is “armhf” instead of “i386”
  • The repo URL is “http://ports.ubuntu.com/ubuntu-ports”, instead of “http://archive.ubuntu.com/ubuntu”

Note we can also set up the root filesystem from debian repos. Below is an example to set up debian sid for armhf 32bit architecture:

  • Install packages and bootstrap root filesystem
sudo apt-get install schroot debootstrap
sudo debootstrap --arch=armhf sid /var/chroot/sid-armhf http://ftp.debian.org/debian/
  • Modify and add to /etc/schroot/schroot.conf file
[sid32]
description=Debian Sid 32bit
directory=/var/chroot/sid-armhf
root-users=ubuntu
users=ubuntu
type=directory
personality=linux32
  • Create and enter sid32 session, “schroot -c sid32”

About MIPS64

  • Multilib works for MIPS64.
    • sudo apt install gcc-multilib g++-multilib
    • compile with -mabi=32 flags, i.e., “gcc -mabi=32 hello.c”
  • Multi-Arch does not work for MIPS64, at least from 32bit app development perspective
  • I have not tried chroot approach on MIPS64 yet. Let me know if you have had any success.

Last Words

  • In Ubuntu chroot environment, the initial apt repo source is limited to main. You may find many packages are missing. To fix this, edit /etc/apt/source.list
deb http://archive.ubuntu.com/ubuntu xenial main universe multiverse

How to build/run Android Cuttlefish emulator on AWS

Background

Cuttlefish is new virtual-machine based Android emulator.  Earlier I have written  an article on how to build/run it on PC and ARM64 machines.  Towards the end of 2019, AWS has introduced a1.metal instance which allows KVM to run on their ARM64 machines.  It opens the possibility of running cuttlefish on AWS (which itself opens a lot of possibilities!)

The steps are similar to those I mentioned before.  This article summarizes them here specifically for AWS a1.metal instance, running Ubuntu 19.10.

Build AOSP cuttlefish images on x86_64

This step is done on PC, while all the rest steps are done on AWS a1.metal instance.

  • Refer to https://source.android.com/setup/build/building to set up your host machine
  • Check out the source from master and build distribution packages, which will be transferred to a1.metal instance later.  This step takes very loooong time.
mkdir cuttlefish
repo init -u https://android.googlesource.com/platform/manifest
repo sync -j8
source build/envsetup.sh
lunch aosp_cf_arm64_phone-userdebug
make dist

If you like to download from a branch and like to download as little as possible, the following command do so with android10-gsi branch without git history.

repo init --depth=1 -u https://android.googlesource.com/platform/manifest -b android10-gsi
repo sync -f --force-sync --no-clone-bundle --no-tags -j$(nproc)

Setup AWS a1.metal

Start an Ubuntu 19.10 instance on a1.metal.  First,  we install GUI for better debugging and viewing. 

sudo apt-get update -y 
sudo apt-get install lxde xrdp -y
sudo passwd ubuntu

Setup to run x86_64 binaries

Many tools (e.g., cros_vm) in cuttlefish are still built as x86_64 binaries, not as arm64.  Current solution is to use qemu-user to run those binaries (*ouch!*).  As such, we set up x86_64(amd64) as the secondary architecture on a1.metal.

  • Override /etc/apt/sources.list file with the following content
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports eoan main restricted universe multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports eoan-updates main restricted universe multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports eoan-backports main restricted universe multiverse
deb [arch=arm64,armhf] http://ports.ubuntu.com/ubuntu-ports eoan-security main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ eoan main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ eoan-updates main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ eoan-backports main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ eoan-security main restricted universe multiverse
  • Install qemu-user-static and add amd64 secondary architecture
sudo apt install qemu-user-static
sudo dpkg --add-architecture amd64
sudo apt install libc6:amd64
  • After this you should be able to run simple x86_64 binaries such as “cat”.
    • scp over “cat” program from your x86_64 linux machine
    • it should run!

Build and install cuttlefish-common package

  • install packages needed for build
sudo apt install dpkg-dev
sudo apt install cdbs config-package-dev debhelper
  • Download and build
mkdir cuttlefish-common
cd cuttlefish-common
git clone https://github.com/google/android-cuttlefish.git
cd android-cuttlefish
dpkg-buildpackage --no-sign
  • Install
sudo apt install bridge-utils dnsmasq-base f2fs-tools libarchive-tools libfdt1 libwayland-client0 net-tools python2
sudo dpkg -i ../cuttlefish-common_0.9.13_arm64.deb

Setup cuttlefish for running

  • copy (scp) the following  the files from x86_64 PC host:
out/dist/aosp_cf_arm64_phone-img-eng.jsun.zip
out/dist/cvd-host_package.tar.gz
  • untar cvd-host_package.tar.gz to ~/cuttlefish/host directory
  • unzip the zip file to ~/cuttlefish/image directory
  • Add user to proper groups before running; power off machine; then power on again. 
sudo usermod -aG kvm $USER
sudo usermod -aG cvdnetwork $USER

Run Cuttlefish

You have 2 choices to view the screen of emulated Android device:

  1. Use remote desktop and view screen via local VNC connection to Cuttlefish emulator
  2. Use a web browser and view the screen via remote WebRTC connection

View via Local VNC

  • Start a remote desktop viewer and connect to your EC2 a1.metal instance (Note: you need to open port 3389)
  • Below steps are running on remote EC2 a1.metal instance via remote desktop
  • Start a LXTerminal and run the following commands to start cuttlefish
export ANDROID_PRODUCT_OUT=~/cuttlefish/image/
export ANDROID_HOST_OUT=~/cuttlefish/host/
export PATH=$PATH:$ANDROID_HOST_OUT/bin
launch_cvd -decompress_kernel=true
  • Start browser and download VNC viewer
    • download tightvnc viewer (jar file): https://www.tightvnc.com/download.php
    • install java if not done yet: sudo apt install openjdk-11-jre
  • Start a second LXTerminal and run this command : java -jar tightvnc-jviewer.jar
    • Please use 127.0.0.1 as IP address and 6444 as port number
  • To stop cvd, run stop_cvd

View via WebRTC

  • Note you need to enable port 8443 on EC2 a1.metal instance
  • On EC2 instance run
launch_cvd -start_webrtc -webrtc_public_ip=`curl http://169.254.169.254/latest/meta-data/public-ipv4` -decompress_kernel=true
  • On local PC, start a browser on local machine, and connect via “https://<public IP>:8443”

As of writing today (4/5, 2020), the WebRTC method is not working yet.  It shows a black screen.

Install NumPy and Matplotlib on Chromebook/Linux(Beta)

Linux(Beta) on Chromebook is really cool. You can easily and officially turn it on by following a very simple step. Apparently there are also ways to enable audio capture and GPU acceleration as well.

I was playing with Lenovo N23 Yoga , which is an AAarch64(ARM64) Chromebook powered by MTK8173 chipset. It turned out to be an interesting experience. Specifically I was able to do some simple Python development.

Step 1 – Enable Linux (beta)

Follow the instructions at this page.

Step 2 – Install debian packages

The Linux environment seems to be a container-type environment, running Debian Linux. Python3 is already installed.

sudo apt update
sudo apt install python3-pip pkg-config libpng-dev libfreetype6-dev python3-tk

Step 3 – Install PIP3 packages

pip3 install cython
pip3 install numpy
pip3 install matplotlib

Step 4 – Try it out

Create the following Python file try.py:

import numpy
import matplotlib.pyplot as plt

x = numpy.random.normal(5.0, 1.0, 100000)

plt.hist(x, 100)
plt.show()

Then run it by typing “python3 try.py”. If everything goes well, you should see some picture like the following:

Install WordPress on Ubuntu 18.04

As I said in my Home Page, I finally spent some time and migrated my ancient homepage to WordPress, the most popular web hosting platform (>60% of web sites).

However, quite contrarily to my expectations, the process is rather complicated. I went through quite a few hiccups, taking more than a couple of days, to reach today’s state. So I decide to write my experience down to hopefully save someone’s else pain.

For the Inpatients

  • Don’t follow the official instructions. It looks easy and simple, but WordPress is too old and does not seem to be easily updateable.
  • Don’t use WordPress docker container. A lot of trouble to get MySQL setup and connected. You still have a broken environment that many plug-in’s don’t work. In my case, I need to send emails (who don’t?), and that is VERY HARD to do with container.
  • I suppose Bitnami WordPress on AWS might be a fine choice. But I find more flexibility in just doing it myself, and it is actually not that hard, with a good instruction.
  • I ended up installing WordPress directory on Ubuntu 18.04
    • I install WordPress as a subdrectory of WWW root (wordpress/). This way I can migrate my original web site (in classic HTML) to WWW directory and co-exist with new shiny WordPress pages.
    • I chose Apache2 and MySQL. You can use Niginx and Mariabdb as well.

Installation

  • install required packages
apt update
apt install apache2 mysql php php-mysql
apt install php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip php-gd
  • configure mysql
create database wordpress;
grant SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER on wordpress.* to 'wp_admin'@'localhost' identified by 'somepasswordofyourown';
  • install wordpress
cd /tmp && wget https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz -C /var/www/html/
mkdir /var/www/html/wordpress/uploads
chown -R www-data.www-data /var/www/html/wordpress/
  • create /etc/apache2/sites-available/wordpress.conf file:
<Directory /var/www/html/wordpress>
    Options FollowSymLinks
    AllowOverride Limit Options FileInfo
    DirectoryIndex index.php
    Order allow,deny
    Allow from all
</Directory>
<Directory /var/www/html/wordpress/wp-content>
    Options FollowSymLinks
    Order allow,deny
    Allow from all
</Directory>
  • enable WordPress in apache2
sudo apache2ctl configtest      # test syntax
sudo a2ensite wordpress
sudo a2enmod rewrite
sudo systemctl restart apache2
  • Initialize WordPress
    • Open a browser and go to “http://<server ip/name>/wordpress”
    • Enter site name, database name (“wordpress”), database user (“wp_admin”) and password.
    • You are done! Well, sort of. The rest is about WordPress itself, which is another topic.

References

How to Cross-Build Debian/MIPS Kernel

Background

I was trying to install Debian/MIPS on QEMU and found out that I need to build/update the kernel.  The existing instructions mostly talk about native build, which is painfully slow on QEMU.  I tried once and it took almost 10 hours!  There are some references to cross-build debian kernel and none applies straightforwardly.    I decided to write a blog on how I did it.

Prepare the host

  • My host is Ubuntu 18.04
  • I’m building 64bit MIPS little endian kernel for malta board
  • Need install a build related packages :
    • apt install -y build-essential linux-source bc kmod cpio flex cpio libncurses5-dev bison libssl-dev
  • Need to install crosscompile tools.  Fortunately we only need gcc and binutils for compiling kernel
    • apt install -y binutils-mips64-linux-gnuabi64 gcc-mips64-linux-gnuabi64

Set up the source

  • Download and unpack kernel source and config from debian site
    • cd download
    • wget http://security.debian.org/debian-security/pool/updates/main/l/linux/linux-source-4.19_4.19.67-2+deb10u2_all.deb
    • wget http://security.debian.org/debian-security/pool/updates/main/l/linux/linux-config-4.19_4.19.67-2+deb10u2_mips64el.deb
  • Extract the kernel source from .deb file
    • dpkg -x download/linux-source-4.19_4.19.67-2+deb10u2_all.deb .
    • tar xf usr/src/linux-source-4.19.tar.xz
  • Copy and modify the kernel config as you see fit
    • dpkg -x download/linux-config-4.19_4.19.67-2+deb10u2_mips64el.deb .
    • unxz usr/src/linux-config-4.19/config.mips64el_none_5kc-malta.xz
    • patch -p0 -b < kconfig.patch
    • cp usr/src/linux-config-4.19/config.mips64el_none_5kc-malta linux-source-4.19/.config
  • Make deb packages for kernel
    • cd linux-source-4.19
    • make ARCH=mips CROSS_COMPILE=mips64-linux-gnuabi64- oldconfig
    • make ARCH=mips CROSS_COMPILE=mips64-linux-gnuabi64- KDEB_PKGVERSION=1 -j`nproc` bindeb-pkg

Download the source

Below the script file and kernel config patch would work together to execute the above steps automatically.