Zum Inhalt

Ubuntu LTS Server Provisioning: Subiquity Autoinstall, ZFS/LVM-on-LUKS2, AppArmor & De-Snapping

Executive Summary: Ubuntu LTS (24.04 Noble Numbat) powers a massive share of cloud instances, AI/CUDA compute nodes, and enterprise Kubernetes clusters. However, a default Ubuntu Server installation includes telemetry agents, Snapd background loop mounts, and permissive network defaults. This architectural guide details a hardened Ubuntu LTS Server deployment—covering declarative Subiquity Cloud-Init autoinstall.yaml provisioning, LVM-on-LUKS2 or Native ZFS Root (ZFSBootMenu), complete removal or pinning of snapd where desired, AppArmor mandatory access control, and Netplan VLAN/Bridge configuration.

  • Subiquity autoinstall.yaml


    Provision bare-metal and KVM servers unattended using Cloud-Init compatible YAML declarations for storage, LUKS2, networking, and SSH keys.

  • Minimal Loop-Free Footprint


    Eliminate snapd squashfs loop mounts, ubuntu-report, and MOTD advertisement scripts (motd-news) for a clean, deterministic server baseline.

  • Declarative Netplan (networkd)


    Configure LACP 802.3ad network bonds, 802.1Q VLAN trunks, and KVM bridges cleanly via /etc/netplan/ rendered to systemd-networkd.

  • AppArmor & UFW / nftables


    Enforce path-based Mandatory Access Control (aa-status) alongside automated unattended-upgrades from noble-security.


1. Architecture: Subiquity Provisioning Pipeline & Storage Stack

Ubuntu Server uses the Subiquity installer backed by Curtin (for fast block-level image extraction and partitioning) and Cloud-Init (for first-boot identity, SSH, package, and late-command orchestration):

%%{init: {'flowchart': {'wrappingWidth': 600, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
    subgraph BootMedia["Ubuntu 24.04 LTS Live Server ISO"]
        Subiquity["Subiquity + Curtin Engine<br/>Reads user-data (autoinstall)"]
    end

    subgraph DiskLayout["Curtin Encrypted Storage Layout"]
        ESP["/boot/efi (1 GiB FAT32)<br/>+ /boot (2 GiB ext4)"]
        LUKS["LUKS2 Container (dm_crypt)<br/>LVM Volume Group (ubuntu-vg)"]
        LVs["lv_root (ext4/XFS) +<br/>lv_var + lv_log"]
    end

    subgraph FirstBoot["Cloud-Init Post-Provisioning"]
        Netplan["Netplan -> systemd-networkd<br/>Static IP / VLAN / Bridge"]
        Hardening["AppArmor Enforcing +<br/>Remove Telemetry & Snapd"]
    end

    Subiquity --> ESP
    Subiquity --> LUKS
    LUKS --> LVs
    LVs --> Netplan
    Netplan --> Hardening

2. Cryptographic Verification of Ubuntu LTS Server Media

Download ubuntu-24.04.*-live-server-amd64.iso, SHA256SUMS, and SHA256SUMS.gpg, and verify Canonical's Archive Signing Key before flashing:

Verifying Ubuntu LTS ISO Signature & SHA-256 Digest
# 1. Retrieve Canonical CD Image Signing Key (8439 38DF 228D 22F7 B374 2BC0 D94A A3F0 EFE2 1092)
gpg --keyserver keyserver.ubuntu.com --recv-keys 843938DF228D22F7B3742BC0D94AA3F0EFE21092

# 2. Verify GPG signature and ISO checksum
gpg --verify SHA256SUMS.gpg SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS

3. Declarative Zero-Touch Provisioning (autoinstall.yaml)

Instead of manually stepping through interactive prompts, serve user-data and meta-data over HTTP or a labeled CIDATA USB volume to deploy an encrypted, minimal Ubuntu 24.04 LTS server:

user-data (Subiquity Autoinstall Specification)
#cloud-config
autoinstall:
  version: 1
  locale: en_US.UTF-8
  keyboard:
    layout: de
    variant: nodeadkeys
  timezone: Europe/Berlin

  # Install minimal server variant without bloatware or third-party snaps
  source:
    id: ubuntu-server-minimal
    search_drivers: false

  identity:
    hostname: ubuntu-node-01
    username: nejat
    # Generate via: mkpasswd --method=SHA-512 --rounds=500000
    password: "$6$rounds=500000$YourHashedPasswordHere"

  ssh:
    install-server: true
    allow-pw: false
    authorized-keys:
      - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... nejat@workstation"

  storage:
    layout:
      name: lvm
      sizing-policy: scaled
      password: "InitialLUKS2PassphraseRotatePostBoot"

  packages:
    - curl
    - git
    - neovim
    - nftables
    - unattended-upgrades
    - needrestart

  late-commands:
    - curtin in-target -- target=/target -- systemctl disable --now motd-news.timer

Disabling Subiquity LVM 50% Allocation Cap

When performing a manual interactive Ubuntu Server installation with Guided LVM, Subiquity defaults to allocating only 50% (or max 100 GiB) of the Volume Group to ubuntu-lv (/), leaving the rest unallocated for snapshots. You can either increase this value directly on the installer's storage summary screen or expand it online post-install via sudo lvextend -l +100%FREE -r /dev/ubuntu-vg/ubuntu-lv.


4. Post-Install De-Snapping & Telemetry Removal

If you require a pure .deb server environment without snapd mounting squashfs loop devices in df -h and lsblk, purge snapd and place an APT pin in /etc/apt/preferences.d/ so apt never reinstalls it as a transitive dependency:

Removing Snapd, Disabling Ubuntu MOTD Ads & Pinning APT
# 1. Stop and purge snapd and any default snaps (lxd, core22)
sudo systemctl disable --now snapd.service snapd.socket snapd.seeded.service
sudo apt purge -y snapd ubuntu-advantage-tools popularity-contest
sudo rm -rf /snap /var/snap /var/lib/snapd /var/cache/snapd

# 2. Prevent APT from ever reinstalling snapd
cat << 'EOF' | sudo tee /etc/apt/preferences.d/nosnap.pref
Package: snapd
Pin: release a=*
Pin-Priority: -10
EOF

# 3. Disable dynamic MOTD external HTTP calls (motd-news)
sudo sed -i 's/ENABLED=1/ENABLED=0/' /etc/default/motd-news
sudo chmod -x /etc/update-motd.d/10-help-text /etc/update-motd.d/50-motd-news

5. Declarative Networking with Netplan (systemd-networkd)

Ubuntu Server uses Netplan (/etc/netplan/*.yaml, strict 0600 permissions) to compile network topology into systemd-networkd units. Below is a production configuration defining a static IPv4/IPv6 host interface alongside a KVM virtualization bridge (br0):

/etc/netplan/01-server-network.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp1s0:
      dhcp4: false
      dhcp6: false

  bridges:
    br0:
      interfaces: [enp1s0]
      addresses:
        - 192.168.10.40/24
        - fd88:cafe:10::40/64
      routes:
        - to: default
          via: 192.168.10.1
      nameservers:
        addresses:
          - 192.168.10.2
        search:
          - lan.nejat-hakan.de
      parameters:
        stp: false
        forward-delay: 0

Apply and test the Netplan configuration safely with automatic 120-second rollback protection (netplan try):

Securing Permissions, Testing Netplan & Auditing AppArmor
# 1. Enforce mandatory 0600 permissions on Netplan configuration files
sudo chmod 0600 /etc/netplan/*.yaml

# 2. Test network changes with automatic rollback if SSH connectivity drops
sudo netplan try

# 3. Verify AppArmor Mandatory Access Control profiles are in enforce mode
sudo aa-status