NixOS vs Ubuntu Server

This entry is part 2 of 2 in the series Introduction To NixOS

Introduction To NixOS

Introduction To NixOS – The Declarative Operating System

NixOS vs Ubuntu Server

Ubuntu Server follows the same model that most Linux system administrators have used for twenty years. Packages are installed via apt, configuration files live in /etc, services are started and enabled with systemctl, and the system state at any point in time is the product of all the commands ever run on it.

# Standard Ubuntu Server workflow
sudo apt update
sudo apt install -y nginx postgresql git

# Enable and start services
sudo systemctl enable --now nginx
sudo systemctl enable --now postgresql

# Edit the nginx config directly
sudo nano /etc/nginx/sites-available/default

# Check service status
sudo systemctl status nginx
Bash

This model is immediately familiar to anyone with Linux experience, and it works well in practice for a single server or small team. The problems surface at scale, or over time. After six months of incremental changes, patches applied mid-incident, and one-off manual edits, the running system may bear little resemblance to any documentation. This phenomenon, known as configuration drift, is one of the primary motivations for tools like Ansible, Chef, and Puppet, which attempt to impose structure on top of an inherently mutable system.

Ubuntu Server 24.04 LTS ships with the Linux 6.8 kernel, AppArmor 4, and a range of security hardening features including unprivileged user namespace restrictions and binary hardening. As with all Ubuntu LTS releases, it comes with five years of free security maintenance for the main repository, extendable to ten years via Ubuntu Pro. That support lifecycle is a genuine advantage for production environments where stability and long-term patch coverage matter more than cutting-edge features.

# Ubuntu Server: enable automatic security updates
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

# Verify the configuration
cat /etc/apt/apt.conf.d/20auto-upgrades

# Output:
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";
Bash

Starting with Ubuntu 18.04 LTS, unattended-upgrades is included in both desktop and server installations to apply security updates automatically on a daily basis. Canonical also provides the Livepatch service, which applies kernel security patches without requiring a reboot, a significant operational benefit for high-availability deployments.

How NixOS Works: The Declarative Model

On NixOS, the equivalent of those apt install commands and manual /etc edits is a single Nix expression in /etc/nixos/configuration.nix. Rather than telling the system what to do step by step, you describe the state you want, and NixOS builds it.

{ config, pkgs, ... }:
{
  # Web server
  services.nginx = {
    enable      = true;
    virtualHosts."example.com" = {
      forceSSL   = true;
      enableACME = true;
    };
  };

  # Database
  services.postgresql = {
    enable  = true;
    package = pkgs.postgresql_16;
  };

  # System packages
  environment.systemPackages = with pkgs; [ git htop curl ];

  # Firewall
  networking.firewall = {
    enable          = true;
    allowedTCPPorts = [ 22 80 443 ];
  };

  system.stateVersion = "24.11";
}
Bash

Apply this with sudo nixos-rebuild switch and NixOS resolves the entire dependency graph, builds or fetches every required package, writes all configuration files, enables the appropriate systemd units, and activates the new system state atomically. If anything goes wrong, the previous generation remains available at the boot loader.

“Our developers now spend much less time fighting environment issues and more time shipping features. The initial learning curve was steep, but the benefits became clear within weeks.”

Marcus Wong, CTO, speaking about a production migration from Ubuntu to NixOS for a microservices architecture.
Source: markaicode.com

Because NixOS stores all packages in isolation in /nix/store and uses a declarative configuration model, upgrading NixOS systems is extremely reliable, and the ability to roll back upgrades is built into the base system. There is no third-party tool like Timeshift needed, and no manual snapshot to remember to take before a risky update.

Package Management: APT vs Nix Side by Side

The table below shows how common package management tasks translate between the two distributions. The syntax difference is surface-level; the deeper difference is that Nix operations are transactional and reversible by default, whereas APT operations modify system state directly.

TaskUbuntu Server (APT)NixOS (Nix/config)
Install a packagesudo apt install nginxAdd services.nginx.enable = true; to config, then nixos-rebuild switch
Remove a packagesudo apt remove nginxRemove the line from config, rebuild
Update all packagessudo apt update && sudo apt upgradesudo nix flake update && nixos-rebuild switch
Roll back an updateManual (apt-mark, dpkg, Timeshift)nixos-rebuild switch --rollback or boot menu
Install a specific versionComplex; requires APT pinning or PPAsPin the Nixpkgs commit in flake.lock
Try a package without installingNo native equivalentnix shell nixpkgs#htop
Reproduce the setup on another serverRequires Ansible, Chef, or manual scriptingCopy configuration.nix and run nixos-install

Watch: NixOS Review: The Most Powerful Linux Distro in 2026? (LearnLinuxTV)

Jay from LearnLinuxTV published this comprehensive NixOS review in early 2026, examining practicality, beginner accessibility, and the immutable architecture from a server administrator’s perspective. It pairs well with this section’s comparison of the two package management philosophies.

▶ Watch the LearnLinuxTV NixOS Review

Real-World Configuration, Security, and Deployment

To make the comparison concrete, consider the task of setting up a production-ready server running Nginx with automatic TLS certificates, PostgreSQL 16, and UFW (or equivalent) firewall rules. On Ubuntu Server, this is a sequence of imperative steps accumulated over time.

Ubuntu Server Setup

## --- Ubuntu Server: Production Web Stack ---

# Update and install dependencies
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx postgresql certbot python3-certbot-nginx ufw

# Configure firewall
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

# Obtain an SSL certificate
sudo certbot --nginx -d example.com

# Create a PostgreSQL database and user
sudo -u postgres psql <<EOF
CREATE DATABASE myapp;
CREATE USER myuser WITH ENCRYPTED PASSWORD 'strongpassword';
GRANT ALL PRIVILEGES ON DATABASE myapp TO myuser;
EOF

# Enable services on boot
sudo systemctl enable nginx postgresql
Bash

These steps work reliably, but they exist only in your shell history and any documentation you remembered to write. Run them on a second server six months later and you may find that the certbot version, the PostgreSQL minor release, or a default Nginx configuration has changed. Reproducing the exact state requires careful scripting or a configuration management tool layered on top.

NixOS Equivalent

{ config, pkgs, ... }:
{
  # Firewall
  networking.firewall = {
    enable          = true;
    allowedTCPPorts = [ 22 80 443 ];
  };

  # Nginx with automatic ACME/Let's Encrypt TLS
  security.acme = {
    acceptTerms = true;
    defaults.email = "[email protected]";
  };

  services.nginx = {
    enable               = true;
    recommendedGzipSettings    = true;
    recommendedOptimisation    = true;
    recommendedProxySettings   = true;
    recommendedTlsSettings     = true;
    virtualHosts."example.com" = {
      forceSSL   = true;
      enableACME = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:3000";
      };
    };
  };

  # PostgreSQL 16
  services.postgresql = {
    enable      = true;
    package     = pkgs.postgresql_16;
    enableTCPIP = false;
    ensureDatabases = [ "myapp" ];
    ensureUsers = [{
      name              = "myuser";
      ensureDBOwnership = "myapp";
    }];
  };

  system.stateVersion = "24.11";
}
Bash

Apply this to any machine with sudo nixos-rebuild switch and the result is identical: the same Nginx version, the same PostgreSQL release, the same firewall rules, the same ACME configuration. Not approximately the same: exactly the same. The Nix store’s content-addressed package hashing guarantees it.

Watch: NixOS Tutorial: Configuration Basics Explained

This well-regarded tutorial walks through the fundamentals of NixOS configuration from scratch, covering services, packages, users, and the rebuild workflow. It is particularly useful for Ubuntu administrators who want to understand how the NixOS declarative model maps to familiar server administration tasks.

▶ Watch “NixOS Configuration Basics, Explained”

Security: Two Different Postures

Security comparisons between Linux distributions are often misleading when they focus on surface features rather than the underlying model. Both Ubuntu Server and NixOS are genuinely secure, but they achieve it differently, and each has areas where it holds an advantage.

Ubuntu Server Security Model

Ubuntu Server benefits from Canonical’s dedicated security team, which tracks CVEs, issues patches, and maintains the Ubuntu CVE Tracker. Ubuntu 24.04 LTS ships AppArmor 4 and unprivileged user namespace restrictions as default security features, supported by Canonical’s ongoing binary hardening programme. The Ubuntu Pro subscription extends security coverage and adds real-time kernel patching via Livepatch. For organisations running regulated workloads, Ubuntu’s long-term support commitments and Canonical’s enterprise contracts carry significant weight with compliance teams.

# Ubuntu: harden SSH quickly
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl reload sshd

# Check AppArmor status
sudo aa-status
Bash

NixOS’s Security Model

NixOS takes a structurally different approach. NixOS provides a consistent and reproducible system environment by isolating packages, which reduces the likelihood of conflicts between applications and their dependencies. Because the base system is immutable (activated from the Nix store and never modified in place), a compromised runtime cannot persistently overwrite system binaries. The entire system is rebuilt from declarations on each nixos-rebuild switch, meaning any drift introduced by an attacker is eliminated on the next rebuild.

Configuring SSH hardening declaratively in NixOS means the same settings are enforced on every machine in your fleet simultaneously, with no risk that a manual edit on one server was forgotten on another:

services.openssh = {
  enable = true;
  settings = {
    PasswordAuthentication = false;
    PermitRootLogin        = "no";
    KbdInteractiveAuthentication = false;
    X11Forwarding          = false;
    # Allow only a specific group to SSH in
    AllowGroups            = [ "sshusers" ];
  };
  # Enforce key-based auth only
  authorizedKeysFiles = [ "%h/.ssh/authorized_keys" ];
};
Bash

One area where Ubuntu holds a clear advantage is proprietary hardware support, including GPU drivers, Wi-Fi firmware, and vendor-specific kernel modules. NixOS can support these, but the process requires more deliberate configuration, and the NixOS Wiki notes several edge cases involving non-free firmware. The difference matters less on a headless server than on a workstation, but it is worth acknowledging.

“One of the unique features of NixOS is its adherence to isolated, immutable environments for different apps, including the dependencies of a package. Unlike Debian-based distros, you almost never run into dependency hell.”

fd93.me, “Why I Left NixOS for Ubuntu” (May 2024). Despite ultimately returning to Ubuntu for daily desktop use, the author acknowledges NixOS’s structural security advantages.
Read the full article.

Introduction To NixOS

Introduction To NixOS – The Declarative Operating System

With over 15 years experience in software engineering, consulting, ethical hacking and website development, I've continuously honed my skills as a problem-solving wizard. With expertise spanning the dynamic worlds of Laravel, WordPress, and PHP 8, I'm not just a programmer; I'm an avid explorer of innovative solutions, discovering something new every day.

Post Comment