NixOS - Server 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.
Installing NixOS with LUKS disk encryption is described in another note.
Installation
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
):
- Select the node
- Select
System
>Network
- Edit the Linux Bridge
- Turn ON
VLAN aware
and clickOK
You can then enter theVLAN Tag
at the network device of the NixOS VM (underHardware
).
Then I connected to the Plasma Desktop GUI via the console and went through the installation steps.
Configuration
Below is the configuration.nix
that you can find under /etc/nixos
. I have supplemented the default configuration with:
-
unstableTarball
: Add the unstable channel declaratively which can be useful if you need services or packages with a higher version. Then you can use for exampleunstable.cockpit
as package or just usecockpit
to use the standard channel. I’ve made a separate note for this. -
cockpit-apps
: Custom packages for Cockpit. - .
fs.inotify settings
: For optimization for Syncthing, among others. -
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. - Extra
user options
. This is self-evident. -
allow unfree packages
: Could be useful (or not). -
systempackages
, including:-
openssl
: Useful for generating certificates. -
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.
-
-
environment.etc."current-system-packages".text
: After switching configurations, a file is created where you can easily find all installed system packages and the corresponding versions! Just usecat /etc/current-system-packages
. -
nix daemon config
: Automatic garbage collection and store optimization. Very handy. -
openssh service
is enabled. -
security.sudo.wheelNeedsPassword
: Run sudo without a password. This may not always be recommended. -
services.fstrim
is enabled. I was told that this would be better for an SSD.To verify TRIM support run:
lsblk --discard
. And check the values of DISC-GRAN (discard granularity) and DISC-MAX (discard max bytes) columns. Non-zero values indicate TRIM support. -
services.qemuGuest.enable
: Guest agent for Proxmox. Don’t forget to set theQEMU Guest Agent
toEnabled
in theOptions
of the NixOS VM. -
cifs mount
: So that I can access files on my fileserver that runs as a container within Proxmox. ReplaceIP
and and enter your username and password in thesmb-secrets
file. -
services.cockpit
: Cockpit is a web-based GUI to administer servers
Podman specific
-
system.activationScripts
: This will run a script to create folders needed for Podman containers. It will also create a Caddyfile for Caddy and the configuration for phpMyAdmin. -
virtualisation
: Podman is set as backend. I have set up the containers with separate nix files (for example Homer, Caddy, MariaDB and phpMyAdmin). -
systemd.services.create-podman-network
: 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 replacexx
with my VLAN Tag.
Desktop environment specific
-
services.xserver
: This will setup KDE Plasma as desktop environment. Because this is a server configuration, the default settings are sufficient for me as described here. I will use the terminal more often. - ` environment.plasma5.excludePackages`: Not all applications that come pre-installed with the KDE Plasma desktop environment are desirable for me.
-
services.xrdp
: Very basic settings for XDRP server so I can use remote desktop to connect to the KDE desktop. Guacamole can be used to access the desktop environment and CLI with a web browser.
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
. With sudo nix-env --profile /nix/var/nix/profiles/system --delete-generations old
you can delete all old 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, ... }:
let
# add unstable channel declaratively
# https://stackoverflow.com/questions/48831392/how-to-add-nixos-unstable-channel-declaratively-in-configuration-nix
unstableTarball =
fetchTarball
https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz;
cockpit-apps = pkgs.callPackage packages/cockpit/default.nix { inherit pkgs; };
in
{
disabledModules = [ "services/web-apps/guacamole-client.nix" "services/web-apps/guacamole-server.nix" ]; # disable the stable channel version
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
(unstableTarball + "/nixos/modules/services/web-apps/guacamole-client.nix")
(unstableTarball + "/nixos/modules/services/web-apps/guacamole-server.nix")
];
nixpkgs.config = {
packageOverrides = pkgs: {
unstable = import unstableTarball {
config = config.nixpkgs.config;
};
};
};
# 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_IDENTIFICATION = "nl_NL.UTF-8";
LC_MEASUREMENT = "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 xserver
services.xserver = {
enable = true;
layout = "gb"; # keymap in X11
xkbVariant = "";
displayManager = {
sddm.enable = true;
};
desktopManager.plasma5.enable = true;
};
# https://nixos.wiki/wiki/KDE
environment.plasma5.excludePackages = with pkgs.libsForQt5; [
elisa
gwenview
okular
oxygen
khelpcenter
konsole
plasma-browser-integration
print-manager
];
# Remote desktop protocol
services.xrdp = {
enable = true;
defaultWindowManager = "startplasma-x11";
};
# 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;
};
# Remote desktop protocol
services.xrdp = {
enable = true;
defaultWindowManager = "startplasma-x11";
#openFirewall = true;
};
# Guacamole
services.guacamole-server = {
enable = true;
host = "127.0.0.1";
userMappingXml = ./guacamole/user-mapping.xml;
package = pkgs.unstable.guacamole-server;
};
services.guacamole-client = {
enable = true;
enableWebserver = true;
settings = {
guacd-port = 4822;
guacd-hostname = "127.0.0.1";
};
package = pkgs.unstable.guacamole-client;
};
# Allow unfree packages - by default NixOS doesn't allow installing software with unfree licenses
nixpkgs.config.allowUnfree = true; #
environment.systemPackages = with pkgs; [
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
wget
htop
curl
openssl
cifs-utils
gnome.gedit # simple text editor to replace okular (KDE)
unstable.cockpit
cockpit-apps.podman-containers
#cockpit-apps.virtual-machines # replaced by quickemu
unstable.quickemu
unstable.quickgui
];
# this creates /etc/current-system-packages with a list of all packages and their version
# https://www.reddit.com/r/NixOS/comments/fsummx/how_to_list_all_installed_packages_on_nixos/
environment.etc."current-system-packages".text =
let
packages = builtins.map (p: "${p.name}") config.environment.systemPackages;
sortedUnique = builtins.sort builtins.lessThan (lib.unique packages);
formatted = builtins.concatStringsSep "\n" sortedUnique;
in formatted;
security.sudo.wheelNeedsPassword = false;
# Good for SSD
services.fstrim = {
enable = true;
};
# Enable the guest agent for proxmox
services.qemuGuest.enable = true;
# Cockpit
services.cockpit = {
enable = true;
port = 9090;
settings = {
WebService = {
AllowUnencrypted = 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#}\n\nhomer.home.arpa {\n tls internal\n handle {\n reverse_proxy 192.168.xx.xx:8080\n }\n}\>
# MariaDB
install -d -m 755 /home/beheer/mariadb/config -o root -g root
install -d -m 755 /home/beheer/mariadb/data -o root -g root
# phpMyAdmin
install -d -m 755 /home/beheer/phpmyadmin -o root -g root
test -f /home/beheer/phpmyadmin/config.user.inc.php || echo -e "<?php\n\n\$cfg['ShowPhpInfo'] = true; // Adds a link to phpinfo() on the home page\n\$cfg['SendErrorReports'] = 'never';" > /home/beh>
'';
};
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;
mariadb = import ./containers/mariadb.nix;
phpmyadmin = import ./containers/phpmyadmin.nix;
};
};
};
systemd.services.create-podman-network = 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
'';
};
# 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 https://nixos.org/nixos/options.html).
system.stateVersion = "22.11"; # Did you read the comment?
}
Read other notes
Tags
Notes mentioning this note
- Homer Dashboard - NixOS Container Setup
I was looking for a simple dashboard that I could use as a home page on my clients. I found...
- Caddy - NixOS Container Setup
Caddy is a simple open-source web server.
- Caddy - Reverse Proxy with Pi-hole Local DNS Setup
Since I create Docker/Podman containers with a macvlan and a reserved IP address, I also wanted to use my local...
- MariaDB - NixOS Container Setup
MariaDB is a fork of the MySQL database. I use this database, among other things, to store data from [[Docker...
- phpMyAdmin - NixOS Container Setup
phpMyAdmin is a free webbased software tool intended to handle the administration of MySQL
- NixOS - Updating and Upgrading
For some time now I have been looking for an interesting lightweight linux distribution that could replace Ubuntu
- NixOS - Cockpit Setup
Cockpit is a modern web-based graphical interface for servers. You can use it to administer servers and it has a...
- NixOS - Add Podman Containers UI to Cockpit
With Cockpit Podman Containers you can manage Podman containers in your browser
- NixOS - Add Virtual Machines UI to Cockpit
With Cockpit Virtual Machines you can create, run, and manage virtual machines in your browser
- NixOS - Installation with LUKS Disk Encryption
I thought it would be a good idea to install NixOS on an encrypted disk. If something happens to the...
- NixOS - Add Unstable Channel Packages and Services to Configuration
Some packages are lagging behind within the default channel of NixOS. Then it is nice to have the option to...
- NixOS - Guacamole Clientless Remote Desktop Gateway Setup
Once Guacamole is installed on a machine, in my case running NixOS, all you need to access your desktop environment...
Comments
No comments found for this note.
Join the discussion for this note on this ticket. Comments appear on this page instantly.