Installing TailOS on Raspberry Pi 3
Hardware Required
| Item | Notes |
|---|---|
| Raspberry Pi 3B or 3B+ | |
| MicroSD card (8 GB+) | |
| USB-to-TTL serial adapter (3.3V) | For serial console (FTDI, CP2102, etc.) |
| 5V / 2.5A power supply | Official RPi PSU recommended |
| Host Linux machine | For building and flashing |
Quick Start
# 1. Build TailOS and create the SD card image
make sd-image
# 2. Flash to SD card (replace /dev/sdX with your SD card device)
sudo dd if=tailos_sd.img of=/dev/sdX bs=4M status=progress
sync
# 3. Wire serial console, insert SD card, power on
Serial Console Wiring
Connect the USB-to-TTL serial adapter to the RPi3 GPIO header:
USB-TTL Adapter RPi3 GPIO Header
+-----------+ +----------------+
| | | |
| TX o----+----------->| Pin 10 (RXD) | GPIO 15
| | | |
| RX o<---+-----------o| Pin 8 (TXD) | GPIO 14
| | | |
| GND o----+----------->| Pin 6 (GND) |
| | | |
+-----------+ +----------------+
Important: Do NOT connect the VCC/5V pin from the serial adapter to the RPi. Power the RPi from its own power supply.
Open the serial terminal on your host:
screen /dev/ttyUSB0 115200
# or
minicom -D /dev/ttyUSB0 -b 115200
SD Card Image Structure
The make sd-image command produces tailos_sd.img with the following layout:
+===========================================================================+
| tailos_sd.img (193 MiB) |
+===========================================================================+
| |
| Sector 0: MBR (Master Boot Record) |
| Partition 1: Boot | FAT32 | 64 MiB |
| Partition 2: Data | FAT32 | 128 MiB |
| |
| Partition 1: BOOT |
| +-----------------------------------------------------------------------+|
| | bootcode.bin .... RPi GPU 1st-stage bootloader ||
| | start.elf ....... RPi GPU firmware ||
| | fixup.dat ....... RPi GPU memory fixup ||
| | config.txt ...... Boot configuration (arm_64bit=1, enable_uart=1) ||
| | kernel8.img ..... TailOS (startup + kernel + drivers + servers + tsh)||
| +-----------------------------------------------------------------------+|
| |
| Partition 2: DATA |
| +-----------------------------------------------------------------------+|
| | /usr/bin/ls ..... Directory listing utility ||
| | /usr/bin/pidls .. Process listing utility ||
| +-----------------------------------------------------------------------+|
| |
+===========================================================================+
Boot Sequence
Power On
|
v
GPU ROM -> loads bootcode.bin from boot partition
|
v
bootcode.bin -> loads start.elf
|
v
start.elf -> reads config.txt, loads kernel8.img at 0x80000
|
v
TailOS startup (_start.S)
|-- Switch EL3 -> EL1
|-- Initialize MMU and caches
|-- Jump to kernel
v
TailOS kernel
|-- Initialize process/thread/IPC subsystem
|-- Load drivers from RFS (UART, SD)
|-- Mount data partition via SD driver + FAT server
|-- Start tsh shell
v
/$ _ (serial console ready)
Build Details
The make sd-image target:
- Builds TailOS (
make build-release) - Downloads RPi3 firmware from
raspberrypi/firmware(cached locally) - Converts
tail.rfs(ELF) tokernel8.img(raw binary) viaobjcopy -O binary - Creates a two-partition FAT32 image with MBR
- Populates boot partition with firmware + kernel
- Populates data partition with user binaries from
tail.build[disk]section
Offline Firmware
To use pre-downloaded firmware instead of auto-downloading:
python3 utility/host/deploy_disk/make_sd_image.py \
./tail.build \
$TAIL_PREFIX/os_image/tail.rfs \
$TAIL_PREFIX/target/bin \
tailos_sd.img \
--firmware-dir /path/to/firmware/
The firmware directory must contain: bootcode.bin, start.elf, fixup.dat.
These can be obtained from https://github.com/raspberrypi/firmware/tree/master/boot.
config.txt Reference
The generated config.txt contains:
| Setting | Value | Purpose |
|---|---|---|
arm_64bit |
1 |
Boot in AArch64 mode |
kernel |
kernel8.img |
Kernel filename to load |
disable_commandline_tags |
1 |
Don't pass ATAGS (TailOS doesn't use them) |
gpu_mem |
16 |
Minimize GPU memory (TailOS doesn't use GPU) |
dtoverlay |
disable-bt |
Free PL011 UART from Bluetooth |
enable_uart |
1 |
Enable serial console |
The dtoverlay=disable-bt setting is critical: by default, the RPi3 maps the
full PL011 UART to Bluetooth and provides only the mini UART on GPIO 14/15.
TailOS uses PL011 (at address 0x3F201000), so Bluetooth must be disabled to
make PL011 available on the GPIO pins.
Troubleshooting
No serial output:
- Verify TX/RX wiring (they must be crossed: adapter TX -> RPi RX)
- Ensure baud rate is 115200
- Check that the SD card has
config.txtwithdtoverlay=disable-btandenable_uart=1
RPi power LED on but no activity LED blinking:
- The SD card may not be readable. Re-flash with
ddand verify the boot partition containsbootcode.bin,start.elf, andkernel8.img
Kernel panic or hang after startup:
- Connect via GDB if built with debug:
make run-gdb(QEMU only) - Compare behavior with QEMU first: see install_qemu.md