Why Trixie
Debian 13 became stable on 9 August 2025. It brings Linux 6.12 LTS, systemd 257, OpenSSH 10, Python 3.13, GCC 14, PostgreSQL 17 and a modern Go and Rust toolchain in the main archive. Security support should run to around 2028, and Debian LTS extends it to about 2030.
What hasn't changed is the Debian character: no telemetry, no snap layer, nothing running you didn't ask for. If you want a small, auditable base with years of patches, this is the image.
First boot
apt update && apt full-upgrade -y
apt install -y sudo unattended-upgrades needrestart curl tmux
adduser svc && usermod -aG sudo svc
install -d -m 0700 -o svc -g svc /home/svc/.ssh
install -m 0600 -o svc -g svc ~/.ssh/authorized_keys /home/svc/.ssh/
Then lock SSH down with a drop-in. OpenSSH 10 has removed DSA keys entirely and keeps tightening defaults, so old client keys may need replacing anyway:
printf 'PasswordAuthentication no\nPermitRootLogin no\nAllowUsers svc\n' \
> /etc/ssh/sshd_config.d/local.conf
sshd -t && systemctl reload ssh
Always run sshd -t before reloading. A syntax error in a drop-in stops sshd from accepting new connections.
Sources in deb822
Trixie encourages the structured .sources format. A typical file looks like this:
# /etc/apt/sources.list.d/debian.sources
Types: deb
URIs: http://deb.debian.org/debian
Suites: trixie trixie-updates
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://security.debian.org/debian-security
Suites: trixie-security
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Third-party repositories such as Docker, PGDG or Grafana now document deb822 snippets too. Keep their keys in /etc/apt/keyrings/, not the deprecated apt-key store.
Automatic security updates
echo 'APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";' > /etc/apt/apt.conf.d/20auto-upgrades
systemctl enable --now apt-daily.timer apt-daily-upgrade.timer
unattended-upgrade --dry-run
Pair this with a reboot policy. On a fleet of identical stateless nodes, enable Automatic-Reboot and stagger the reboot times. On a single database server, watch for /run/reboot-required and reboot by hand.
Firewall
nftables is the native filter. Write /etc/nftables.conf with a default-drop input chain, allow established traffic, loopback and the ports you serve, and enable the nftables service. If you prefer a front-end, ufw and firewalld both package cleanly on Trixie. Pick one tool and don't mix them. Then add matching rules in the portal firewall so unwanted traffic is dropped before it reaches the VM at all.
Changes worth knowing
- /tmp is tmpfs. Trixie mounts
/tmpin RAM by default, capped at half of memory. On a 2 GB Spark, a big build that unpacks into/tmpcan run out of RAM. PointTMPDIRat disk for heavy jobs, or masktmp.mount. - i386 is gone as a full architecture. You are on amd64 anyway, but 32-bit multiarch packages are thinner than before.
- Wider use of systemd-resolved and networkd in minimal images. Check
resolvectl statusbefore editing/etc/resolv.confby hand. - PostgreSQL 17 by default. A dump from a 15 cluster restores fine, but
pg_upgradeclusteris the cleaner route for in-place moves.
Kernel 6.12 on NVMe
The 6.12 LTS kernel is a good match for fast virtual storage. Multi-queue block I/O is the default, io_uring is mature, and the EEVDF scheduler in this series handles mixed interactive and batch load better than older kernels did. You don't need to tune anything to benefit. If you run a database, watch iostat -x 5 under real load before changing schedulers or readahead. On NVMe-backed disks the bottleneck is usually memory or queries, not the block layer.
Want a quick sanity check after deploying? Install fio and run a short 4k random-read test against a scratch file. Use the numbers as a baseline for your own server over time, not as a comparison with anyone else's marketing.
Plan sizing
A Trixie install idles in roughly 150 MB of RAM. That makes Spark genuinely useful for a reverse proxy, a WireGuard endpoint or a small API. A Forgejo or Gitea instance with a few dozen repositories sits happily on Boost. See self-hosted Git. If you are compiling Rust or running PostgreSQL 17 with real traffic, Turbo or Nitro gives you headroom without paying for cores you won't use.