HISPEC RTC Build: Headless Real-time Ubuntu 24.04 FEI Server#
- Authors:
Elijah A-B, Dan Ech
- Date:
2026-08-22
- Hostname:
hispecfei- Primary User:
hsfei- Engineering User:
hsdev- OS:
Real-time Ubuntu 24.04 LTS (PREEMPT_RT via Ubuntu Pro)
- Supersedes:
fei_server_build_notes.rst,rtc_buildnote.rst
0. Scope & Design Principles#
This document merges the FEI server build notes and the TCC / real-time kernel build notes into a single headless RTC recipe.
The OS is Real-time Ubuntu 24.04 LTS — Ubuntu with Canonical’s
PREEMPT_RT kernel, deployed through an Ubuntu Pro subscription
(§5). This is a genuine real-time operating system, not a tuned generic
kernel: PREEMPT_RT replaces the default scheduler with a fully preemptible
priority-based one, converts spinlocks to sleeping rt-mutexes with priority
inheritance, and forces IRQ handlers into schedulable kernel threads. It
provides a bounded upper limit on execution time.
What “RTC” scopes here: a COTS x86_64 server running that RT kernel with
hard CPU shielding, Intel TCC enabled in firmware, and background services
stripped — dedicated to the camera/controller loop.
Note
Real-time Ubuntu 24.04 is based on upstream kernel v6.8 with the
PREEMPT_RT patchset applied, on amd64 and arm64. Ubuntu Pro is
free for personal and small-scale commercial use on up to 5 machines;
Caltech/COO deployments should use the institutional subscription.
Design rules applied throughout:
The RT kernel is the foundation, not an optimization. Every tuning step in §6, §7 and §12 assumes
PREEMPT_RTis already running. Do not treat §5 as optional.No desktop environment. Ubuntu Server 24.04.1 LTS, no GNOME, no display manager, no snaps beyond the base set.
Install only what the instrument needs. Every package group below is justified; anything GUI-only that the instrument does not require was cut.
GUIs still work — remotely. X11 is not run locally. Instead the box exports GUIs over SSH X11 forwarding and a pinned TigerVNC session (10. Remote GUI, Plots & Image Export). Plots and images are produced headlessly and pulled off the machine as files.
Nothing runs on shielded cores except instrument code. Shell sessions, VNC, and services are confined to housekeeping cores.
Note
$ prompts are omitted. Unless a block says otherwise, run as hsfei
with sudo. Steps marked [reboot] require a restart before continuing.
1. Prerequisites & Media Preparation#
All drives are erased before starting — this is a 0% → 100% build.
USB Drive A: Ubuntu Installer#
OS: Ubuntu Server 24.04.1 LTS (
.iso, not Desktop)Source: official Ubuntu download
Format: bootable ISO (
dd/ Rufus / balenaEtcher)
USB Drive B: Cloud-Init (CIDATA)#
Format: FAT32
Volume label:
CIDATA(exact, uppercase — the installer matches on it)Required files, in the root directory:
user-data— YAML autoinstall configurationmeta-data— empty file, but it must exist or the boot check fails
Warning
On the previous build the automated cloud-init install failed and the manual installer path was used instead. Prepare Drive B, but expect to fall back to the manual walkthrough in 2. OS Installation (Ubuntu Server 24.04.1). Do not burn schedule time debugging autoinstall on a one-off machine.
Target Hardware Inventory#
Record these before install; several later steps depend on them.
Item |
Value / How to obtain |
|---|---|
CPU physical core count |
|
Boot / OS drive |
Samsung 990 Pro 1 TB (NVMe) |
Data drive(s) |
2 TB — RAID 1 pending (15. Pending Tasks) |
Management NIC |
|
Archon fiber NIC |
e.g. |
FT4222 SPI board |
|
2. OS Installation (Ubuntu Server 24.04.1)#
Installation Parameters#
Language / Keyboard: English
Networking: Ethernet connected, no proxy. Leave DHCP for now; the static addresses are applied in 4. Network Configuration (Headless / netplan).
Mirror:
http://us.archive.ubuntu.com/ubuntu/(default)Server profile: minimized install — decline the “Featured Server Snaps” list entirely.
OpenSSH: Install it. This is a headless machine; without
sshdthe build stops here.
Important
The old FEI note selected the default “Popular Snaps”. For the pseudo-RTC,
select none. snapd timers are a jitter source and are disabled in
7. Service Stripping.
Storage Configuration#
Primary drive: Samsung 990 Pro (1 TB) — root filesystem
Secondary 2 TB drive: formatted
ext4, mounted at/usr(carried over from the previous build)Software RAID 1: bypassed at install time — see 15. Pending Tasks
Warning
Mounting a separate device at /usr requires the initramfs to mount it
before switch_root. It works on 24.04, but it is a non-standard layout.
If the RAID rebuild in 15. Pending Tasks gives you an excuse to
re-partition, prefer keeping /usr on root and mounting the 2 TB drive at
/data or /srv.
Credentials#
Server name:
hispecfeiPrimary user created at install:
hsfei(getssudo)Password: set during installation — not documented here
First Boot#
sudo apt update && sudo apt upgrade -y
3. Identity: Hostname, Users, Groups#
Hostname#
sudo hostnamectl set-hostname hispecfei
Map the loopback alias in /etc/hosts:
127.0.1.1 hispecfei
Verify:
hostnamectl
Groups#
sudo groupadd -f hispecfei # instrument / deployment group
sudo groupadd -f eng # engineering read+write on /opt
Engineering User#
hsfei is the primary account created at install. hsdev is the
engineering/development account used for day-to-day work and owns the hardware
device nodes.
sudo adduser hsdev
sudo usermod -aG sudo,dialout,hispecfei,eng hsdev
sudo usermod -aG dialout,hispecfei,eng hsfei
Idempotent re-run (safe on an already-provisioned box — skips existing accounts):
for u in hsfei hsdev; do
sudo useradd -m -s /bin/bash "$u" 2>/dev/null || true
done
Note
The new hostname takes full effect on reboot.
usermodgroup changes require a logout/login. To pick updialoutin the current shell only:newgrp dialout.Confirm with
id hsdevbefore troubleshooting any permission error.
SSH Keys (headless requirement)#
Install your public key for both accounts before you rely on the machine being remote-only:
ssh-copy-id hsfei@hispecfei
ssh-copy-id hsdev@hispecfei
Then harden /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin no
X11Forwarding yes
X11UseLocalhost yes
sudo systemctl restart ssh
X11Forwarding yes is what makes 10. Remote GUI, Plots & Image Export work — do not
omit it while stripping the desktop.
4. Network Configuration (Headless / netplan)#
There is no GUI network panel on a server install. Both interfaces are configured declaratively in netplan.
Create /etc/netplan/01-hispecfei.yaml:
network:
version: 2
renderer: networkd
ethernets:
# --- Management / site network ---
MGMT_IFACE:
dhcp4: no
addresses: [192.168.29.107/24]
routes:
- to: default
via: 192.168.29.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
# --- Archon fiber link (isolated, no gateway) ---
enp202s0f0np0:
dhcp4: no
addresses: [10.0.0.10/24]
mtu: 9000
Replace MGMT_IFACE with the real name from ip -br link. Apply:
sudo chmod 600 /etc/netplan/01-hispecfei.yaml
sudo netplan try # auto-reverts in 120 s if you lose the link
sudo netplan apply
Warning
Use netplan try first. On a headless box a bad netplan file with no
console access means a physical trip to the machine.
Archon Host Entry#
Add to /etc/hosts:
10.0.0.2 archon
Connect the Archon to the fiber port labelled archon and verify:
ping -c 3 archon
ip -br addr show enp202s0f0np0
Refer to archongui.rst for Archon-side configuration.
Note
The 10.0.0.0/24 Archon link carries no default route on purpose. Keep
instrument traffic off the management network.
5. Deploy the Real-Time OS (Real-time Ubuntu)#
This is the step that makes the machine an RTC. Everything after it is tuning.
5.1 What You Get#
Canonical’s realtime-kernel is Ubuntu 24.04 with the upstream
PREEMPT_RT patchset on kernel v6.8:
Fully preemptible kernel — priority-based scheduling replaces the default CFS behaviour for RT tasks; kernel code itself becomes preemptible.
Threaded IRQ handlers — hardware interrupts run as schedulable kernel threads that an RT task can preempt, rather than blocking arbitrarily.
Priority inheritance rt-mutexes — spinlocks become sleeping locks with PI, bounding priority inversion.
High-resolution timers — precise wakeups instead of tick-granular ones.
The practical result is a bounded worst-case latency, which is the property the camera loop needs. Throughput is slightly lower than the generic kernel — that trade is intentional.
5.2 Attach Ubuntu Pro#
The RT kernel is delivered only through Ubuntu Pro (elijahab account).
sudo pro attach # interactive - prompts for the token
pro status
Warning
Do not paste the Pro token into this document, a script, or shell
history. Run sudo pro attach with no argument so it prompts, or use
HISTCONTROL=ignorespace with a leading space. If a token has ever been
echoed into a shared file, rotate it.
5.3 Choose the Kernel Variant#
Two variants matter here. Pick before enabling — switching later means another kernel install and reboot.
Variant |
Use when |
|---|---|
(default) |
Generic |
|
Intel platform, and you want Intel TCC and TSN support built in. Validated on Intel Atom® X6000E and 11th/12th/13th Gen Intel® Core™. |
Important
This build enables TCC Mode in BIOS (§6), so ``intel-iotg`` is very likely the correct variant. The Intel-optimized kernel is what carries the TCC and TSN enablement; on the generic RT kernel you get the firmware-level TCC benefits but not the kernel-side feature support.
Confirm the CPU generation against the supported list before committing:
lscpu | grep -i 'model name'
List what your Pro subscription actually offers, then enable:
# Generic real-time kernel
sudo pro enable realtime-kernel
# -- OR -- Intel IOTG optimized (TCC / TSN enabled)
sudo pro enable realtime-kernel --variant=intel-iotg
Accept the prompt to install and switch the default boot kernel.
Note
The variant flag is only accepted at enable time. To change variants
afterwards, sudo pro disable realtime-kernel first.
5.4 Verify [reboot]#
sudo reboot
# After boot:
uname -a # expect PREEMPT_RT (and -realtime flavour)
uname -r
pro status | grep realtime # expect: realtime-kernel enabled
cat /sys/kernel/realtime 2>/dev/null # expect: 1
Confirm the RT scheduling classes are live:
chrt -m # SCHED_FIFO / SCHED_RR priority ranges
grep -c . /proc/pressure/cpu # PSI available
Warning
Record ``uname -r`` in the as-built log now. Out-of-tree drivers
(FT4222 helpers, any DKMS module) are built against a specific kernel. When
Pro ships an RT kernel update, those modules must be rebuilt and the
cyclictest baseline (§13) re-measured before the machine goes back on
sky.
Tip
To roll back to the generic kernel for debugging, see Canonical’s switch from real-time to generic kernel. Keep a generic kernel entry in the GRUB menu as an escape hatch.
6. CPU Shielding, GRUB & TCC#
GRUB Kernel Parameters#
Six cores (0–5) are shielded from the OS scheduler, RCU callbacks and the
timer tick. Edit /etc/default/grub:
GRUB_CMDLINE_LINUX_DEFAULT="quiet clocksource=tsc tsc=reliable nmi_watchdog=0 nosoftlockup isolcpus=domain,0-5 rcu_nocbs=0-5 nohz_full=0-5 irqaffinity=6-15 kthread_cpus=6-15"
Adjust 6-15 to your actual housekeeping range —
cat /sys/devices/system/cpu/present gives the total.
Parameter rationale:
Parameter |
Purpose |
|---|---|
|
Pin to the TSC; avoids HPET/ACPI read latency spikes |
|
Removes periodic NMI perf interrupts |
|
Suppresses soft-lockup warnings from long RT bursts |
|
Removes cores 0–5 from all scheduling domains |
|
Offloads RCU callbacks off the isolated cores |
|
Stops the 1 kHz tick when one task is runnable |
|
Directs all hardware IRQs to housekeeping cores — corrected, see below |
|
Restricts kernel threads to housekeeping cores |
Warning
``irqaffinity=0`` in the original RTC note is a copy-paste bug — corrected above.
Canonical’s Intel TCC tutorial uses isolcpus=3 … irqaffinity=0: core 3 is
isolated and IRQs are sent to core 0, which is a housekeeping core.
The original note copied that line but widened the isolated set to 0-5
while leaving irqaffinity=0 unchanged — which now points every hardware
interrupt into the shielded set, at the one core the RT threads most
depend on.
The rule is simply that the irqaffinity range and the isolcpus range
must not overlap. Canonical states this directly: “isolate one or more CPUs
to run the real-time application and the others to handle the IRQs and
kthreads.”
Note
splash was also dropped from the original line — it is meaningless on a
headless server.
Apply and reboot:
sudo update-grub
sudo reboot # [reboot]
Verify after boot:
cat /proc/cmdline
cat /sys/devices/system/cpu/isolated # expect 0-5
cat /sys/devices/system/cpu/nohz_full # expect 0-5
cat /sys/devices/system/cpu/present # total core count
Confirm no IRQ is still bound to a shielded core:
# Any line showing only cores 0-5 in the affinity list is a problem
for i in /proc/irq/[0-9]*; do
printf '%-8s %s\n' "$(basename "$i")" "$(cat "$i"/smp_affinity_list 2>/dev/null)"
done | sort -k2
Stray IRQs can be re-pointed at runtime (not persistent across reboot):
echo 6-15 | sudo tee /proc/irq/<IRQ-NUMBER>/smp_affinity_list
Warning
Never set an IRQ’s affinity mask to zero — every IRQ must be handled by at least one CPU.
Disable irqbalance#
irqbalance actively redistributes interrupts across all cores at runtime,
which silently undoes the irqaffinity boot parameter. It must be off.
sudo systemctl disable --now irqbalance
systemctl status irqbalance
Confine systemd Services to Housekeeping Cores#
Set a global default affinity so every systemd-managed service — present and
future — stays off the shielded cores. Edit /etc/systemd/system.conf:
[Manager]
CPUAffinity=6-15
sudo systemctl daemon-reexec # or reboot
This is broader and more reliable than per-unit CPUAffinity=, and it covers
the VNC unit in §10.3 automatically. Keep the per-unit setting anyway as
defence in depth.
BIOS Configuration Checklist#
Reboot and enter BIOS (
F2,Del, orEsc).Hyper-Threading / SMT / Logical Processors → Disabled. Deterministic execution requires one thread per physical core.
TCC Mode → Enabled. On Intel reference BIOS this lives under Intel® Advanced Menu ‣ Time Coordinated Computing. If the option is not present, the board vendor may have hidden it — consult the vendor or set the underlying options manually per Intel’s TCC User Guide.
Perform a double reboot — TCC settings are not fully applied until the second POST.
Note
TCC Mode subsumes the manual C-state work. Enabling it disables C-states and their sub-options, and optimizes power-state and frequency-transition handling. Canonical measured average scheduling jitter dropping from ~100 µs to sub-10 µs on an isolated core purely from this one firmware knob.
The mechanism matters for this instrument: an isolated core running a periodic task that finishes early idles for the remainder of the cycle, and the Linux idle subsystem then drops it into a deep C-state with a long exit latency. That exit latency is the jitter. If TCC Mode is unavailable on this board, disable C-states below C1 manually and set the power profile to Maximum Performance.
Inspect C-state configuration from the OS:
for cpu in /sys/devices/system/cpu/cpu*/cpuidle/state*; do
echo -n "$cpu: "; cat "$cpu"/name
echo -n " Target residency: "; cat "$cpu"/residency
echo -n " Exit latency: "; cat "$cpu"/latency
echo -n " Disabled [1=yes]: "; cat "$cpu"/disable
done
Further Intel Optimizations (optional)#
If the cyclictest baseline in §13 is not tight enough, two further Intel
features are worth evaluating:
Cache Allocation Technology (CAT) — partitions last-level cache so best-effort workloads on housekeeping cores cannot evict the RT task’s working set. Directly relevant when large frame buffers move through the machine.
Speed Shift / HWP — tunes frequency-transition responsiveness on the isolated cores.
See Canonical’s Optimizing real-time performance on Intel CPUs tutorial.
Tip
With shielding active, pin instrument threads to cores 0–5 using taskset,
chrt, cset, or the codebase’s own affinity settings. Nothing lands
there automatically.
7. Service Stripping#
Disable background daemons, timers and update machinery. On a headless server
several of these may already be absent — || true keeps the block
copy-pasteable.
for svc in \
irqbalance.service \
cups.service cups-browsed.service \
ModemManager.service \
avahi-daemon.service avahi-daemon.socket \
bluetooth.service \
apt-daily.timer apt-daily-upgrade.timer \
unattended-upgrades.service \
motd-news.timer \
snapd.service snapd.socket snapd.seeded.service \
fwupd-refresh.timer \
man-db.timer \
systemd-oomd.service
do
sudo systemctl disable --now "$svc" 2>/dev/null || true
done
Also disable the periodic locate/tracker indexers if present:
sudo systemctl disable --now plocate-updatedb.timer 2>/dev/null || true
Audit what is left:
systemctl list-units --type=service --state=running
systemctl list-timers --all
Warning
Disabling unattended-upgrades means security patching is now manual.
Schedule a maintenance window; do not simply forget about it.
Note
Keep ssh, systemd-networkd, systemd-timesyncd (or chrony),
and ubuntu-advantage enabled. Losing SSH on a headless RTC is the one
unrecoverable mistake in this document.
8. System Packages#
8.1 Core Build & Runtime (required)#
sudo apt update
sudo apt install -y \
build-essential \
cmake \
git \
pkg-config \
software-properties-common \
wget curl \
net-tools iproute2 \
htop \
tmux \
rsync \
libffi-dev libssl-dev zlib1g-dev libbz2-dev liblzma-dev \
libreadline-dev libsqlite3-dev libncursesw5-dev \
libxml2-dev libxmlsec1-dev xz-utils llvm \
python3-pip python3-dev python3-venv \
libboost-all-dev \
libcfitsio-dev libccfits-dev \
libopencv-dev \
libzmq3-dev
8.2 Real-Time Tooling (required)#
sudo apt install -y \
cset \
util-linux \
rt-tests \
linuxptp \
stress-ng
rt-tests provides cyclictest, used in 13. Verification & Acceptance.
8.3 Headless GUI Export (required — see 10. Remote GUI, Plots & Image Export)#
Minimal X client libraries and a lightweight window manager. No display manager, no desktop environment.
sudo apt install -y \
xauth x11-apps x11-utils \
tigervnc-standalone-server tigervnc-common \
openbox \
xterm \
fonts-dejavu-core
Note
xauth is the package people forget. Without it ssh -X silently fails
to set $DISPLAY and every remote GUI attempt dies with
cannot open display.
8.4 Qt Runtime (only if instrument GUIs are Qt-based)#
Install only if a tool you actually run on this machine needs Qt. Prefer running Qt GUIs on an operator workstation.
sudo apt install -y \
python3-pyqt5 \
qtbase5-dev qtbase5-dev-tools \
libxcb-xinerama0 libxkbcommon-x11-0
Warning
qt5-default does not exist on Ubuntu 24.04 (removed after 20.04).
The old FEI troubleshooting note recommending it is obsolete — use
qtbase5-dev and set QT_SELECT=5 if a legacy build script demands it.
8.5 KROOT / Keck Environment (optional, machine-dependent)#
Skip this on a pure pseudo-RTC. Install only if this box must build KROOT. This pulls in a large Tcl/Tk/Motif/X toolchain that is otherwise dead weight.
sudo apt install -y \
openconnect \
subversion cvs at \
python-dev-is-python3 python3-docutils \
libxt-dev libxml2-dev libncurses-dev \
tcl tcl-dev tcl-thread tcllib tk tk-dev expect \
tclx tcl-fitstcl libpq-dev \
g++ gfortran \
libboost-dev libboost-system-dev libboost-filesystem-dev \
python3-tk python3-pil.imagetk \
libpam-dev \
pandoc groff rst2pdf \
python3-ephem \
pyqt5-dev-tools \
make m4 autoconf \
xorg-dev xaw3dg-dev \
libmotif-dev \
libc6-dev-i386 \
snmp \
flex flex-doc bison bison-doc
9. Python Environment#
Headless Matplotlib#
There is no local display. Force the non-interactive backend system-wide so
plotting scripts never block or crash on $DISPLAY:
sudo tee /etc/profile.d/mpl-headless.sh > /dev/null <<'EOF'
export MPLBACKEND=Agg
EOF
Scripts then write figures to disk and you retrieve them per
10. Remote GUI, Plots & Image Export. Override interactively when tunnelling a GUI:
MPLBACKEND=Qt5Agg python plot.py.
Local Engineer Virtual Environments#
Option A — inherit the deployed global packages:
python3 -m venv --system-site-packages ~/fei-venv
source ~/fei-venv/bin/activate
Option B — fully isolated sandbox:
python3 -m venv ~/fei-venv_sandbox
source ~/fei-venv_sandbox/bin/activate
pip install --upgrade pip
Note
Never pip install into /opt/hispecfei/env for experimental work.
That environment is the deployed baseline — use Option A or B.
10. Remote GUI, Plots & Image Export#
The machine is headless. Three complementary paths get pixels off it, in increasing order of weight. Prefer the lightest one that does the job.
10.1 Files First (preferred)#
For plots, FITS previews and diagnostics, write files and pull them down. No X server, no VNC, zero jitter on the RT cores.
# From your workstation
rsync -avz hsdev@hispecfei:/data/plots/ ./plots/
scp hsdev@hispecfei:/data/frames/latest.fits .
Or serve a directory read-only over an SSH tunnel:
# On hispecfei (bind to loopback only)
cd /data/plots && python3 -m http.server 8000 --bind 127.0.0.1
# On your workstation
ssh -L 8000:localhost:8000 hsdev@hispecfei
# then browse http://localhost:8000
Note
Binding to 127.0.0.1 and reaching it through the SSH tunnel keeps the
server off the site network. Do not bind 0.0.0.0.
10.2 SSH X11 Forwarding (single applications)#
For one-off Qt/Tk tools, forward the individual window — no persistent desktop.
Requires X11Forwarding yes (§3) and xauth (§8.3) on the server, and an
X server on the client (native on Linux, XQuartz on macOS, VcXsrv/MobaXterm on
Windows).
# From your workstation
ssh -X hsdev@hispecfei
xeyes # smoke test
xdpyinfo | head # confirms the forwarded display
# -Y (trusted) only if -X trips an extension error, and only on a trusted LAN
ssh -Y hsdev@hispecfei
Tip
X11 forwarding is chatty over high-latency links. For anything that redraws continuously, use VNC (§10.3) instead — it compresses far better.
10.3 TigerVNC Session (persistent desktop)#
For a session that survives disconnect — long-running Archon GUIs, alignment tools, multi-window work.
Set the VNC password (as hsdev):
vncpasswd
Configure a minimal Openbox session in ~/.vnc/xstartup:
mkdir -p ~/.vnc
cat > ~/.vnc/xstartup <<'EOF'
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
export MPLBACKEND=Qt5Agg
exec openbox-session
EOF
chmod +x ~/.vnc/xstartup
Start the server, pinned off the shielded cores. This is the critical RTC detail — VNC must never run on cores 0–5:
# Adjust 6-15 to your housekeeping core range
taskset -c 6-15 vncserver :1 \
-localhost yes \
-geometry 1920x1080 \
-depth 24
-localhost yes binds VNC to loopback only. Reach it through an SSH tunnel:
# On your workstation
ssh -L 5901:localhost:5901 hsdev@hispecfei
# then point any VNC client at localhost:5901
Stop the session:
vncserver -kill :1
Optional — run it as a pinned systemd user service. Create
/etc/systemd/system/vncserver@.service:
[Unit]
Description=TigerVNC server on display %i (housekeeping cores only)
After=network-online.target
[Service]
Type=forking
User=hsdev
WorkingDirectory=/home/hsdev
# Confine to housekeeping cores - keeps VNC off the shielded set
CPUAffinity=6-15
Nice=10
ExecStartPre=-/usr/bin/vncserver -kill :%i
ExecStart=/usr/bin/vncserver :%i -localhost yes -geometry 1920x1080 -depth 24
ExecStop=/usr/bin/vncserver -kill :%i
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now vncserver@1.service
Warning
CPUAffinity= in the unit file and taskset on the command line are
both mandatory habits on this machine. An unpinned VNC session will migrate
onto an isolated core and inject latency into the camera loop — the exact
failure this whole build exists to prevent.
Important
Never expose VNC (5900–5910) directly to the network. Always
-localhost yes + SSH tunnel. TigerVNC’s native auth is weak and the
Archon network must stay clean.
11. Hardware Drivers & Subsystems#
11.1 Physik Instrumente (PI) Driver#
Download the Linux driver package from the Physik Instrumente Software Suite on a workstation and copy it over with
scp(the RTC has no browser).Extract, then run the installer:
cd <path_to_unpacked_PI_driver> sudo ./INSTALL
Installer prompt responses:
Prompt
Answer
Do you agree to the General Software License Agreement? [yn]
y(license text shown in pager)
qInstall the PI
${PI_PRODUCT_NAME}high level GCS library? [ynq]yTo enable the access rights to a user group now press ‘y’
yEnable the access rights to a user group now? [ynq]
y(license text shown again)
nInstall
${PIPython}now? [ynq]nInstall
${PI Terminal}now? [ynq]yPlease enter the name of the user group …
dialout
Note
PIPython is declined at the installer prompt on purpose — it is
installed into the managed venv via pip install pipython (§9) so the
deployed environment stays reproducible.
11.2 SPI Driver (libft4222)#
Extract the archive:
tar xfvz libft4222-1.4.4.232.tgzExpected contents:
build-x86_32/build-x86_64build-arm-v6-hf/build-arm-v7-hf/build-arm-v7-sf/build-arm-v7-hf-uclibc/build-arm-v8libft4222-linux-1.4.4.221(mips, based on libftd2xx v1.4.27)examples/libft4222.h,ftd2xx.h,WinTypes.hinstall4222.sh
Install the library:
sudo ./install4222.shThis copies
libft4222.so.1.4.4.232to/usr/local/liband the headers to/usr/local/include, and creates the version-independent symlinklibft4222.so.sudo ldconfig ldconfig -p | grep ft4222
Build the example test binary:
cd examples # Dynamic link cc get-version.c -lft4222 -Wl,-rpath,/usr/local/lib -o ft4222-version # Static link cc -static get-version.c -lft4222 -Wl,-rpath,/usr/local/lib \ -ldl -lpthread -lrt -lstdc++ -o ft4222-version-static
Note
The original notes ran
ccundersudo. That is unnecessary — compiling into your own directory needs no privileges, and root-owned build artifacts cause permission problems later. Dropped.Run the test:
./ft4222-versionExpected output:
Chip version: 42220400, LibFT4222 version: 010404E8
Warning
The original note suggested sudo apt-get install binutils-2.26 if static
linking failed. No such package exists on Ubuntu 24.04 — that advice is
from a much older release. If static linking fails on 24.04, link
dynamically (the supported path) or investigate the actual linker error;
do not chase a versioned binutils package.
11.3 FT4222 udev Rules (non-root USB access)#
Create
/etc/udev/rules.d/99_HISPEC_spi_ftdi_4222.rules:SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="601c", OWNER="hsdev", MODE="0660", GROUP="dialout"Reload:
sudo udevadm control --reload-rules sudo udevadm trigger
Replug the board and verify ownership:
lsusb | grep 0403 ls -l /dev/bus/usb/*/* | grep -i 0403
The node should be owned by
hsdev, groupdialout, mode0660. The SPI board is then usable withoutsudo.
Note
SPI master mode: the Slave Select (SS) pin must be tied high.
11.4 CameraD (camera-interface)#
cd ~
git clone https://github.com/CaltechOpticalObservatories/camera-interface.git
cd camera-interface/build
rm -rf ./*
cmake .. -DCONTROLLER=archon -DINSTRUMENT=hispec_tracking_camera
make -j"$(nproc)"
Record the commit hash in the as-built log:
git -C ~/camera-interface rev-parse --short HEAD
See archongui.rst for Archon-side configuration and GUI usage.
12. Real-Time Process Placement#
12.1 Real-Time Scheduling Privileges#
Allow non-root processes to request FIFO real-time priority:
sudo setcap 'cap_sys_nice=eip' "$(command -v chrt)"
chrt -f 60 ./<executable>
Alternatively grant it per-group in /etc/security/limits.d/99-rt.conf:
@eng - rtprio 95
@eng - memlock unlimited
@eng - nice -20
Log out and back in to apply.
12.2 Pinning to Shielded Cores#
# Direct affinity
taskset -c 0-5 chrt -f 80 ./camerad
# Or via cpuset shielding (cores 0-5 shielded, rest for the system)
sudo cset shield --cpu 0-5 --kthread=on
sudo cset shield --exec -- chrt -f 80 ./camerad
sudo cset shield --reset # tear down
12.3 What Must Never Touch Cores 0–5#
VNC / Xvnc / Openbox (§10.3 — pinned to housekeeping cores)
SSH sessions and interactive shells
rsync/scptransfershtop, monitoring agents, log shippersCompilation (
make -j) — build on housekeeping cores or another machine
Tip
Add this to /home/hsdev/.bashrc so no login shell ever lands on a
shielded core:
taskset -cp 6-15 $$ > /dev/null 2>&1
13. Verification & Acceptance#
Run this after the final reboot. Record the results as the as-built baseline.
Check |
Command |
Expected |
|---|---|---|
Hostname |
|
|
Users / groups |
|
|
RT kernel |
|
contains |
RT flag |
|
|
Ubuntu Pro |
|
|
Kernel variant |
|
|
Kernel cmdline |
|
matches §6 |
Isolated cores |
|
|
Tickless cores |
|
|
IRQ affinity |
|
no entry confined to 0–5 |
irqbalance off |
|
|
systemd affinity |
|
|
SMT disabled |
|
|
C-states (TCC) |
|
deep states |
Clocksource |
|
|
No desktop |
|
|
Services stripped |
|
short list only |
Management net |
|
|
Archon link |
|
0% loss |
Python |
|
|
FT4222 |
|
|
udev perms |
|
|
X11 forward |
|
window appears |
VNC |
tunnel |
Openbox session |
VNC pinning |
|
not 0–5 |
Latency Baseline#
Run under representative load and keep the numbers:
# 30 minutes, RT prio 80, one thread per shielded core, hist output
sudo cyclictest -m -S -p80 -i200 -h400 -D30m -a 0-5 > cyclictest_baseline.txt
# Repeat while stressing the housekeeping cores
stress-ng --cpu 8 --taskset 6-15 --timeout 30m &
sudo cyclictest -m -S -p80 -i200 -h400 -D30m -a 0-5 > cyclictest_loaded.txt
Compare max latency loaded vs. idle. A large gap means something is still
scheduled on the isolated cores — recheck irqaffinity (§6) first.
14. Troubleshooting#
Symptom |
Resolution |
|---|---|
|
Install |
|
Untrusted-X extension restriction. Acceptable on a trusted LAN; verify
the client’s |
VNC connects to a grey screen |
|
VNC refuses remote connections |
Expected — |
Qt app: |
Install |
Advice to install |
Obsolete. Package removed after Ubuntu 20.04. Use |
Matplotlib fails with no display |
|
FT4222 not found |
|
FT4222 ABI mismatch on |
Requires |
SPI master mode misbehaves |
Slave Select (SS) must be tied high. |
Static link fails, linker looks old |
Link dynamically. Do not chase |
|
Install |
Latency spikes under load |
Work the list in order: (1) |
RT kernel not booting after a Pro update |
Select the previous kernel from the GRUB menu. Out-of-tree modules need
rebuilding against the new |
|
|
Locked out after |
Physical console required. Always use |
Group membership not taking effect |
|
15. Pending Tasks#
[ ] RAID 1 — finalize hardware or software RAID 1 for the data drives. Revisit the
/usr-on-second-drive layout at the same time (§2).[ ] Static IP — confirm
192.168.29.107is applied and reserved on the site network (§4); the previous build was still on DHCP.[ ] Kernel variant — confirm whether
--variant=intel-iotgapplies to this CPU and re-enable if the generic RT kernel was installed first (§5.3).[ ] Intel CAT / Speed Shift — evaluate if the §13 latency baseline is not tight enough (§6).
[ ] Patching policy —
unattended-upgradesis disabled (§7); define a manual maintenance window.[ ] Backups — no backup strategy defined for
/opt/hispecfeior instrument configuration.[ ] Software stack — track upstream GitHub build notes for Python libraries, C++ sources and hardware drivers.
[ ] As-built log — record kernel version,
camera-interfacecommit, driver versions andcyclictestbaselines.
16. Final Step#
Reboot to apply kernel parameters, BIOS settings, service changes and udev rules, then work through §13.
sudo reboot
Done.
17. References#
Real-time Ubuntu#
Tuning#
Intel TCC#
Measurement#
Instrument#
archongui.rst— Archon GUI and controller configuration