Compare commits

..

No commits in common. "main" and "multihost" have entirely different histories.

98 changed files with 159 additions and 5121 deletions

1
.envrc
View file

@ -1 +0,0 @@
use_nix

View file

@ -1,33 +1,3 @@
# nixfiles
# nixos-config
My NixOS configuration files.
The canonical location for this repository is https://git.unspecified.systems/qenya/nixfiles. If you're viewing it elsewhere, it is a mirror and may not be up-to-date.
## Machines
### Managed
* `kilgharrah`: Custom-built personal desktop; also currently running Jellyfin, Navidrome and Audiobookshelf servers (and an FTP server, for shits and giggles)
* `tohru`: Dell Latitude 5300, personal laptop
* `elucredassa`: Acer Aspire A315-53, old laptop with a broken keyboard that now sits in a corner being a backup server
* `yevaud`: Oracle Cloud free AMD VM, hosts a Forgejo instance and WireGuard server for the other machines in the network
* `orm`: Oracle Cloud free AMD VM, hosts an instance of Actual Budget and a PostgreSQL server for other services that need one
* `kalessin`: Oracle Cloud free ARM VM, currently idling
### Referenced only
* `shaw`: [My girlfriend's NAS](https://github.com/randomnetcat/nix-configs/tree/main/hosts/shaw)
* `latias`: My Steam Deck
## Usage
### Building
To build locally, run `nixos-rebuild switch --flake .#[hostname]` as root.
To build the remote machines, run `colmena apply`. See the [colmena documentation](https://colmena.cli.rs/) for command-line options. Notable options include:
* `--on [hostname]`: build a specific machine only
* `--reboot`: reboot after building (but note [this bug](https://github.com/zhaofengli/colmena/issues/166) means it may hang even when the reboot completes successfully)
### Updating
`nix flake update --commit-lock-file`
My NixOS configuration files

View file

@ -1,29 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qenya.base-graphical;
in
{
imports = [
./gnome.nix
./sound.nix
];
options.qenya.base-graphical.enable = mkEnableOption "Base configuration for graphical environments";
config = mkIf cfg.enable {
services.xserver.enable = true;
services.libinput.enable = true;
services.printing.enable = true;
services.avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
};
fonts.packages = with pkgs; [
corefonts
];
};
}

View file

@ -1,21 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkMerge mkOption types;
cfg = config.qenya.base-graphical;
in
{
config = mkIf cfg.enable {
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
# TODO: agree on this with randomcat as it affects her too, since for some reason this is system-wide
# environment.gnome.excludePackages = with pkgs.gnome; [
# pkgs.gnome-tour
# epiphany # GNOME Web
# geary
# gnome-calendar
# gnome-contacts
# gnome-music
# ];
};
}

View file

@ -1,20 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qenya.base-graphical;
in
{
config = mkIf cfg.enable {
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
services.pulseaudio.enable = false; # this theoretically defaults to false but something else seems to be flipping it
environment.systemPackages = with pkgs; [ helvum ]; # patchbay
};
}

View file

@ -1,17 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qenya.base-server;
in
{
options.qenya.base-server.enable = mkEnableOption "Base configuration for headless servers";
config = mkIf cfg.enable {
time.timeZone = "Etc/UTC";
# Allow remote deployment with colmena
deployment.targetUser = null;
security.sudo.wheelNeedsPassword = false;
};
}

View file

@ -1,35 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf optionals;
in
{
boot.loader = {
systemd-boot.enable = true;
systemd-boot.editor = false;
systemd-boot.memtest86.enable = mkIf config.nixpkgs.hostPlatform.isx86 true;
efi.canTouchEfiVariables = true;
};
boot.kernelPatches = optionals config.nixpkgs.hostPlatform.isx86 [
# Fix the /proc/net/tcp seek issue
# Impacts tailscale: https://github.com/tailscale/tailscale/issues/16966
{
name = "proc: fix missing pde_set_flags() for net proc files";
patch = pkgs.fetchurl {
name = "fix-missing-pde_set_flags-for-net-proc-files.patch";
url = "https://patchwork.kernel.org/project/linux-fsdevel/patch/20250821105806.1453833-1-wangzijie1@honor.com/raw/";
hash = "sha256-DbQ8FiRj65B28zP0xxg6LvW5ocEH8AHOqaRbYZOTDXg=";
};
}
];
services.resolved = {
enable = true;
fallbackDns = [ ];
dnsovertls = "true";
extraConfig = ''
DNS=2a07:e340::4#base.dns.mullvad.net 194.242.2.4#base.dns.mullvad.net 2606:1a40::11#p2.freedns.controld.com 76.76.2.11#p2.freedns.controld.com
'';
};
}

View file

@ -1,19 +0,0 @@
{
imports = [
./base-graphical
./base-server
./users
./boot.nix
./gpg.nix
./home-manager.nix
./misc.nix
./nginx.nix
./nix.nix
./packages.nix
./sanoid.nix
./security.nix
./ssh.nix
./steam.nix
./tailscale.nix
];
}

View file

@ -1,8 +0,0 @@
{ config, lib, pkgs, ... }:
{
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
}

View file

@ -1,12 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
{
home-manager = {
useUserPackages = true;
useGlobalPkgs = true;
backupFileExtension = "backup";
extraSpecialArgs = {
inherit inputs;
};
};
}

View file

@ -1,12 +0,0 @@
{ config, lib, pkgs, ... }:
{
nix.gc = {
automatic = true;
dates = "weekly";
randomizedDelaySec = "45min";
options = "--delete-older-than 30d";
};
nix.optimise.automatic = true;
services.fstrim.enable = true;
}

View file

@ -1,25 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.nginx = {
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
appendHttpConfig = ''
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;
add_header Content-Security-Policy "default-src https: data: blob: ws: 'unsafe-inline' 'wasm-unsafe-eval'; object-src 'none'; base-uri 'self';" always;
add_header Referrer-Policy strict-origin-when-cross-origin;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-Clacks-Overhead "GNU Terry Pratchett" always;
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
'';
};
security.acme = {
acceptTerms = true;
defaults.email = "auto@qenya.tel";
};
}

View file

@ -1,33 +0,0 @@
{ config, lib, pkgs, ... }:
{
nix.settings.experimental-features = "nix-command flakes";
nixpkgs.flake = {
source = lib.cleanSource pkgs.path;
setNixPath = true;
setFlakeRegistry = true;
};
nixpkgs.config.allowUnfree = true;
nix.settings.trusted-users = [ "@wheel" ];
# Dependency of jellyfin-media-player, which hasn't upgraded to Qt6 yet
# Related tickets:
# - https://github.com/NixOS/nixpkgs/pull/435067
# - https://github.com/NixOS/nixpkgs/issues/437865
# - https://github.com/jellyfin/jellyfin-media-player/issues/282
nixpkgs.config.permittedInsecurePackages = [
"qtwebengine-5.15.19"
];
nix.package = pkgs.lixPackageSets.stable.lix;
nixpkgs.overlays = [
(final: prev: {
inherit (final.lixPackageSets.stable)
nixpkgs-review
nix-direnv
nix-eval-jobs
nix-fast-build
colmena;
})
];
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
btop
git
wget
# hardware troubleshooting
lshw
parted
smartmontools
# network troubleshooting
inetutils
lsof
tcpdump
netcat # <3
wireguard-tools
];
environment.wordlist.enable = true;
}

View file

@ -1,35 +0,0 @@
{ config, pkgs, inputs, ... }:
{
config = {
services.sanoid = {
enable = true;
extraArgs = [ "--verbose" ];
# Local snapshots for important datasets
templates."production" = {
yearly = 0;
monthly = 3;
daily = 30;
hourly = 36;
autosnap = true;
autoprune = true;
};
# Reduced-retention version for datasets that are backed up to the NAS
templates."safe" = {
yearly = 0;
monthly = 0;
daily = 7;
hourly = 24;
autosnap = true;
autoprune = true;
};
# datasets."rpool_sggau1/reese/system" = {
# useTemplate = [ "safe" ];
# recursive = "zfs";
# };
};
};
}

View file

@ -1,5 +0,0 @@
{ config, lib, pkgs,... }:
{
security.sudo.execWheelOnly = true;
}

View file

@ -1,21 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) concatMapAttrs;
keys = import ../keys.nix;
in
{
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
programs.ssh.knownHosts = concatMapAttrs
(host: key: {
"${host}.birdsong.network".publicKey = key;
})
keys.machines;
}

View file

@ -1,16 +0,0 @@
{ config, lib, pkgs, ... }:
{
config = lib.mkIf config.programs.steam.enable {
programs.steam = {
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
localNetworkGameTransfers.openFirewall = true;
gamescopeSession.enable = true;
extest.enable = true;
protontricks.enable = true;
};
services.joycond.enable = true;
};
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.tailscale = {
enable = true;
openFirewall = true;
extraUpFlags = [ "--login-server" "https://headscale.unspecified.systems" ];
extraDaemonFlags = [ "--no-logs-no-support" ]; # disable telemetry
};
systemd.services.tailscaled-autoconnect = {
after = [ "tailscaled.service" "network-online.target" ];
wants = [ "tailscaled.service" "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
script = ''
sleep 2 # wait for tailscaled to settle
${lib.getExe config.services.tailscale.package} up --reset ${lib.escapeShellArgs config.services.tailscale.extraUpFlags}
'';
};
networking.domain = "birdsong.network";
}

View file

@ -1,32 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption types genAttrs;
cfg = config.fountain;
in
{
# TODO: consider DRY-ing these
imports = [
./gaelan.nix
./qenya.nix
./randomcat.nix
./trungle.nix
];
options.fountain = {
admins = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of users who should have root on this system";
};
};
config = {
users.mutableUsers = false;
users.users = genAttrs cfg.admins
(name: {
extraGroups = [ "wheel" ];
});
};
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkEnableOption;
keys = import ../../keys.nix;
cfg = config.fountain.users.gaelan;
in
{
options.fountain.users.gaelan = {
enable = mkEnableOption "user gaelan";
};
config = mkIf cfg.enable {
users.users.gaelan = {
uid = 1003;
isNormalUser = true;
group = "gaelan";
openssh.authorizedKeys.keys = keys.users.gaelan;
};
users.groups.gaelan.gid = config.users.users.gaelan.uid;
};
}

View file

@ -1,28 +0,0 @@
{ config, lib, pkgs, self, ... }:
let
inherit (lib) mkIf mkEnableOption;
keys = import ../../keys.nix;
cfg = config.fountain.users.qenya;
in
{
options.fountain.users.qenya = {
enable = mkEnableOption "user qenya";
};
config = mkIf cfg.enable {
users.users.qenya = {
uid = 1001;
isNormalUser = true;
group = "qenya";
shell = pkgs.zsh;
openssh.authorizedKeys.keys = keys.users.qenya;
};
users.groups.qenya.gid = config.users.users.qenya.uid;
programs.zsh.enable = true;
home-manager.users."qenya" = self.homeManagerModules."qenya";
};
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkEnableOption;
keys = import ../../keys.nix;
cfg = config.fountain.users.randomcat;
in
{
options.fountain.users.randomcat = {
enable = mkEnableOption "user randomcat";
};
config = mkIf cfg.enable {
users.users.randomcat = {
uid = 1000;
isNormalUser = true;
group = "randomcat";
openssh.authorizedKeys.keys = keys.users.randomcat;
};
users.groups.randomcat.gid = config.users.users.randomcat.uid;
};
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkEnableOption;
keys = import ../../keys.nix;
cfg = config.fountain.users.trungle;
in
{
options.fountain.users.trungle = {
enable = mkEnableOption "user trungle";
};
config = mkIf cfg.enable {
users.users.trungle = {
uid = 1002;
isNormalUser = true;
group = "trungle";
openssh.authorizedKeys.keys = keys.users.trungle;
};
users.groups.trungle.gid = config.users.users.trungle.uid;
};
}

280
flake.lock generated
View file

@ -1,294 +1,24 @@
{
"nodes": {
"agenix": {
"inputs": {
"darwin": [],
"home-manager": [],
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1754433428,
"narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
"owner": "ryantm",
"repo": "agenix",
"rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
"type": "github"
},
"original": {
"owner": "ryantm",
"repo": "agenix",
"type": "github"
}
},
"colmena": {
"inputs": {
"flake-compat": [],
"flake-utils": "flake-utils",
"nix-github-actions": [],
"nixpkgs": [
"nixpkgs"
],
"stable": []
},
"locked": {
"lastModified": 1755272288,
"narHash": "sha256-ypTPb2eKcOBbOoyvPV0j4ZOXs4kayo73/2KI456QnE0=",
"owner": "zhaofengli",
"repo": "colmena",
"rev": "5bf4ce6a24adba74a5184f4a9bef01d545a09473",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"repo": "colmena",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1756770412,
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "4524271976b625a4a605beefd893f270620fd751",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1756679287,
"narHash": "sha256-Xd1vOeY9ccDf5VtVK12yM0FS6qqvfUop8UQlxEB+gTQ=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "07fc025fe10487dd80f2ec694f1cd790e752d0e8",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-25.05",
"repo": "home-manager",
"type": "github"
}
},
"home-manager-unstable": {
"inputs": {
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1757256385,
"narHash": "sha256-WK7tOhWwr15mipcckhDg2no/eSpM1nIh4C9le8HgHhk=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "f35703b412c67b48e97beb6e27a6ab96a084cd37",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1757244434,
"narHash": "sha256-AeqTqY0Y95K1Fgs6wuT1LafBNcmKxcOkWnm4alD9pqM=",
"lastModified": 1716361217,
"narHash": "sha256-mzZDr00WUiUXVm1ujBVv6A0qRd8okaITyUp4ezYRgc4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "092c565d333be1e17b4779ac22104338941d913f",
"rev": "46397778ef1f73414b03ed553a3368f0e7e33c2f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"ref": "nixos-23.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1754788789,
"narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "a73b9c743612e4244d865a2fdee11865283c04e6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-small": {
"locked": {
"lastModified": 1757312038,
"narHash": "sha256-34XfbJT/fDl4OQNbtx1dHQRQGRodnHtZcM3VlM9d/5o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "16721e9cbabc2847dd62591e5ec8f2ea54379588",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1757068644,
"narHash": "sha256-NOrUtIhTkIIumj1E/Rsv1J37Yi3xGStISEo8tZm3KW4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8eb28adfa3dc4de28e792e3bf49fcf9007ca8ac9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable-small": {
"locked": {
"lastModified": 1757308260,
"narHash": "sha256-y/mYfpaSicNLq3AtR6BrgK7MZl4PiAWAfnYjKHr/zEA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e568c4e9e6231f948f0d1f3c90859b41e8791186",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
}
},
"plasma-manager": {
"inputs": {
"home-manager": [
"home-manager-unstable"
],
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1756632588,
"narHash": "sha256-ydam6eggXf3ZwRutyCABwSbMAlX+5lW6w1SVZQ+kfSo=",
"owner": "nix-community",
"repo": "plasma-manager",
"rev": "d47428e5390d6a5a8f764808a4db15929347cd77",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "plasma-manager",
"type": "github"
}
},
"randomcat": {
"flake": false,
"locked": {
"lastModified": 1757296776,
"narHash": "sha256-j/0sale7a8dDl7fZJSujANEF8EGt6hHl+Cw1UXN8/Mk=",
"owner": "randomnetcat",
"repo": "nix-configs",
"rev": "2fcdb2d229a34190cfa24edbeabf4f34bdd5099c",
"type": "github"
},
"original": {
"owner": "randomnetcat",
"repo": "nix-configs",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"colmena": "colmena",
"flake-parts": "flake-parts",
"home-manager": "home-manager",
"home-manager-unstable": "home-manager-unstable",
"nixpkgs": "nixpkgs",
"nixpkgs-small": "nixpkgs-small",
"nixpkgs-unstable": "nixpkgs-unstable",
"nixpkgs-unstable-small": "nixpkgs-unstable-small",
"plasma-manager": "plasma-manager",
"randomcat": "randomcat",
"scoutshonour": "scoutshonour"
}
},
"scoutshonour": {
"inputs": {
"nixpkgs": [
"nixpkgs-unstable"
]
},
"locked": {
"lastModified": 1735301893,
"narHash": "sha256-d95MCTUYMCcOQv4LpmWxPuVnx7McezXYs2Idw8u8ngI=",
"ref": "main",
"rev": "f447cd380ea1fb81a0ff8f292b6bbdf0be9c9520",
"revCount": 23,
"type": "git",
"url": "https://git.qenya.tel/qenya/nix-scoutshonour"
},
"original": {
"ref": "main",
"type": "git",
"url": "https://git.qenya.tel/qenya/nix-scoutshonour"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
"nixpkgs": "nixpkgs"
}
}
},

157
flake.nix
View file

@ -1,155 +1,14 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
nixpkgs-small.url = "github:NixOS/nixpkgs/nixos-25.05-small";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-unstable-small.url = "github:NixOS/nixpkgs/nixos-unstable-small";
home-manager = {
url = "github:nix-community/home-manager/release-25.05";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager-unstable = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
plasma-manager = {
url = "github:nix-community/plasma-manager";
inputs.nixpkgs.follows = "nixpkgs-unstable";
inputs.home-manager.follows = "home-manager-unstable";
};
flake-parts.url = "github:hercules-ci/flake-parts";
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.darwin.follows = "";
inputs.home-manager.follows = "";
};
colmena = {
url = "github:zhaofengli/colmena";
inputs.nixpkgs.follows = "nixpkgs";
inputs.stable.follows = "";
inputs.nix-github-actions.follows = "";
inputs.flake-compat.follows = "";
};
randomcat = {
url = "github:randomnetcat/nix-configs";
flake = false;
};
scoutshonour = {
url = "git+https://git.qenya.tel/qenya/nix-scoutshonour?ref=main";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
};
outputs = inputs@{ self, nixpkgs, nixpkgs-small, nixpkgs-unstable, flake-parts, colmena, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ ./flake ];
systems = [ "x86_64-linux" "aarch64-linux" ];
perSystem = { pkgs, system, ... }: {
devShells.default = pkgs.mkShell {
packages = [
# TODO: improve the way this override works
(inputs.colmena.packages.${system}.colmena.override {
nix-eval-jobs = pkgs.lixPackageSets.stable.nix-eval-jobs;
})
inputs.agenix.packages.${system}.default
inputs.plasma-manager.packages.${system}.rc2nix
];
};
};
flake.nixosConfigurations = self.outputs.colmenaHive.nodes;
flake.colmenaHive = colmena.lib.makeHive self.outputs.colmena;
# The name of this output type is not standardised. I have picked
# "homeManagerModules" as the discussion here suggests it's the most common:
# https://github.com/nix-community/home-manager/issues/1783
#
# However, note CppNix >= 2.22.3, >= 2.24 has blessed "homeModules":
# https://github.com/NixOS/nix/pull/10858
flake.homeManagerModules = {
"qenya".imports = [ ./home/qenya ];
"qenya@shaw".imports = [ ./hosts/shaw/home.nix ];
};
fountain.backup = {
keys = {
elucredassa = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFa3hjej6KGmS2aQ4s46Y7U8pN4yyR2FuMofpHRwXNk syncoid@elucredassa" ];
};
sync = {
"orm-state" = {
dataset = "state";
sourceHost = "orm";
targetHost = "elucredassa";
source = "rpool_orm";
target = "rpool_elucredassa/backup/orm";
};
"kalessin-state" = {
dataset = "state";
sourceHost = "kalessin";
targetHost = "elucredassa";
source = "rpool_kalessin";
target = "rpool_elucredassa/backup/kalessin";
};
};
};
flake.colmena =
let
home-manager = inputs.home-manager.nixosModules.home-manager;
home-manager-unstable = inputs.home-manager-unstable.nixosModules.home-manager;
in
{
meta = {
nixpkgs = import nixpkgs-unstable { system = "x86_64-linux"; };
nodeNixpkgs = {
kilgharrah = import nixpkgs-unstable { system = "x86_64-linux"; };
tohru = import nixpkgs { system = "x86_64-linux"; };
elucredassa = import nixpkgs-small { system = "x86_64-linux"; };
yevaud = import nixpkgs-small { system = "x86_64-linux"; };
orm = import nixpkgs-small { system = "x86_64-linux"; };
kalessin = import nixpkgs-small { system = "aarch64-linux"; };
tehanu = import nixpkgs-small { system = "aarch64-linux"; };
};
specialArgs = {
inherit self;
inherit inputs;
};
};
defaults = { config, lib, pkgs, ... }: {
deployment.targetHost = lib.mkDefault config.networking.fqdn;
deployment.buildOnTarget = lib.mkDefault true;
imports = [
inputs.agenix.nixosModules.default
./common
./services
(builtins.toPath "${inputs.randomcat}/services/default.nix")
];
};
kilgharrah.deployment.targetHost = null; # disable remote deployment
tohru.deployment.targetHost = null; # disable remote deployment
elucredassa.deployment.targetHost = "100.73.34.182"; # TODO: no fqdn yet
kilgharrah.imports = [ ./hosts/kilgharrah home-manager-unstable ];
tohru.imports = [ ./hosts/tohru home-manager ];
elucredassa.imports = [ ./hosts/elucredassa home-manager ];
yevaud.imports = [ ./hosts/yevaud home-manager ];
orm.imports = [ ./hosts/orm home-manager ];
kalessin.imports = [ ./hosts/kalessin home-manager ];
tehanu.imports = [ ./hosts/tehanu home-manager ];
};
outputs = { self, nixpkgs, ... }@inputs: {
nixosConfigurations.tohru = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hosts/tohru/configuration.nix
];
};
};
}

View file

@ -1,134 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.fountain.backup;
keys = import ../keys.nix;
syncOptions = {
dataset = lib.mkOption {
type = lib.types.str;
description = ''
The name of the dataset to be synced (not including its parent
datasets, if any). This will be the same on the source and target.
It must already exist on the source, defined with the
{option}`randomcat.services.zfs` module, and not exist on the target.
'';
};
sourceHost = lib.mkOption {
type = lib.types.str;
description = ''
The host from which the dataset should be synced. Must be an entry in
{option}`flake.colmena`.
'';
};
targetHost = lib.mkOption {
type = lib.types.str;
description = ''
The host to which the dataset should be synced. Must be an entry in
{option}`flake.colmena`.
'';
};
source = lib.mkOption {
type = lib.types.str;
description = ''
The path to the synced dataset in the ZFS namespace on the source host,
excluding the component that is the name of the dataset itself.
'';
};
target = lib.mkOption {
type = lib.types.str;
description = ''
The path to the synced dataset in the ZFS namespace on the target host,
excluding the component that is the name of the dataset itself. It must
already exist, defined with the {option}`randomcat.services.zfs`
module.
'';
};
};
in
{
options.fountain.backup = {
keys = lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.singleLineStr);
default = { };
description = ''
Lists of verbatim OpenSSH public keys that may be used to identify the
syncoid user on each target host. The key to each list must be the
host's hostname, as listed in {option}`flake.colmena`.
'';
example = {
host = [ "ssh-rsa AAAAB3NzaC1yc2etc/etc/etcjwrsh8e596z6J0l7 example@host" ];
bar = [ "ssh-ed25519 AAAAC3NzaCetcetera/etceteraJZMfk3QPfQ foo@bar" ];
};
};
sync = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule { options = syncOptions; });
default = { };
description = ''
Details of ZFS datasets whose snapshots should be synced from machine
to machine using syncoid. Syncoid will run hourly at 15 past the hour
and copy all ZFS snapshots from the source dataset to the target
dataset (recursing into child datasets).
See descriptions for the individual options for more details. The name
of each attribute in this set is arbitrary and used to generate systemd
unit names.
This module does not actually cause snapshots to be taken; sanoid must
be configured separately to do this.
'';
example = {
"orm-state" = {
dataset = "state";
sourceHost = "orm";
targetHost = "elucredassa";
source = "rpool_orm";
target = "rpool_elucredassa/backup/orm";
};
};
};
};
# TODO: add some assertions to verify the options
config.flake.colmena = lib.mkMerge (lib.mapAttrsToList
(name: sync:
let
inherit (sync) dataset sourceHost targetHost source target;
sourceFqdn = "${sourceHost}.birdsong.network";
in
{
${sourceHost} = { pkgs, ... }: {
randomcat.services.zfs.datasets."${source}/${dataset}".zfsPermissions.users.backup = [ "hold" "send" ];
users.users.backup = {
group = "backup";
isSystemUser = true;
useDefaultShell = true;
openssh.authorizedKeys.keys = cfg.keys.${targetHost};
packages = with pkgs; [ mbuffer lzop ]; # syncoid uses these if available but doesn't pull them in automatically
};
users.groups.backup = { };
};
${targetHost} = {
randomcat.services.zfs.datasets.${target}.zfsPermissions.users.syncoid = [ "mount" "create" "receive" "recordsize" ];
services.syncoid = {
enable = true;
interval = "*-*-* *:15:00";
commonArgs = [ "--no-sync-snap" ];
commands = {
${name} = {
source = "backup@${sourceFqdn}:${source}/${dataset}";
target = "${target}/${dataset}";
recursive = true;
recvOptions = "ux recordsize o compression=lz4";
};
};
};
};
})
cfg.sync
);
}

View file

@ -1,19 +0,0 @@
# https://git.lix.systems/the-distro/infra/src/commit/fbb23bf517206175764f154ddfd304b9ec501f87/colmena.nix
{ lib, ... }: {
options.flake.colmena = lib.mkOption {
type = lib.types.submodule {
freeformType = lib.types.attrsOf (lib.mkOptionType {
name = "NixOS module";
description = "module containing NixOS options and/or config";
descriptionClass = "noun";
check = value: builtins.isAttrs value || builtins.isFunction value || builtins.isPath value;
merge = loc: defs: {
imports = map (def: def.value) defs;
};
});
options.meta = lib.mkOption {
type = lib.types.attrs;
};
};
};
}

View file

@ -1,6 +0,0 @@
{
imports = [
./backup.nix
./colmena.nix
];
}

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

View file

@ -1,26 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
# dconf is the configuration manager for GNOME.
let
isGnome = osConfig.services.xserver.desktopManager.gnome.enable;
in
{
dconf.enable = isGnome;
dconf.settings = {
"org/gnome/settings-daemon/plugins/color".night-light-enabled = true;
"org/gnome/desktop/sound".event-sounds = false;
"org/gnome/desktop/sound".allow-volume-above-100-percent = true;
"org/gnome/settings-daemon/plugins/power".power-saver-profile-on-low-battery = true;
};
imports = [
./desktop.nix
./keyboard.nix
./mouse-touchpad.nix
./multitasking.nix
./shell.nix
./wellbeing.nix
];
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
let inherit (lib) mkIf;
in {
dconf.settings = {
"org/gnome/desktop/background" = {
picture-options = "zoom";
picture-uri = "${config.home.homeDirectory}/.background-image";
picture-uri-dark = "${config.home.homeDirectory}/.background-image";
};
"org/gnome/desktop/screensaver" = {
picture-options = "zoom";
picture-uri = "${config.home.homeDirectory}/.background-image";
};
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
enable-hot-corners = false;
};
};
home.file.".background-image" = mkIf config.dconf.enable {
source = ./background-image.jpg;
};
}

View file

@ -1,12 +0,0 @@
# { config, lib, pkgs, ... }:
{
dconf.settings = {
"org/gnome/desktop/wm/keybindings" = {
# These are largely useless on most normal systems
# and conflict with VS Code's default keybinds for "Copy Line Up/Down"
move-to-workspace-up = [ ];
move-to-workspace-down = [ ];
};
};
}

View file

@ -1,16 +0,0 @@
{ config, lib, pkgs, ... }:
{
dconf.settings = {
"org/gnome/desktop/peripherals/mouse" = {
natural-scroll = false;
};
"org/gnome/desktop/peripherals/touchpad" = {
click-method = "fingers";
disable-while-typing = false;
natural-scroll = true; # the correct option, whatever Janet says
tap-to-click = true;
two-finger-scrolling-enabled = true;
};
};
}

View file

@ -1,11 +0,0 @@
{ config, lib, pkgs, ... }:
{
dconf.settings = {
"org/gnome/mutter" = {
edge-tiling = true;
dynamic-workspaces = true;
workspaces-only-on-primary = true;
};
};
}

View file

@ -1,26 +0,0 @@
{ config, lib, pkgs, ... }:
{
dconf.settings = {
"org/gnome/shell" = {
disable-user-extensions = true;
# TODO: this is fine for now on tohru (the only GNOME system I use) but shouldn't depend on certain apps being installed
favorite-apps = [
"discord.desktop"
"org.gnome.Evolution.desktop"
"firefox.desktop"
"torbrowser.desktop"
"steam.desktop"
"codium.desktop"
"org.gnome.Console.desktop"
"org.gnome.Nautilus.desktop"
"org.gnome.SystemMonitor.desktop"
];
# TODO: fill this out (needs preinstalled stuff removing first)
# app-picker-layout = [
# ...
# ];
};
};
}

View file

@ -1,19 +0,0 @@
{ config, lib, pkgs, ... }:
# These features are cool and I would like to keep trying them, but they are
# horribly bugged in GNOME 48.1. Consider re-enabling them when 48.2 is
# released. See, e.g.:
# https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8289
# https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8299
# https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8305
# https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8376
# https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8398
{
dconf.settings = {
# "org/gnome/desktop/screen-time-limits".daily-limit-enabled = true;
# "org/gnome/desktop/break-reminders".selected-breaks = [ "eyesight" "movement" ];
"org/gnome/desktop/screen-time-limits".daily-limit-enabled = false;
"org/gnome/desktop/break-reminders".selected-breaks = [ ];
};
}

View file

@ -1,16 +0,0 @@
{
imports = [
./dconf
./feishin.nix
./firefox.nix
./fonts.nix
./git.nix
./packages.nix
./tmux.nix
./vscode.nix
./xdg-mime-apps.nix
./zsh.nix
];
home.stateVersion = "23.11";
}

View file

@ -1,24 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
# Feishin ideally wants to see mpv at runtime, but this isn't catered for by
# the derivation in nixpkgs as it isn't strictly necessary.
# An easier way to do this would be to write mpv's full nix store path to
# Feishin's config. But Feishin has one JSON file for config and state, and
# we'd rather not overwrite the latter. Until and unless home-manager grows
# support for partially patching files, we live with this.
let
inherit (lib) mkIf;
isGraphical = osConfig.services.xserver.enable;
in
{
home.packages = mkIf isGraphical [
(pkgs.feishin.overrideAttrs (originalAttrs: {
buildInputs = originalAttrs.buildInputs ++ [ pkgs.mpv ];
postFixup = ''
${originalAttrs.postFixup or ""}
wrapProgram $out/bin/feishin --prefix PATH : ${lib.makeBinPath [ pkgs.mpv ]}
'';
}))
];
}

View file

@ -1,86 +0,0 @@
{ config, lib, pkgs, osConfig, inputs, ... }:
let
inherit (lib) mkIf;
isGraphical = osConfig.services.xserver.enable;
in
{
programs.firefox = lib.mkIf isGraphical {
enable = true;
languagePacks = [ "en-GB" ];
policies = {
ExtensionSettings = {
# uBlock Origin
"uBlock0@raymondhill.net" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi";
installation_mode = "force_installed";
private_browsing = true;
};
# 1Password
"{d634138d-c276-4fc8-924b-40a0ea21d284}" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/1password-x-password-manager/latest.xpi";
installation_mode = "force_installed";
default_area = "navbar";
};
# Disqus Auto-Expander
"disqus-auto-expander@john30013.com" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/disqus-auto-expander/latest.xpi";
installation_mode = "force_installed";
};
# Indie Wiki Buddy
"{cb31ec5d-c49a-4e5a-b240-16c767444f62}" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/indie-wiki-buddy/latest.xpi";
installation_mode = "force_installed";
};
# SteamDB
"firefox-extension@steamdb.info" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/steam-database/latest.xpi";
installation_mode = "force_installed";
};
};
};
profiles.default = {
settings = {
"browser.startup.page" = 3; # resume previous session
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
# disable telemetry
"datareporting.healthreport.uploadEnabled" = false;
"app.shield.optoutstudies.enabled" = false;
"browser.crashReports.unsubmittedCheck.autoSubmit2" = false;
# disable prefetch?
# DNS over HTTPS
"network.trr.custom_uri" = "https://base.dns.mullvad.net/dns-query";
"network.trr.excluded-domains" = "detectportal.firefox.com";
"network.trr.mode" = 3;
"network.trr.uri" = "https://base.dns.mullvad.net/dns-query";
"browser.search.suggest.enabled" = false;
"browser.urlbar.suggest.searches" = false;
"dom.security.https_only_mode" = true;
"browser.contentblocking.category" = "strict"; # Enhanced Tracking Protection
# I think these are implied by the above
# "privacy.donottrackheader.enabled" = true;
# "privacy.trackingprotection.enabled" = true;
# "privacy.trackingprotection.emailtracking.enabled" = true;
# "privacy.trackingprotection.socialtracking.enabled" = true;
"privacy.sanitize.sanitizeOnShutdown" = true;
"privacy.clearOnShutdown_v2.historyFormDataAndDownloads" = false;
"dom.private-attribution.submission.enabled" = false; # disable "Privacy-Preserving Attribution for Advertising"
"extensions.autoDisableScopes" = 0; # automatically enable extensions installed through nix
# external password manager
"signon.rememberSignons" = false;
"extensions.formautofill.creditCards.enabled" = false;
};
};
};
}

View file

@ -1,17 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
let
inherit (lib) mkIf;
isGraphical = osConfig.services.xserver.enable;
in
mkIf isGraphical {
fonts.fontconfig = {
enable = true;
};
home.packages = with pkgs; [
meslo-lgs-nf
];
programs.vscode.profiles.default.userSettings."terminal.integrated.fontFamily" = "MesloLGS NF";
}

View file

@ -1,14 +0,0 @@
{ config, lib, pkgs, ... }:
{
programs.git = {
enable = true;
userName = "Katherina Walshe-Grey";
userEmail = "git@qenya.tel";
extraConfig = {
init.defaultBranch = "main";
pull.rebase = true;
push.autoSetupRemote = true;
};
};
}

View file

@ -1,41 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
let
inherit (lib) optionals;
isGraphical = osConfig.services.xserver.enable;
isGnome = osConfig.services.xserver.desktopManager.gnome.enable;
isPlasma = osConfig.services.desktopManager.plasma6.enable;
in
{
home.packages = with pkgs; [
eza # like `ls` but fancier
hexyl # like `xxd` but cooler
ripgrep # like `grep` but faster
tree # like `ls -R` but nicer
units
zip
unzip
# Extremely important
fortune
cowsay
lolcat
] ++ optionals isGraphical [
_1password-gui
discord
# https://github.com/NixOS/nixpkgs/issues/427155
# gimp-with-plugins
jellyfin-media-player
tor-browser-bundle-bin
zoom-us
# libreoffice
libreoffice
hunspell
hunspellDicts.en_GB-ise
] ++ optionals isGnome [
celluloid
] ++ optionals isPlasma [
haruna
];
}

View file

@ -1,33 +0,0 @@
{ config, lib, pkgs, ... }:
{
# Derived from https://github.com/srid/nixos-config/blob/master/home/tmux.nix
programs.tmux = {
enable = true;
clock24 = true;
shortcut = "a"; # `screen` muscle memory compatibility
baseIndex = 1; # this is a UI, 0-indexing is not appropriate, fight me
newSession = true; # skip the manual step
escapeTime = 0; # otherwise I keep reflexively hammering Esc
secureSocket = false; # make sessions survive user logout
plugins = with pkgs; [
tmuxPlugins.better-mouse-mode
];
mouse = true;
extraConfig = ''
# https://old.reddit.com/r/tmux/comments/mesrci/tmux_2_doesnt_seem_to_use_256_colors/
set -g default-terminal "xterm-256color"
set -ga terminal-overrides ",*256col*:Tc"
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
set-environment -g COLORTERM "truecolor"
# easy-to-remember split pane commands
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind c new-window -c "#{pane_current_path}"
'';
};
}

View file

@ -1,93 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
let
inherit (lib) mkIf mkDefault;
isGraphical = osConfig.services.xserver.enable;
in
{
programs.vscode = mkIf isGraphical {
enable = true;
package = pkgs.vscodium;
mutableExtensionsDir = false;
profiles.default = {
enableExtensionUpdateCheck = false;
enableUpdateCheck = false;
extensions = with pkgs.vscode-extensions; [
ms-python.black-formatter
mkhl.direnv
dbaeumer.vscode-eslint
golang.go
eamodio.gitlens
jdinhlife.gruvbox
vadimcn.vscode-lldb
matangover.mypy
jnoortheen.nix-ide
ms-python.python
shopify.ruby-lsp
charliermarsh.ruff
rust-lang.rust-analyzer
];
userSettings = {
"css.format.spaceAroundSelectorSeparator" = true;
"css.format.newlineBetweenSelectors" = false;
"debug.allowBreakpointsEverywhere" = true;
"extensions.autoUpdate" = false;
"files.insertFinalNewline" = true;
"git.autofetch" = true;
"git.confirmSync" = false;
"git.enableSmartCommit" = true;
"git.inputValidation" = true;
"git.inputValidationSubjectLength" = null;
"javascript.updateImportsOnFileMove.enabled" = "always";
"nix.enableLanguageServer" = true;
"nix.serverPath" = "${pkgs.nil}/bin/nil";
"nix.serverSettings".nil = {
diagnostics.ignored = [ "unused_binding" "unused_with" ];
formatting.command = [ "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt" ];
nix.flake.autoArchive = true;
};
"rust-analyzer.check.command" = "clippy";
"terminal.integrated.allowChords" = false;
"terminal.integrated.defaultProfile.linux" = "zsh";
"workbench.colorTheme" = "Gruvbox Dark Medium";
"[go]" = {
"editor.defaultFormatter" = "golang.go";
"editor.formatOnSave" = false;
};
"go.alternateTools" = {
"go" = "${pkgs.go}/bin/go";
"golangci-lint" = "${pkgs.golangci-lint}/bin/golangci-lint";
"gopls" = "${pkgs.gopls}/bin/gopls";
"dlv" = "${pkgs.delve}/bin/dlv";
"staticcheck" = "${pkgs.go-tools}/bin/staticcheck";
};
"go.lintTool" = "golangci-lint";
"go.toolsManagement.checkForUpdates" = "off";
"gopls" = {
"formatting.gofumpt" = true;
"ui.semanticTokens" = true;
};
"[python]" = {
"editor.defaultFormatter" = "ms-python.black-formatter";
"editor.formatOnSave" = true;
"editor.codeActionsOnSave" = {
"source.fixAll" = "explicit";
"source.organizeImports" = "explicit";
};
};
"python.createEnvironment.contentButton" = "show";
"python.defaultInterpreterPath" = "${pkgs.python3}/bin/python";
"ruff.nativeServer" = "on";
"ruff.path" = [ "${pkgs.ruff}/bin/ruff" ];
"mypy.dmypyExecutable" = "${pkgs.mypy}/bin/dmypy";
"[ruby]" = {
"editor.formatOnSave" = true;
"editor.formatOnType" = true;
};
};
};
};
}

View file

@ -1,21 +0,0 @@
{ config, lib, pkgs, osConfig, ... }:
let
isGraphical = osConfig.services.xserver.enable;
in
{
xdg.mimeApps = {
enable = isGraphical;
defaultApplications = {
"application/pdf" = [ "org.gnome.Evince.desktop" "org.kde.okular.desktop" ];
"application/zip" = [ "org.gnome.FileRoller.desktop" "org.kde.ark.desktop" ];
"image/gif" = [ "org.gnome.Loupe.desktop" "org.kde.gwenview.desktop" ];
"image/jpeg" = [ "org.gnome.Loupe.desktop" "org.kde.gwenview.desktop" ];
"image/png" = [ "org.gnome.Loupe.desktop" "org.kde.gwenview.desktop" ];
"text/plain" = [ "org.gnome.TextEditor.desktop" "org.kde.kate.desktop" ];
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/mailto" = "org.gnome.Evolution.desktop"; # TODO: email on KDE - is Kontact any good?
};
};
}

View file

@ -1,43 +0,0 @@
{ config, lib, pkgs, ... }:
{
home.packages = with pkgs; [ direnv ];
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
dotDir = ".config/zsh";
shellAliases = {
ll = "ls -l";
# don't clobber
mv = "mv -i";
rename = "rename -i";
nix-shell = ''nix-shell --command "zsh"'';
};
history = {
size = 10000;
path = "${config.xdg.dataHome}/zsh/history";
ignorePatterns = [ "rm *" "pkill *" ];
};
oh-my-zsh = {
enable = true;
plugins = [ "git" "sudo" "direnv" ];
theme = ""; # defer to powerlevel10k
};
initContent = ''
source ${pkgs.zsh-powerlevel10k}/share/zsh-powerlevel10k/powerlevel10k.zsh-theme
source ${./.p10k.zsh}
'';
envExtra = ''
DEFAULT_USER=qenya
'';
};
}

View file

@ -1,43 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
let
inherit (lib) mkForce;
in
{
imports = [
./filesystems.nix
./hardware.nix
./networking.nix
];
nixpkgs.hostPlatform = "x86_64-linux";
networking.hostName = "elucredassa";
networking.hostId = "a8ec6755";
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "rtsx_pci_sdmmc" ];
boot.kernelModules = [ "kvm-intel" ];
qenya.base-server.enable = true;
i18n.defaultLocale = "en_GB.UTF-8";
console.keyMap = "uk";
services.xserver.xkb.layout = "gb";
# These are populated by fountain.backup
randomcat.services.zfs.datasets = {
"rpool_elucredassa/backup" = { mountpoint = "none"; };
"rpool_elucredassa/backup/kalessin" = { mountpoint = "none"; };
"rpool_elucredassa/backup/orm" = { mountpoint = "none"; };
};
qenya.services.distributed-builds = {
enable = true;
keyFile = "/etc/ssh/ssh_host_ed25519_key";
builders = [ "kilgharrah" ];
};
fountain.users.qenya.enable = true;
fountain.admins = [ "qenya" ];
system.stateVersion = "24.11";
}

View file

@ -1,23 +0,0 @@
{ config, lib, pkgs, ... }:
{
boot.initrd.luks.devices = {
"luks-rpool-elucredassa".device = "/dev/disk/by-uuid/5ece5b58-c57a-41ae-b086-03707c39c9a7";
};
fileSystems = {
"/" = {
device = "rpool_elucredassa/root";
fsType = "zfs";
};
"/boot" = {
device = "/dev/disk/by-uuid/2519-E2D6";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
};
swapDevices = [{ device = "/dev/disk/by-uuid/c7c48325-e90d-414d-b579-84cb45616ee9"; }];
boot.supportedFilesystems = [ "ntfs" ]; # for USB drives
}

View file

@ -1,11 +0,0 @@
{ config, lib, pkgs, ... }:
{
hardware.enableAllFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
services.fwupd.enable = true;
# this is an old laptop
services.logind.lidSwitch = "ignore";
}

View file

@ -1,36 +0,0 @@
{ config, lib, pkgs, ... }:
{
systemd.network.enable = true;
networking.useDHCP = false;
systemd.network.networks."10-wan" = {
matchConfig.Name = "enp1s0f1";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
Tunnel = "sit-he-ipv6";
};
linkConfig.RequiredForOnline = "routable";
};
systemd.network.netdevs."25-he-ipv6" = {
netdevConfig = {
Name = "sit-he-ipv6";
Kind = "sit";
Description = "Hurricane Electric IPv6 Tunnel";
MTUBytes = 1480;
};
tunnelConfig = {
Remote = "216.66.88.98";
TTL = 255;
};
};
systemd.network.networks."25-he-ipv6" = {
matchConfig.Name = "sit-he-ipv6";
networkConfig.Address = [ "2001:470:1f1c:3e::2/64" ];
routes = [{ Destination = [ "::/0" ]; }];
};
}

View file

@ -1,52 +0,0 @@
{ config, lib, pkgs, ... }:
let
keys = import ../../keys.nix;
in
{
imports = [
./hardware-configuration.nix
./networking.nix
];
nixpkgs.hostPlatform = "aarch64-linux";
networking.hostName = "kalessin";
networking.hostId = "534b538e";
fountain.users.qenya.enable = true;
fountain.users.randomcat.enable = true;
fountain.users.trungle.enable = true;
fountain.admins = [ "qenya" "randomcat" ];
qenya.base-server.enable = true;
qenya.services.remote-builder = {
enable = true;
authorizedKeys.keys = [ ];
};
randomcat.services.zfs.datasets = {
"rpool_kalessin/state" = { mountpoint = "none"; };
"rpool_kalessin/state/headscale" = { mountpoint = "/var/lib/headscale"; };
"rpool_kalessin/state/owncast" = { mountpoint = "/var/lib/owncast"; };
};
services.sanoid.datasets."rpool_kalessin/state" = {
useTemplate = [ "production" ];
recursive = "zfs";
};
qenya.services.owncast = {
enable = true;
domain = "live.qenya.tel";
dataDir = "/var/lib/owncast";
};
qenya.services.headscale = {
enable = true;
domain = "headscale.unspecified.systems";
dataDir = "/var/lib/headscale";
};
system.stateVersion = "23.11";
}

View file

@ -1,38 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_scsi" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "rpool_kalessin/root";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "rpool_kalessin/nix";
fsType = "zfs";
};
fileSystems."/var" =
{ device = "rpool_kalessin/var";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/2ADE-A033";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices = [ ];
}

View file

@ -1,6 +0,0 @@
{ config, lib, pkgs, ... }:
{
networking.useNetworkd = true;
networking.interfaces.enp0s6.useDHCP = true;
}

View file

@ -1,8 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.sanoid.datasets."rpool_albion/state" = {
useTemplate = [ "production" ];
recursive = "zfs";
};
}

View file

@ -1,66 +0,0 @@
{ config, lib, pkgs, ... }:
let
keys = import ../../keys.nix;
in
{
imports = [
./backup.nix
./filesystems.nix
./hardware.nix
./networking.nix
./plasma.nix
./ftp.nix
];
nixpkgs.hostPlatform = "x86_64-linux";
networking.hostName = "kilgharrah";
networking.hostId = "72885bb5";
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" ];
boot.kernelModules = [ "kvm-intel" ];
qenya.base-graphical.enable = true;
time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8";
console.keyMap = "uk";
services.xserver.xkb.layout = "gb";
fountain.users.qenya.enable = true;
age.secrets.user-password-kilgharrah-qenya.file = ../../secrets/user-password-kilgharrah-qenya.age;
users.users.qenya.hashedPasswordFile = config.age.secrets.user-password-kilgharrah-qenya.path;
fountain.admins = [ "qenya" ];
home-manager.users.qenya = { pkgs, ... }: {
home.packages = with pkgs; [ obs-studio ];
};
qenya.services.remote-builder = {
enable = true;
authorizedKeys.keys = [
keys.machines.yevaud
keys.machines.orm
keys.machines.tohru
keys.machines.elucredassa
];
};
programs.steam.enable = true;
qenya.services.audiobookshelf = {
enable = true;
domain = "audiobookshelf.qenya.tel";
};
qenya.services.jellyfin = {
enable = true;
domain = "jellyfin.qenya.tel";
};
qenya.services.navidrome = {
enable = true;
domain = "music.qenya.tel";
dataDir = "/srv/music";
};
system.stateVersion = "24.05";
}

View file

@ -1,93 +0,0 @@
{ config, lib, pkgs, ... }:
{
# SSD on board
boot.initrd.luks.devices = {
"cryptroot".device = "/dev/disk/by-uuid/b414aaba-0a36-4135-a7e1-dc9489286acd";
};
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@" "compress=zstd" ];
};
"/home" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@home" "compress=zstd" ];
};
"/nix" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@nix" "compress=zstd" "noatime" ];
};
"/swap" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@swap" "noatime" ];
};
"/root" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@root" "compress=zstd" ];
};
"/srv" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@srv" "compress=zstd" ];
};
"/var/cache" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@cache" "compress=zstd" "noatime" ];
};
"/var/tmp" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@tmp" "compress=zstd" "noatime" ];
};
"/var/log" = {
device = "/dev/disk/by-uuid/ad4cbc18-8849-40ed-b0bf-097f8f46346b";
fsType = "btrfs";
options = [ "subvol=@log" "compress=zstd" "noatime" ];
};
"/boot" = {
device = "/dev/disk/by-uuid/9582-E78D";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
};
swapDevices = [{
device = "/swap/swapfile";
size = 32 * 1024;
}];
# HDD in bay
environment.etc.crypttab.text = ''
albion UUID=8a924f24-9b65-4f05-aeda-5b4080cc7aa1 /root/luks-albion.key
'';
randomcat.services.zfs.datasets = {
"rpool_albion/data" = { mountpoint = "none"; };
"rpool_albion/data/steam" = { mountpoint = "/home/qenya/.local/share/Steam"; };
"rpool_albion/state" = { mountpoint = "none"; };
"rpool_albion/state/audiobookshelf" = { mountpoint = "/var/lib/audiobookshelf"; };
"rpool_albion/state/jellyfin" = { mountpoint = "/var/lib/jellyfin"; };
"rpool_albion/state/navidrome" = { mountpoint = "/var/lib/navidrome"; };
"rpool_albion/srv" = { mountpoint = "none"; };
"rpool_albion/srv/audiobookshelf" = { mountpoint = "/srv/audiobookshelf"; };
"rpool_albion/srv/ftp" = { mountpoint = "/srv/ftp"; };
"rpool_albion/srv/jellyfin" = { mountpoint = "/srv/jellyfin"; };
"rpool_albion/srv/music" = { mountpoint = "/srv/music"; };
};
# Other
boot.supportedFilesystems = [ "ntfs" "zfs" ];
}

View file

@ -1,70 +0,0 @@
{ config, lib, pkgs, ... }:
{
age.secrets.ftp-userDb-qenya = {
# To update this, see the nixos docs for services.vsftpd.userDbPath. Note
# that the command it gives to create a userDb, if applied to an *existing*
# userDb, will *add* the entries from the source file, overwriting any
# entries with the same username but leaving other existing entries intact.
# Also note the database format does not salt hashes.
file = ../../secrets/ftp-userDb-qenya.age;
# we have to specify this manually because pam_userdb strips the extension
path = "/etc/vsftpd/userDb.db";
};
services.vsftpd = {
enable = true;
localUsers = true;
forceLocalLoginsSSL = true;
forceLocalDataSSL = true;
rsaCertFile = "${config.security.acme.certs."ftp.qenya.tel".directory}/fullchain.pem";
rsaKeyFile = "${config.security.acme.certs."ftp.qenya.tel".directory}/key.pem";
enableVirtualUsers = true;
userlistDeny = false; # turn userlist from a denylist into an allowlist
userlist = [ "qenya" ]; # this is just a list of the users in the userDb
userDbPath = "/etc/vsftpd/userDb";
localRoot = "/srv/ftp";
extraConfig = ''
# nothing in the default cipher suite is enabled in modern ssl clients!
ssl_ciphers=HIGH
# set this to something firewallable
pasv_min_port=51000
pasv_max_port=51099
# don't bother with upgrading to TLS, just listen on FTPS only
implicit_ssl=YES
listen_port=990
'';
};
services.nginx = {
enable = true;
virtualHosts = {
"ftp.qenya.tel" = {
forceSSL = true;
useACMEHost = "ftp.qenya.tel";
locations."/".return = "503";
};
};
};
security.acme.certs = {
"ftp.qenya.tel" = {
webroot = "/var/lib/acme/acme-challenge";
group = "acme_ftp.qenya.tel";
};
};
users.groups."acme_ftp.qenya.tel".members = [
"vsftpd" # not configurable in the vsftpd nixos module
config.services.nginx.group
];
networking.firewall.allowedTCPPorts = [ 990 80 443 ];
networking.firewall.allowedTCPPortRanges = [{ from = 51000; to = 51099; }];
}

View file

@ -1,57 +0,0 @@
{ config, lib, pkgs, ... }:
{
hardware.enableAllFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
services.fwupd.enable = true;
services.xserver.videoDrivers = [ "nvidia" ];
hardware.nvidia.open = false;
nixpkgs.config.cudaSupport = true;
nix.settings = {
# Community cache with prebuilt packages with cudaSupport enabled
substituters = [ "https://nix-community.cachix.org" ];
trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ];
};
# # Downgrade to driver version 535 as 550 has problems with Wayland
# hardware.nvidia.package =
# let
# rcu_patch = pkgs.fetchpatch {
# url = "https://github.com/gentoo/gentoo/raw/c64caf53/x11-drivers/nvidia-drivers/files/nvidia-drivers-470.223.02-gpl-pfn_valid.patch";
# hash = "sha256-eZiQQp2S/asE7MfGvfe6dA/kdCvek9SYa/FFGp24dVg=";
# };
# in
# config.boot.kernelPackages.nvidiaPackages.mkDriver {
# version = "535.154.05";
# sha256_64bit = "sha256-fpUGXKprgt6SYRDxSCemGXLrEsIA6GOinp+0eGbqqJg=";
# sha256_aarch64 = "sha256-G0/GiObf/BZMkzzET8HQjdIcvCSqB1uhsinro2HLK9k=";
# openSha256 = "sha256-wvRdHguGLxS0mR06P5Qi++pDJBCF8pJ8hr4T8O6TJIo=";
# settingsSha256 = "sha256-9wqoDEWY4I7weWW05F4igj1Gj9wjHsREFMztfEmqm10=";
# persistencedSha256 = "sha256-d0Q3Lk80JqkS1B54Mahu2yY/WocOqFFbZVBh+ToGhaE=";
# patches = [ rcu_patch ];
# };
services.printing.drivers = [ pkgs.hplip ];
# enable playing from bluray drive
boot.kernelModules = [ "sg" ];
environment.systemPackages = [
((pkgs.vlc.override {
libbluray = (pkgs.libbluray.override {
withJava = true;
withAACS = true;
withBDplus = true;
});
}).overrideAttrs (originalAttrs: {
buildInputs = originalAttrs.buildInputs ++ [ pkgs.libdvdcss ];
# TODO: nixpkgs bug: libbluray needs patching to look at the nix store path of jdk17 when searching for a jdk
# as a workaround, wrap vlc and set JAVA_HOME, which it uses instead of searching when specified
nativeBuildInputs = originalAttrs.nativeBuildInputs ++ [ pkgs.makeWrapper ];
postFixup = ''
${originalAttrs.postFixup or ""}
wrapProgram $out/bin/vlc --set JAVA_HOME ${pkgs.jdk17.home}
'';
}))
];
}

View file

@ -1,15 +0,0 @@
{ config, lib, pkgs, ... }:
{
systemd.network.enable = true;
networking.useDHCP = false;
systemd.network.networks."10-wan" = {
matchConfig.Name = "enp2s0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
}

View file

@ -1,109 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
let
inherit (lib) mkForce;
in
{
services.xserver.displayManager.gdm.enable = mkForce false;
services.xserver.desktopManager.gnome.enable = mkForce false;
services.displayManager.sddm.enable = true;
services.displayManager.sddm.wayland.enable = true;
services.desktopManager.plasma6.enable = true;
environment.systemPackages = with pkgs; [
(catppuccin-kde.override {
flavour = [ "mocha" ];
accents = [ "mauve" ];
winDecStyles = [ "modern" ];
})
];
home-manager.users.qenya = { pkgs, ... }: {
imports = [
inputs.plasma-manager.homeManagerModules.plasma-manager
];
programs.plasma = {
enable = true;
overrideConfig = true;
workspace = {
lookAndFeel = "Catppuccin-Mocha-Mauve";
colorScheme = "CatppuccinMochaMauve";
splashScreen.engine = "KSplashQML";
splashScreen.theme = "Catppuccin-Mocha-Mauve";
windowDecorations.library = "org.kde.kwin.aurorae";
windowDecorations.theme = "__aurorae__svg__CatppuccinMocha-Modern";
};
# For the moment, this hosts some network-accessible services, so we want it on 24/7
powerdevil.AC.autoSuspend.action = "nothing";
panels = [
# Dock
{
height = 49; # 41 * 1.2
lengthMode = "fit";
location = "bottom";
alignment = "center";
hiding = "dodgewindows";
widgets = [{
name = "org.kde.plasma.icontasks";
config.General = {
fill = false;
iconSpacing = 2;
launchers = lib.concatStringsSep "," [
"applications:firefox.desktop"
"applications:codium.desktop"
"applications:steam.desktop"
"applications:discord.desktop"
"applications:com.obsproject.Studio.desktop"
"applications:org.kde.dolphin.desktop"
"applications:org.kde.konsole.desktop"
"applications:org.kde.plasma-systemmonitor.desktop"
];
maxStripes = 1;
showOnlyCurrentDesktop = false;
showOnlyCurrentScreen = false;
};
}];
screen = "all";
}
# Top bar
{
height = 29; # 24 * 1.2
location = "top";
alignment = "left";
floating = false;
widgets = [
{
name = "org.kde.plasma.kickoff";
config.General = {
lengthFirstMargin = 7;
};
}
{ name = "org.kde.plasma.panelspacer"; }
{
name = "org.kde.plasma.digitalclock";
config.Appearance = {
autoFontAndSize = false;
customDateFormat = "dddd, d MMM";
dateDisplayFormat = "BesideTime";
dateFormat = "custom";
fontFamily = "Inter";
fontStyleName = "Bold";
fontWeight = 700;
boldText = true;
showWeekNumbers = true;
};
}
{ name = "org.kde.plasma.panelspacer"; }
{ name = "org.kde.plasma.systemtray"; }
];
screen = "all";
}
];
};
};
}

View file

@ -1,69 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./networking.nix
];
nixpkgs.hostPlatform = "x86_64-linux";
networking.hostName = "orm";
networking.hostId = "00000000";
fountain.users.qenya.enable = true;
fountain.admins = [ "qenya" ];
qenya.base-server.enable = true;
qenya.services.distributed-builds = {
enable = true;
keyFile = "/etc/ssh/ssh_host_ed25519_key";
builders = [ "kilgharrah" ];
};
nix.settings.max-jobs = 0;
randomcat.services.zfs.datasets = {
"rpool_orm/state" = { mountpoint = "none"; };
"rpool_orm/state/actual" = { mountpoint = "/var/lib/private/actual"; };
"rpool_orm/state/postgresql" = { mountpoint = "/var/lib/postgresql"; };
};
services.sanoid.datasets."rpool_orm/state" = {
useTemplate = [ "production" ];
recursive = "zfs";
};
services.postgresql = {
enable = true;
package = pkgs.postgresql_17;
dataDir = "/var/lib/postgresql/17";
# managing imperatively instead of using ensureDatabases/ensureUsers
enableTCPIP = true;
settings = {
port = 5432;
# TODO: fix SSL
# ssl = true;
};
# only allow remote connections from within Tailscale
authentication = pkgs.lib.mkOverride 10 ''
#type database DBuser auth-method
local all all trust # used by nixos for local monitoring
host sameuser all 100.64.0.0/10 scram-sha-256
host sameuser all fd7a:115c:a1e0::/48 scram-sha-256
'';
};
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 5432 ];
qenya.services.actual = {
enable = true;
domain = "actual.unspecified.systems";
};
fountain.services.web-redirect = {
enable = true;
domains = {
"actual.qenya.tel" = "actual.unspecified.systems";
};
};
system.stateVersion = "23.11";
}

View file

@ -1,40 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "rpool_orm/root";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "rpool_orm/nix";
fsType = "zfs";
};
fileSystems."/var" =
{ device = "rpool_orm/var";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/3739-E8C1";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices =
[ { device = "/dev/disk/by-uuid/a0ac8f60-25f9-4dec-af70-e3f4cd36c575"; }
];
}

View file

@ -1,6 +0,0 @@
{ config, lib, pkgs, ... }:
{
networking.useNetworkd = true;
networking.interfaces.ens3.useDHCP = true;
}

View file

@ -1,11 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.syncthing = {
enable = true;
extraOptions = [
"--gui-address=:8385"
"--home=/home/qenya/state/syncthing"
];
};
}

View file

@ -1,19 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./networking.nix
];
nixpkgs.hostPlatform = "aarch64-linux";
networking.hostName = "tehanu";
networking.hostId = "8e1185ab";
fountain.users.qenya.enable = true;
fountain.admins = [ "qenya" ];
qenya.base-server.enable = true;
system.stateVersion = "23.11";
}

View file

@ -1,38 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_scsi" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "rpool_tehanu/root";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "rpool_tehanu/nix";
fsType = "zfs";
};
fileSystems."/var" =
{ device = "rpool_tehanu/var";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/629B-BA09";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices = [ ];
}

View file

@ -1,6 +0,0 @@
{ config, lib, pkgs, ... }:
{
networking.useNetworkd = true;
networking.interfaces.enp0s6.useDHCP = true;
}

View file

@ -0,0 +1,90 @@
{ config, lib, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.systemd-boot.editor = false;
networking.hostName = "tohru";
networking.hostId = "31da19c1";
networking.networkmanager.enable = true;
time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8";
console.keyMap = "uk";
services.xserver.enable = true;
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
services.xserver.xkb.layout = "gb";
services.printing.enable = true;
sound.enable = true;
hardware.pulseaudio.enable = true;
# Enable touchpad support (enabled default in most desktopManager).
services.xserver.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
users.users.bluebird = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ];
packages = with pkgs; [
tor-browser-bundle-bin
firefox
tree
];
};
# 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.
bitwarden
git
plocate
wget
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = 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;
nixpkgs.config.allowUnfree = true;
hardware.enableAllFirmware = true;
services.fwupd.enable = true;
services.fstrim.enable = true;
boot.initrd.luks.devices = {
"rpool".device = "/dev/nvme0n1p2";
};
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "23.11";
}

View file

@ -1,69 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
let
inherit (lib) mkForce;
in
{
imports = [
./filesystems.nix
./hardware.nix
./networking.nix
./syncthing.nix
];
nixpkgs.hostPlatform = "x86_64-linux";
networking.hostName = "tohru";
networking.hostId = "31da19c1";
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "rtsx_pci_sdmmc" ];
boot.kernelModules = [ "kvm-intel" ];
qenya.base-graphical.enable = true;
time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8";
console.keyMap = "uk";
services.xserver.xkb.layout = "gb";
# tohru does not have the resources to run this under other load and is generally powered off when not in use.
# instead, just run `nix-store --optimise` every so often.
nix.optimise.automatic = mkForce false;
fountain.users.qenya.enable = true;
fountain.admins = [ "qenya" ];
age.secrets.user-password-tohru-qenya.file = ../../secrets/user-password-tohru-qenya.age;
users.users.qenya.hashedPasswordFile = config.age.secrets.user-password-tohru-qenya.path;
users.users.qenya.extraGroups = [
"networkmanager" # UI wifi configuration
"dialout" # access to serial ports
];
nixpkgs.overlays = [ inputs.scoutshonour.overlays.default ];
home-manager.users.qenya = { pkgs, ... }: {
home.packages = with pkgs; [
keepassxc
apostrophe
foliate
nicotine-plus
tuba
# games
openttd
prismlauncher
scoutshonour.digital-a-love-story
scoutshonour.dont-take-it-personally-babe
];
};
qenya.services.distributed-builds = {
enable = true;
keyFile = "/etc/ssh/ssh_host_ed25519_key";
builders = [ "kilgharrah" ];
};
programs.evolution.enable = true; # not in home-manager yet; not declaratively configurable yet
programs.steam.enable = true;
system.stateVersion = "23.11";
}

View file

@ -1,51 +0,0 @@
{ config, lib, pkgs, ... }:
{
boot.initrd.luks.devices = {
"rpool".device = "/dev/nvme0n1p2";
};
boot.supportedFilesystems = [ "ntfs" ]; # for USB drives
fileSystems = {
"/" = {
device = "rpool/root";
fsType = "zfs";
};
"/nix" = {
device = "rpool/nix";
fsType = "zfs";
};
"/var" = {
device = "rpool/var";
fsType = "zfs";
};
"/config" = {
device = "rpool/config";
fsType = "zfs";
};
"/home" = {
device = "rpool/home";
fsType = "zfs";
};
"/data" = {
device = "rpool/data";
fsType = "zfs";
};
"/data/syncthing" = {
device = "rpool/data/syncthing";
fsType = "zfs";
};
"/data/steam" = {
device = "rpool/data/steam";
fsType = "zfs";
};
"/boot" = {
device = "/dev/disk/by-uuid/7DD4-487E";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
};
swapDevices = [{ device = "/dev/disk/by-uuid/a066313e-2467-4e07-ad0c-aeb7ff3f8d97"; }];
}

View file

@ -0,0 +1,54 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "rpool/root";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "rpool/nix";
fsType = "zfs";
};
fileSystems."/var" =
{ device = "rpool/var";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "rpool/home";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/7DD4-487E";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno2.useDHCP = lib.mkDefault true;
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,10 +0,0 @@
{ config, lib, pkgs, ... }:
{
hardware.enableAllFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
services.fwupd.enable = true;
services.printing.drivers = [ pkgs.hplip ];
}

View file

@ -1,8 +0,0 @@
{ config, lib, pkgs, ... }:
{
networking.useNetworkd = true;
systemd.network.wait-online.enable = false;
networking.networkmanager.enable = true;
}

View file

@ -1,53 +0,0 @@
{ config, lib, pkgs, ... }:
{
services.syncthing = {
enable = true;
user = "qenya";
dataDir = "/data/syncthing";
openDefaultPorts = true;
overrideDevices = true;
overrideFolders = true;
settings = {
devices = {
"kilgharrah" = { id = "RDT7IGD-76FZ6LY-37PPB2W-DWPQRPR-LZ4AXF7-4GIIHYJ-RVXUUSG-ZXPN3AZ"; };
"latias" = { id = "EN4W2SB-LB4AAZQ-6AQIE7G-S3BSCSP-V2EUNMM-KAQEHW3-PPAPGBO-PXRPWAL"; };
"shaw" = { id = "NC7WMZS-GQETJYR-IAYGD65-GHTSTVP-VAAG43K-W7N3LO5-C5OQMZ2-DTK6YA7"; };
};
folders = {
"Sync" = {
id = "uln2v-zwzwj";
path = "~/Sync";
devices = [ "kilgharrah" "shaw" ];
};
"Documents" = {
id = "alp59-7gs9s";
path = "~/Documents";
devices = [ "kilgharrah" "shaw" ];
};
"Music" = {
id = "7xvkf-y62s7";
path = "~/Music";
devices = [ "kilgharrah" "shaw" ];
};
"Pictures" = {
id = "tbmhx-ep7wk";
path = "~/Pictures";
devices = [ "kilgharrah" "shaw" ];
};
"ES-DE" = {
id = "c1cbh-llw94";
path = "~/ES-DE";
devices = [ "kilgharrah" "latias" "shaw" ];
};
"ROMs" = {
id = "dcze4-v6act";
path = "~/ROMs";
devices = [ "kilgharrah" "latias" "shaw" ];
};
};
};
};
}

View file

@ -1,49 +0,0 @@
{ config, lib, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./networking.nix
./experiments/pennykettle.nix
];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
networking.hostName = "yevaud";
networking.hostId = "09673d65";
fountain.users.qenya.enable = true;
fountain.admins = [ "qenya" ];
qenya.base-server.enable = true;
qenya.services.distributed-builds = {
enable = true;
keyFile = "/etc/ssh/ssh_host_ed25519_key";
builders = [ "kilgharrah" ];
};
nix.settings.max-jobs = 0;
randomcat.services.zfs.datasets = {
"rpool/state" = { mountpoint = "none"; };
"rpool/state/forgejo" = { mountpoint = "/var/lib/forgejo"; };
};
services.sanoid.datasets."rpool/state" = {
useTemplate = [ "production" ];
recursive = "zfs";
};
qenya.services.forgejo = {
enable = true;
domain = "git.unspecified.systems";
};
fountain.services.web-redirect = {
enable = true;
domains = {
"git.katherina.rocks" = "git.unspecified.systems";
"git.qenya.tel" = "git.unspecified.systems";
};
};
system.stateVersion = "23.11";
}

View file

@ -1,66 +0,0 @@
{ config, lib, pkgs, ... }:
{
networking.firewall.allowedUDPPorts = [ 51820 ];
networking.firewall.interfaces."tailscale0".allowedTCPPorts = config.networking.firewall.allowedTCPPorts ++ [ 1080 ];
environment.systemPackages = [ pkgs.wireguard-tools ];
networking.wireguard.interfaces."wg-protonvpn" = {
ips = [ "10.2.0.2/32" ];
peers = [{
allowedIPs = [ "0.0.0.0/0" "::/0" ];
endpoint = "217.138.216.162:51820";
publicKey = "C+u+eQw5yWI2APCfVJwW6Ovj3g4IrTOfe+tMZnNz43s=";
}];
privateKeyFile = config.age.secrets.protonvpn-pennykettle1.path;
listenPort = 51820;
table = "957851094"; # randomly generated
};
networking.localCommands = ''
ip rule add from 10.2.0.2/32 table 957851094
'';
networking.firewall.checkReversePath = "loose";
age.secrets.protonvpn-pennykettle1 = {
file = ../../../secrets/protonvpn-pennykettle1.age;
owner = "root";
group = "systemd-network";
mode = "640";
};
services.dante = {
enable = true;
config = ''
debug: 2
internal: tailscale0
external: wg-protonvpn
# auth/tls handled by tailscale
clientmethod: none
socksmethod: none
# allow connections from tailscale
# "0/0" matches any v4 or v6 address
client pass {
from: 100.64.0.0/10 to: 0/0
log: error connect disconnect
}
client pass {
from: fd7a:115c:a1e0::/48 to: 0/0
log: error connect disconnect
}
socks pass {
from: 0/0 to: 0/0
protocol: tcp udp
log: error connect disconnect iooperation
}
'';
};
systemd.services.dante = {
wants = [ "tailscaled-autoconnect.service" ];
after = [ "tailscaled-autoconnect.service" ];
};
}

View file

@ -1,40 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "rpool/root";
fsType = "zfs";
};
fileSystems."/nix" =
{ device = "rpool/nix";
fsType = "zfs";
};
fileSystems."/var" =
{ device = "rpool/var";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/107D-5AB3";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices =
[ { device = "/dev/disk/by-uuid/f8b6eb35-33ad-4e19-bf3d-cac5ec38a8dc"; }
];
}

View file

@ -1,5 +0,0 @@
{ config, lib, pkgs, ... }:
{
networking.interfaces.ens3.useDHCP = true;
}

View file

@ -1,34 +0,0 @@
{
machines = {
reese = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPd0qGxvcMLDwX1bqYpwOUL5c/CIgBllMFr+bGkwiwAn root@reese";
bear = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZ9Kn1CIcDHaleKHf7zO6O30Rbxs/FwL0/Ie+mEjZJr root@bear";
shaw = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMC0AomCZZiUV/BCpImiV4p/vGvFaz5QNc+fJLXmS5p root@shaw";
groves = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPQNZ/Q+x7mDYfYXftpZpWkfPByyMBbYmVFobM4vSDW2 root@groves";
tohru = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOk8wuGzF0Y7SaH9aimo3SmCz99MTQwL+rEVhx0jsueU root@tohru";
yevaud = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHUAgyQhl390yUObLUI+jEbuNrZ2U6+8px628DolD+T root@yevaud";
orm = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGc9rkcdOVWozBFj3kLVnSyUQQbyyH+UG+bLawanQkRQ root@orm";
kalessin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOPt3iSSmgnlsv1/jafgZgI7o8UuXzcAL45hID2ThfS8 root@kalessin";
tehanu = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ1fNylfLo7Z8m/DroRlj7cHMLhYL7boP3r/upVrtMJQ root@tehanu";
kilgharrah = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOgGF3gzzlMbxxk3UAAgHJ7sDdjqtrw7UW16M1XhXtz2 root@kilgharrah";
elucredassa = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA+Y/vqGNc1wXUAg4XMAAcLupkggywj2LpYDwA16ONbH root@elucredassa";
carter = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEHHHYG6A995Po05+JXQsvB79ZoIiSOJnW6AiJgVYPic root@carter";
};
users = {
qenya = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFjBuuxo+w3yED0aPnsNb8S90p/GgBqFEG9K4ETZ5Wkq qenya@kilgharrah"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJEmkV9arotms79lJPsLHkdzAac4eu3pYS08ym0sB/on qenya@tohru"
];
randomcat = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDHagOaeTR+/7FL9sErciMw30cmV/VW8HU7J3ZFU5nj9 janet@randomcat.org"
];
trungle = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAA57legzdIcYTVVri4Wc0CvgWefbRhmUqhu0F/5f8FB reuben@glenda-artix"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHAuYWPfYVKdjBY/gBMt2n11Seb+hMqjui1PQ6C4ph8i richard@tress"
];
gaelan = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFbDvPKnPXe+58QgdgK8yZ3Ac9dkJdtHJ3pQwWhszM7McwCzCEO/b940K0orLjfeUruC+hGJZO8heIh0J6JwSK907aS2wpHofU9q7bMT0PYeuHrSb2iFrOFIkTIWpO8hnWad8TGKOlOdNTKEdB9zwxXEKTFb9QW1Z27Zql79W44jUvaOTb7gKUps37O77lHEJDModaRsXS2523pSbrTZKDwZ73+S0ECeNUwwzLUyOOUHfENEXnM18hWm8mV0iU7kxFcmS33z9rWlWPNiCXnBnSi5LPgBarYOAqQf56f9OisafKqvc3uX+yn0kGCDWglVGUkbhfSIP9+w+yv/h/NJWIJlJC92ndbktAqAQW4gb7lXYxpbdoWcmqEy97q0e2vyBdhcVXwZ+0q+U8I74m8trq36ieHDtLKYkiFBX6zvrLP4I5OZU+EecdV2HcMoU8HNa5u1mvG+oHaEgkR70a5cQtrPzWLS/OMLqvWL39vO7RNskzwWCSuWScxDGitr+BunRRbL4aKNkkPjdDlIqb/SfSrFikOo75f5Ku4I32nbM7SNpIjA4cHe50rx1UB8lT+RwHdxL99OdoxIPCe6OLA5uT8VGPXkvqd/ZIFOL2HaM+uPLaYbjwLrHlwSOLgGbehmsSD369EXv6NAc5wbzsSLJQhJ66d5unnzGjn4dRt9sbDw== gbs@canishe.com"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHId+2dJYiZK++p8lu9Bax0J29JjeuU4qcIBdLwEz3lm gbs@canishe.com"
];
};
}

View file

@ -1,18 +0,0 @@
let
keys = import ./keys.nix;
secrets = with keys; {
ftp-userDb-qenya = [ machines.kilgharrah ] ++ keys.users.qenya;
user-password-kilgharrah-qenya = [ machines.kilgharrah ] ++ keys.users.qenya;
user-password-tohru-qenya = [ machines.tohru ] ++ keys.users.qenya;
protonvpn-pennykettle1 = [ machines.yevaud ] ++ keys.users.qenya;
};
in
builtins.listToAttrs (
map
(secretName: {
name = "secrets/${secretName}.age";
value.publicKeys = secrets."${secretName}";
})
(builtins.attrNames secrets)
)

Binary file not shown.

View file

@ -1,9 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 uJfgGw +h4WiWyMlQZ5iaMFTl/whUD0vJnIN0GYeqRbZ0MIH0o
eKio4DsSJlrvSAjmR0naDO/lmB78o7cy7QC9WZjHUa0
-> ssh-ed25519 seJ9Iw xov8WY0TxEj5/wkWg1T0kmrbpXsNhDLnZwqyIg0eExA
wu5QApQk6K8Fu5XMTrWY2veoYbJVuQmn3DJXewVB860
-> ssh-ed25519 900ILw N6RbpHr4Vwgm0BUCuMXzVo3VEgrl29NF8ZJU5Far7yk
KdA1dZXmcSF3cH9bVdmIbj7iZO3uuSY+isjswDzSu+Y
--- YtnS9FqXVat2hi9BLvX+71HEZDw3zcxIQ7Dp5+iao4c
¢¼ða'þš|<7C>‡N7N”†ÊT5]O¤0Säm<-1ë»ëª:d®„g¡^/ä†u7µïNû?XþMçûìÄì~Þs.9c¾C

View file

@ -1,38 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
let
inherit (lib) mkIf mkOption mkEnableOption types;
cfg = config.qenya.services.actual;
in
{
options.qenya.services.actual = {
enable = mkEnableOption "Actual Budget";
domain = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://127.0.0.1:5006/";
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.actual = {
enable = true;
# nixos 25.05 is on actual-server 25.6.1 which contains an annoying bug
# nixpkgs maintainers declined to backport a newer version, so get this from unstable for now
# ref. https://github.com/NixOS/nixpkgs/issues/423541
package = (import inputs.nixpkgs-unstable-small { system = "x86_64-linux"; }).actual-server;
settings.port = 5006;
};
};
}

View file

@ -1,35 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qenya.services.audiobookshelf;
in
{
options.qenya.services.audiobookshelf = {
enable = mkEnableOption "Audiobookshelf";
domain = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8234/";
proxyWebsockets = true;
};
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.audiobookshelf.enable = true;
services.audiobookshelf.port = 8234;
};
}

View file

@ -1,14 +0,0 @@
{
imports = [
./actual.nix
./audiobookshelf.nix
./distributed-builds.nix
./forgejo.nix
./headscale.nix
./jellyfin.nix
./navidrome.nix
./owncast.nix
./remote-builder.nix
./web-redirect.nix
];
}

View file

@ -1,54 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (builtins) elem;
inherit (lib) mkIf mkEnableOption mkOption types optional;
cfg = config.qenya.services.distributed-builds;
in
{
options.qenya.services.distributed-builds = {
enable = mkEnableOption "distributed builds";
keyFile = mkOption {
type = types.path;
description = ''
Path to the OpenSSH private key to be used for distributed builds.
'';
};
builders = mkOption {
type = types.listOf types.str;
default = [ ];
description = ''
List of builders to attempt to use for distributed builds.
'';
example = [ "kalessin" ];
};
};
config = mkIf cfg.enable {
assertions = [{
assertion = cfg ? keyFile;
message = "must specify a private key to be used for distributed builds";
}];
nix.distributedBuilds = true;
nix.settings.builders-use-substitutes = true;
nix.buildMachines =
(optional (elem "kalessin" cfg.builders) {
hostName = "kalessin.birdsong.network";
sshUser = "remotebuild";
sshKey = cfg.keyFile;
systems = [ "aarch64-linux" ];
maxJobs = 2;
supportedFeatures = [ "big-parallel" ];
})
++ (optional (elem "kilgharrah" cfg.builders) {
hostName = "kilgharrah.birdsong.network";
sshUser = "remotebuild";
sshKey = cfg.keyFile;
systems = [ "x86_64-linux" ];
maxJobs = 12;
supportedFeatures = [ "big-parallel" ];
});
};
}

View file

@ -1,56 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qenya.services.forgejo;
in
{
options.qenya.services.forgejo = {
enable = mkEnableOption "Forgejo";
domain = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
# TODO: email out
# TODO: interface customisation
services = {
nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://[::1]:3000/";
};
};
};
forgejo = {
enable = true;
settings = {
DEFAULT.APP_NAME = cfg.domain;
cache = {
ADAPTER = "twoqueue";
HOST = ''{"size": 100, "recent_ratio": 0.25, "ghost_ratio": 0.5}'';
};
database = {
DB_TYPE = "sqlite3";
SQLITE_JOURNAL_MODE = "WAL";
};
security.LOGIN_REMEMBER_DAYS = 365;
server = {
DOMAIN = cfg.domain;
HTTP_PORT = 3000;
ROOT_URL = "https://${cfg.domain}/";
};
service.DISABLE_REGISTRATION = true;
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
};
}

View file

@ -1,53 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption mkEnableOption types;
cfg = config.qenya.services.headscale;
in
{
options.qenya.services.headscale = {
enable = mkEnableOption "Headscale";
domain = mkOption {
type = types.str;
};
dataDir = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:32770/";
proxyWebsockets = true;
};
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.headscale = {
enable = true;
address = "0.0.0.0"; # required to disable built-in ACME client for some reason
port = 32770;
settings = {
server_url = "https://${cfg.domain}:443";
prefixes.allocation = "random";
dns = {
magic_dns = true;
base_domain = "birdsong.network";
};
# disable built-in ACME client
tls_cert_path = null;
tls_key_path = null;
};
};
};
}

View file

@ -1,31 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.qenya.services.jellyfin;
in
{
options.qenya.services.jellyfin = {
enable = mkEnableOption "Jellyfin";
domain = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://127.0.0.1:8096/";
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.jellyfin.enable = true;
};
}

View file

@ -1,38 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption mkEnableOption types;
cfg = config.qenya.services.navidrome;
in
{
options.qenya.services.navidrome = {
enable = mkEnableOption "Navidrome";
domain = mkOption {
type = types.str;
};
dataDir = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://127.0.0.1:4533/";
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.navidrome.enable = true;
services.navidrome.settings = {
MusicFolder = cfg.dataDir;
BaseUrl = "https://${cfg.domain}";
};
};
}

View file

@ -1,39 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption mkEnableOption types;
cfg = config.qenya.services.owncast;
in
{
options.qenya.services.owncast = {
enable = mkEnableOption "Owncast";
domain = mkOption {
type = types.str;
};
dataDir = mkOption {
type = types.str;
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:32769/";
proxyWebsockets = true;
};
};
};
};
networking.firewall.allowedTCPPorts = [ 80 443 1935 ]; # 1935 for rtmp
services.owncast.enable = true;
services.owncast.port = 32769;
services.owncast.dataDir = cfg.dataDir;
};
}

View file

@ -1,44 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption mkEnableOption types;
cfg = config.qenya.services.remote-builder;
in
{
options.qenya.services.remote-builder = {
enable = mkEnableOption "remote builder";
authorizedKeys = {
keys = mkOption {
type = types.listOf types.singleLineStr;
default = [ ];
description = ''
A list of verbatim OpenSSH public keys that should be authorized to
use this remote builder. See
`users.users.<name>.openssh.authorizedKeys.keys`.
'';
};
keyFiles = mkOption {
type = types.listOf types.path;
default = [ ];
description = ''
A list of files each containing one OpenSSH public key that should be
authorized to use this remote builder. See
`users.users.<name>.openssh.authorizedKeys.keyFiles`.
'';
};
};
};
config = mkIf cfg.enable {
users.users.remotebuild = {
isSystemUser = true;
group = "nogroup";
shell = "/bin/sh";
openssh.authorizedKeys.keys = cfg.authorizedKeys.keys;
openssh.authorizedKeys.keyFiles = cfg.authorizedKeys.keyFiles;
};
nix.nrBuildUsers = 64;
nix.settings.trusted-users = [ "remotebuild" ];
};
}

View file

@ -1,30 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf mkOption mkEnableOption types;
cfg = config.fountain.services.web-redirect;
in
{
options.fountain.services.web-redirect = {
enable = mkEnableOption "Module to do simple 301 redirects from one domain to another";
domains = mkOption {
type = types.attrsOf types.str;
description = "Mapping from source domain to destination domain";
};
};
config = mkIf cfg.enable {
services.nginx = {
enable = true;
virtualHosts = builtins.mapAttrs
(name: value: {
forceSSL = true;
enableACME = true;
locations."/".return = "301 https://${value}$request_uri";
})
cfg.domains;
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
};
}

View file

@ -1,9 +0,0 @@
let
shell = (import
(fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/refs/tags/v1.0.1.tar.gz";
sha256 = "0m9grvfsbwmvgwaxvdzv6cmyvjnlww004gfxjvcl806ndqaxzy4j";
})
{ src = ./.; }).shellNix;
in
shell.devShells.${builtins.currentSystem}