NixOS module compatibility layer for non-NixOS Linux systems.
Use familiar NixOS modules (services.postgresql, services.k3s, systemd.services, etc.) on Ubuntu, Debian, Arch, Fedora, or any other Linux distribution with Nix installed.
- NixOS modules on any Linux — Use the same declarative configuration syntax
- Automatic /etc generation — systemd units, tmpfiles, sysctl configs
- Safe activation — Backup before apply, dry-run mode, diff preview
- Host-friendly — Doesn't overwrite critical system files (PAM, fstab, sudoers)
- Selective output — Suppresses NixOS-specific units, keeps only what you need
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
system-manager.url = "github:kitsunoff/system-manager";
};
outputs = { self, nixpkgs, system-manager }: {
# Define your system configuration
systemConfigs.myserver = system-manager.lib.makeSystemConfig {
system = "x86_64-linux";
modules = [
({ pkgs, ... }: {
system.stateVersion = "24.11";
services.postgresql = {
enable = true;
package = pkgs.postgresql_16;
};
systemd.services.myapp = {
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.hello}/bin/hello";
};
})
];
};
# Build output
packages.x86_64-linux.myserver =
self.systemConfigs.myserver.config.system.build.systemManagerToplevel;
};
}nix build .#myservernix run .#apply -- --dry-run myserversudo nix run .#apply -- myserver/nix/store/xxx-system-manager-myserver/
├── etc/
│ ├── hostname
│ ├── hosts
│ ├── systemd/
│ │ └── system/
│ │ ├── postgresql.service
│ │ └── myapp.service
│ ├── sysctl.d/
│ ├── tmpfiles.d/
│ └── sudoers.d/
├── activate # Activation script
├── nixos-version
└── system
System Manager intentionally skips files that would conflict with your host system:
| Category | Files | Reason |
|---|---|---|
| Shell configs | /etc/profile, /etc/bashrc |
Contain Nix store paths |
| System identity | /etc/os-release, /etc/lsb-release |
Would misidentify OS |
| Authentication | /etc/pam.d/*, /etc/login.defs |
PAM configs use Nix paths |
| Name resolution | /etc/nsswitch.conf |
Could break DNS/auth |
| Valid shells | /etc/shells |
Contains Nix store paths |
| SSH client | /etc/ssh/ssh_config |
Contains Nix Include paths |
| Filesystems | /etc/fstab |
Host manages mounts |
| Sudo | /etc/sudoers |
Uses /etc/sudoers.d/ instead |
services.postgresql = {
enable = true;
package = pkgs.postgresql_16;
enableTCPIP = true;
settings = {
max_connections = 100;
shared_buffers = "256MB";
};
};services.k3s = {
enable = true;
role = "server";
extraFlags = toString [
"--disable=traefik"
"--disable=servicelb"
];
};
boot.kernel.sysctl = {
"net.bridge.bridge-nf-call-iptables" = 1;
"net.ipv4.ip_forward" = 1;
};systemd.services.myapp = {
description = "My Application";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${pkgs.myapp}/bin/myapp";
Restart = "always";
User = "myapp";
};
};
users.users.myapp = {
isSystemUser = true;
group = "myapp";
};
users.groups.myapp = {};Usage: system-manager-apply [OPTIONS] <config-name>
Arguments:
config-name Name of the system configuration (e.g., myserver)
Will build: .#systemConfigurations.<config-name>
Options:
-n, --dry-run Show what would be done without making changes
-y, --yes Skip confirmation prompt
-f, --flake Path to flake (default: current directory)
-h, --help Show this help message- Builds configuration via
nix build - Shows current vs new (store paths)
- Saves previous generation to
/var/lib/system-manager/previous - Runs activation script (creates users, copies
/etc, etc.) - Runs
systemctl daemon-reload - Updates
/var/lib/system-manager/currentsymlink
System Manager uses nixpkgs.lib.nixosSystem with a compatibility layer that:
- Mocks boot/hardware options —
boot.*,hardware.*,fileSystems.*accept values but produce no output - Forces mutableUsers — Users are created if missing, not overwritten
- Suppresses upstream systemd units — Host's systemd already has basic.target, multi-user.target, etc.
- Disables dangerous activation scripts — No
/bin/shoverwrite, no/procmount attempts - Redirects configs — sudoers →
/etc/sudoers.d/nixos, not/etc/sudoers
- Linux system (Ubuntu, Debian, Arch, Fedora, etc.)
- Nix package manager installed
- systemd (for service management)
- Root access (for applying configuration)
system-manager/
├── flake.nix # Main entry point
├── compat/
│ ├── eval.nix # Configuration evaluator
│ ├── mocks/
│ │ ├── boot.nix # Mock boot.* options
│ │ ├── hardware.nix # Mock hardware.* options
│ │ └── filesystems.nix
│ └── overrides/
│ ├── activation.nix # Disable dangerous scripts
│ ├── systemd.nix # Suppress upstream units
│ ├── users.nix # Force mutableUsers
│ ├── packages.nix # Clear default packages
│ └── sudo.nix # Redirect to sudoers.d
├── modules/
│ └── toplevel.nix # Custom toplevel without kernel
└── apply/
└── apply.sh # Apply script
MIT