initial commit
This commit is contained in:
3
hosts/common/core/darwin.nix
Normal file
3
hosts/common/core/darwin.nix
Normal file
@@ -0,0 +1,3 @@
|
||||
# Core functionality for every nix-darwin host
|
||||
# NOTE(starter): Declare any darwin-specific, core configurations here.
|
||||
{ }
|
||||
103
hosts/common/core/default.nix
Normal file
103
hosts/common/core/default.nix
Normal file
@@ -0,0 +1,103 @@
|
||||
# FIXME(starter): modify this file and the other .nix files in `nix-config/hosts/common/core/` to declare
|
||||
# settings that will occur across all hosts
|
||||
|
||||
# IMPORTANT: This is used by NixOS and nix-darwin so options must exist in both!
|
||||
{
|
||||
inputs,
|
||||
outputs,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
isDarwin,
|
||||
...
|
||||
}:
|
||||
let
|
||||
platform = if isDarwin then "darwin" else "nixos";
|
||||
platformModules = "${platform}Modules";
|
||||
in
|
||||
{
|
||||
imports = lib.flatten [
|
||||
inputs.home-manager.${platformModules}.home-manager
|
||||
|
||||
(map lib.custom.relativeToRoot [
|
||||
"modules/common"
|
||||
"modules/hosts/common"
|
||||
"modules/hosts/${platform}"
|
||||
"hosts/common/core/${platform}.nix"
|
||||
#"hosts/common/core/sops.nix" # Core because it's used for backups, mail
|
||||
"hosts/common/core/ssh.nix"
|
||||
#"hosts/common/core/services" # uncomment this line if you add any modules to services directory
|
||||
"hosts/common/users/primary"
|
||||
"hosts/common/users/primary/${platform}.nix"
|
||||
])
|
||||
];
|
||||
|
||||
#
|
||||
# ========== Core Host Specifications ==========
|
||||
#
|
||||
# FIXME(starter): modify the hostSpec options below to define values that are common across all hosts
|
||||
# such as the username and handle of the primary user (see also `nix-config/hosts/common/users/primary`)
|
||||
hostSpec = {
|
||||
username = "panotaka";
|
||||
handle = "panotaka";
|
||||
# FIXME(starter): modify the attribute sets hostSpec will inherit from your nix-secrets.
|
||||
# If you're not using nix-secrets then remove the following six lines below.
|
||||
|
||||
};
|
||||
|
||||
networking.hostName = config.hostSpec.hostName;
|
||||
|
||||
# System-wide packages, in case we log in as root
|
||||
environment.systemPackages = [ pkgs.openssh ];
|
||||
|
||||
# Force home-manager to use global packages
|
||||
home-manager.useGlobalPkgs = true;
|
||||
|
||||
# If there is a conflict file that is backed up, use this extension
|
||||
home-manager.backupFileExtension = "bk";
|
||||
|
||||
#
|
||||
# ========== Overlays ==========
|
||||
#
|
||||
nixpkgs = {
|
||||
overlays = [
|
||||
outputs.overlays.default
|
||||
];
|
||||
config = {
|
||||
allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
#
|
||||
# ========== Nix Nix Nix ==========
|
||||
#
|
||||
nix = {
|
||||
# This will add each flake input as a registry
|
||||
# To make nix3 commands consistent with your flake
|
||||
registry = lib.mapAttrs (_: value: { flake = value; }) inputs;
|
||||
|
||||
# This will add your inputs to the system's legacy channels
|
||||
# Making legacy nix commands consistent as well, awesome!
|
||||
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
|
||||
|
||||
settings = {
|
||||
# See https://jackson.dev/post/nix-reasonable-defaults/
|
||||
connect-timeout = 5;
|
||||
log-lines = 25;
|
||||
min-free = 128000000; # 128MB
|
||||
max-free = 1000000000; # 1GB
|
||||
|
||||
trusted-users = [ "@wheel" ];
|
||||
# Deduplicate and optimize nix store
|
||||
auto-optimise-store = true;
|
||||
warn-dirty = false;
|
||||
|
||||
allow-import-from-derivation = true;
|
||||
|
||||
experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
36
hosts/common/core/nixos.nix
Normal file
36
hosts/common/core/nixos.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
# Core functionality for every nixos host
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
# Database for aiding terminal-based programs
|
||||
environment.enableAllTerminfo = true;
|
||||
# Enable firmware with a license allowing redistribution
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
# This should be handled by config.security.pam.sshAgentAuth.enable
|
||||
security.sudo.extraConfig = ''
|
||||
Defaults lecture = never # rollback results in sudo lectures after each reboot, it's somewhat useless anyway
|
||||
Defaults pwfeedback # password input feedback - makes typed password visible as asterisks
|
||||
Defaults timestamp_timeout=120 # only ask for password every 2h
|
||||
# Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
|
||||
Defaults env_keep+=SSH_AUTH_SOCK
|
||||
'';
|
||||
|
||||
#
|
||||
# ========== Nix Helper ==========
|
||||
#
|
||||
# Provide better build output and will also handle garbage collection in place of standard nix gc (garbace collection)
|
||||
# FIXME(starter): customize garbage collection rules as desired.
|
||||
programs.nh = {
|
||||
enable = true;
|
||||
clean.enable = true;
|
||||
clean.extraArgs = "--keep-since 20d --keep 20";
|
||||
flake = "/home/user/${config.hostSpec.home}/nix-config";
|
||||
};
|
||||
|
||||
#
|
||||
# ========== Localization ==========
|
||||
#
|
||||
# FIXME(starter): customize localization values as desired.
|
||||
i18n.defaultLocale = lib.mkDefault "en_US.UTF-8";
|
||||
time.timeZone = lib.mkDefault "America/Edmonton";
|
||||
}
|
||||
9
hosts/common/core/services/default.nix
Normal file
9
hosts/common/core/services/default.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
# Add your core services to the same directory as this default.nix file.
|
||||
# They will automatically be imported below.
|
||||
{
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = (lib.custom.scanPaths ./.);
|
||||
}
|
||||
11
hosts/common/core/ssh.nix
Normal file
11
hosts/common/core/ssh.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
programs.ssh = lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||
startAgent = true;
|
||||
enableAskPassword = true;
|
||||
};
|
||||
}
|
||||
65
hosts/common/disks/btrfs-disk.nix
Normal file
65
hosts/common/disks/btrfs-disk.nix
Normal file
@@ -0,0 +1,65 @@
|
||||
# `...` is needed because dikso passes diskoFile
|
||||
{
|
||||
lib,
|
||||
disk ? "/dev/vda",
|
||||
withSwap ? false,
|
||||
swapSize,
|
||||
...
|
||||
}:
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
disk0 = {
|
||||
type = "disk";
|
||||
device = disk;
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
priority = 1;
|
||||
name = "ESP";
|
||||
start = "1M";
|
||||
end = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "defaults" ];
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" ]; # Override existing partition
|
||||
# Subvolumes must set a mountpoint in order to be mounted,
|
||||
# unless their parent is mounted
|
||||
subvolumes = {
|
||||
"@root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@swap" = lib.mkIf withSwap {
|
||||
mountpoint = "/.swapvol";
|
||||
swap.swapfile.size = "${swapSize}G";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
71
hosts/common/disks/luks-btrfs-disk.nix
Normal file
71
hosts/common/disks/luks-btrfs-disk.nix
Normal file
@@ -0,0 +1,71 @@
|
||||
# `...` is needed because dikso passes diskoFile
|
||||
{
|
||||
lib,
|
||||
disk ? "/dev/vda",
|
||||
withSwap ? false,
|
||||
swapSize,
|
||||
...
|
||||
}:
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
device = disk;
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
luks = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "crypted";
|
||||
# disable settings.keyFile if you want to use interactive password entry
|
||||
#passwordFile = "/tmp/secret.key"; # Interactive
|
||||
settings = {
|
||||
allowDiscards = true;
|
||||
};
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" ]; # Override existing partition
|
||||
# Subvolumes must set a mountpoint in order to be mounted,
|
||||
# unless their parent is mounted
|
||||
subvolumes = {
|
||||
"@root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@swap" = lib.mkIf withSwap {
|
||||
mountpoint = "/.swapvol";
|
||||
swap.swapfile.size = "${swapSize}G";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
21
hosts/common/optional/audio.nix
Normal file
21
hosts/common/optional/audio.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
# NOTE(starter): configure your audio needs as required.
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
hardware.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
wireplumber.enable = true;
|
||||
jack.enable = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = builtins.attrValues {
|
||||
inherit (pkgs)
|
||||
playerctl # cli utility and lib for controlling media players
|
||||
# pamixer # cli pulseaudio sound mixer
|
||||
;
|
||||
};
|
||||
}
|
||||
4
hosts/common/optional/kde.nix
Normal file
4
hosts/common/optional/kde.nix
Normal file
@@ -0,0 +1,4 @@
|
||||
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
|
||||
{
|
||||
services.desktopManager.plasma6.enable = true;
|
||||
}
|
||||
13
hosts/common/optional/minimal-user.nix
Normal file
13
hosts/common/optional/minimal-user.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
# NOTE: This module is required for nixos-installer
|
||||
{ config, ... }:
|
||||
{
|
||||
# Set a temp password for use by minimal builds like installer and iso
|
||||
users.users.${config.hostSpec.username} = {
|
||||
isNormalUser = true;
|
||||
# This is a hashed version of the plain-text password "nixos" for use in the ISO. Even though,
|
||||
# the password is known, we use `hashedPassword` here instead of `password` to mitigate
|
||||
# occurrences of the latter not being used during build.
|
||||
password = "password";
|
||||
extraGroups = [ "wheel" ];
|
||||
};
|
||||
}
|
||||
10
hosts/common/optional/sddm.nix
Normal file
10
hosts/common/optional/sddm.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
|
||||
{
|
||||
services.displayManager = {
|
||||
sddm.enable = true;
|
||||
sddm.wayland = {
|
||||
enable = true;
|
||||
compositor = "kwin";
|
||||
};
|
||||
};
|
||||
}
|
||||
36
hosts/common/optional/services/openssh.nix
Normal file
36
hosts/common/optional/services/openssh.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
# FIXME(starter): if you are not defining ports in your "soft" nix-secrets, you can
|
||||
# replace the following line with: sshPort = 22;
|
||||
# and substitute 22 with a custom port number if needed.
|
||||
sshPort = 22;
|
||||
in
|
||||
|
||||
{
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
ports = [ sshPort ];
|
||||
|
||||
settings = {
|
||||
# Harden
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
# Automatically remove stale sockets
|
||||
StreamLocalBindUnlink = "yes";
|
||||
# Allow forwarding ports to everywhere
|
||||
GatewayPorts = "clientspecified";
|
||||
};
|
||||
|
||||
hostKeys = [
|
||||
{
|
||||
path = "/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ sshPort ];
|
||||
}
|
||||
5
hosts/common/optional/xfce.nix
Normal file
5
hosts/common/optional/xfce.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
# NOTE(starter): This is just a basic enabling of the XFCE windows manager for simplicity
|
||||
{
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.xserver.desktopManager.xfce.enableScreensaver = false;
|
||||
}
|
||||
67
hosts/common/users/exampleSecondUser/default.nix
Normal file
67
hosts/common/users/exampleSecondUser/default.nix
Normal file
@@ -0,0 +1,67 @@
|
||||
# FIXME(starter): this is an example of how a secondary user called "exampleSecondUser" can be declared.
|
||||
# NOTE that this file's parent directory matches the username!
|
||||
# Modify the directory name and all instances of `exampleSecondUser` in this file to a real username to
|
||||
# make use of this file. You'll also need to import this file in the relevant `nix-config/hosts/[platform]/[hostname]/default.nix`
|
||||
# host file for the user to be created on the host.
|
||||
# NOTE that this file also assumes you will be declaring the user's password via sops.
|
||||
# .
|
||||
# If you have no need for secondary users, simple delete this file and its parent directory, and ensure that
|
||||
# your `nix-confitg/hosts/[platform]/[hostname]/default.nix` files do not import this file.
|
||||
|
||||
#
|
||||
# Basic user for viewing exampleSecondUser
|
||||
#
|
||||
|
||||
{
|
||||
inputs,
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hostSpec = config.hostSpec;
|
||||
secretsSubPath = "passwords/exampleSecondUser";
|
||||
in
|
||||
{
|
||||
# Decrypt passwords/exampleSecondUser to /run/secrets-for-users/ so it can be used to create the user
|
||||
sops.secrets.${secretsSubPath}.neededForUsers = true;
|
||||
users.mutableUsers = false; # Required for password to be set via sops during system activation!
|
||||
|
||||
users.users.exampleSecondUser = {
|
||||
isNormalUser = true;
|
||||
hashedPasswordFile = config.sops.secrets.${secretsSubPath}.path;
|
||||
shell = pkgs.zsh; # default shell
|
||||
extraGroups = [
|
||||
"audio"
|
||||
"video"
|
||||
];
|
||||
|
||||
packages = [ pkgs.home-manager ];
|
||||
};
|
||||
}
|
||||
# Import this user's personal/home configurations
|
||||
// lib.optionalAttrs (inputs ? "home-manager") {
|
||||
home-manager = {
|
||||
extraSpecialArgs = {
|
||||
inherit pkgs inputs;
|
||||
hostSpec = config.hostSpec;
|
||||
};
|
||||
users.exampleSecondUser.imports = lib.flatten (
|
||||
lib.optional (!hostSpec.isMinimal) [
|
||||
(
|
||||
{ config, ... }:
|
||||
import (lib.custom.relativeToRoot "home/exampleSecondUser/${hostSpec.hostName}.nix") {
|
||||
inherit
|
||||
pkgs
|
||||
inputs
|
||||
config
|
||||
lib
|
||||
hostSpec
|
||||
;
|
||||
}
|
||||
)
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
7
hosts/common/users/primary/darwin.nix
Normal file
7
hosts/common/users/primary/darwin.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
# User config applicable only to darwin
|
||||
{ config, ... }:
|
||||
{
|
||||
users.users.${config.hostSpec.username} = {
|
||||
home = "/Users/${config.hostSpec.username}";
|
||||
};
|
||||
}
|
||||
68
hosts/common/users/primary/default.nix
Normal file
68
hosts/common/users/primary/default.nix
Normal file
@@ -0,0 +1,68 @@
|
||||
# NOTE(starter): this is the primary user across all hosts. The username for primary is defined in hostSpec,
|
||||
# and is declared in `nix-config/common/core/default.nix`
|
||||
|
||||
# User config applicable to both nixos and darwin
|
||||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hostSpec = config.hostSpec;
|
||||
pubKeys = lib.filesystem.listFilesRecursive ./keys;
|
||||
in
|
||||
{
|
||||
users.users.${hostSpec.username} = {
|
||||
name = hostSpec.username;
|
||||
shell = pkgs.bash; # default shell
|
||||
|
||||
# These get placed into /etc/ssh/authorized_keys.d/<name> on nixos
|
||||
openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
|
||||
};
|
||||
|
||||
# Create ssh sockets directory for controlpaths when homemanager not loaded (i.e. isMinimal)
|
||||
systemd.tmpfiles.rules =
|
||||
let
|
||||
user = config.users.users.${hostSpec.username}.name;
|
||||
group = config.users.users.${hostSpec.username}.group;
|
||||
in
|
||||
# you must set the rule for .ssh separately first, otherwise it will be automatically created as root:root and .ssh/sockects will fail
|
||||
[
|
||||
"d /home/${hostSpec.username}/.ssh 0750 ${user} ${group} -"
|
||||
"d /home/${hostSpec.username}/.ssh/sockets 0750 ${user} ${group} -"
|
||||
];
|
||||
|
||||
# No matter what environment we are in we want these tools
|
||||
programs.zsh.enable = true;
|
||||
environment.systemPackages = [
|
||||
pkgs.just
|
||||
pkgs.rsync
|
||||
];
|
||||
}
|
||||
# Import the user's personal/home configurations, unless the environment is minimal
|
||||
// lib.optionalAttrs (inputs ? "home-manager") {
|
||||
home-manager = {
|
||||
extraSpecialArgs = {
|
||||
inherit pkgs inputs;
|
||||
hostSpec = config.hostSpec;
|
||||
};
|
||||
users.${hostSpec.username}.imports = lib.flatten (
|
||||
lib.optional (!hostSpec.isMinimal) [
|
||||
(
|
||||
{ config, ... }:
|
||||
import (lib.custom.relativeToRoot "home/${hostSpec.username}/${hostSpec.hostName}.nix") {
|
||||
inherit
|
||||
pkgs
|
||||
inputs
|
||||
config
|
||||
lib
|
||||
hostSpec
|
||||
;
|
||||
}
|
||||
)
|
||||
]
|
||||
);
|
||||
};
|
||||
}
|
||||
1
hosts/common/users/primary/keys/README.md
Normal file
1
hosts/common/users/primary/keys/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Add your ssh public keys to this directory. E.g. id_foo.pub
|
||||
44
hosts/common/users/primary/nixos.nix
Normal file
44
hosts/common/users/primary/nixos.nix
Normal file
@@ -0,0 +1,44 @@
|
||||
# User config applicable only to nixos
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hostSpec = config.hostSpec;
|
||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||
in
|
||||
{
|
||||
users.mutableUsers = false; # Only allow declarative credentials; Required for password to be set via sops during system activation!
|
||||
users.users.${hostSpec.username} = {
|
||||
home = "/home/${hostSpec.username}";
|
||||
isNormalUser = true;
|
||||
password = "password";
|
||||
|
||||
extraGroups = lib.flatten [
|
||||
"wheel"
|
||||
(ifTheyExist [
|
||||
"audio"
|
||||
"video"
|
||||
"docker"
|
||||
"git"
|
||||
"networkmanager"
|
||||
"scanner" # for print/scan"
|
||||
"lp" # for print/scan"
|
||||
])
|
||||
];
|
||||
};
|
||||
|
||||
# No matter what environment we are in we want these tools for root, and the user(s)
|
||||
programs.git.enable = true;
|
||||
|
||||
# root's ssh key are mainly used for remote deployment, borg, and some other specific ops
|
||||
users.users.root = {
|
||||
shell = pkgs.bash;
|
||||
hashedPasswordFile = config.users.users.${hostSpec.username}.hashedPasswordFile;
|
||||
hashedPassword = config.users.users.${hostSpec.username}.hashedPassword; # This comes from hosts/common/optional/minimal.nix and gets overridden if sops is working
|
||||
openssh.authorizedKeys.keys = config.users.users.${hostSpec.username}.openssh.authorizedKeys.keys; # root's ssh keys are mainly used for remote deployment.
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user