My iPad Productivity and Travel Kit, 2023 Edition

Weeks ago, I watched yet another discussion about unfold even as Summer break began. At the time there was too much going on for me to write about it, but after a couple of weeks of vacation I have a few thoughts to share.

The Essentials (and a bit more)

This year I took the following gear with me on vacation:

These are what I normally take on weekend trips, and the whole thing (plus a couple of chargers) fits into a small messenger bag. Even though I got an , I still prefer to travel with the because it’s a lot easier to handle and quite unobtrusive even when used on a table–anything bigger just feels too heavy, distracting or imposing when traveling.

For our ten-day at the beach, I also took along:

  • My .
  • A (so we could watch Prime, HBO, Apple TV+ and Plex on).
  • A Mercusys ME30 Wi-Fi Extender (since we already knew the place we would be staying at).
  • An ancient Intel MacBook Air 13” that I refurbished myself (cleaned it up and added a new battery two years ago, and we use it as a travel computer for the family).

The ME30 took the place of my old, reliable NEXX WT3020, which I ordinarily bring along to use as a (2.4GHz only) Wi-Fi extender or as a hotel firewall to have an isolated LAN for my gear (with DNS ad-blocking to boot). It’s an unremarkable, and seemingly solid piece of gear that just worked (all I needed to do was to pair it via WPS), and which I recommend if all you need is a cheap, no-frills wireless extender.

The Linux Sidecar

Picking up on the , the key motivation for this post is that I use the Pi as a “sidecar” for my iPad, and have done so for years.

This works for me because, as far as I’m concerned, productivity revolves around researching, writing and coding, and typically low-level or back-end code at that. Plus it helps that my workflow is heavily biased towards the command line.

Although I can do a lot on the iPad itself, it can be argued that using an external device is cheating, but I don’t see it that way: I use the iPad as a smart terminal and the Pi as a tiny portable server, and the combination is what makes it work for me.

Using it I can code, run all kinds of services and do all sorts of development-related tasks that I (still) can’t do on the iPad by itself (although I have quite a few more options for that these days).

And, in general, bringing a tiny, personal Linux machine along with you has a lot of advantages–when I travel for work I can also use it to tunnel back to my home network, and have my personal drafts and other files with me without storing them on my work machine.

Hardware

I first started doing this with Android phones but it became too much hassle, so I switched to a .

This year I used a Zero 2W, because even though it lacks 5GHz Wi-Fi and 400MHz of clock speed when compared to the , I have wanted to try one out as a “travel server” for quite a long time due to the slightly nicer form factor (which looks really nice with the brushed aluminium Flirc case I got for it):

My Zero 2W in a Flirc case, with a Micro-SD card for scale.

One key point is that unlike newer, more powerful s, I can run it off a battery pack for longer than the iPad. In fact, I never power it off my iPad (the mini can’t handle it, and I suspect it would throttle if I tried powering it off an iPad Pro).

Bluetooth PAN

This is something I get a fair amount of questions about, since I typically use to connect directly from my iPad to the Pi while on the go, and most people don’t realize how well it can work.

My preference for harks back to the days when I hung an off curtain hangers to have 3G connectivity, and setting up a Personal Area Network between the (or any Linux machine) and an iOS device is just a modern version of that with a slightly different protocol.

To get it working, you need to configure bluez to set up a Personal Area Network (something I’ve had a gist about up for ages and that I’ve since automated away) with a cloud-init script that you can easily translate into manual commands:

#cloud-config
package_upgrade: true
packages:
  - bluez
  - bluez-tools

write_files:
  - path: /etc/systemd/system/bt-agent.service
    content: |
      [Unit]
      Description=Bluetooth Agent
      [Service]
      ExecStart=/usr/bin/bt-agent -c NoInputNoOutput
      Type=simple
      [Install]
      WantedBy=multi-user.target

  - path: /etc/systemd/system/bt-network.service
    content: |
      [Unit]
      Description=Bluetoot PAN
      After=pan0.network
      [Service]
      ExecStart=/usr/bin/bt-network -s nap pan0
      ExecStartPost=bt-adapter --set Discoverable 1
      Type=simple
      [Install]
      WantedBy=network.target

  - path: /etc/systemd/network/pan0.netdev
    content: |
      [NetDev]
      Name=pan0
      Kind=bridge

  - path: /etc/systemd/network/pan0.network
    content: |
      [Match]
      Name=pan0
      [Network]
      Address=172.20.1.1/24
      DHCPServer=yes

runcmd:
  - systemctl enable systemd-networkd
  - systemctl start systemd-networkd
  - systemctl enable bt-agent
  - systemctl start bt-agent
  - systemctl enable bt-network
  - systemctl start bt-network
  - bt-adapter --set Discoverable 1

You then pair and connect to the Pi from the Bluetooth settings in your iOS device, and up pops an Ethernet entry in Preferences with an emulated LAN:

This is what it looks like after pairing and connecting to the Pi.

I love this setup because:

  • I can use it anywhere, even in places where I can’t get Wi-Fi.
  • It requires zero extra hardware.
  • Depending on the devices and distances involved, you can actually get multi-megabit speeds over that pseudo-Ethernet link (not that I’ve run any benchmarks, but I can confirm that running a remote desktop over this is entirely viable, as long as you have the CPU power for it).
  • It provides me with secure “headless” access to everything running on the Pi, and the ability to change the configuration without a mouse and keyboard.

What this means in practice is that I can treat this direct link as a private LAN and do all sorts of interesting things, even when sitting in a lounge without an Internet connection. And if I have one, I can even use the Pi itself as a packet filtering gateway.

For overnight stays, things are a bit different: I tend to ssh in via Bluetooth and edit wpa_supplicant.conf to get the Pi up on some Wi-Fi (either the NEXX WT3020 or something trustworthy).

Update: USB Ethernet

September 20 2023: I forgot there is also the possibility of accessing the Zero via its OTG port by configuring it as an Ethernet device. This might work in iOS with a powered hub, but I don’t have one handy.

The following file shows what I needed to do to get it working with Linux and Mac (Windows 11 requires the RNDIS driver, which requires some contortions):

#cloud-config

# Sets up the Ethernet gadget on a Raspberry Pi with OTG

# Since write_files' append may have trouble with the /boot partition
# and is best suited to appending rather than modifying files
# add the following to /boot/cmdline.txt after "rootwait":
# modules-load=dwc2,g_ether

# To connect to a Windows 11 host:
# Check that you get an extra COM port in Device Manager and then:
# -> Windows Update (make sure to hit "Check for updates")
#  -> Advanced Options
#   -> Optional Updates 
#    -> Select "Acer Incorporated - Other Hardware - USB Ethernet/RNDIS Gadget"

write_files:

  - path: /boot/config.txt
    append: true
    content: |
      # Enable Ethernet gadget
      dtoverlay=dwc2

    path: /etc/systemd/network/usb0.network
    content: |
      [Match]
      Name=usb0

      [Network]
      Address=172.21.1.1/24
      DHCPServer=yes

    path: /etc/modprobe.d/g_ether.conf
    content: |
      # this may be required for older USB hosts - uncomment if so
      #options g_ether use_eem=0

There are other ways to do this, but this approach ties well with the above.

Software

This is where things have evolved the most over the past five years. On the iPad, my current go-to apps are:

  • for ssh, a local setup for my drafts, a little development (I can use most of what I need as long as it’s pure or ), and the occasional test.
  • iSH for stuff that can’t run, like .
  • Working Copy and Shortcuts to post articles, photos and links, as well as syncing git repositories to my iPad (which I can edit from or iSH if needed).
  • Remote Desktop for any GUI stuff (I’ve often used it to access work e-mail and other stuff in the past, but this year I only used it to access my home network).
  • Mobius Sync to keep my drafts and a few scripts synced with other machines via (which also means automatic remote backups to my home NAS).

This is a pretty sweet setup, since thanks to file providers I can use any editor to code inside a Working Copy repository, a synced folder or an exported network filesystem. And since I can pretty much live inside and , working on the Pi (or even locally on the iPad itself) is a no-brainer.

Finally, I run Tailscale on both the iPad and the Pi, which means I can access all of my machines (home services and cloud ones) with ease.

On The Pi Side

The Pi can run a surprising amount of stuff, even with 512MB RAM. This year, I packed it with:

  • My complete setup (actually, all my dotfiles, which I maintain in a private git repo).
  • A minimal openbox desktop, with Firefox ESR in case I needed a non-iOS browser locally. This is very slow to use via Remote Desktop on the Zero 2W with just 512MB or RAM, but OK on a beefier Pi.
  • and n8n instances, (which I use for quick hacks and API integration prototypes), both running under piku (which I also use to host my projects locally).
  • Several flavors of (plus , Fennel, a bunch of other -related stuff, and )

The baseline OS was vanilla Raspbian, although I’ve used Ubuntu in other occasions. The key thing is that I’ve committed to aarch64 on all my ARM boards a while back, which makes those 512MB RAM feel much tighter but allows me to run more modern software.

Future Upgrades

As always, I keep hoping that Apple somehow makes it viable to run some sort of official sandboxed environment on the iPad. Linux VMs would be amazing (although extremely unlikely), and without those I can only hope that and iSH keep improving even further.

Last week I also tried Code, which was quite the surprise: it is a Swift app that emulates the VS Code look and feel (using the Monaco editor as well), and that, surprisingly enough, can edit remote files via ssh. It was a bit unstable and didn’t support syntax highlighting, so if you want a “normal” coding editor, I’d recommend Textastic for now (and Blink or Secure Shellfish to access remote files).

As to the hardware, the Zero 2W is still hobbled by its measly 512MB of RAM, and even though I was able to in it with ease, having something better would be nice. Packing a full Raspberry Pi 4 would fix that, but I want to keep it as small as possible–I really like the Zero/3A+ form factors and their lower power requirements.

A while back I explored alternatives like the , but the software support was a mess and due to the pandemic shortages I had to wait until this year to have a spare Zero 2W for this purpose. I still wish it had more than 512MB RAM, but otherwise the four cores and a moderately speedy SD Card are quite enough for CLI work.

It bears noting that since I knew where we were staying, I seriously considered taking something beefy like the with me–but even as the homelab geek in me would have loved to take a “pocket” Proxmox server along, it would have been overkill and hardly in line with my penchant for seasonal minimalism.

A number of people have suggested the Radxa Zero in the past, but at the nicer configs (4GB of RAM) the price point is too close to a low-end Intel machine, and I’m not sure I want to risk repeating the fiasco with something that may lack adequate support.

Time will tell. For now, I’m happy with my setup, but I’m already looking forward to next year’s vacation…

This page is referenced in: