Compare commits

..

1 commit

Author SHA1 Message Date
b71c63bb27 Configure Cloudflare Tunnel to publicly serve
...services from homelab
2025-04-18 01:44:21 +01:00
291 changed files with 2966 additions and 4898 deletions
.forgejo/workflows
README.mdflake.lockflake.nix
home
hosts
modules

View file

@ -1,7 +0,0 @@
on: push
jobs:
check:
runs-on: nixos
steps:
- uses: actions/checkout@v4
- run: nix develop -c just check

View file

@ -1,7 +0,0 @@
| Hostname | Description | Manufacturer | Model | Role |
|------------|-------------------------|--------------|----------------------------------------|---------|
| `PW05CH3L` | My work laptop. | Lenovo | ThinkPad L13 | Laptop |
| `lemp11` | My son's laptop. | System76 | Lemur Pro | Laptop |
| `t480` | My personal laptop. | Lenovo | ThinkPad T480 | Laptop |
| `t490` | My other son's laptop. | Lenovo | ThinkPad T490 | Laptop |
| `nixedo` | My homelab/home server. | TUXEDO | InfinityBook Pro Gen7 (MK1) (Standard) | Server |

110
flake.lock generated
View file

@ -8,11 +8,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1747575206,
"narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=",
"lastModified": 1736955230,
"narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=",
"owner": "ryantm",
"repo": "agenix",
"rev": "4835b1dc898959d8547a871ef484930675cb47f1",
"rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c",
"type": "github"
},
"original": {
@ -29,11 +29,11 @@
]
},
"locked": {
"lastModified": 1744478979,
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
"lastModified": 1700795494,
"narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
"rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
"type": "github"
},
"original": {
@ -50,11 +50,11 @@
]
},
"locked": {
"lastModified": 1747621015,
"narHash": "sha256-j0fo1rNxZvmFLMaE945UrbLJZAHTlQmq0/QMgOP4GTs=",
"lastModified": 1744145203,
"narHash": "sha256-I2oILRiJ6G+BOSjY+0dGrTPe080L3pbKpc+gCV3Nmyk=",
"owner": "nix-community",
"repo": "disko",
"rev": "cec44d77d9dacf0c91d3d51aff128fefabce06ee",
"rev": "76c0a6dba345490508f36c1aa3c7ba5b6b460989",
"type": "github"
},
"original": {
@ -108,11 +108,11 @@
]
},
"locked": {
"lastModified": 1745494811,
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
"lastModified": 1703113217,
"narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
"rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
"type": "github"
},
"original": {
@ -128,11 +128,11 @@
]
},
"locked": {
"lastModified": 1747565775,
"narHash": "sha256-B6jmKHUEX1jxxcdoYHl7RVaeohtAVup8o3nuVkzkloA=",
"lastModified": 1744902080,
"narHash": "sha256-px7OEMQYhS9StY3sTYYeM/jJspk6SXgoPU7OmOSx+1c=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "97118a310eb8e13bc1b9b12d67267e55b7bee6c8",
"rev": "2c71aae678c03a39c2542e136b87bd040ae1b3cb",
"type": "github"
},
"original": {
@ -144,11 +144,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1747129300,
"narHash": "sha256-L3clA5YGeYCF47ghsI7Tcex+DnaaN/BbQ4dR2wzoiKg=",
"lastModified": 1744633460,
"narHash": "sha256-fbWE4Xpw6eH0Q6in+ymNuDwTkqmFmtxcQEmtRuKDTTk=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "e81fd167b33121269149c57806599045fd33eeed",
"rev": "9a049b4a421076d27fee3eec664a18b2066824cb",
"type": "github"
},
"original": {
@ -164,11 +164,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1746453552,
"narHash": "sha256-r66UGha+7KVHkI7ksrcMjnw/mm9Sg4l5bQlylxHwdGU=",
"lastModified": 1744290088,
"narHash": "sha256-/X9XVEl0EiyisNbF5srrxXRSVoRqdwExuqyspYqqEjQ=",
"owner": "nix-community",
"repo": "NixOS-WSL",
"rev": "be618645aa0adf461f778500172b6896d5ab2d01",
"rev": "60b4904a1390ac4c89e93d95f6ed928975e525ed",
"type": "github"
},
"original": {
@ -180,11 +180,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1745391562,
"narHash": "sha256-sPwcCYuiEopaafePqlG826tBhctuJsLx/mhKKM5Fmjo=",
"lastModified": 1703013332,
"narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8a2f738d9d1f1d986b5a4cd2fd2061a7127237d7",
"rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
"type": "github"
},
"original": {
@ -194,13 +194,29 @@
"type": "github"
}
},
"nixpkgs-stable": {
"nixpkgs-2405": {
"locked": {
"lastModified": 1747485343,
"narHash": "sha256-YbsZyuRE1tobO9sv0PUwg81QryYo3L1F3R3rF9bcG38=",
"lastModified": 1735563628,
"narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9b5ac7ad45298d58640540d0323ca217f32a6762",
"rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2411": {
"locked": {
"lastModified": 1744440957,
"narHash": "sha256-FHlSkNqFmPxPJvy+6fNLaNeWnF1lZSgqVCl/eWaJRc4=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "26d499fc9f1d567283d5d56fcf367edd815dba1d",
"type": "github"
},
"original": {
@ -210,6 +226,22 @@
"type": "github"
}
},
"nixpkgs-master": {
"locked": {
"lastModified": 1744910415,
"narHash": "sha256-mtb99yEpghJKQL3xpWfEsp0zx8UiqSrt5BN3e0n8kVs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "ec237aaad5a720b39223fcce41676b0c40307372",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1742937945,
@ -228,11 +260,11 @@
},
"nixpkgs_3": {
"locked": {
"lastModified": 1747542820,
"narHash": "sha256-GaOZntlJ6gPPbbkTLjbd8BMWaDYafhuuYRNrxCGnPJw=",
"lastModified": 1744463964,
"narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "292fa7d4f6519c074f0a50394dbbe69859bb6043",
"rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650",
"type": "github"
},
"original": {
@ -244,11 +276,11 @@
},
"nixpkgs_4": {
"locked": {
"lastModified": 1747542820,
"narHash": "sha256-GaOZntlJ6gPPbbkTLjbd8BMWaDYafhuuYRNrxCGnPJw=",
"lastModified": 1744463964,
"narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "292fa7d4f6519c074f0a50394dbbe69859bb6043",
"rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650",
"type": "github"
},
"original": {
@ -265,11 +297,11 @@
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1747636484,
"narHash": "sha256-oSQM85HjMmks8Qj2nrTggmg2wlQHpyjc7ytlZnrpxLM=",
"lastModified": 1744904898,
"narHash": "sha256-wLepe0sdFFgXUOLY2t+GrfjBquiGFgNydQkQYGh6UwQ=",
"owner": "nix-community",
"repo": "NUR",
"rev": "922b1706eba8109c6c715f9af54355cf1338f189",
"rev": "9ea0c40c52673079dfe50e82ddbb78679723be05",
"type": "github"
},
"original": {
@ -286,7 +318,9 @@
"nixos-hardware": "nixos-hardware",
"nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs_3",
"nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-2405": "nixpkgs-2405",
"nixpkgs-2411": "nixpkgs-2411",
"nixpkgs-master": "nixpkgs-master",
"nur": "nur"
}
},

View file

@ -7,17 +7,17 @@
url = "github:nix-community/disko";
};
home-manager = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/home-manager/master";
};
home-manager.inputs.nixpkgs.follows = "nixpkgs";
home-manager.url = "github:nix-community/home-manager/master";
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-2405.url = "github:nixos/nixpkgs/nixos-24.05";
nixpkgs-2411.url = "github:nixos/nixpkgs/nixos-24.11";
nixpkgs-master.url = "github:nixos/nixpkgs/master";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
nur.url = "github:nix-community/NUR";
};
@ -60,10 +60,6 @@
overlays = import ./overlays { inherit inputs; };
homeManagerModules.default = import ./modules/home-manager;
nixosModules.default = import ./modules/nixos;
nixosConfigurations = {
lemp11 = nixpkgs.lib.nixosSystem {
specialArgs = specialArgs // {
@ -142,6 +138,19 @@
./hosts/PW05CH3L/configuration.nix
];
};
hetznix = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
agenix.nixosModules.default
disko.nixosModules.disko
./hosts/hetznix/configuration.nix
];
};
};
nixosModules = import ./modules { lib = nixpkgs.lib; };
};
}

View file

@ -1,7 +0,0 @@
{ outputs, ... }:
{
imports = [
outputs.homeManagerModules.default
];
}

View file

@ -1,52 +0,0 @@
{ config, options, ... }:
{
imports = [ ../common ];
cli = {
bookmarkthis.enable = true;
direnv.enable = true;
fzf.enable = true;
git = {
enable = true;
user.emailAddress = "oliver.davies@tfw.wales";
};
node.enable = true;
notes.enable = true;
ranger.enable = true;
starship.enable = true;
tmux.enable = true;
tmux-sessionizer = {
enable = true;
directories =
let
inherit (config.xdg.userDirs) documents extraConfig;
repos = extraConfig.XDG_REPOS_DIR;
in
options.cli.tmux-sessionizer.directories.default
++ [
repos
"${repos}/*"
documents
];
};
todos.enable = true;
zsh.enable = true;
};
coding = {
neovim.enable = true;
phpactor.enable = true;
};
xdg.configFile."pam-gnupg".text = ''
C0D940F9A390F286FCAAE8439D501171E39D0A47
'';
}

View file

@ -1,11 +0,0 @@
{
imports = [ ../common ];
cli.zsh.enable = true;
desktop.media = {
handbrake.enable = true;
makemkv.enable = true;
mpv.enable = true;
};
}

View file

@ -1,13 +0,0 @@
{
imports = [
../common
./nixedo/modules/email-filters.nix
];
cli = {
fzf.enable = true;
starship.enable = true;
zsh.enable = true;
};
}

View file

@ -1,45 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.nixedo.${name};
name = "email-filters";
in
{
options.nixedo.${name} = {
configFile = lib.mkOption {
default = "${config.home.homeDirectory}/Code/${name}/config.lua";
internal = true;
};
};
config = {
systemd.user = {
services.${name} = {
Install.WantedBy = [ "default.target" ];
Service = {
ExecStart = "${lib.getExe pkgs.imapfilter} -c ${cfg.configFile}";
Type = "oneshot";
};
Unit.Description = name;
};
timers.${name} = {
Install.WantedBy = [ "timers.target" ];
Timer = {
OnCalendar = "*-*-* 06..23:00/5";
Unit = "${name}.service";
};
Unit.Description = "Automatically runs email filters with imapfilter.";
};
};
};
}

View file

@ -1,112 +0,0 @@
{ config, options, ... }:
{
imports = [ ../common ];
cli = {
bluetuith.enable = true;
bookmarkthis.enable = true;
direnv.enable = true;
fzf.enable = true;
git = {
enable = true;
user.emailAddress = "oliver@oliverdavies.uk";
};
node.enable = true;
notes = {
enable = true;
directory = "${config.xdg.userDirs.documents}/wiki/notes";
};
ranger.enable = true;
starship.enable = true;
tmux.enable = true;
tmux-sessionizer = {
enable = true;
directories =
let
inherit (config.xdg.userDirs) documents extraConfig;
repos = extraConfig.XDG_REPOS_DIR;
in
options.cli.tmux-sessionizer.directories.default
++ [
repos
"${repos}/*"
documents
];
};
todos.enable = true;
zsh.enable = true;
};
coding = {
neovim.enable = true;
phpactor.enable = true;
};
desktop = {
browsers = {
firefox = {
enable = true;
homepageUrl = "https://nixedo.oliverdavies.uk";
};
qutebrowser.enable = true;
};
flameshot.enable = true;
gtk.enable = true;
media = {
handbrake.enable = true;
makemkv.enable = true;
mpv.enable = true;
};
};
programs = {
dev-commit = {
enable = true;
repoPaths =
let
personal = "${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/personal";
in
[
"${personal}/email-filters"
"${personal}/nix-config"
"${personal}/oliverdavies.uk-tome"
"${personal}/opentofu-dns"
];
schedule = {
enable = true;
time = "daily";
};
};
zsh.shellAliases =
let
inherit (config.xdg.userDirs) documents;
in
{
"wiki-push" =
"rsync -avzP ${documents}/wiki nixedo.oliverdavies.uk:${documents} --delete --delete-after";
};
};
xdg.configFile."pam-gnupg".text = ''
098EE055DAD2B9CB68154C6759DD38292D2273B6
1E21B58D69FFEFAD077F152A50FEA938A3413F50
'';
}

View file

@ -1,3 +0,0 @@
{
imports = [ ../common ];
}

View file

@ -1,27 +1,37 @@
{ pkgs, ... }:
{ inputs, username, ... }:
{
imports = [
../common
../../users/opdavies.nix
];
cli = {
docker.enable = true;
password-store = {
enable = true;
extensions = with pkgs.passExtensions; [
pass-otp
];
};
let
git = {
name = "Oliver Davies";
emailAddress = "oliver.davies@tfw.wales";
};
in
{
imports = with inputs.self.nixosModules; [
editor-nvim
mixins-common
mixins-direnv
mixins-docker
mixins-fzf
mixins-node
mixins-notes
mixins-phpactor
mixins-ranger
mixins-scripts
mixins-starship
mixins-tmux
mixins-zsh
users-opdavies
(import ../../modules/mixins/git.nix { inherit git; })
./modules/wiki.nix
];
wsl = {
enable = true;
defaultUser = "opdavies";
defaultUser = username;
};
home-manager.users.opdavies.home.sessionVariables.WAYLAND_DISPLAY = "";

View file

@ -0,0 +1,37 @@
{ lib, ... }:
with lib;
{
home-manager.users.opdavies =
{ config, pkgs, ... }:
{
home =
let
remoteIpAddress = "192.168.1.111";
wikiPath = "${config.xdg.userDirs.documents}/wiki";
in
{
packages = [
(pkgs.writeShellApplication {
name = "wiki-pull";
text = ''
${getExe pkgs.rsync} -avz --update \
--exclude result \
${remoteIpAddress}:${wikiPath}/ ${wikiPath} "$@"
'';
})
(pkgs.writeShellApplication {
name = "wiki-push";
text = ''
${getExe pkgs.rsync} -avz --update \
${wikiPath}/ ${remoteIpAddress}:${wikiPath} "$@"
'';
})
];
};
};
}

View file

@ -1,5 +0,0 @@
{
imports = [
./opdavies.nix
];
}

View file

@ -1,7 +0,0 @@
{ config, ... }:
{
users.users.opdavies = { };
home-manager.users.opdavies = import ../../../home/opdavies/${config.networking.hostName}.nix;
}

View file

@ -0,0 +1,47 @@
{
inputs,
lib,
modulesPath,
pkgs,
...
}:
{
imports = with inputs.self.nixosModules; [
(modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/profiles/qemu-guest.nix")
./disks.nix
./hardware-configuration.nix
./networking.nix
./secrets.nix
./security
./services
../../modules/users/opdavies.nix
];
nix = {
extraOptions = ''
trusted-users = root opdavies
'';
};
boot.loader.grub = {
efiSupport = true;
efiInstallAsRemovable = true;
};
environment.systemPackages = map lib.lowPrio [
pkgs.curl
pkgs.gitMinimal
pkgs.tree
pkgs.vim
pkgs.wget
];
users.users.root.openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDkkbYaCD9NUIQT0NnsmlyfepwjxBYeiJSBCotOpdPTyc5inFAd29DiVw98j4skfaHdzjcqWmMFmDQWM6tGkK7eg8n0WuaABmsjdEbzTtfjHwM0tRDCIh5AtoT4IvoLhwLjEI2jKM05BGCQ2m5lS//AYJK1DjiV4UH+IjXHz6oy/3eFzQwANjxWS+mbR565p21yuAu1DKEyaGeVzT1xDhgzlnZG7Cys/rFgUYpIvYDHMOFxG6hsDB8vqyHiTXniniti5tdvGGYHgRGQcynRTU12aerrqHTIOefrElXJdf3/PA8FIY/Pd3MmZocY/vvQe0EVHXWrNtnHOF3MFQ1tFyfubKO51Dcp9KmzHnyBvO4CtvGVr/upSVWfo0I/EqkIqvCvBbdSIPeH9V5hAcyWENGF4Wf0/Yqtc0dBhfXJmPVBsC2ghZp9oERK+h5Xs7DpzkT0vtkN+wjgA5weIuG8e2UVNO29LWASzlychVqb7BVa6kNn5CyGwauyIGsYvAFnUjkyJpK8qleNM3VO5x9aw26IhSKlnSE9PAdX8p7PpdoWfxWRekKTc4h6iAe7pFOENvuokAvCNsE5LolR4VrYKXjA0m3nupDNWYexAWfR3lSeSlKd9nD3OENS0biJKayZHs11iDUTxm5u5gm/U60b4z0zDXjh1H/DI/pSCG6jjaXDpw== opdavies@lemp11"
];
system.stateVersion = "24.05";
}

57
hosts/hetznix/disks.nix Normal file
View file

@ -0,0 +1,57 @@
{ lib, ... }:
{
disko.devices = {
disk.disk1 = {
device = lib.mkDefault "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
name = "boot";
size = "1M";
type = "EF02";
};
esp = {
name = "ESP";
size = "500M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
name = "root";
size = "100%";
content = {
type = "lvm_pv";
vg = "pool";
};
};
};
};
};
lvm_vg = {
pool = {
type = "lvm_vg";
lvs = {
root = {
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [
"defaults"
];
};
};
};
};
};
};
}

View file

@ -0,0 +1,37 @@
# 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 = [
"ahci"
"xhci_pci"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
# 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.enp1s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -0,0 +1,19 @@
{
networking = {
firewall.allowedTCPPorts = [
80
443
];
interfaces.enp1s0 = {
useDHCP = true;
ipv4.addresses = [
{
address = "116.203.11.255";
prefixLength = 32;
}
];
};
};
}

View file

@ -0,0 +1,5 @@
{
age.secrets = {
cloudflare.file = ../../secrets/cloudflare.age;
};
}

View file

@ -0,0 +1,20 @@
{ config, ... }:
{
security.acme = {
acceptTerms = true;
defaults = {
dnsProvider = "cloudflare";
email = "oliver@oliverdavies.uk";
environmentFile = config.age.secrets.cloudflare.path;
webroot = null;
};
certs."oliverdavies.uk" = {
domain = "oliverdavies.uk";
extraDomainNames = [ "*.oliverdavies.uk" ];
};
};
}

View file

@ -0,0 +1,3 @@
{
imports = [ ./acme.nix ];
}

View file

@ -0,0 +1,5 @@
{
services.caddy.enable = true;
imports = [ ./vhosts ];
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."bootstrap-with-tailwind.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/bootstrap-with-tailwind.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,18 @@
{
imports = [
./bootstrap-with-tailwind.oliverdavies.uk.nix
./eric.nix
./florida-drupalcamp-tailwind-css.oliverdavies.uk.nix
./luke.oliverdavies.uk.nix
./phpsw-sculpin-demo.oliverdavies.uk.nix
./rebuilding-acquia.oliverdavies.uk.nix
./rebuilding-bartik.oliverdavies.uk.nix
./rebuilding-bristol-js.oliverdavies.uk.nix
./rebuilding-symfony.oliverdavies.uk.nix
./tailwindcss-demo.oliverdavies.uk.nix
./talking-drupal-tailwindcss.oliverdavies.uk.nix
./wp-tailwind.oliverdavies.uk.nix
./www.oliverdavies.uk.nix
./zet.oliverdavies.uk.nix
];
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."eric.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/eric
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."florida-drupalcamp-tailwind-css.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/florida-drupalcamp-tailwind-css.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."luke.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/luke.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."phpsw-sculpin-demo.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/phpsw-sculpin-demo.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."rebuilding-acquia.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/rebuilding-acquia.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."rebuilding-bartik.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/rebuilding-bartik.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."rebuilding-bristol-js.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/rebuilding-bristol-js.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."rebuilding-symfony.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/rebuilding-symfony.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."tailwindcss-demo.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/tailwindcss-demo.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."talking-drupal-tailwindcss.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/talking-drupal-tailwindcss.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."wp-tailwind.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/wp-tailwind.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,71 @@
{
services.caddy.virtualHosts = {
"oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
redir https://www.oliverdavies.uk{uri}
'';
};
"www.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig =
let
tomePaths = [
"core"
"sites/default/files"
"themes/custom/opdavies"
"tome-test"
];
tomeConfig = builtins.concatStringsSep "\n\n" (
builtins.map (path: ''
handle /${path} {
root * /var/www/vhosts/www.oliverdavies.uk-tome
file_server
}
handle_path /${path}/* {
root * /var/www/vhosts/www.oliverdavies.uk-tome/${path}
file_server
}
'') tomePaths
);
redirects = import ./www.oliverdavies.uk-redirects.nix;
redirectLines = builtins.concatStringsSep "\n" (
map (r: "redir ${r.from} ${r.to} permanent") redirects
);
in
''
encode gzip
file_server
root * /var/www/vhosts/www.oliverdavies.uk-sculpin
handle_errors {
@404 {
expression {http.error.status_code} == 404
}
rewrite @404 /404/index.html
file_server
}
${tomeConfig}
@articles path_regexp ^/articles/(.*)$
@talks path_regexp ^/talks/(.*)$
@talks-archive path_regexp ^/talks/archive/(.*)$
redir @articles /blog/{re.1} permanent
redir @talks-archive /presentations/{re.1} permanent
redir @talks /presentations/{re.1} permanent
${redirectLines}
'';
};
};
}

View file

@ -0,0 +1,12 @@
{
services.caddy.virtualHosts."zet.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = ''
encode gzip
root * /var/www/vhosts/zet.oliverdavies.uk
file_server
header X-Robots-Tag "noindex, nofollow"
'';
};
}

View file

@ -0,0 +1,8 @@
{
imports = [
./caddy
./forgejo.nix
./jitsi.nix
./openssl.nix
];
}

View file

@ -0,0 +1,30 @@
{ config, ... }:
{
services = {
forgejo = {
enable = true;
settings = {
server = {
DOMAIN = "code.oliverdavies.uk";
HTTP_PORT = 2223;
ROOT_URL = "https://${config.services.forgejo.settings.server.DOMAIN}";
SSH_DOMAIN = "ssh.oliverdavies.uk";
};
service = {
DISABLE_REGISTRATION = true;
};
};
};
caddy.virtualHosts."${config.services.forgejo.settings.server.DOMAIN}" = {
useACMEHost = "oliverdavies.uk";
extraConfig = "reverse_proxy localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}";
};
openssh.settings.AllowUsers = [ "forgejo" ];
};
}

View file

@ -0,0 +1,25 @@
{
services = {
jitsi-meet = {
enable = false;
caddy.enable = true;
nginx.enable = false;
secureDomain.enable = true;
hostName = "meet.oliverdavies.uk";
prosody = {
enable = true;
lockdown = true;
};
jicofo = {
enable = true;
};
};
};
nixpkgs.config.permittedInsecurePackages = [
"jitsi-meet-1.0.8043"
];
}

View file

@ -0,0 +1,10 @@
{
services.openssh = {
enable = true;
settings = {
AllowUsers = [ "opdavies" ];
PermitRootLogin = "no";
};
};
}

View file

@ -1,25 +1,21 @@
{ pkgs, ... }:
{ inputs, ... }:
{
imports = [
../common
imports = with inputs.self.nixosModules; [
./hardware-configuration.nix
./hardware.nix
./programs.nix
./services.nix
../../users/opdavies.nix
../../users/eric.nix
mixins-common
mixins-zram
mixins-zsh
users-opdavies
users-eric
users-luke
];
core = {
bluetooth.enable = true;
zram.enable = true;
};
desktop.media.makemkv.enable = true;
nixpad.enable = true;
# Bootloader.
boot = {
loader = {
@ -45,14 +41,4 @@
polkit.enable = true;
rtkit.enable = true;
};
users.users.eric.packages = with pkgs; [
git
vscodium
];
environment.systemPackages = with pkgs; [
fastfetch
htop
];
}

View file

@ -0,0 +1,6 @@
{
hardware = {
bluetooth.enable = true;
sane.enable = true;
};
}

View file

@ -1,8 +1,9 @@
{ pkgs, ... }:
{
programs = {
firefox = {
enable = true;
languagePacks = [ "en-GB" ];
preferences = {
"intl.accept_languages" = "en-GB, en";

View file

@ -1,6 +1,14 @@
{
services = {
auto-cpufreq.enable = true;
avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
};
blueman.enable = true;
gvfs.enable = true;
openssh.enable = true;
power-profiles-daemon.enable = false;
@ -27,6 +35,9 @@
layout = "gb";
variant = "";
};
desktopManager.cinnamon.enable = true;
displayManager.lightdm.enable = true;
};
};
}

View file

@ -2,35 +2,63 @@
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
{ inputs, ... }:
{
imports = [
../common
imports = with inputs.self.nixosModules; [
./hardware-configuration.nix
./homelab.nix
./modules
./ports.nix
./secrets.nix
./services
./services.nix
../../users/opdavies.nix
mixins-common
mixins-docker
mixins-fzf
mixins-starship
mixins-zsh
users-opdavies
./modules/acme.nix
./modules/audiobookshelf.nix
./modules/cloudflared.nix
./modules/containers
./modules/forgejo.nix
./modules/immich.nix
./modules/jellyfin.nix
./modules/paperless.nix
];
core.openssh.enable = true;
cli.podman.enable = true;
desktop.dconf.enable = true;
services.cloudflared = {
enable = true;
# TODO: why didn't it work when adding this to jitsi.nix?
nixpkgs.config.permittedInsecurePackages = [
"jitsi-meet-1.0.8043"
];
tunnels."e1514105-327f-4984-974e-e2fbaca76466" = {
credentialsFile = config.age.secrets.cloudflared.path;
default = "http_status:404";
ingress = {
"test.oliverdavies.uk" = {
service = "http://localhost:8000";
};
};
};
};
nixosModules = {
audiobookshelf.enable = true;
immich.enable = true;
jellyfin.enable = true;
paperless.enable = true;
pihole.enable = true;
};
programs.dconf.enable = true;
services.logind.lidSwitchExternalPower = "ignore";
boot.loader = {
efi = {
canTouchEfiVariables = true;
efiSysMountPoint = "/boot/efi";
};
systemd-boot.enable = true;
@ -38,19 +66,10 @@
networking.networkmanager.enable = true;
users.users.opdavies.extraGroups = [ "media" ];
powerManagement.powertop.enable = true;
users.groups.media = { };
networking.firewall.allowedTCPPorts = [
80
443
];
environment.systemPackages = with pkgs; [
tree
vim
];
}

View file

@ -1,39 +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, ... }:
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" ];
boot.initrd.availableKernelModules = [
"xhci_pci"
"thunderbolt"
"nvme"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.kernelParams = [ "i8042.reset" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/40649879-4ee6-4668-8257-fe81a7773024";
fsType = "ext4";
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/7c6d69ec-ba06-4ddb-b9c4-62b3994fda91";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/24B1-88CB";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
fileSystems."/boot/efi" = {
device = "/dev/disk/by-uuid/B729-9A75";
fsType = "vfat";
};
swapDevices = [ ];
swapDevices = [
{ device = "/dev/disk/by-uuid/5db0a0e6-93fb-4d0b-8fb0-fdb3cb76b89d"; }
];
# 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.enp0s20f0u1.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s13f0u1.useDHCP = lib.mkDefault true;
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,25 +0,0 @@
{
homelab = {
enable = true;
cloudflared.tunnelId = "e1514105-327f-4984-974e-e2fbaca76466";
domain = "oliverdavies.uk";
services = {
audiobookshelf.enable = true;
forgejo.enable = true;
gitea-actions-runner.enable = true;
home-assistant.enable = true;
homepage-dashboard.enable = true;
immich.enable = true;
jellyfin.enable = true;
jitsi.enable = true;
paperless.enable = true;
peertube.enable = true;
tubearchivist.enable = true;
uptime-kuma.enable = true;
vaultwarden.enable = true;
};
};
}

View file

@ -4,54 +4,16 @@
security.acme = {
acceptTerms = true;
certs =
let
certs = {
"oliverdavies.uk" = {
domain = "oliverdavies.uk";
in
{
${domain} = {
inherit domain;
dnsProvider = "cloudflare";
email = "oliver@oliverdavies.uk";
environmentFile = config.age.secrets.cloudflare.path;
webroot = null;
dnsProvider = "cloudflare";
email = "oliver@oliverdavies.uk";
environmentFile = config.age.secrets.cloudflare.path;
webroot = null;
extraDomainNames =
let
subdomains = [
"2020"
"audiobookshelf"
"bootstrap-with-tailwind"
"code"
"eric"
"florida-drupalcamp-tailwind-css"
"home"
"jellyfin"
"luke"
"nixedo"
"paperless"
"photos"
"phpsw-sculpin-demo"
"rebuilding-acquia"
"rebuilding-bartik"
"rebuilding-bristol-js"
"rebuilding-symfony"
"tailwindcss-demo"
"talking-drupal-tailwindcss"
"tome"
"tubearchivist"
"uptime"
"vaultwarden"
"wp-tailwind"
"www"
"zet"
];
domains = map (subdomain: "${subdomain}.${domain}") subdomains;
in
domains;
};
extraDomainNames = [ "*.oliverdavies.uk" ];
};
};
};
}

View file

@ -3,52 +3,23 @@
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "audiobookshelf";
cfg = config.nixosModules.audiobookshelf;
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "audiobookshelf.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Audiobookshelf";
type = types.str;
};
homepage.description = mkOption {
default = "Self-hosted audiobook and podcast server";
type = types.str;
};
homepage.icon = mkOption {
default = "audiobookshelf";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
options.nixosModules.audiobookshelf.enable = mkEnableOption "Enable audiobookshelf";
config = mkIf cfg.enable {
services = {
${service}.enable = true;
audiobookshelf = {
enable = true;
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
port = 4001;
};
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.port}";
recommendedProxySettings = true;
};
caddy.virtualHosts."audiobookshelf.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = "reverse_proxy localhost:${toString config.services.audiobookshelf.port}";
};
};
};

View file

@ -7,6 +7,12 @@
tunnels."e1514105-327f-4984-974e-e2fbaca76466" = {
credentialsFile = config.age.secrets.cloudflared.path;
default = "http_status:404";
ingress = {
"test.oliverdavies.uk" = {
service = "http://localhost:8000";
};
};
};
};
}

View file

@ -1,6 +1,5 @@
{
imports = [
# ./pi-hole.nix
./tubearchivist.nix
./pi-hole.nix
];
}

View file

@ -1,40 +1,101 @@
{ config, lib, ... }:
{
config,
pkgs,
lib,
...
}:
with lib;
let
service = "pihole";
port = config.homelab.ports.${service};
port = 8082;
in
{
virtualisation.oci-containers.containers.${service} = {
image = "pihole/pihole:latest";
options.nixosModules.pihole.enable = mkEnableOption "Enable pihole";
environment = {
PIHOLE_DNS_1 = "8.8.8.8";
PIHOLE_DNS_2 = "8.8.4.4";
TZ = "Europe/London";
config = mkIf config.nixosModules.pihole.enable {
virtualisation = {
docker = {
enable = true;
autoPrune.enable = true;
};
oci-containers = {
backend = "docker";
containers."pihole" = {
image = "pihole/pihole:latest";
environment = {
"PIHOLE_DNS_1" = "8.8.8.8";
"PIHOLE_DNS_2" = "8.8.4.4";
"TZ" = "Europe/London";
};
volumes = [
"/home/opdavies/pihole/etc-dnsmasq.d:/etc/dnsmasq.d:rw"
"/home/opdavies/pihole/etc-pihole:/etc/pihole:rw"
];
ports = [
"53:53/tcp"
"53:53/udp"
"67:67/udp"
"${toString port}:80/tcp"
];
log-driver = "journald";
extraOptions = [
"--cap-add=NET_ADMIN"
"--network-alias=pihole"
"--network=pihole_default"
];
};
};
};
volumes = [
"/home/opdavies/pihole/etc-dnsmasq.d:/etc/dnsmasq.d:rw"
"/home/opdavies/pihole/etc-pihole:/etc/pihole:rw"
];
systemd = {
services = {
"docker-pihole" = {
serviceConfig = {
Restart = lib.mkOverride 90 "always";
RestartMaxDelaySec = lib.mkOverride 90 "1m";
RestartSec = lib.mkOverride 90 "100ms";
RestartSteps = lib.mkOverride 90 9;
};
ports = [
"53:53/tcp"
"53:53/udp"
"67:67/udp"
"${port}:80/tcp"
];
after = [ "docker-network-pihole_default.service" ];
requires = [ "docker-network-pihole_default.service" ];
partOf = [ "docker-compose-pihole-root.target" ];
wantedBy = [ "docker-compose-pihole-root.target" ];
};
log-driver = "journald";
"docker-network-pihole_default" = {
path = [ pkgs.docker ];
extraOptions = [
"--cap-add=NET_ADMIN"
];
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "docker network rm -f pihole_default";
};
systemd.services."podman-pihole".serviceConfig = {
Restart = lib.mkOverride 90 "always";
RestartSec = lib.mkOverride 90 "1s";
script = ''
docker network inspect pihole_default || docker network create pihole_default
'';
partOf = [ "docker-compose-pihole-root.target" ];
wantedBy = [ "docker-compose-pihole-root.target" ];
};
};
targets."docker-compose-pihole-root" = {
unitConfig = {
Description = "Root target generated by compose2nix.";
};
wantedBy = [ "multi-user.target" ];
};
};
};
}

View file

@ -1,334 +0,0 @@
{
config,
inputs,
lib,
pkgs,
...
}:
with lib;
let
cfg = homelab.services.${service};
service = "tubearchivist";
homelab = config.homelab;
port = homelab.ports.${service};
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Tube Archivist";
type = types.str;
};
homepage.description = mkOption {
default = "Your self hosted YouTube media server";
type = types.str;
};
homepage.icon = mkOption {
default = "tube-archivist";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
virtualisation = {
oci-containers.backend = "podman";
podman.enable = true;
};
virtualisation.oci-containers.containers."archivist-es" = {
image = "bbilly1/tubearchivist-es";
environment = {
"ES_JAVA_OPTS" = "-Xms1g -Xmx1g";
"discovery.type" = "single-node";
"path.repo" = "/usr/share/elasticsearch/data/snapshot";
"xpack.security.enabled" = "true";
"cluster.routing.allocation.disk.watermark.flood_stage" = "98%";
"cluster.routing.allocation.disk.watermark.high" = "97%";
"cluster.routing.allocation.disk.watermark.low" = "95%";
};
environmentFiles = [
config.age.secrets.tubearchivist-env.path
];
volumes = [
"tubearchivist_es:/usr/share/elasticsearch/data:rw"
];
log-driver = "journald";
extraOptions = [
"--network-alias=archivist-es"
"--network=tubearchivist_default"
];
};
systemd.services."podman-archivist-es" = {
serviceConfig = {
Restart = mkOverride 90 "always";
RestartMaxDelaySec = mkOverride 90 "1m";
RestartSec = mkOverride 90 "100ms";
RestartSteps = mkOverride 90 9;
};
after = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_es.service"
];
requires = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_es.service"
];
partOf = [
"podman-compose-tubearchivist-root.target"
];
wantedBy = [
"podman-compose-tubearchivist-root.target"
];
};
virtualisation.oci-containers.containers."archivist-redis" = {
image = "redis";
volumes = [
"tubearchivist_redis:/data:rw"
];
dependsOn = [
"archivist-es"
];
log-driver = "journald";
extraOptions = [
"--network-alias=archivist-redis"
"--network=tubearchivist_default"
];
};
systemd.services."podman-archivist-redis" = {
serviceConfig = {
Restart = mkOverride 90 "always";
RestartMaxDelaySec = mkOverride 90 "1m";
RestartSec = mkOverride 90 "100ms";
RestartSteps = mkOverride 90 9;
};
after = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_redis.service"
];
requires = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_redis.service"
];
partOf = [
"podman-compose-tubearchivist-root.target"
];
wantedBy = [
"podman-compose-tubearchivist-root.target"
];
};
virtualisation.oci-containers.containers."tubearchivist" = {
image = "bbilly1/tubearchivist";
environment = {
"ES_URL" = "http://archivist-es:9200";
"HOST_GID" = "1000";
"HOST_UID" = "1000";
"REDIS_CON" = "redis://archivist-redis:6379";
"TA_HOST" = "https://${cfg.url}";
"TZ" = "Europe/London";
};
environmentFiles = [
config.age.secrets.tubearchivist-env.path
];
volumes = [
"/mnt/media/${service}/cache:/cache:rw"
"/mnt/media/${service}/media:/youtube:rw"
];
ports = [
"${toString port}:8000/tcp"
];
dependsOn = [
"archivist-es"
"archivist-redis"
];
log-driver = "journald";
extraOptions = [
"--health-cmd=[\"curl\", \"-f\", \"http://localhost:8000/health\"]"
"--health-interval=2m0s"
"--health-retries=3"
"--health-start-period=30s"
"--health-timeout=10s"
"--network-alias=tubearchivist"
"--network=tubearchivist_default"
];
};
systemd.services."podman-tubearchivist" = {
serviceConfig = {
Restart = mkOverride 90 "always";
RestartMaxDelaySec = mkOverride 90 "1m";
RestartSec = mkOverride 90 "100ms";
RestartSteps = mkOverride 90 9;
};
after = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_cache.service"
"podman-volume-tubearchivist_media.service"
];
requires = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_cache.service"
"podman-volume-tubearchivist_media.service"
];
partOf = [
"podman-compose-tubearchivist-root.target"
];
wantedBy = [
"podman-compose-tubearchivist-root.target"
];
};
systemd.services."podman-network-tubearchivist_default" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "podman network rm -f tubearchivist_default";
};
script = ''
podman network inspect tubearchivist_default || podman network create tubearchivist_default
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_cache" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_cache || podman volume create tubearchivist_cache
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_es" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_es || podman volume create tubearchivist_es
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_media" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_media || podman volume create tubearchivist_media
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_redis" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_redis || podman volume create tubearchivist_redis
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.targets."podman-compose-tubearchivist-root" = {
unitConfig = {
Description = "Root target generated by compose2nix.";
};
wantedBy = [ "multi-user.target" ];
};
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString port}";
recommendedProxySettings = true;
proxyWebsockets = true;
extraConfig = ''
proxy_buffering off;
'';
};
};
age.secrets.tubearchivist-env.file = "${inputs.self}/secrets/tubearchivist-env.age";
};
}

View file

@ -1,34 +0,0 @@
{ lib, ... }:
with lib;
{
options.homelab = {
enable = mkEnableOption "Enable homelab services and configuration";
cloudflared.tunnelId = mkOption {
example = "00000000-0000-0000-0000-000000000000";
type = types.str;
};
domain = mkOption {
description = "The base domain to use for this homelab.";
type = types.str;
};
};
imports = [
./acme.nix
./audiobookshelf.nix
./cloudflared.nix
./containers
./forgejo.nix
./home-assistant.nix
./immich.nix
./jellyfin.nix
./jitsi.nix
./nginx
./paperless.nix
./peertube.nix
];
}

View file

@ -2,59 +2,32 @@
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "forgejo";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
options.nixosModules.forgejo.enable = mkEnableOption "Enable forgejo";
url = mkOption {
default = "code.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Forgejo";
type = types.str;
};
homepage.description = mkOption {
default = "Beyond coding. We forge.";
type = types.str;
};
homepage.icon = mkOption {
default = "forgejo";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
config = mkIf config.nixosModules.forgejo.enable {
services = {
${service} = {
forgejo = {
enable = true;
stateDir = "/var/www/${service}";
group = "media";
stateDir = "/mnt/media/forgejo";
settings = {
server = {
DOMAIN = cfg.url;
ROOT_URL = "https://${cfg.url}";
DOMAIN = "forgejo.oliverdavies.uk";
HTTP_PORT = 2223;
};
service.DISABLE_REGISTRATION = true;
service = {
DISABLE_REGISTRATION = true;
};
};
};
cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = {
${cfg.url} = "http://localhost:${toString config.services.${service}.settings.server.HTTP_PORT}";
caddy.virtualHosts."${config.services.forgejo.settings.server.DOMAIN}" = {
useACMEHost = "oliverdavies.uk";
extraConfig = "reverse_proxy localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}";
};
};
};

View file

@ -1,97 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "home-assistant";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "home.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Home Assisant";
type = types.str;
};
homepage.description = mkOption {
default = "Open source home automation that puts local control and privacy first.";
type = types.str;
};
homepage.icon = mkOption {
default = "home-assistant";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
home-assistant = {
enable = true;
config = {
external_url = "https://home.${homelab.domain}";
name = "Home";
time_zone = "Europe/London";
unit_system = "metric";
http = {
trusted_proxies = [
"127.0.0.1"
"::1"
];
use_x_forwarded_for = true;
};
mobile_app = { };
# sia = { };
};
extraComponents = [
"default_config"
"elgato"
"hive"
"met"
"mobile_app"
# "sia"
"tplink"
"tplink_tapo"
"weather"
"webostv"
"wiz"
];
extraPackages =
python3Packages: with python3Packages; [
setuptools
];
openFirewall = true;
};
nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.config.http.server_port}";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -7,64 +7,22 @@
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "immich";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
options.nixosModules.immich.enable = mkEnableOption "Enable immich";
url = mkOption {
default = "photos.${homelab.domain}";
type = types.str;
config = mkIf config.nixosModules.immich.enable {
services.immich = {
enable = true;
group = "media";
mediaLocation = "/mnt/media/immich";
};
homepage.name = mkOption {
default = "Immich";
type = types.str;
environment.systemPackages = [ pkgs.immich-cli ];
services.caddy.virtualHosts."immich.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
extraConfig = "reverse_proxy localhost:${toString config.services.immich.port}";
};
homepage.description = mkOption {
default = "Self-hosted photo and video management solution";
type = types.str;
};
homepage.icon = mkOption {
default = "immich";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
group = "media";
mediaLocation = "/mnt/media/${service}";
};
nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.immich.port}";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
};
environment.systemPackages = with pkgs; [
immich-cli
immich-go
];
};
}

View file

@ -2,64 +2,21 @@
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "jellyfin";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
options.nixosModules.jellyfin.enable = mkEnableOption "Enable jellyfin";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
config = mkIf config.nixosModules.jellyfin.enable {
services.jellyfin = {
enable = true;
openFirewall = true;
group = "media";
configDir = "/mnt/media/jellyfin";
};
homepage.name = mkOption {
default = "Jellyfin";
type = types.str;
};
services.caddy.virtualHosts."jellyfin.oliverdavies.uk" = {
useACMEHost = "oliverdavies.uk";
homepage.description = mkOption {
default = "The Free Software Media System";
type = types.str;
};
homepage.icon = mkOption {
default = "jellyfin";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
configDir = "/mnt/media/${service}";
group = "media";
openFirewall = true;
};
nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:8096";
recommendedProxySettings = true;
extraConfig = ''
proxy_buffering off;
'';
};
};
extraConfig = "reverse_proxy localhost:8096";
};
};
}

View file

@ -1,41 +0,0 @@
{ config, lib, ... }:
let
cfg = config.homelab.services.${service};
homelab = config.homelab;
service = "jitsi";
inherit (lib) mkEnableOption mkOption types;
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "meet.${homelab.domain}";
type = types.str;
};
};
config = lib.mkIf cfg.enable {
services = {
jitsi-meet = {
enable = false;
hostName = cfg.url;
secureDomain.enable = true;
};
nginx.virtualHosts.${cfg.url} = {
enableACME = false;
forceSSL = false;
};
cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = {
# TODO: is this the correct port?
${cfg.url} = "http://localhost:5280";
};
};
};
}

View file

@ -1,55 +0,0 @@
{ config, ... }:
let
sites = import ./sites.nix { ports = config.homelab.ports; };
in
{
services = {
nginx = {
enable = true;
virtualHosts = builtins.listToAttrs (
map (site: {
name = site.url;
value = {
root = site.root;
listen = [
{
addr = "localhost";
port = site.port;
}
];
locations."/".tryFiles = "$uri $uri/index.html =404";
extraConfig = builtins.concatStringsSep "\n\n" [
site.extraConfig or ""
''
port_in_redirect off;
# Remove trailing slashes.
rewrite ^/(.*)/$ /$1 permanent;
''
];
};
}) sites
);
};
cloudflared.tunnels."e1514105-327f-4984-974e-e2fbaca76466" = {
ingress = builtins.listToAttrs (
map (site: {
name = site.url;
value = "http://localhost:${toString site.port}";
}) sites
);
};
};
users.users.${config.services.nginx.user}.extraGroups = [ "acme" ];
imports = [ ./www.oliverdavies.uk ];
}

View file

@ -1,29 +0,0 @@
{ ports }:
let
mkSite =
name: overrides:
let
root = "/var/www/vhosts/${name}" + (overrides.rootSuffix or "");
port = ports."nginx-${name}";
url = "${name}.oliverdavies.uk";
in
{ inherit port root url; } // overrides;
sites = [
(mkSite "eric" {
rootSuffix = "/public";
extraConfig = ''
add_header X-Robots-Tag "noindex, nofollow";
'';
})
(mkSite "luke" {
extraConfig = ''
add_header X-Robots-Tag "noindex, nofollow";
'';
})
];
in
sites

View file

@ -1,111 +0,0 @@
{ config, ... }:
let
ports = config.homelab.ports;
port = ports.nginx-website-sculpin;
redirects = builtins.concatStringsSep "\n" (
map (r: "rewrite ^${r.from}/?$ ${r.to} redirect;") (import ./redirects.nix)
);
tome = {
root = "/var/www/vhosts/website-tome";
paths = [
"archive"
"core"
"daily/.+"
"examples"
"homelab"
"rss/daily.xml"
"sites/default/files"
"themes/custom/opdavies"
"tome-test"
];
port = ports.nginx-website-tome;
};
tomeLocations = builtins.listToAttrs (
map (path: {
name = "~ ^/${path}";
value = {
root = tome.root;
tryFiles = "$uri $uri.html $uri/index.html =404";
};
}) tome.paths
);
in
{
services = {
nginx.virtualHosts = {
"www.oliverdavies.uk" = {
root = "/var/www/vhosts/website-sculpin";
listen = [
{
inherit port;
addr = "localhost";
}
];
locations = tomeLocations // {
"/".tryFiles = "$uri $uri.html $uri/index.html =404";
};
extraConfig = ''
port_in_redirect off;
# Remove trailing slashes.
rewrite ^/(.*)/$ /$1 permanent;
error_page 404 /404;
rewrite ^/talks/archive/?$ /talks permanent;
rewrite ^/talks/(.*)$ /presentations/$1 permanent;
rewrite ^/talks/?$ /presentations permanent;
${redirects}
'';
};
"oliverdavies.uk" = {
forceSSL = true;
globalRedirect = "www.oliverdavies.uk";
useACMEHost = "oliverdavies.uk";
};
"tome.oliverdavies.uk" = {
listen = [
{
addr = "localhost";
port = tome.port;
}
];
locations."/".tryFiles = "$uri $uri.html $uri/index.html =404";
root = tome.root;
extraConfig = ''
add_header X-Robots-Tag "noindex, nofollow";
port_in_redirect off;
# Remove trailing slashes.
rewrite ^/(.*)/$ /$1 permanent;
'';
};
};
cloudflared.tunnels."e1514105-327f-4984-974e-e2fbaca76466" = {
ingress = {
"oliverdavies.uk" = "http://localhost:${toString port}";
"tome.oliverdavies.uk" = "http://localhost:${toString tome.port}";
"www.oliverdavies.uk" = "http://localhost:${toString port}";
};
};
};
}

View file

@ -3,60 +3,27 @@
with lib;
let
cfg = homelab.services.paperless;
homelab = config.homelab;
service = "paperless";
url = "paperless.oliverdavies.uk";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
options.nixosModules.paperless.enable = mkEnableOption "Enable paperless";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Paperless-ngx";
type = types.str;
};
homepage.description = mkOption {
default = "Document management system";
type = types.str;
};
homepage.icon = mkOption {
default = "paperless";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
config = mkIf config.nixosModules.paperless.enable {
services = {
${service} = {
paperless = {
enable = true;
dataDir = "/mnt/media/${service}";
dataDir = "/mnt/media/paperless";
settings = {
PAPERLESS_URL = "https://${cfg.url}";
PAPERLESS_URL = "https://${url}";
};
};
nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
caddy.virtualHosts."${url}" = {
useACMEHost = "oliverdavies.uk";
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.port}";
recommendedProxySettings = true;
};
extraConfig = "reverse_proxy localhost:28981";
};
};
};

View file

@ -1,88 +0,0 @@
{
config,
inputs,
lib,
...
}:
let
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
cfg = homelab.services.${service};
homelab = config.homelab;
service = "peertube";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "videos.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Peertube";
type = types.str;
};
homepage.description = mkOption {
default = "A free and open-source, decentralized, ActivityPub federated video platform";
type = types.str;
};
homepage.icon = mkOption {
default = "peertube";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
configureNginx = true;
enableWebHttps = false;
localDomain = cfg.url;
database = {
createLocally = true;
};
redis = {
createLocally = true;
enableUnixSocket = true;
};
secrets.secretsFile = config.age.secrets.peertube-env.path;
settings = {
webserver = {
hostname = config.services.${service}.localDomain;
port = lib.mkForce 443;
};
};
};
cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = {
${cfg.url} = "http://localhost:${toString config.services.${service}.listenWeb}";
};
};
age.secrets."${service}-env" = {
file = "${inputs.self}/secrets/${service}-env.age";
owner = config.services.${service}.user;
};
};
}

View file

@ -1,35 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
options.homelab.ports = mkOption {
internal = true;
type = types.attrsOf types.port;
};
config.homelab.ports = {
homepage-dashboard = 8097;
pihole = 8082;
tubearchivist = 8099;
vaultwarden = 8022;
nginx-website-sculpin = 8095;
nginx-website-tome = 8098;
nginx-bootstrap-with-tailwind = 8081;
nginx-eric = 8084;
nginx-florida-drupalcamp-tailwind-css = 8083;
nginx-luke = 8094;
nginx-phpsw-sculpin-demo = 8085;
nginx-rebuilding-acquia = 8086;
nginx-rebuilding-bartik = 8087;
nginx-rebuilding-bristol-js = 8088;
nginx-rebuilding-symfony = 8089;
nginx-tailwindcss-demo = 8090;
nginx-talking-drupal-tailwindcss = 8093;
nginx-wp-tailwind = 8091;
nginx-zet = 8092;
};
}

View file

@ -2,5 +2,6 @@
age.secrets = {
cloudflare.file = ../../secrets/cloudflare.age;
cloudflared.file = ../../secrets/cloudflared-credentials.age;
tubearchivist.file = ../../secrets/tubearchivist.age;
};
}

View file

@ -0,0 +1,6 @@
{
services = {
caddy.enable = true;
openssh.enable = true;
};
}

View file

@ -1,5 +0,0 @@
{
imports = [
./tubearchivist.nix
];
}

View file

@ -1,49 +0,0 @@
{
config,
inputs,
pkgs,
...
}:
{
imports = [
./homepage
./mastodon.nix
./samba.nix
./uptime-kuma.nix
./vaultwarden.nix
];
services = {
postgresqlBackup.enable = true;
tailscale.enable = true;
};
services.gitea-actions-runner.instances.default = {
enable = true;
hostPackages = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nix
nodejs
wget
];
labels = [
"nixos:host"
];
name = config.networking.hostName;
tokenFile = config.age.secrets.forgejo-runner-token.path;
url = config.services.forgejo.settings.server.ROOT_URL;
};
age.secrets = {
forgejo-runner-token.file = "${inputs.self}/secrets/forgejo-runner-token.age";
};
}

View file

@ -1,63 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "homepage-dashboard";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${config.networking.hostName}.${homelab.domain}";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
listenPort = homelab.ports.${service};
openFirewall = true;
customCSS = ''
#information-widgets {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
div#footer {
display: none;
}
.services-group {
margin-bottom: 3rem;
}
'';
services = (import ./services.nix { inherit config lib; });
settings = {
headerStyle = "clean";
hideVersion = "true";
layout = (import ./layout.nix);
statusStyle = "dot";
};
};
glances.enable = true;
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/".proxyPass =
"http://localhost:${toString config.services.homepage-dashboard.listenPort}";
};
};
};
}

View file

@ -1,57 +0,0 @@
{ config }:
{
Glances =
let
port = toString config.services.glances.port;
in
[
{
Info = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "info";
chart = false;
version = 4;
};
};
}
{
"CPU Temp" = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "sensor:Package id 0";
chart = false;
version = 4;
};
};
}
{
Processes = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "process";
chart = false;
version = 4;
};
};
}
{
Network = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "network:enp0s20f0u1";
chart = false;
version = 4;
};
};
}
];
}

View file

@ -1,23 +0,0 @@
[
{
Glances = {
columns = 4;
header = false;
style = "row";
};
}
{
Media = {
header = true;
style = "column";
};
}
{
Services = {
header = true;
style = "column";
};
}
]

View file

@ -1,32 +0,0 @@
{ config, lib }:
with lib;
let
homelab = config.homelab.services;
homepageCategories = [
"Media"
"Services"
];
homepageServices =
category:
(attrsets.filterAttrs (
name: value: value ? homepage && value.homepage.category == category
) homelab);
services = lists.forEach homepageCategories (cat: {
"${cat}" =
lib.lists.forEach (lib.attrsets.mapAttrsToList (name: value: name) (homepageServices "${cat}"))
(x: {
"${homelab.${x}.homepage.name}" = {
icon = homelab.${x}.homepage.icon;
description = homelab.${x}.homepage.description;
href = "https://${homelab.${x}.url}";
siteMonitor = "https://${homelab.${x}.url}";
};
});
});
in
services ++ [ (import ./glances.nix { inherit config; }) ]

View file

@ -1,84 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = config.homelab.services.${service};
domain = "oliverdavies.uk";
service = "mastodon";
in
{
options.homelab.services.${service} = {
url = mkOption {
default = "social.${domain}";
internal = true;
type = types.str;
};
};
config = {
services = {
${service} = {
enable = false;
configureNginx = false;
localDomain = domain;
streamingProcesses = 3;
extraConfig = {
SINGLE_USER_MODE = "true";
WEB_DOMAIN = cfg.url;
};
smtp = {
fromAddress = "social@${domain}";
};
};
cloudflared.tunnels.${config.homelab.cloudflared.tunnelId} = {
ingress = {
"${cfg.url}" = "http://localhost";
};
};
nginx = {
upstreams.mastodon-streaming = {
extraConfig = ''
least_conn;
'';
servers = builtins.listToAttrs (
map (i: {
name = "unix:/run/mastodon-streaming/streaming-${toString i}.socket";
value = { };
}) (range 1 config.services.mastodon.streamingProcesses)
);
};
virtualHosts."social.oliverdavies.uk" = {
root = "${config.services.mastodon.package}/public/";
locations = {
"/".tryFiles = "$uri @proxy";
"/api/v1/streaming/" = {
proxyPass = "http://mastodon-streaming";
proxyWebsockets = true;
};
"/system/".alias = "/var/lib/mastodon/public-system/";
"@proxy" = {
proxyPass = "http://unix:/run/mastodon-web/web.socket";
proxyWebsockets = true;
};
};
extraConfig = ''
client_max_body_size 100m;
'';
};
};
};
};
}

View file

@ -1,28 +0,0 @@
{
services.samba = {
enable = true;
openFirewall = true;
settings = {
home = {
path = "/home/opdavies";
browseable = true;
writable = true;
"valid users" = [ "opdavies" ];
"force group" = "media";
"create mask" = "0660";
"directory mask" = "0770";
};
media = {
path = "/mnt/media";
browseable = true;
writable = true;
"valid users" = [ "opdavies" ];
"force group" = "media";
"create mask" = "0660";
"directory mask" = "0770";
};
};
};
}

View file

@ -1,55 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "uptime-kuma";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "uptime.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Uptime Kuma";
type = types.str;
};
homepage.description = mkOption {
default = "A fancy self-hosted monitoring tool";
type = types.str;
};
homepage.icon = mkOption {
default = "uptime-kuma";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service}.enable = true;
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.settings.PORT}";
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -1,65 +0,0 @@
{
config,
lib,
options,
...
}:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "vaultwarden";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Vaultwarden";
type = types.str;
};
homepage.description = mkOption {
default = "Unofficial Bitwarden compatible server written in Rust";
type = types.str;
};
homepage.icon = mkOption {
default = "bitwarden";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
config = {
DOMAIN = "https://${cfg.url}";
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = homelab.ports.${service};
SIGNUPS_ALLOWED = false;
};
};
cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = {
"${cfg.url}" = "http://${config.services.${service}.config.ROCKET_ADDRESS}:${
toString config.services.${service}.config.ROCKET_PORT
}";
};
};
};
}

View file

@ -1,44 +1,61 @@
{ pkgs, ... }:
{ inputs, pkgs, ... }:
let
git = {
name = "Oliver Davies";
emailAddress = "oliver@oliverdavies.uk";
};
in
{
imports = [
../common
imports = with inputs.self.nixosModules; [
./hardware-configuration.nix
./modules
./secrets.nix
./services.nix
../../users/opdavies.nix
editor-nvim
mixins-bluetooth
mixins-common
mixins-direnv
mixins-docker
mixins-firefox
mixins-flameshot
mixins-fonts
mixins-fzf
mixins-gnupg
mixins-gtk
mixins-qutebrowser
mixins-mpv
mixins-node
mixins-notes
mixins-phpactor
mixins-pipewire
mixins-ranger
mixins-screenkey
mixins-scripts
mixins-starship
mixins-thunar
mixins-tmux
mixins-zram
mixins-zsh
profiles-dwm
profiles-xbanish
(import ../../modules/mixins/git.nix { inherit git; })
(import ../../modules/mixins/kanata.nix {
devices = [
"/dev/input/event1"
];
})
users-opdavies
./modules/cron.nix
./modules/neomutt.nix
./modules/newsboat
./modules/ollama.nix
./modules/wiki.nix
];
cli.password-store = {
enable = true;
extensions = with pkgs.passExtensions; [
pass-audit
pass-otp
pass-update
];
};
core = {
bluetooth.enable = true;
openssh.enable = true;
pipewire.enable = true;
xbanish.enable = true;
zram.enable = true;
};
desktop = {
dconf.enable = true;
dwm.enable = true;
fonts.enable = true;
media.makemkv.enable = true;
st.enable = true;
thunar.enable = true;
};
boot = {
loader = {
systemd-boot = {
@ -70,15 +87,13 @@
backup-websites
brightnessctl
build-glove80
cdrkit
cpufrequtils
displayselect
dvdbackup
dvdplusrwtools
ffmpegthumbnailer
gimp
gscan2pdf
gtypist
handbrake
hunspellDicts.en-gb-large
isync
kdePackages.kdenlive
@ -95,7 +110,6 @@
shotwell
slack
sxiv
tailscale
ttyper
upload-to-files
xcape
@ -104,4 +118,38 @@
zeroad
zoom-us
];
networking.hosts = {
"192.168.1.116" = [ "nixedo" ];
};
services = {
auto-cpufreq.enable = true;
avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
};
gvfs.enable = true;
openssh.enable = true;
power-profiles-daemon.enable = false;
printing.enable = true;
pulseaudio.enable = false;
throttled.enable = true;
thermald.enable = true;
upower.enable = true;
xserver = {
enable = true;
xkb = {
layout = "gb";
variant = "";
};
};
};
programs.dconf.enable = true;
}

View file

@ -1,8 +0,0 @@
{
imports = [
./cron.nix
./neomutt.nix
./newsboat
./ollama.nix
];
}

View file

@ -0,0 +1,33 @@
{ lib, ... }:
with lib;
{
home-manager.users.opdavies =
{ config, pkgs, ... }:
{
home.packages = with pkgs; [
(pkgs.writeShellApplication (
let
remoteIpAddresses = [
"116.203.11.255"
"192.168.1.116"
];
wikiPath = "${config.xdg.userDirs.documents}/wiki";
in
{
name = "wiki-push";
text = builtins.concatStringsSep "\n" (
map (ipAddress: ''
${getExe pkgs.rsync} -avz --update \
--delete --delete-after \
${wikiPath}/ ${ipAddress}:${wikiPath} "$@"
'') remoteIpAddresses
);
}
))
];
};
}

View file

@ -1,24 +0,0 @@
{
services = {
auto-cpufreq.enable = true;
gvfs.enable = true;
power-profiles-daemon.enable = false;
printing.enable = true;
pulseaudio.enable = false;
tailscale.enable = true;
throttled.enable = true;
thermald.enable = true;
upower.enable = true;
xserver = {
enable = true;
displayManager.startx.enable = true;
xkb = {
layout = "gb";
variant = "";
};
};
};
}

View file

@ -1,24 +1,20 @@
{
imports = [
../common
{ inputs, pkgs, ... }:
{
imports = with inputs.self.nixosModules; [
./hardware-configuration.nix
./hardware.nix
./programs.nix
./secrets.nix
./services
./users.nix
../../users/luke.nix
../../users/opdavies.nix
mixins-common
mixins-zram
users-opdavies
];
core = {
bluetooth.enable = true;
zram.enable = true;
};
desktop.dconf.enable = true;
nixpad.enable = true;
boot = {
loader = {
systemd-boot = {
@ -37,4 +33,21 @@
'';
networking.networkmanager.enable = true;
security = {
polkit.enable = true;
rtkit.enable = true;
};
environment.systemPackages = with pkgs; [
gtypist
pam_gnupg
sxiv
ttyper
yt-dlp
];
networking.hosts = {
"192.168.1.116" = [ "nixedo" ];
};
}

7
hosts/t490/programs.nix Normal file
View file

@ -0,0 +1,7 @@
{ pkgs, ... }:
{
programs = {
dconf.enable = true;
};
}

5
hosts/t490/secrets.nix Normal file
View file

@ -0,0 +1,5 @@
{
age.secrets = {
cloudflare.file = ../../secrets/cloudflare.age;
};
}

View file

@ -5,6 +5,7 @@
enable = true;
systemCronJobs = [
"*/15 * * * * opdavies ${pkgs.imapfilter}/bin/imapfilter -c ~/Code/email-filters/config.lua"
"0 8,20 * * * opdavies ${pkgs.isync}/bin/mbsync -a"
];
};

View file

@ -2,6 +2,7 @@
imports = [
./cron.nix
./interception-tools.nix
./redshift.nix
./sound.nix
./udev.nix
./xserver.nix

View file

@ -3,10 +3,10 @@
with lib;
let
cfg = config.redshift;
cfg = config.nixosModules.redshift;
in
{
options.redshift.enable = mkEnableOption "Enable redshift";
options.nixosModules.redshift.enable = mkEnableOption "Enable redshift";
config = mkIf cfg.enable {
location = {

15
hosts/t490/users.nix Normal file
View file

@ -0,0 +1,15 @@
{ pkgs, username, ... }:
{
users.users.${username} = {
extraGroups = [ "media" ];
packages = with pkgs; [
abook
android-tools
via
];
};
users.groups.media = { };
}

57
modules/default.nix Normal file
View file

@ -0,0 +1,57 @@
# Based on https://github.com/MatthewCroughan/nixcfg/blob/afab322e6da20cc038d8577dd4a365673702d183/modules/default.nix.
# Autoloads files within modules/ and makes them available by their module
# type and name, e.g. `mixins-zsh`, `editor-nvim` and `users-opdavies` when
# imported with `inputs.self.nixosModules`.
{ lib }:
let
inherit (builtins)
attrNames
filter
listToAttrs
map
readDir
toString
;
inherit (lib)
filterAttrs
foldAttrs
hasSuffix
mapAttrsToList
nameValuePair
removeSuffix
zipListsWith
;
inherit (lib.filesystem) listFilesRecursive;
generateModules =
folder: prefix:
let
findSuffix = suffix: dir: (filter (x: (hasSuffix suffix (toString x))) (listFilesRecursive dir));
allNixFiles = findSuffix ".nix" folder;
allModuleNames = map (removeSuffix ".nix") (map baseNameOf allNixFiles);
zippedList = (
zipListsWith (x: y: nameValuePair (prefix + "-" + x) (import y)) allModuleNames allNixFiles
);
in
listToAttrs zippedList;
generateModulesAuto =
root:
let
moduleFolderNames = attrNames (filterAttrs (n: v: v == "directory") (readDir (toString root)));
moduleFolderPaths = map (x: (toString root) + "/" + x) moduleFolderNames;
zippedList = listToAttrs (
zipListsWith (x: y: nameValuePair x y) moduleFolderNames moduleFolderPaths
);
in
foldAttrs (item: acc: item) { } (mapAttrsToList (n: v: generateModules v n) zippedList);
in
generateModulesAuto ./.

View file

@ -3,7 +3,3 @@ vim.opt_local.spell = true
vim.opt_local.wrap = true
vim.keymap.set("n", "<leader>su", "Bi{{site.url}}/<Esc>")
-- Convert lines into a markdown list.
vim.keymap.set("n", "<leader>l", "vip:norm I- <CR>")
vim.keymap.set("v", "<leader>l", ":norm I- <CR>")

View file

@ -0,0 +1,5 @@
local opt = vim.opt_local
opt.cursorline = false
opt.number = true
opt.relativenumber = true

View file

@ -11,10 +11,3 @@ table.insert(sources, { name = "buffer" })
table.insert(sources, { name = "path" })
cmp.setup.buffer { sources = sources }
-- Convert lines into a list.
vim.keymap.set("n", "<leader>l", "vip:norm I* <CR>")
vim.keymap.set("v", "<leader>l", ":norm I* <CR>")
vim.keymap.set("n", "<leader>ta", '_iTextAnnotation "<Esc>A"<Esc>j')
vim.keymap.set("v", "<leader>ta", ':norm ITextAnnotation "<Esc>gv:norm A"<Esc>')

Some files were not shown because too many files have changed in this diff Show more