NixOS - My Configuration and Switch to Podman

For some time now I have been looking for an interesting lightweight linux distribution that could replace Ubuntu.

Now I’ve found NixOS and I have no idea why it hadn’t crossed my path sooner. So far I am very happy with it, it feels very clean. With NixOS you can configure everything in one place. Think for example of users and groups, a few nix packages such as wget, htop, curl, openssl etc. Or, for example, mounting cifs directories or adding docker/podman containers. What makes this very powerful is that you can easily switch to a new configuration and possibly perform a rollback again.

I also decided to switch from Docker to Podman. Why? Because Podman is open source and has a daemonless architecture, you can read more about it here. This means that I will adjust my notes on this digital garden accordingly.


Within Proxmox I added NixOS as a VM by downloading the Graphical ISO image (Plasma Desktop, 64-bit Intel/AMD).

First I uploaded the ISO to the Proxmox local storage and selected SHA-256 as the hash algorithm. The checksum can be found next to the download button on the NixOS download site.

I also thought it would be nice to place NixOS in the new server VLAN. For that I had to adjust the following setting within the node (pve):

  1. Select the node
  2. Select System > Network
  3. Edit the Linux Bridge
  4. Turn ON VLAN aware and click OK You can then enter the VLAN Tag at the network device of the NixOS VM (under Hardware).

Then I connected to the Plasma Desktop GUI via the console and went through the installation steps.


Below is the configuration.nix that you can find under /etc/nixos. I have supplemented the default configuration with:

  1. Fs.inotify settings. For optimization for Syncthing, among others.
  2. DHCP for the main networking interface. The MAC address comes from the VM and is given a reserved static IP address by the Unifi gateway.
  3. Extra user options. This is self-evident.
  4. Allow unfree packages. Could be useful (or not).
  5. Systempackages, including:
    1. for Proxmox. Don’t forget to set the QEMU Guest Agent to Enabled in the Options of the NixOS VM.
    2. openssl: useful for generating certificates.
    3. cifs-utils: for the cifs mounts. The package may not even need to be added here, but it is then only useful to have for the man pages.
  6. Nix daemon config: automatic garbage collection and store optimization. Very handy.
  7. Openssh service is enabled.
  8. Security.sudo.wheelNeedsPassword: run sudo without a password. This may not always be recommended.
  9. Services.fstrim: is enabled. I was told that this would be better for an SSD.
  10. Services.qemuGuest.enable: see point 5.1.
  11. Cifs mount: so that I can access files on my fileserver that runs as a container within Proxmox. Replace IP and and enter your username and password in the smb-secrets file.
Podman specific
  1. system.activationScripts: this will run a script to create folders needed for some Podman containers.
  2. Virtualisation: Podman is set as backend. There are references to the containers I have set up in separate nix files (homer and caddy for example). I will talk more about this in other notes.
  3. This ensures that the Podman macvlan network I use for all containers is always created if it doesn’t exist. This is very useful, for example when installing a new NixOS VM. Within the IP addresses I replace xx with my VLAN Tag.
Switching between configurations

After modifying the configuration.nix you just need to run: sudo nixos-rebuild switch to switch between configurations. If it doesn’t work the way you want, you can go back with sudo nixos-rebuild switch --rollback. Here you can read more about updating and upgrading NixOS. Each time you switch, a generation is added that you can view with sudo nix-env -p /nix/var/nix/profiles/system --list-generations.

# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

  imports =
    [ # Include the results of the hardware scan.

  # Bootloader.
  boot.loader.grub.enable = true;
  boot.loader.grub.device = "/dev/sda";
  boot.loader.grub.useOSProber = true;

  boot.kernel.sysctl = {
    # Note that inotify watches consume 1kB on 64-bit machines.
    "fs.inotify.max_user_watches"   = 1048576;   # default:  8192
    "fs.inotify.max_user_instances" =    1024;   # default:   128
    "fs.inotify.max_queued_events"  =   32768;   # default: 16384

  # Enable networking
  networking.hostName = "nixos"; # Define your hostname. 
  networking.networkmanager.enable = true;
  networking.interfaces.ens18.useDHCP = true;

  # Set your time zone.
  time.timeZone = "Europe/Amsterdam";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "nl_NL.UTF-8";
    LC_MONETARY = "nl_NL.UTF-8";
    LC_NAME = "nl_NL.UTF-8";
    LC_NUMERIC = "nl_NL.UTF-8";
    LC_PAPER = "nl_NL.UTF-8";
    LC_TELEPHONE = "nl_NL.UTF-8";
    LC_TIME = "nl_NL.UTF-8";

  # Configure keymap in X11
  services.xserver = {
    layout = "gb";
    xkbVariant = "";

  # Configure console keymap
  console.keyMap = "uk";

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.beheer = {
    isNormalUser = true;
    description = "Beheer";
    extraGroups = [ "networkmanager" "wheel" "podman" ];
    packages = with pkgs; [];
    home = "/home/beheer";
    createHome = true;

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
  #  vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.

  # Nix daemon config
  nix = {
    # Automate garbage collection
    gc = {
      automatic = true;
      dates = "weekly";
      options = "--delete-older-than 7d";

    settings = {
      # Automate `nix store --optimise`
      auto-optimise-store = true;

  # List services that you want to enable:
  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  networking.firewall.enable = false;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on
  system.stateVersion = "22.11"; # Did you read the comment?

  security.sudo.wheelNeedsPassword = false;

  # Good for SSD
  services.fstrim = {
    enable = true;

  # Enable the guest agent for proxmox
  services.qemuGuest.enable = true;

  # Samba Client - cifs mount
  fileSystems."/mnt/fileserver/backup" = {
    device = "//IP/backup";
    fsType = "cifs";
    options = let
      # this line prevents hanging on network split
      automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
     in ["${automount_opts},credentials=/etc/nixos/smb-secrets,file_mode=0777,dir_mode=0777,iocharset=utf8"];

  # Create directories for the containers
  system.activationScripts = {
    script.text = ''
      # Homer
      install -d -m 755 /home/beheer/homer/assets -o root -g root
      # Caddy
      install -d -m 755 /home/beheer/caddy/site -o root -g root
      install -d -m 755 /home/beheer/caddy/data -o root -g root
      install -d -m 755 /home/beheer/caddy/config -o root -g root
      test -f /home/beheer/caddy/Caddyfile || echo -e "#{\n#       debug\n#}" > /home/beheer/caddy/Caddyfile

  virtualisation = {
    podman = {
      enable = true;
      # Create a `docker` alias for podman, to use it as a drop-in replacement
      dockerCompat = true;
      # Required for containers under podman-compose to be able to talk to each other.
      defaultNetwork.settings.dns_enabled = true; # release 23.05
      # defaultNetwork.dnsname.enable = true; # use with older releases

    oci-containers = {
      backend = "podman";

      containers = {
        homer = import ./containers/homer.nix;
        caddy = import ./containers/caddy.nix; # Add manually the Caddyfile before using this container
  }; = with config.virtualisation.oci-containers; {
    serviceConfig.Type = "oneshot";
    wantedBy = [ "${backend}-homer.service" "${backend}-caddy.service" ];
    script = ''
      ${pkgs.podman}/bin/podman network exists net_macvlan || \
        ${pkgs.podman}/bin/podman network create --driver=macvlan --gateway=192.168.xx.1 --subnet=192.168.xx.0/24 -o parent=ens18 net_macvlan

Read other notes


    No comments found for this note.

    Join the discussion for this note on this ticket. Comments appear on this page instantly.


    Notes mentioning this note

    Notes Graph