Modular, multiuser, multiapp and multihost configuration for NixOS (also NixOS-WSL); reproducible, extensible and maintainable in one branch.
- π General description
- ποΈ Quick Start (WSL)
- ποΈ Quick Start (Pure NixOS)
- βοΈ Project Structure
- π€ Declaring users (multiuser)
- π₯οΈ Declaring hosts (multihost)
- π§© Declaring apps (multiapp)
- π Deployment
- π Deployment + Migration
- π§ System rebuild
- π Rebuild + Migration
- π Documentation
- π§ Notes
- βοΈ License
This repository defines a universal architecture for multiple NixOS systems management in one flake:
- Multihost: each file on
hosts/represents a different machine - Multiuser:
myUsersmodule with Home Manager automatic integration - Home Manager Profiles: configurations per user on
hmProfiles/ - Reusable Modules: PostgreSQL, web stack, graphical environment, WSL, etc
- One Branch: all the hosts are built from the same base
The objective is to allow each host to declare only the essentials, while the rest is configured automatically
-
Enable WSL if you haven't done already:
wsl --install --no-distribution
-
Download
nixos-wsl.tar.gzfrom the latest release. -
Import the tarball into WSL:
wsl --import NixOS --version 2 $env:USERPROFILE\NixOS\ nixos-wsl.tar.gz
-
You can now run NixOS:
wsl -d NixOS -
Clone this repository and rebuild
git clone https://github.com/OswaldoMoper/NixosConfig.git cd NixosConfig sudo nixos-rebuild switch --flake .#spartanWSL
For more detailed instructions, refer to the documentation
For details about the NixOS-WSL base image, refer to the official project.
-
Install NixOS from an official ISO: https://nixos.org/download
-
Clone this repo:
git clone https://github.com/OswaldoMoper/NixosConfig.git cd NixosConfig -
Rebuild using the corresponding host:
sudo nixos-rebuild switch --flake .#<hostname>Example:
sudo nixos-rebuild switch --flake .#laptop -
Reboot if necessary:
sudo reboot now
βββ flake.nix
βββ scripts/
β βββ deploy-migration.sh
β βββ nixos-rebuild-migration.sh
βββ hosts/
β βββ hardware/
β β βββ server.nix β Not included
β β βββ laptop.nix β Not included
β βββ spartanWSL.nix
β βββ laptop.nix β Not included
β βββ server.nix β Not included
βββ nixosModules/
β βββ common.nix
β βββ graphical.nix
β βββ postgresql.nix
β βββ user.nix β multiuser module
β βββ webstack.nix
βββ hmProfiles/
βββ dev.nix β Not included yet
βββ motorsport.nix β Not included yet
βββ default.nix β Not included yetEach user is declared on the corresponding host:
{pkgs, ... }: {
# ... other host configurations ...
myUsers.omoper = {
enable = true;
fullName = "Oscar Oswaldo Moya Perez";
email = "example@gmail.com";
home = {
enable = true;
git = {
enable = true;
tag = "OswaldoMoper";
};
msmtp = {
enable = true;
passwordFile = "/home/omoper/password.txt";
};
sshKeys = {
enable = true;
baseName = {
enable = true;
name = "OswaldoMoper";
};
};
vscode.enable = true;
};
};
# ... other host configurations ...
}This activates:
- git per user
- msmtp per user
- SSH + ssh-agent
- VSCode
- Declarative config per user
Each file on hosts/ represents a machine:
{ pkgs, ... }: {
# This repository doesn't include hardware configs
imports = [ ./hardware/configuration.nix ];
# You can ignore this attribute and nixos will use the filename
networking.hostName = "spartanWSL";
graphical.enable = true;
wsl.enable = true;
myUsers.omoper.enable = true;
}The flake automatically detects all hosts in the hosts/ directory.
To use an external app, add the input reference in flake.nix
{
# ... other inputs ...
inputs.nixTalk.url = "github:OswaldoMoper/nixTalk";
# ... other flake configurations ...
}If the app is a web app that you are going to host, define the following in the corresponding host file:
{pkgs, ... }: {
# ... other host configurations ...
webStack.enable = true;
webStack.email = "example@mail.com";
webStack.manager = "admin";
webStack.apps = [
{
name = "nixTalk";
domain = "nixTalk.oswaldomoper.com";
port = 2000;
environment = {
nixTalk_STATIC = "/home/<name>/nixTalk/static";
nixTalk_PORT = "2000";
nixTalk_UPLOAD = "/home/<name>/upload";
nixTalk_APPROOT = "https://nixTalk.oswaldomoper.com";
nixTalk_PGUSER = "a postgres user";
nixTalk_PGPASS = "a secretly cripted password";
nixTalk_PGHOST = "localhost or your db host";
nixTalk_PGPORT = "5432 or the port you use";
nixTalk_PGDATABASE = "nixTalk or the name of your database";
nixTalk_PGPOOLSIZE = "10";
};
package = inputs.nixTalk.packages.${pkgs.system}.nixTalk-wrapper;
}
];
# ... other host configurations ...
}When webStack.enable = true
webStack.emailmust be non-emptywebStack.appsmust contain at leat one app
and the module automatically:
- enables Nginx
- creates one virtualHost per app
- configures ACME certificates when
mode = "nginx" - configures Cloudflare Tunnel when
mode = "tunnel" - creates one systemd service per app
- injects the
environmentvariables into the service
NOTES:
webStack.apps.[*].environmentaccepts strings, paths, packages and null values (same type assystemd.services.<name>.environment).webStack.apps.[*].portvalues must be uniquewebStack.modecontrols how apps are exposed:"nginx"for direct HTTPS with ACME,"tunnel"for Cloudflare Tunnel (default)
This repository supports declarative deployments using a deploy-rs based DSL. Each host can optionally define a remote deployment target.
Inside the host file:
{pkgs, ... }: {
# ... other host configurations ...
deployment.myServer = {
hostname = "0.0.0.0";
profiles.system = {
sshUser = "example";
path = deploy-rs.lib.activate.nixos self.nixosConfigurations.myServer;
user = "root"
};
};
environment.systemPackages = [
# ... other systemPackages ...
inputs.deploy-rs.defaultPackage.${pkgs.system}
# ... other systemPackages ...
];
# ... other host configurations ...
}nix run .#deploy -- --hostname myServeror
deploy -- --hostname myServerThis will:
- build the system
- upload the closure
- activate the new configuration
This flake includes a helper script that performs safe PostgreSQL migrations during deploys.
- connects to the remote server
- creates a full PostgreSQL backup
- downloads the backup locally
- runs
deploy-rs - detects if PostgreSQL version changed
- restores the database if needed
nix run .#deploy-migration -- myServeror
deploy-migration -- myServerdeploy-migration is optional. Only hosts that perform remote deployments need it.
To enable it on a specific host:
{pkgs,...}: {
# ... other host configurations ...
deployment.myServer = {
hostname = "0.0.0.0";
profiles.system = {
sshUser = "example";
path = deploy-rs.lib.activate.nixos self.nixosConfigurations.myServer;
user = "root"
};
};
environment.systemPackages = [
# ... other systemPackages ...
inputs.deploy-rs.defaultPackage.${pkgs.system}
self.packages.${pkgs.system}.deploy-migration
# ... other systemPackages ...
];
# ... other host configurations ...
}This keeps deployment tooling out of machines that don't need it (e.g. laptops, WSL, development hosts).
The very first rebuild run
sudo nixos-rebuild switch --flake .#<hostname>Example
sudo nixos-rebuild switch --flake .#spartanWSLThis repository includes a local helper tool that extends nixos-rebuild with automatic PostgreSQL backup and restore logic.
Use this tool when rebuilding local machines (laptops, desktops, WSL, development servers).
- creates a full PostgreSQL backup before rebuilding
- runs
nixos-rebuild - detects if the PostgreSQL version changed
- restores the databases if needed
This ensures safe upgrades when switching between NixOS generations that includes PostgreSQL version bumps.
sudo nixos-rebuild-migration switch --flake .#<hostname>Example:
sudo nixos-rebuild-migration switch --flake .#spartanWSLUse nixos-rebuild-migration instead of nixos-rebuild when:
- your host uses PostgreSQL module
- you are updating NixOS to a new release
- you suspect PostgreSQL might upgrade
- you want safe, automatic backup/restore behavior
For normal rebuild without PostgreSQL changes, it behaves exactly like nixos-rebuild.
nixos-rebuild-migration is also optional.
Only hosts that use PostgreSQL locally should enable it.
To enable it:
{pkgs,...}: {
# ... other host configurations ...
environment.systemPackages = [
# ... other systemPackages ...
self.packages.${pkgs.system}.nixos-rebuild-migration
# ... other systemPackages ...
];
# ... other host configurations ...
}This avoids installing PostgreSQL migration tooling on machines that don't use PostgreSQL.
Full documentation is available in the /docs/ directory:
- Architecture
- Common Modules
- Users
- Graphical configuration
- Hosts
- Web stack
- PostgreSQL
- Deployment
- Migration scripts
This repository is designed to:
- Maintain a single branch
- Build all your systems from a single flake
- Enable declarative users with integrated Home Manager
- Avoid duplication across hosts
- Enable modular growth (roles, profiles, services, etc.)
This project is licensed under the BSD 3-Clause License.