A complete guide to building a bootable Ubuntu Server USB drive running CasparCG, with live boot capability, optional local installation via Calamares, and a dedicated ext4 media partition on the internal drive.
[ USB Drive ] [ Internal 2TB Drive ]
Ubuntu Server Windows Partition (untouched)
CasparCG + services ----------------------------
Penguins' Eggs + Calamares ext4 Media Partition (1TB)
NVIDIA DKMS drivers Logs, media assets, config
| |
└──── boots live ──────────────────── reads/writes ──────┘
What this guide covers:
Do this first, before touching Linux. You only need to do it once.
Win + X → select Disk Management1048576
(that is exactly 1TB in MB)
⚠️ If Windows says it cannot shrink by the full amount, it means unmovable files (hibernate file, page file) are blocking it. Disable hibernation first:
powershell (run as Administrator): powercfg /h offThen retry the shrink.
This is the machine you will use to build the master image. It should have the same GPU as your target machines (or at minimum the same NVIDIA GPU generation).
Download Ubuntu Server 22.04 LTS from ubuntu.com and install it normally. During installation:
caspar)sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential curl wget git software-properties-common
CasparCG needs to start without human interaction. Configure auto-login:
sudo mkdir -p /etc/systemd/system/getty@tty1.service.d/
sudo nano /etc/systemd/system/getty@tty1.service.d/override.conf
Paste this content:
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin caspar --noclear %I $TERM
Using DKMS ensures the driver kernel module is automatically recompiled when the image is booted on a machine with a different kernel version or minor hardware variation.
sudo apt install -y dkms linux-headers-$(uname -r) linux-headers-generic
sudo add-apt-repository ppa:graphics-drivers/ppa -y
sudo apt update
sudo apt install -y nvidia-driver-550 nvidia-dkms-550
Replace
550with the current recommended driver version for your GPU. To check which version is recommended:ubuntu-drivers devices
After installation, confirm the driver is registered with DKMS:
dkms status
Expected output (version numbers will vary):
nvidia/550.xx.xx, 6.x.x-xx-generic, x86_64: installed
sudo reboot
# After reboot:
nvidia-smi
You should see your GPU listed with driver version confirmed.
sudo apt install -y \
ffmpeg \
fonts-liberation \
libgles2 \
libgles2-mesa \
libx11-6 \
libxrandr2 \
libxinerama1 \
libxi6 \
libxcursor1 \
openjdk-17-jre
Download the Desktop Video package from the Blackmagic Design website:
https://www.blackmagicdesign.com/support/family/capture-and-playback
Install it:
sudo dpkg -i desktopvideo_*.deb
sudo apt --fix-broken install -y
sudo reboot
After reboot, verify DeckLink is detected:
BlackmagicFirmwareUpdater status
sudo mkdir -p /home/casparcg/highascg
cd /home/casparcg/highascg
# Download latest CasparCG release (check github.com/CasparCG/server for current version)
wget https://github.com/CasparCG/server/releases/download/v2.3.3/casparcg_server-2.3.3-Linux.tar.gz
tar -xzf casparcg_server-*.tar.gz --strip-components=1
sudo chown -R caspar:caspar /home/casparcg/highascg
Edit the CasparCG configuration file:
nano /home/casparcg/highascg/config/casparcg.config
Set the media and log paths to point to the data partition mount point (which we will set up in Part 5):
<configuration>
<paths>
<media-path>/mnt/caspar-data/media/</media-path>
<log-path>/mnt/caspar-data/logs/</log-path>
<data-path>/mnt/caspar-data/data/</data-path>
<template-path>/mnt/caspar-data/templates/</template-path>
</paths>
<!-- Your channel and consumer configuration below -->
<channels>
<channel>
<video-mode>1080i5000</video-mode>
<consumers>
<decklink>
<device>1</device>
<key-device>2</key-device>
</decklink>
</consumers>
</channel>
</channels>
</configuration>
Adjust
video-modeand DeckLink device numbers for your setup.
These will be created again in Part 5 when we prepare the partition, but define them here for reference:
/mnt/caspar-data/
media/
logs/
data/
templates/
sudo nano /etc/systemd/system/casparcg.service
Paste the following:
[Unit]
Description=CasparCG Playout Server
After=network.target caspar-data.mount
Requires=caspar-data.mount
[Service]
Type=simple
User=caspar
WorkingDirectory=/home/casparcg/highascg
ExecStart=/home/casparcg/highascg/run.sh
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Enable the service:
sudo systemctl daemon-reload
sudo systemctl enable casparcg.service
This is done from the Ubuntu system (either booted from USB or installed). The unallocated space created in Part 1 will now become a formatted, auto-mounting ext4 partition.
lsblk
Look for your 2TB drive — it will show the Windows NTFS partition and the unallocated space. Identify the device name (e.g. /dev/sda) and note the partition number of the unallocated space.
Example output:
sda 2TB
├─sda1 100MB vfat (Windows EFI)
├─sda2 128MB (Windows MSR)
├─sda3 931GB ntfs (Windows C:)
└─ free (your 1TB unallocated space)
sudo parted /dev/sda
Inside parted:
(parted) print free # confirm free space location
(parted) mkpart primary ext4 932GB 2000GB # adjust start/end to match your free space
(parted) print # confirm new partition
(parted) quit
Use the exact start and end values shown by
print free— do not guess them.
# Refresh partition table
sudo partprobe /dev/sda
# Format (replace sda4 with your actual new partition number)
sudo mkfs.ext4 -L caspar-data /dev/sda4
The -L caspar-data sets a volume label — we’ll use this for reliable mounting.
sudo mkdir -p /mnt/caspar-data
Using the label means the partition mounts correctly regardless of whether it appears as sda4, sdb4, etc. on different machines:
sudo nano /etc/fstab
Add this line at the end:
LABEL=caspar-data /mnt/caspar-data ext4 defaults,nofail,x-systemd.automount 0 2
nofailis critical — it tells the system to boot normally even if this partition is not present (important for live USB scenarios on machines where the internal drive may be different).
sudo mount /mnt/caspar-data
sudo mkdir -p /mnt/caspar-data/{media,logs,data,templates}
sudo chown -R caspar:caspar /mnt/caspar-data
This ensures the partition is mounted before CasparCG starts, even if fstab is slow:
sudo nano /etc/systemd/system/caspar-data.mount
[Unit]
Description=CasparCG Data Partition
Before=casparcg.service
[Mount]
What=LABEL=caspar-data
Where=/mnt/caspar-data
Type=ext4
Options=defaults,nofail
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable caspar-data.mount
Add a startup check script so CasparCG falls back gracefully if the data partition isn’t found:
sudo nano /home/casparcg/highascg/run.sh
#!/bin/bash
MOUNT=/mnt/caspar-data
# Wait up to 10 seconds for the data partition to mount
for i in $(seq 1 10); do
if mountpoint -q "$MOUNT"; then
echo "Data partition mounted at $MOUNT"
break
fi
echo "Waiting for data partition... ($i/10)"
sleep 1
done
# If partition never mounted, use local fallback paths
if ! mountpoint -q "$MOUNT"; then
echo "WARNING: Data partition not found. Using local fallback paths."
mkdir -p /home/casparcg/highascg/fallback/{media,logs,data,templates}
export CASPAR_MEDIA=/home/casparcg/highascg/fallback/media
else
export CASPAR_MEDIA=$MOUNT/media
fi
exec /home/casparcg/highascg/casparcg
chmod +x /home/casparcg/highascg/run.sh
# Official apt repo (PPA KEY.gpg is empty — use penguins-eggs.net instead)
curl -fsSL https://penguins-eggs.net/repos/KEY.asc | sudo gpg --dearmor -o /usr/share/keyrings/penguins-eggs-repos.gpg
echo "deb [signed-by=/usr/share/keyrings/penguins-eggs-repos.gpg] https://penguins-eggs.net/repos/deb stable main" | \
sudo tee /etc/apt/sources.list.d/penguins-eggs-repos.list
sudo apt update
sudo apt install -y penguins-eggs
sudo eggs dad -d
This creates the Eggs configuration directory at /etc/penguins-eggs.d/ and sets up defaults.
Eggs uses an exclusion file to skip directories when building the ISO. This is how you keep the image lean and avoid including unwanted content.
Edit the exclusions file:
sudo nano /etc/penguins-eggs.d/exclude.list
Add the following — each line is a path that will be excluded from the ISO:
# System runtime directories (always exclude)
/proc
/sys
/dev
/run
/tmp
# Swap
/swapfile
*.swap
# CasparCG data partition mount point
# (this is on the internal drive, not the USB — exclude entirely)
/mnt/caspar-data
# CasparCG media, logs, and data (exclude from image)
# These live on the data partition, not the OS
/home/casparcg/highascg/media
/home/casparcg/highascg/logs
/home/casparcg/highascg/data
/home/casparcg/highascg/fallback
# Large or machine-specific files
/var/log
/var/cache/apt/archives
/var/tmp
/home/caspar/.cache
/home/caspar/Downloads
/root/.cache
# NVIDIA compiled module cache (will recompile via DKMS on target hardware)
/var/lib/dkms/*/build
/usr/src/nvidia-*/*/dkms.conf.orig
# Any test media you may have had locally during setup
/home/casparcg/highascg/test-media
Important: The
/mnt/caspar-dataexclusion is critical. Without it, Eggs would try to include whatever is currently mounted there (your internal drive’s media partition) into the ISO — potentially gigabytes of media files.
sudo eggs produce --dry-run 2>&1 | grep -i exclud
You should see your excluded paths listed in the output.
sudo eggs dad --help
sudo eggs status
Confirm everything looks correct — partition layout, user accounts, services.
--clone — required for casparcg)HighAsCG and the surrounding install assume the casparcg system user: systemd units, file ownership under /opt, and the home tree under /home/casparcg. A plain sudo eggs produce (without --clone) removes all host users from the live root and replaces them with a generic live account. That is why the build log shows lines like Removing user: casparcg — it is normal for the default mode, but wrong for this stack.
Always build with --clone so accounts and home directories from this machine are included in the squashfs. On a dedicated image-build host with generic passwords, the larger ISO and copied home trees are usually acceptable.
sudo eggs produce --clone --max --basename casparcg-live
Optional before the build: remove accounts you do not want in the image at all (for example an extra desktop user). Do not remove casparcg on the build host before produce, or the clone will not contain that user.
# Example only — removes user coolux from the SOURCE machine before imaging
# sudo deluser coolux
Flags explained:
--clone — include user accounts and user data in the live filesystem (keeps casparcg and /home/casparcg)--max — maximum compression (slower build, smaller ISO)--basename — sets the output filenameThe build will take longer than a non-clone image and the ISO will be larger (rough guide: often ~8–25+ GB depending on what is under /home and what your exclude.list still strips). The ISO will be saved to:
/home/eggs/
ls -lh /home/eggs/*.iso
Without --clone, a lean Caspar-only root might land around 3–6 GB. With --clone, expect a much larger file; that is expected.
# Identify your USB drive - BE CAREFUL to select the right device
lsblk
# Flash (replace sdX with your USB device - NOT a partition, the whole device)
sudo dd if=/home/eggs/casparcg-live.iso of=/dev/sdX bs=4M status=progress oflag=sync
Use Balena Etcher (free, from etcher.balena.io):
.iso filesudo dd if=casparcg-live.iso of=/dev/rdiskX bs=4m
F12, F8, or Del at POST)# Check CasparCG service status
systemctl status casparcg.service
# Check data partition is mounted
mountpoint /mnt/caspar-data
df -h /mnt/caspar-data
# Check NVIDIA driver loaded correctly on this hardware
nvidia-smi
# Check DeckLink detected
BlackmagicFirmwareUpdater status
On first boot with different hardware, DKMS will automatically recompile the NVIDIA kernel module. This happens in the background and may take 1–3 minutes. You can monitor it:
journalctl -f -u dkms
# or
dkms status
CasparCG’s systemd service will wait for the system to be ready before starting.
If the user wants to install the system permanently to the local machine (faster than USB, no USB required to boot):
Calamares is included in the Eggs-built ISO:
sudo calamares
Or if a desktop environment is available, it may appear as an “Install System” icon.
/ (root)/dev/sda)casparcg if the installer asks you to reconcile users — many clone installs keep the cloned accounts)Remove the USB drive. The machine will boot from the internal drive. CasparCG will autostart, and the caspar-data partition will mount automatically via fstab.
| Purpose | Path |
|---|---|
| CasparCG installation | /home/casparcg/highascg/ |
| CasparCG config | /home/casparcg/highascg/config/casparcg.config |
| CasparCG startup script | /home/casparcg/highascg/run.sh |
| Systemd service | /etc/systemd/system/casparcg.service |
| Data partition mount | /mnt/caspar-data/ |
| Media files | /mnt/caspar-data/media/ |
| Logs | /mnt/caspar-data/logs/ |
| Templates | /mnt/caspar-data/templates/ |
| Eggs ISO output | /home/eggs/ |
| Eggs exclusions | /etc/penguins-eggs.d/exclude.list |
| fstab | /etc/fstab |
CasparCG doesn’t start on boot
journalctl -u casparcg.service -n 50
Data partition not mounting
journalctl -u caspar-data.mount
lsblk -f # check if partition is visible and has correct label
NVIDIA driver not loaded after boot on new hardware
dkms status
journalctl -b | grep -i nvidia
# If missing, trigger recompile manually:
sudo dkms autoinstall
Eggs ISO too large
# Check what is taking up space before building:
sudo du -sh /* | sort -rh | head -20
# Add any large unexpected directories to exclude.list
Build log says Removing user: casparcg
You ran eggs produce without --clone. Cancel if still safe, then rebuild with sudo eggs produce --clone ... (see §7.2). Default Eggs behaviour strips host users from the ISO workspace and creates only the live user; that breaks a casparcg-centric install.
DeckLink not detected
# Check kernel module is loaded
lsmod | grep blackmagic
# Reload if needed
sudo modprobe blackmagic
BlackmagicFirmwareUpdater status
Guide covers Ubuntu Server 22.04 LTS, CasparCG 2.3.x, Penguins’ Eggs latest, NVIDIA driver 550 series. Adjust version numbers as needed for current releases.