Compare commits
38 commits
2e4203b7e1
...
7a0588afd2
Author | SHA1 | Date | |
---|---|---|---|
7a0588afd2 | |||
b35b792cef | |||
675db09c39 | |||
420250037f | |||
0c4c5a0fa0 | |||
6a3d739322 | |||
f5cf3559e2 | |||
24d95b3e75 | |||
3240c35efb | |||
596cc1e2e7 | |||
7acfc92e7a | |||
622e85c129 | |||
e21105f241 | |||
81436b4192 | |||
![]() |
cf2f29a73f | ||
42bc948c3c | |||
8327f85db5 | |||
ec9cb51b00 | |||
030430becd | |||
e610efa978 | |||
8cbdeda943 | |||
1898aca426 | |||
![]() |
4749662b6a | ||
![]() |
441ba09c48 | ||
![]() |
62e086cf4a | ||
![]() |
53b4cc2ee5 | ||
![]() |
fb758ef3c4 | ||
![]() |
d425f537b5 | ||
![]() |
cffcd62b3c | ||
![]() |
9d6d46229a | ||
![]() |
82817412fc | ||
![]() |
c8ca72d834 | ||
![]() |
761c4e7c7d | ||
![]() |
0540b3d641 | ||
![]() |
29877e469d | ||
![]() |
1a2597de28 | ||
![]() |
25c07a884a | ||
![]() |
94b2c86208 |
59 changed files with 4118 additions and 563 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
build
|
||||
result
|
||||
*.qcow2
|
||||
homefree-image
|
||||
lan-client-image
|
||||
|
|
20
.sops.yaml
Normal file
20
.sops.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
# see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml
|
||||
keys:
|
||||
- &user_homefree 06321D7F20335A7E08595BA905D137EE114BA2C2
|
||||
- &server_homefree 0BC4F8FF51F3167F06683FFB19008821C072983E
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
- path_regex: secrets/homefree/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
63
README.md
63
README.md
|
@ -12,3 +12,66 @@ liberate you from giant cloud providers.
|
|||
― Neal Stephenson, The Diamond Age: Or, a Young Lady's Illustrated Primer
|
||||
|
||||
## Don't suckle the Feed. Cultivate the Seed.
|
||||
|
||||
## Installing
|
||||
|
||||
Install NixOS directly, or use a deployment system such as [NixOS Anywhere](https://github.com/nix-community/nixos-anywhere)
|
||||
|
||||
Update system's configuration to look like something in [example-flake.nix](./example-flake.nix)
|
||||
|
||||
Configure system by setting up values as defined in the [HomeFree module](./module.nix)
|
||||
|
||||
## Adding a secret
|
||||
|
||||
```
|
||||
nix-shell -p sops --run "sops secrets/authentik.yaml"
|
||||
```
|
||||
|
||||
Then add a key or keys, e.g.
|
||||
|
||||
```
|
||||
env-vars: |
|
||||
VAR1 = abc
|
||||
VAR2 = def
|
||||
```
|
||||
|
||||
Then reference in Nix config as follows:
|
||||
|
||||
```
|
||||
config.sops.secrets.app.env-vars.path
|
||||
```
|
||||
|
||||
Or point directly to the path, e.g.
|
||||
```
|
||||
sops.secrets."app" = {
|
||||
owner = "homefree";
|
||||
path = "/run/secrets/app/env-vars";
|
||||
restartUnits = [ "app.service" ];
|
||||
};
|
||||
```
|
||||
and reference the path in config
|
||||
|
||||
## Getting server key
|
||||
|
||||
After starting the vm using `make run`, run `make generate-sops-config`
|
||||
|
||||
Then, within the VM:
|
||||
|
||||
```
|
||||
cd ~/nixcfg
|
||||
make build
|
||||
```
|
||||
|
||||
## Initializing Authentik
|
||||
|
||||
Browse to:
|
||||
|
||||
http://ha.homefree.lan:9000/if/flow/initial-setup/
|
||||
|
||||
## Changing password for Authentik
|
||||
|
||||
ak create_recovery_key 10 akadmin
|
||||
|
||||
## Setting up HAProxy to transparently proxy TSL requests to Caddy
|
||||
|
||||
https://forum.opnsense.org/index.php?topic=18538.msg84958#msg84958
|
||||
|
|
84
TODOS.md
84
TODOS.md
|
@ -1,84 +0,0 @@
|
|||
TODOS
|
||||
=====
|
||||
|
||||
* setup VLANs
|
||||
* https://wiki.nftables.org/wiki-nftables/index.php/Main_Page
|
||||
* https://serverfault.com/questions/858556/transparent-firewall-with-nftables-and-vlans
|
||||
* https://serverfault.com/questions/1057819/route-untagged-vlan-to-a-tagged-vlan-with-nftables
|
||||
* setup ipv6
|
||||
* Make a flake that sets up host machine for dev
|
||||
* Figure out how to use host id_rsa.pub in build, rather than hard-coded key
|
||||
* maybe share ~/.ssh/ida_rsa.pub into machine? would cause problems if share failed
|
||||
* Determine if there are any problems with disabling "wait for network" to get rid of error
|
||||
* Look into microvm instead of qemu, which has been difficult to work with
|
||||
* https://github.com/astro/microvm.nix
|
||||
* setup DNSSEC for dnsmasq, IPV6
|
||||
* https://blog.josefsson.org/2015/10/26/combining-dnsmasq-and-unbound/
|
||||
|
||||
### Solutions
|
||||
* Firewall
|
||||
* https://www.jjpdev.com/posts/home-router-nixos/
|
||||
* NAS
|
||||
* https://github.com/reckenrode/nixos-configs/tree/c556206df2611af2f9ea83954aae1b51461e44c5/hosts/x86_64-linux/meteion
|
||||
* https://www.reddit.com/r/NixOS/comments/yr21p1/offtheshelf_nas_supporting_nixos/
|
||||
* reverse proxy
|
||||
* Traefik
|
||||
* HAProxy
|
||||
* nginx-proxy-manager
|
||||
* caddy
|
||||
* ad block
|
||||
* Unbound
|
||||
* AdGuard
|
||||
* PiHole
|
||||
* intrusion protection
|
||||
* https://www.redhat.com/sysadmin/security-intrusion-detection
|
||||
* fail2ban
|
||||
* Suricata
|
||||
* OSSEC-HIDS
|
||||
* Snort
|
||||
* Zeek
|
||||
* Tripwire
|
||||
* certs
|
||||
* certbot
|
||||
* caddy
|
||||
* SSO
|
||||
* https://github.com/greenpau/caddy-security
|
||||
* authentik
|
||||
* authelia
|
||||
* keycloak
|
||||
* VPN
|
||||
* Tailscale/Headscale
|
||||
* https://tailscale.com/kb/1136/tailnet
|
||||
* https://github.com/tailscale/golink
|
||||
* https://github.com/tailscale-dev/tclip
|
||||
* wireguard
|
||||
* openvpn
|
||||
* Backup
|
||||
* bacula
|
||||
* kopia
|
||||
* restic
|
||||
* Hypervisor
|
||||
* https://vpsadminos.org/
|
||||
|
||||
### VyOS comparison
|
||||
|
||||
* Netfiter - does it use nftables? How does its config language map to Netfilter? Can it be extracted?
|
||||
* FRR - high performance IP routing suite - any use for this in a home router?
|
||||
* strongSwan - IPsec VPN. IPsec is slower than Wireguard but clients are built into OSes
|
||||
* Acel-PPP - VPN/tunnel server for PPPoE, PPtP, L2TPv2, SSTP, IPoE
|
||||
* FastNetMon - DDoS detection
|
||||
* Squid - caching proxy
|
||||
* PowerDNS - commercial grade DNS server
|
||||
|
||||
### DONE
|
||||
|
||||
* Setup host so default network virbr0 starts at boot
|
||||
* currently need to us "sudo virsh net-start --network default"
|
||||
* Does hardware-configuration.nix root disk device need to be updated with each build?
|
||||
* Get VM starting from command line
|
||||
* Figure out way to setup SSH without needing to lookup IP in virt-manager
|
||||
* Use user network, map SSH to unused port
|
||||
* https://unix.stackexchange.com/questions/489891/qemu-access-guest-vm-from-the-host-machine
|
||||
* better though would be to add hostname, e.g. homefree-vm
|
||||
* Share folder automatically setup by qemu xml?
|
||||
* https://www.debugpoint.com/share-folder-virt-manager/
|
|
@ -12,8 +12,8 @@ build_image() {
|
|||
HOST=$1
|
||||
nix build .#nixosConfigurations.${HOST}.config.formats.qcow
|
||||
mkdir -p ./build
|
||||
mv ./result ./${HOST}.qcow2
|
||||
rsync -L ./${HOST}.qcow2 ./build/${HOST}.qcow2
|
||||
mv ./result ./${HOST}-image
|
||||
rsync -L ./${HOST}-image/nixos.qcow2 ./build/${HOST}.qcow2
|
||||
chmod 750 ./build/${HOST}.qcow2
|
||||
}
|
||||
|
||||
|
|
15
default.nix
15
default.nix
|
@ -1,6 +1,17 @@
|
|||
{ ...}:
|
||||
{ homefree-inputs, ... }:
|
||||
{
|
||||
_module.args.homefree-inputs = homefree-inputs;
|
||||
|
||||
imports = [
|
||||
./configuration.nix
|
||||
homefree-inputs.nixos-generators.nixosModules.all-formats
|
||||
homefree-inputs.nixos-hardware.nixosModules.common-cpu-intel
|
||||
homefree-inputs.nixos-hardware.nixosModules.common-pc-laptop
|
||||
homefree-inputs.disko.nixosModules.disko
|
||||
homefree-inputs.sops-nix.nixosModules.sops
|
||||
homefree-inputs.authentik-nix.nixosModules.default
|
||||
homefree-inputs.nixvim.nixosModules.nixvim
|
||||
./modules/ddclient-multi.nix
|
||||
./module.nix
|
||||
./hosts/homefree/configuration.nix
|
||||
];
|
||||
}
|
||||
|
|
32
example-system-flake.nix
Normal file
32
example-system-flake.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
description = "HomeFree Instance";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
|
||||
homefree.url = "github:erahhal/HomeFree";
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
...
|
||||
}@inputs:
|
||||
{
|
||||
nixosConfigurations = {
|
||||
homefree =
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
in
|
||||
inputs.nixpkgs.lib.nixosSystem {
|
||||
system = system;
|
||||
modules = [
|
||||
inputs.homefree.nixosModules.default
|
||||
];
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit system;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
608
flake.lock
generated
608
flake.lock
generated
|
@ -3,17 +3,17 @@
|
|||
"adblock-unbound": {
|
||||
"inputs": {
|
||||
"adblockStevenBlack": "adblockStevenBlack",
|
||||
"flake-utils": "flake-utils",
|
||||
"lancache-domains": "lancache-domains",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1688055723,
|
||||
"narHash": "sha256-8WtkSAr4qYA3o6kiOCESK3rHJmIsa6TMBrT3/Cbfvro=",
|
||||
"lastModified": 1704832551,
|
||||
"narHash": "sha256-6xS/ANMIh3b4Ia3Ubl9rtb3LVw9QldihnP3IvuG9zwQ=",
|
||||
"owner": "MayNiklas",
|
||||
"repo": "nixos-adblock-unbound",
|
||||
"rev": "9356ccd526fdcf91bfee7f0ebebae831349d43cc",
|
||||
"rev": "a5d3731836b1c2ca65834e07be03c02daca5b434",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -38,56 +38,172 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"agenix": {
|
||||
"authentik-nix": {
|
||||
"inputs": {
|
||||
"darwin": "darwin",
|
||||
"home-manager": "home-manager",
|
||||
"authentik-src": "authentik-src",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-parts": "flake-parts",
|
||||
"flake-utils": "flake-utils",
|
||||
"napalm": "napalm",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"poetry2nix": "poetry2nix",
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703433843,
|
||||
"narHash": "sha256-nmtA4KqFboWxxoOAA6Y1okHbZh+HsXaMPFkYHsoDRDw=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "417caa847f9383e111d1397039c9d4337d024bf0",
|
||||
"lastModified": 1730763915,
|
||||
"narHash": "sha256-+UPc6ZJHWJ9fQFAeqSqsQDCFDIXT+f3HiIOnHFIyrig=",
|
||||
"owner": "erahhal",
|
||||
"repo": "authentik-nix",
|
||||
"rev": "daba454bd25cea9796e525d225f06fb0782abba6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"owner": "erahhal",
|
||||
"ref": "no-docs",
|
||||
"repo": "authentik-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"authentik-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1730315123,
|
||||
"narHash": "sha256-UYOdBlkGeIGCG/pCGLANWv1bKTdBEUp6jTiLG7BpY7E=",
|
||||
"owner": "goauthentik",
|
||||
"repo": "authentik",
|
||||
"rev": "e8b5e4c1272151f4a3666e53754f7deefb8e2fb3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "goauthentik",
|
||||
"ref": "version/2024.8.4",
|
||||
"repo": "authentik",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devshell": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1700795494,
|
||||
"narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
|
||||
"lastModified": 1728330715,
|
||||
"narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"ref": "master",
|
||||
"repo": "nix-darwin",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731274291,
|
||||
"narHash": "sha256-cZ0QMpv5p2a6WEE+o9uu0a4ma6RzQDOQTbm7PbixWz8=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "486250f404f4a4f4f33f8f669d83ca5f6e6b7dfc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"revCount": 57,
|
||||
"type": "tarball",
|
||||
"url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726153070,
|
||||
"narHash": "sha256-HO4zgY0ekfwO5bX0QH/3kJ/h4KvUDFZg8YpkNwIbg1U=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "bcef6817a8b2aa20a5a6dbb19b43e63c5bf8619a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730504689,
|
||||
"narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "506278e768c2a08bec68eb62932193e341f55c90",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": [
|
||||
"authentik-nix",
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -96,19 +212,89 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"nixvim",
|
||||
"flake-compat"
|
||||
],
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730302582,
|
||||
"narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703113217,
|
||||
"narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
|
||||
"lastModified": 1731235328,
|
||||
"narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
|
||||
"rev": "60bb110917844d354f3c18e05450606a435d2d10",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -117,17 +303,108 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"ixx": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"nixvim",
|
||||
"nuschtosSearch",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nuschtosSearch",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729958008,
|
||||
"narHash": "sha256-EiOq8jF4Z/zQe0QYVc3+qSKxRK//CFHMB84aYrYGwEs=",
|
||||
"owner": "NuschtOS",
|
||||
"repo": "ixx",
|
||||
"rev": "9fd01aad037f345350eab2cd45e1946cc66da4eb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NuschtOS",
|
||||
"ref": "v0.0.6",
|
||||
"repo": "ixx",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"lancache-domains": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1679999806,
|
||||
"narHash": "sha256-oDZ2pSf8IgofRS4HaRppGcd4kHQj48AC9dkS++avYy8=",
|
||||
"owner": "uklans",
|
||||
"repo": "cache-domains",
|
||||
"rev": "31b2ba1e0a7c419327cb97f589b508d78b9aecbf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "uklans",
|
||||
"repo": "cache-domains",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"napalm": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"authentik-nix",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"authentik-nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1725806412,
|
||||
"narHash": "sha256-lGZjkjds0p924QEhm/r0BhAxbHBJE1xMOldB/HmQH04=",
|
||||
"owner": "willibutz",
|
||||
"repo": "napalm",
|
||||
"rev": "b492440d9e64ae20736d3bec5c7715ffcbde83f5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "willibutz",
|
||||
"ref": "avoid-foldl-stack-overflow",
|
||||
"repo": "napalm",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730448474,
|
||||
"narHash": "sha256-qE/cYKBhzxHMtKtLK3hlSR3uzO1pWPGLrBuQK7r0CHc=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "683d0c4cd1102dcccfa3f835565378c7f3cbe05e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-editor": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1681140879,
|
||||
"narHash": "sha256-eyLPtopt7lRvmRDJx7gSBYUtYGfOSVXarf0KbLbw/Sw=",
|
||||
"lastModified": 1703105021,
|
||||
"narHash": "sha256-Ne9NG7x45a8aJyAN+yYWbr/6mQHBVVkwZZ72EZHHRqw=",
|
||||
"owner": "vlinkz",
|
||||
"repo": "nix-editor",
|
||||
"rev": "ab2a7e94ca176589c1e8236ce31cd89044e4818f",
|
||||
"rev": "b5017f8d61753ce6a3a1a2aa7e474d59146a8ae3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -136,13 +413,35 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"authentik-nix",
|
||||
"poetry2nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1703863825,
|
||||
"narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixlib": {
|
||||
"locked": {
|
||||
"lastModified": 1693701915,
|
||||
"narHash": "sha256-waHPLdDYUOHSEtMKKabcKIMhlUOHPOOPQ9UyFeEoovs=",
|
||||
"lastModified": 1729990941,
|
||||
"narHash": "sha256-hUP9oxmnOmNnKcDOf5Y55HQ+NnoT0+bLWHLQWLLw9Ks=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "f5af57d3ef9947a70ac86e42695231ac1ad00c25",
|
||||
"rev": "7d68864343650322045894951602d6e82b5296d7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -159,11 +458,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1696058303,
|
||||
"narHash": "sha256-eNqKWpF5zG0SrgbbtljFOrRgFgRzCc4++TMFADBMLnc=",
|
||||
"lastModified": 1731341898,
|
||||
"narHash": "sha256-2L34Jrd73o6q6t8xMVVK7cj4qk5uHYbSIh72qtIKWWs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixos-generators",
|
||||
"rev": "150f38bd1e09e20987feacb1b0d5991357532fb5",
|
||||
"rev": "3a5bf194b6b25ee27a2c61afed039f3cb3a0fbfc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -174,11 +473,11 @@
|
|||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1700559156,
|
||||
"narHash": "sha256-gL4epO/qf+wo30JjC3g+b5Bs8UrpxzkhNBBsUYxpw2g=",
|
||||
"lastModified": 1731332224,
|
||||
"narHash": "sha256-0ctfVp27ingWtY7dbP5+QpSQ98HaOZleU0teyHQUAw0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "c3abafb01cd7045dba522af29b625bd1e170c2fb",
|
||||
"rev": "184687ae1a3139faa4746168baf071f60d0310c8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -190,11 +489,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1703013332,
|
||||
"narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
|
||||
"lastModified": 1726937504,
|
||||
"narHash": "sha256-bvGoiQBvponpZh8ClUcmJ6QnsNKw0EMrCQJARK3bI1c=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
|
||||
"rev": "9357f4f23713673f310988025d9dc261c20e70c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -204,49 +503,30 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1725233747,
|
||||
"narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1705033721,
|
||||
"narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=",
|
||||
"lastModified": 1730602179,
|
||||
"narHash": "sha256-efgLzQAWSzJuCLiCaQUCDu4NudNlHdg2NzGLX5GYaEY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea",
|
||||
"rev": "3c2f1c4ca372622cb2f9de8016c9a0b1cbd0f37c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-23.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-trunk": {
|
||||
"locked": {
|
||||
"lastModified": 1700973916,
|
||||
"narHash": "sha256-4W1xIjy67P/8ZcZMZxysTNgjNu9G8DegkI4ac+cnRYY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1744e3fa0103321e7d21d6b907eeff6965adf964",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1700794826,
|
||||
"narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "release-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
|
@ -269,27 +549,27 @@
|
|||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1700787330,
|
||||
"narHash": "sha256-4VIBCyfqnEsdVP/SgKZ3rudwzxGdEqpKfgoWETs/I6k=",
|
||||
"lastModified": 1731139594,
|
||||
"narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7f7851dfc570812c305d89438681b715a4f7beba",
|
||||
"rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.11",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1704842529,
|
||||
"narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=",
|
||||
"lastModified": 1730272153,
|
||||
"narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5",
|
||||
"rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -299,16 +579,98 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixvim": {
|
||||
"inputs": {
|
||||
"devshell": "devshell",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"git-hooks": "git-hooks",
|
||||
"home-manager": "home-manager",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nuschtosSearch": "nuschtosSearch",
|
||||
"treefmt-nix": "treefmt-nix_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731356813,
|
||||
"narHash": "sha256-w0TJwJwZd9so/chWYFFEtOQdnXTCvmNXIHs1FWJDlMM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixvim",
|
||||
"rev": "c892aa20732f982d4cc2b3ef2e2276a2a9a4d45b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixvim",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nuschtosSearch": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"ixx": "ixx",
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731347683,
|
||||
"narHash": "sha256-BcSWCEUBShuB32LPif+EG0XGXyUi2jyjCSpGE1rbOws=",
|
||||
"owner": "NuschtOS",
|
||||
"repo": "search",
|
||||
"rev": "135d202e032be70c93b6d7d53592ef4799d6efde",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NuschtOS",
|
||||
"repo": "search",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"poetry2nix": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"authentik-nix",
|
||||
"flake-utils"
|
||||
],
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixpkgs": [
|
||||
"authentik-nix",
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"authentik-nix",
|
||||
"systems"
|
||||
],
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727169160,
|
||||
"narHash": "sha256-m/3tT0Wvk2V4H15riZC/yT7i7t+8V58HTDpthKV5yhk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "poetry2nix",
|
||||
"rev": "7624b3e0275d9b52dbdda46ef7ffee66b36ff823",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "poetry2nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"adblock-unbound": "adblock-unbound",
|
||||
"agenix": "agenix",
|
||||
"authentik-nix": "authentik-nix",
|
||||
"disko": "disko",
|
||||
"nix-editor": "nix-editor",
|
||||
"nixos-generators": "nixos-generators",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs-trunk": "nixpkgs-trunk",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"nixvim": "nixvim",
|
||||
"sops-nix": "sops-nix"
|
||||
}
|
||||
},
|
||||
|
@ -318,11 +680,11 @@
|
|||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705201153,
|
||||
"narHash": "sha256-y0/a4IMDZrc7lAkR7Gcm5R3W2iCBiARHnYZe6vkmiNE=",
|
||||
"lastModified": 1731364708,
|
||||
"narHash": "sha256-HC0anOL+KmUQ2hdRl0AtunbAckasxrkn4VLmxbW/WaA=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "70dd0d521f7849338e487a219c1a07c429a66d77",
|
||||
"rev": "4c91d52db103e757fc25b58998b0576ae702d659",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -332,6 +694,21 @@
|
|||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1689347949,
|
||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default-linux",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
|
@ -346,6 +723,49 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"authentik-nix",
|
||||
"poetry2nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1719749022,
|
||||
"narHash": "sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730321837,
|
||||
"narHash": "sha256-vK+a09qq19QNu2MlLcvN4qcRctJbqWkX7ahgPZ/+maI=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "746901bb8dba96d154b66492a29f5db0693dbfcc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"locked": {
|
||||
"lastModified": 1667395993,
|
||||
|
|
92
flake.nix
92
flake.nix
|
@ -2,17 +2,20 @@
|
|||
description = "HomeFree Self-Hosting Platform";
|
||||
|
||||
inputs = {
|
||||
# Use stable for main
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
|
||||
|
||||
# Trails trunk - latest packages with broken commits filtered out
|
||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
# Very latest packages - some commits broken
|
||||
nixpkgs-trunk.url = "github:NixOS/nixpkgs";
|
||||
# nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
|
||||
disko.url = "github:nix-community/disko";
|
||||
disko.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
nixvim = {
|
||||
# url = "github:nix-community/nixvim/nixos-24.05";
|
||||
url = "github:nix-community/nixvim";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
nixos-generators = {
|
||||
url = "github:nix-community/nixos-generators";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
@ -20,8 +23,6 @@
|
|||
|
||||
nix-editor.url = "github:vlinkz/nix-editor";
|
||||
|
||||
agenix.url = "github:ryantm/agenix";
|
||||
|
||||
sops-nix.url = "github:Mic92/sops-nix";
|
||||
|
||||
adblock-unbound = {
|
||||
|
@ -29,6 +30,18 @@
|
|||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
authentik-nix = {
|
||||
# url = "github:nix-community/authentik-nix/version/2024.8.3";
|
||||
# url = "github:nix-community/authentik-nix";
|
||||
url = "github:erahhal/authentik-nix/no-docs";
|
||||
## optional overrides. Note that using a different version of nixpkgs can cause issues, especially with python dependencies
|
||||
# inputs.flake-parts.follows = "flake-parts";
|
||||
};
|
||||
|
||||
styx = {
|
||||
url = "github:styx-static/styx";
|
||||
};
|
||||
|
||||
# notnft = {
|
||||
# url = "github:chayleaf/notnft";
|
||||
# inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
@ -40,56 +53,33 @@
|
|||
# };
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixos-generators,
|
||||
nixos-hardware,
|
||||
nixpkgs,
|
||||
agenix,
|
||||
sops-nix,
|
||||
...
|
||||
}@inputs:
|
||||
outputs = { self, ... } @ inputs:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
# Can't use name "inputs" as it gets overridden by parent flakes that define inputs.nixpkgs.lib.nixosSystem
|
||||
homefree-inputs = inputs;
|
||||
# versionInfo = import ./version.nix;
|
||||
# version = versionInfo.version + (inputs.nixpkgs.lib.optionalString (!versionInfo.released) "-dirty");
|
||||
in
|
||||
{
|
||||
nixosModules = rec {
|
||||
homefree = import ./default.nix { inherit homefree-inputs; inherit system; };
|
||||
imports = [ ];
|
||||
default = homefree;
|
||||
lan-client = import ./lan-client.nix { inherit homefree-inputs; inherit system; };
|
||||
};
|
||||
nixosConfigurations = {
|
||||
homefree =
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
in
|
||||
inputs.nixpkgs.lib.nixosSystem {
|
||||
homefree-test = inputs.nixpkgs.lib.nixosSystem {
|
||||
system = system;
|
||||
modules = [
|
||||
nixos-hardware.nixosModules.common-cpu-intel
|
||||
nixos-hardware.nixosModules.common-pc-laptop
|
||||
agenix.nixosModules.default
|
||||
sops-nix.nixosModules.sops
|
||||
# inputs.nixos-router.nixosModules.default
|
||||
# inputs.notnft.lib.${system}
|
||||
|
||||
(import ./hosts/homefree/configuration.nix)
|
||||
self.nixosModules.homefree
|
||||
];
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit system;
|
||||
inherit agenix;
|
||||
inherit sops-nix;
|
||||
};
|
||||
};
|
||||
lan-client =
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
in
|
||||
inputs.nixpkgs.lib.nixosSystem {
|
||||
lan-client = inputs.nixpkgs.lib.nixosSystem {
|
||||
system = system;
|
||||
modules = [
|
||||
nixos-hardware.nixosModules.common-cpu-intel
|
||||
nixos-hardware.nixosModules.common-pc-laptop
|
||||
|
||||
(import ./hosts/lan-client/configuration.nix)
|
||||
self.nixosModules.lan-client
|
||||
];
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit system;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
23
generate-sops-config-host.sh
Executable file
23
generate-sops-config-host.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## Import the user's SSH key into GPG
|
||||
|
||||
cp ~/.ssh/id_rsa /tmp/id_rsa
|
||||
ssh-keygen -p -N "" -f /tmp/id_rsa
|
||||
USER_GPG_FINGERPRINT=$(nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh-to-pgp -private-key -i /tmp/id_rsa | gpg --import --quiet" 2>&1)
|
||||
echo "${USER_GPG_FINGERPRINT}"
|
||||
rm /tmp/id_rsa
|
||||
# set ultimate trust level
|
||||
# nix-shell --quiet -p gnupg --run "echo -e 'trust\n5\ny\n' | gpg --command-fd 0 --edit-key ${USER_GPG_FINGERPRINT}"
|
||||
nix-shell --quiet -p gnupg --run "echo \"${USER_GPG_FINGERPRINT}:6:\" | gpg --import-ownertrust"
|
||||
|
||||
## Import the homefree host SSH key into GPG
|
||||
|
||||
# remove key from known_hosts
|
||||
ssh-keygen -R "[localhost]:2223"
|
||||
# Get GPG fingerprint of server RSA key
|
||||
SERVER_GPG_FINGERPRINT=$(nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh -o LogLevel=ERROR -o StrictHostKeychecking=no -p 2223 homefree@localhost \"sudo cat /etc/ssh/ssh_host_rsa_key\" | ssh-to-pgp -private-key | gpg --import --allow-non-selfsigned-uid --quiet" 2>&1 | head -n 1)
|
||||
echo "${SERVER_GPG_FINGERPRINT}"
|
||||
# set ultimate trust level
|
||||
nix-shell --quiet -p gnupg --run "echo \"${SERVER_GPG_FINGERPRINT}:6:\" | gpg --import-ownertrust"
|
||||
|
52
generate-sops-config-old.sh
Executable file
52
generate-sops-config-old.sh
Executable file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## Import the user's SSH key into GPG
|
||||
|
||||
cp ~/.ssh/id_rsa /tmp/id_rsa
|
||||
ssh-keygen -p -N "" -f /tmp/id_rsa
|
||||
USER_GPG_FINGERPRINT=$(nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh-to-pgp -private-key -i /tmp/id_rsa | gpg --import --quiet" 2>&1)
|
||||
echo "${USER_GPG_FINGERPRINT}"
|
||||
rm /tmp/id_rsa
|
||||
# set ultimate trust level
|
||||
# nix-shell --quiet -p gnupg --run "echo -e 'trust\n5\ny\n' | gpg --command-fd 0 --edit-key ${USER_GPG_FINGERPRINT}"
|
||||
nix-shell --quiet -p gnupg --run "echo \"${USER_GPG_FINGERPRINT}:6:\" | gpg --import-ownertrust"
|
||||
|
||||
## Import the homefree host SSH key into GPG
|
||||
|
||||
# remove key from known_hosts
|
||||
ssh-keygen -R "[localhost]:2223"
|
||||
# Get GPG fingerprint of server RSA key
|
||||
SERVER_GPG_FINGERPRINT=$(nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh -o LogLevel=ERROR -o StrictHostKeychecking=no -p 2223 homefree@localhost \"sudo cat /etc/ssh/ssh_host_rsa_key\" | ssh-to-pgp -private-key | gpg --import --allow-non-selfsigned-uid --quiet" 2>&1 | head -n 1)
|
||||
# set ultimate trust level
|
||||
nix-shell --quiet -p gnupg --run "echo \"${SERVER_GPG_FINGERPRINT}:6:\" | gpg --import-ownertrust"
|
||||
|
||||
# This example uses YAML anchors which allows reuse of multiple keys
|
||||
# without having to repeat yourself.
|
||||
# Also see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml
|
||||
# for a more complex example.
|
||||
cat > .sops.yaml << EOF
|
||||
# see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml
|
||||
keys:
|
||||
- &user_homefree $USER_GPG_FINGERPRINT
|
||||
- &server_homefree $SERVER_GPG_FINGERPRINT
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
- path_regex: secrets/homefree/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
EOF
|
||||
|
||||
for config in $(find secrets -name '*.yaml'); do
|
||||
nix-shell -p sops --run "sops updatekeys $config"
|
||||
done
|
58
generate-sops-config-server.sh
Executable file
58
generate-sops-config-server.sh
Executable file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
## @TODO: consolidate to single script that works on host or on guest
|
||||
## @TODO: If no user key on guest, complain and abort
|
||||
## @TODO: Fix error messages that mess with getting fingerprit
|
||||
## @TODO: Make sure uid matches <curruser>@localhost, as it tells sops where to look for keyring
|
||||
## https://www.reddit.com/r/GnuPG/comments/m76to1/is_there_a_way_to_change_the_name_on_a_key_pair/
|
||||
|
||||
## Import the user's SSH key into GPG
|
||||
|
||||
# cp ~/.ssh/id_rsa /tmp/id_rsa
|
||||
# ssh-keygen -p -N "" -f /tmp/id_rsa
|
||||
# USER_GPG_FINGERPRINT=$(nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh-to-pgp -private-key -i /tmp/id_rsa | gpg --import --allow-non-selfsigned-uid --quiet" 2>&1 | head -2 | tail -1)
|
||||
# echo "${USER_GPG_FINGERPRINT}"
|
||||
# rm /tmp/id_rsa
|
||||
# # set ultimate trust level
|
||||
# # nix-shell --quiet -p gnupg --run "echo -e 'trust\n5\ny\n' | gpg --command-fd 0 --edit-key ${USER_GPG_FINGERPRINT}"
|
||||
# nix-shell --quiet -p gnupg --run "echo \"${USER_GPG_FINGERPRINT}:6:\" | gpg --import-ownertrust"
|
||||
#
|
||||
# ## Import the homefree host SSH key into GPG
|
||||
#
|
||||
# # remove key from known_hosts
|
||||
# ssh-keygen -R "[localhost]:2223"
|
||||
# # Get GPG fingerprint of server RSA key
|
||||
# SERVER_GPG_FINGERPRINT=$(nix-shell --quiet -p gnupg -p ssh-to-pgp --run "sudo cat /etc/ssh/ssh_host_rsa_key | ssh-to-pgp -private-key | gpg --import --allow-non-selfsigned-uid --quiet" 2>&1 | head -2 | tail -1)
|
||||
# # set ultimate trust level
|
||||
# nix-shell --quiet -p gnupg --run "echo \"${SERVER_GPG_FINGERPRINT}:6:\" | gpg --import-ownertrust"
|
||||
#
|
||||
# # This example uses YAML anchors which allows reuse of multiple keys
|
||||
# # without having to repeat yourself.
|
||||
# # Also see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml
|
||||
# # for a more complex example.
|
||||
# cat > .sops.yaml << EOF
|
||||
# # see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml
|
||||
# keys:
|
||||
# - &user_homefree $USER_GPG_FINGERPRINT
|
||||
# - &server_homefree $SERVER_GPG_FINGERPRINT
|
||||
# creation_rules:
|
||||
# - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
# key_groups:
|
||||
# - pgp:
|
||||
# - *user_homefree
|
||||
# - *server_homefree
|
||||
# - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
# key_groups:
|
||||
# - pgp:
|
||||
# - *user_homefree
|
||||
# - *server_homefree
|
||||
# - path_regex: secrets/homefree/[^/]+\.(yaml|json|env|ini)$
|
||||
# key_groups:
|
||||
# - pgp:
|
||||
# - *user_homefree
|
||||
# - *server_homefree
|
||||
# EOF
|
||||
|
||||
for config in $(find secrets -name '*.yaml'); do
|
||||
nix-shell -p sops --run "sops updatekeys $config"
|
||||
done
|
|
@ -1,30 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
cp ~/.ssh/id_rsa /tmp/id_rsa
|
||||
ssh-keygen -p -N "" -f /tmp/id_rsa
|
||||
USER_GPG_FINGERPRINT=$(nix-shell -p gnupg -p ssh-to-pgp --run "ssh-to-pgp -private-key -i ~/.ssh/id_rsa | gpg --import --quiet" 2>&1)
|
||||
rm /tmp/id_rsa
|
||||
ssh -o LogLevel=ERROR -o StrictHostKeychecking=no -p 2223 homefree@localhost "mkdir -p ~/.ssh"
|
||||
scp -P 2223 ~/.ssh/id_rsa homefree@localhost:/home/homefree/.ssh/id_rsa
|
||||
scp -P 2223 ~/.ssh/id_rsa.pub homefree@localhost:/home/homefree/.ssh/id_rsa.pub
|
||||
|
||||
ssh-keygen -R "[localhost]:2223"
|
||||
SERVER_GPG_FINGERPRINT=$(ssh -o StrictHostKeychecking=no -p 2223 homefree@localhost "sudo cat /etc/ssh/ssh_host_rsa_key" | nix-shell -p ssh-to-pgp --run "ssh-to-pgp -o homefree.asc" 2>&1)
|
||||
ssh -o LogLevel=ERROR -o StrictHostKeychecking=no -p 2223 homefree@localhost "cd ~/nixcfg/HomeFree; ./generate-sops-config-server.sh"
|
||||
|
||||
# This example uses YAML anchors which allows reuse of multiple keys
|
||||
# without having to repeat yourself.
|
||||
# Also see https://github.com/Mic92/dotfiles/blob/master/nixos/.sops.yaml
|
||||
# for a more complex example.
|
||||
cat > .sops.yaml << EOF
|
||||
keys:
|
||||
- &user_homefree $USER_GPG_FINGERPRINT
|
||||
- &server_homefree $SERVER_GPG_FINGERPRINT
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
- path_regex: secrets/homefree/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *user_homefree
|
||||
- *server_homefree
|
||||
EOF
|
||||
./generate-sops-config-host.sh
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
{ inputs, ... }:
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
inputs.nixos-generators.nixosModules.all-formats
|
||||
../../profiles/agenix.nix
|
||||
../../profiles/adguardhome.nix
|
||||
../../profiles/authentik.nix
|
||||
../../profiles/common.nix
|
||||
../../profiles/config-editor.nix
|
||||
../../profiles/ddclient.nix
|
||||
../../profiles/dnsmasq.nix
|
||||
../../profiles/home-assistant
|
||||
../../profiles/git.nix
|
||||
../../profiles/gitea.nix
|
||||
../../profiles/hardware-configuration.nix
|
||||
../../profiles/hosting.nix
|
||||
../../profiles/nixvim.nix
|
||||
../../profiles/postgres.nix
|
||||
# ../../profiles/radvd.nix
|
||||
../../profiles/router.nix
|
||||
../../profiles/virtual-machine.nix
|
||||
../../profiles/traffic-shaping.nix
|
||||
../../profiles/unbound.nix
|
||||
../../profiles/unifi.nix
|
||||
../../profiles/vaultwarden.nix
|
||||
../../profiles/wireguard.nix
|
||||
];
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
@ -46,19 +58,20 @@
|
|||
# --------------------------------------------------------------------------------------
|
||||
|
||||
# @TODO: Make this UI configurable
|
||||
time.timeZone = "America/Los_Angeles";
|
||||
## Must be forced due to Authentik hard coding a value of UTC
|
||||
time.timeZone = lib.mkForce config.homefree.system.timeZone;
|
||||
|
||||
networking = {
|
||||
# @TODO: Make this UI configurable
|
||||
hostName = "homefree";
|
||||
hostName = config.homefree.system.hostName;
|
||||
## NetworkManager disabled in favor of networkd
|
||||
useNetworkd = true;
|
||||
wireless = {
|
||||
# Disable wpa_supplicant
|
||||
enable = false;
|
||||
};
|
||||
# wireless = {
|
||||
# # Disable wpa_supplicant
|
||||
# enable = false;
|
||||
# };
|
||||
interfaces = {
|
||||
ens3.useDHCP = true;
|
||||
"${config.homefree.network.wan-interface}".useDHCP = true;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
{ inputs, ... }:
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
inputs.nixos-generators.nixosModules.all-formats
|
||||
../../profiles/common.nix
|
||||
../../profiles/hardware-configuration.nix
|
||||
];
|
||||
|
|
4
import-ssh-keys-to-gpg.sh
Executable file
4
import-ssh-keys-to-gpg.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh-to-pgp -private-key -i ~/.ssh/id_rsa | gpg --import --quiet"
|
||||
nix-shell --quiet -p gnupg -p ssh-to-pgp --run "ssh -o StrictHostKeychecking=no -p 2223 homefree@localhost \"sudo cat /etc/ssh/ssh_host_rsa_key\" | ssh-to-pgp -private-key | gpg --import --quiet"
|
11
lan-client.nix
Normal file
11
lan-client.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{ homefree-inputs, system, ... }:
|
||||
{
|
||||
_module.args.homefree-inputs = homefree-inputs;
|
||||
|
||||
imports = [
|
||||
homefree-inputs.nixos-generators.nixosModules.all-formats
|
||||
homefree-inputs.nixos-hardware.nixosModules.common-cpu-intel
|
||||
homefree-inputs.nixos-hardware.nixosModules.common-pc-laptop
|
||||
./hosts/lan-client/configuration.nix
|
||||
];
|
||||
}
|
373
module.nix
Normal file
373
module.nix
Normal file
|
@ -0,0 +1,373 @@
|
|||
## @TODO: Look at the following for a VM test setup
|
||||
## https://github.com/nix-community/disko/blob/master/module.nix
|
||||
|
||||
{ config, lib, extendModules, ... }:
|
||||
|
||||
# let
|
||||
# vmVariantWithHomefree = extendModules {
|
||||
# modules = [
|
||||
# ./lib/interactive-vm.nix
|
||||
# ];
|
||||
# };
|
||||
# in
|
||||
{
|
||||
options.homefree = {
|
||||
system = {
|
||||
hostName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "homefree";
|
||||
description = "Hostname for the system";
|
||||
};
|
||||
|
||||
## @TODO: Detect during setup
|
||||
timeZone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "America/Los_Angeles";
|
||||
description = "Timezone for the system";
|
||||
};
|
||||
|
||||
## @TODO: Detect during setup
|
||||
defaultLocale = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "en_US.UTF-8";
|
||||
description = "Default locale for the system";
|
||||
};
|
||||
|
||||
localDomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
## @TODO: Should this be "local"?
|
||||
default = "localdomain";
|
||||
description = "local lan domain";
|
||||
};
|
||||
|
||||
## @TODO: Deduplicate this with localDomain
|
||||
## recursive?
|
||||
searchDomainsLocal = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
## @TODO: Should this be "local"?
|
||||
default = [ "localdomain" ];
|
||||
description = "Search domain for the system";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "homefree.host";
|
||||
description = "Domain for the system";
|
||||
};
|
||||
|
||||
additionalDomains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "Additional zones for the system";
|
||||
};
|
||||
|
||||
adminUsername = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "homefree";
|
||||
description = "Username for the system admin";
|
||||
};
|
||||
|
||||
adminHashedPassword = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Hashed password for the system admin
|
||||
Generate with:
|
||||
mkpasswd -m sha-512
|
||||
'';
|
||||
};
|
||||
|
||||
authorizedKeys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "SSH authorized keys for the system admin";
|
||||
};
|
||||
};
|
||||
|
||||
## @TODO: Add default subnet and gateway config, e.g. 10.0.0.0/24, 10.0.0.1
|
||||
## @TODO: This section doesn't make sense. Some network config is in "system" above
|
||||
## and some is in separate services, e.g. unbound and ddns
|
||||
network = {
|
||||
## @TODO: Detect during setup
|
||||
wan-interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ens3";
|
||||
description = "External interface to the internet";
|
||||
};
|
||||
|
||||
wan-bitrate-mbps-down = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "WAN download bitrate in Mbit/s";
|
||||
};
|
||||
|
||||
wan-bitrate-mbps-up = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "WAN upload bitrate in Mbit/s";
|
||||
};
|
||||
|
||||
## @TODO: Detect during setup
|
||||
lan-interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ens5";
|
||||
description = "Internal interface to the local network";
|
||||
};
|
||||
|
||||
static-ip-expiration = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "3d";
|
||||
description = "Expiration time of static IPs";
|
||||
};
|
||||
|
||||
static-ips = lib.mkOption {
|
||||
default = [];
|
||||
description = "Static IP mappings";
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = {
|
||||
mac-address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "MAC address to assign IP to";
|
||||
};
|
||||
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Hostname to assign to IP";
|
||||
};
|
||||
|
||||
ip = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "IP Address";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
## @TODO: Make type for dns override entry
|
||||
dns-overrides = lib.mkOption {
|
||||
description = "dns hostname to IP overrides";
|
||||
default = [];
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = {
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Hostname of override";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Domain of override";
|
||||
};
|
||||
|
||||
ip = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "IP Address";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
enable-adblock = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "enable ad blocking";
|
||||
};
|
||||
|
||||
blocked-domains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "list of domains to block";
|
||||
};
|
||||
};
|
||||
|
||||
dynamic-dns = {
|
||||
interval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "10m";
|
||||
description = "Interval for dynamic DNS client";
|
||||
};
|
||||
|
||||
usev4 = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "webv4, webv4=ipinfo.io/ip";
|
||||
description = "Use format for obtaining ipv4 for dynamic DNS client";
|
||||
};
|
||||
|
||||
usev6 = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "webv6, webv6=v6.ipinfo.io/ip";
|
||||
description = "Use format for obtaining ipv6 for dynamic DNS client";
|
||||
};
|
||||
|
||||
zones = lib.mkOption {
|
||||
description = "Dynamic DNS Zone Config";
|
||||
default = [];
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = {
|
||||
disable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "disable dynamic dns for zone";
|
||||
};
|
||||
|
||||
## @TODO: validate against network.domain and network.additionalDomains?
|
||||
zone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "homefree.host";
|
||||
description = "Zone for dynamic DNS client";
|
||||
};
|
||||
|
||||
protocol = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hetzner";
|
||||
description = "Protocol for dynamic DNS client";
|
||||
};
|
||||
|
||||
username = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "erahhal";
|
||||
description = "Username for dynamic DNS client";
|
||||
};
|
||||
|
||||
domains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "@" "*" "www" "dev" ];
|
||||
description = "Domains for dynamic DNS client";
|
||||
};
|
||||
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "String path to password file";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
wireguard = {
|
||||
listenPort = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 64210;
|
||||
description = "External listening port for clients";
|
||||
};
|
||||
peers = lib.mkOption {
|
||||
description = "List of wireguard peers";
|
||||
example = ''
|
||||
[
|
||||
# List of allowed peers.
|
||||
{ # Feel free to give a meaning full name
|
||||
# Public key of the peer (not a file path).
|
||||
publicKey = "{client public key}";
|
||||
# List of IPs assigned to this peer within the tunnel subnet. Used to configure routing.
|
||||
allowedIPs = [ "10.100.0.2/32" ];
|
||||
}
|
||||
{ # John Doe
|
||||
publicKey = "{john doe's public key}";
|
||||
allowedIPs = [ "10.100.0.3/32" ];
|
||||
}
|
||||
];
|
||||
'';
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Name of peer";
|
||||
};
|
||||
|
||||
publicKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Public key for peer";
|
||||
};
|
||||
|
||||
allowedIPs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "List of IPs assigned to this peer within the tunnel subnet. Used to configure routing.";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
proxied-hosts = lib.mkOption {
|
||||
description = "List of hosts on lan to proxy";
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = {
|
||||
label = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "label of proxy config";
|
||||
};
|
||||
|
||||
description = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "description of proxy config";
|
||||
};
|
||||
|
||||
subdomains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "list of subdomains";
|
||||
};
|
||||
|
||||
http-domains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "list of http domains";
|
||||
};
|
||||
|
||||
https-domains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = "list of https domains";
|
||||
};
|
||||
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "10.0.0.1";
|
||||
description = "host name or address of service to proxy";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "port of service on lan network";
|
||||
};
|
||||
|
||||
public = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to expose on WAN interface";
|
||||
};
|
||||
|
||||
ssl = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether upstream service is using TLS";
|
||||
};
|
||||
|
||||
ssl-no-verify = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to verify certificate of upstream service";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
# options.virtualisation.vmVariantWithHomefree = lib.mkOption {
|
||||
# description = ''
|
||||
# Machine configuration to be added for the vm script available at `.system.build.vmWithHomefree`.
|
||||
# '';
|
||||
# inherit (vmVariantWithHomefree) type;
|
||||
# default = { };
|
||||
# visible = "shallow";
|
||||
# };
|
||||
#
|
||||
# config = {
|
||||
# system.build = {
|
||||
# testVms = lib.mkDefault config.virtualisation.vmVariantWithHomefree.system.build.vmWithHomefree;
|
||||
# };
|
||||
# };
|
||||
}
|
275
modules/ddclient-multi.nix
Normal file
275
modules/ddclient-multi.nix
Normal file
|
@ -0,0 +1,275 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.services.ddclient-multi;
|
||||
boolToStr = bool: if bool then "yes" else "no";
|
||||
dataDir = "/var/lib/ddclient";
|
||||
StateDirectory = builtins.baseNameOf dataDir;
|
||||
RuntimeDirectory = StateDirectory;
|
||||
|
||||
configFile' = pkgs.writeText "ddclient.conf" (''
|
||||
# This file can be used as a template for configFile or is automatically generated by Nix options.
|
||||
cache=${dataDir}/ddclient.cache
|
||||
foreground=YES
|
||||
quiet=${boolToStr cfg.quiet}
|
||||
verbose=${boolToStr cfg.verbose}
|
||||
${lib.optionalString (cfg.use != "") "use=${cfg.use}"}
|
||||
${lib.optionalString (cfg.use == "" && cfg.usev4 != "") "usev4=${cfg.usev4}"}
|
||||
${lib.optionalString (cfg.use == "" && cfg.usev6 != "") "usev6=${cfg.usev6}"}
|
||||
|
||||
${cfg.extraConfig}
|
||||
'' + lib.concatMapStrings (zoneCfg: ''
|
||||
|
||||
login=${zoneCfg.username}
|
||||
password=${if zoneCfg.protocol == "nsupdate" then "/run/${RuntimeDirectory}/${zoneCfg.zone}/ddclient.key" else "@${zoneCfg.zone}_password_placeholder@"}
|
||||
protocol=${zoneCfg.protocol}
|
||||
ssl=${boolToStr zoneCfg.ssl}
|
||||
wildcard=YES
|
||||
${lib.optionalString (zoneCfg.script != "") "script=${zoneCfg.script}"}
|
||||
${lib.optionalString (zoneCfg.server != "") "server=${zoneCfg.server}"}
|
||||
${lib.optionalString (zoneCfg.extraConfig != "") zoneCfg.extraConfig}
|
||||
${lib.optionalString (zoneCfg.zone != "") "zone=${zoneCfg.zone}"}
|
||||
${lib.concatStringsSep "," zoneCfg.domains}
|
||||
'') (lib.filter (zone: zone.disable == false) cfg.zones));
|
||||
configFile = if (cfg.configFile != null) then cfg.configFile else configFile';
|
||||
|
||||
preStart = ''
|
||||
install --mode=600 --owner=$USER ${configFile} /run/${RuntimeDirectory}/ddclient.conf
|
||||
${lib.optionalString (cfg.configFile == null) (lib.concatMapStrings (zoneCfg:
|
||||
if (zoneCfg.protocol == "nsupdate") then ''
|
||||
install --mode=600 --owner=$USER ${zoneCfg.passwordFile} /run/${RuntimeDirectory}/${zoneCfg.zone}/ddclient.key
|
||||
'' else if (zoneCfg.passwordFile != null) then ''
|
||||
"${pkgs.replace-secret}/bin/replace-secret" "@${zoneCfg.zone}_password_placeholder@" "${zoneCfg.passwordFile}" "/run/${RuntimeDirectory}/ddclient.conf"
|
||||
'' else ''
|
||||
sed -i '/^password=@${zoneCfg.zone}_password_placeholder@$/d' /run/${RuntimeDirectory}/ddclient.conf
|
||||
'') cfg.zones)}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "ddclient-multi" "homeDir" ] "")
|
||||
(mkRemovedOptionModule [ "services" "ddclient-multi" "password" ] "Use services.ddclient-multi.passwordFile instead.")
|
||||
(mkRemovedOptionModule [ "services" "ddclient-multi" "ipv6" ] "")
|
||||
];
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
services.ddclient-multi = with lib.types; {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = bool;
|
||||
description = ''
|
||||
Whether to synchronise your machine's IP address with a dynamic DNS provider (e.g. dyndns.org).
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = package;
|
||||
default = pkgs.ddclient;
|
||||
defaultText = lib.literalExpression "pkgs.ddclient";
|
||||
description = ''
|
||||
The ddclient executable package run by the service.
|
||||
'';
|
||||
};
|
||||
|
||||
interval = mkOption {
|
||||
default = "10min";
|
||||
type = str;
|
||||
description = ''
|
||||
The interval at which to run the check and update.
|
||||
See {command}`man 7 systemd.time` for the format.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
default = null;
|
||||
type = nullOr path;
|
||||
description = ''
|
||||
Path to configuration file.
|
||||
When set this overrides the generated configuration from module options.
|
||||
'';
|
||||
example = "/root/nixos/secrets/ddclient.conf";
|
||||
};
|
||||
|
||||
quiet = mkOption {
|
||||
default = false;
|
||||
type = bool;
|
||||
description = ''
|
||||
Print no messages for unnecessary updates.
|
||||
'';
|
||||
};
|
||||
|
||||
use = lib.mkOption {
|
||||
default = "";
|
||||
type = str;
|
||||
description = ''
|
||||
Method to determine the IP address to send to the dynamic DNS provider.
|
||||
'';
|
||||
};
|
||||
|
||||
usev4 = lib.mkOption {
|
||||
default = "webv4, webv4=checkip.dyndns.com/, webv4-skip='Current IP Address: '";
|
||||
type = str;
|
||||
description = ''
|
||||
Method to determine the IPv4 address to send to the dynamic DNS provider. Only used if `use` is not set.
|
||||
'';
|
||||
};
|
||||
|
||||
usev6 = lib.mkOption {
|
||||
default = "webv6, webv6=checkipv6.dyndns.com/, webv6-skip='Current IP Address: '";
|
||||
type = str;
|
||||
description = ''
|
||||
Method to determine the IPv6 address to send to the dynamic DNS provider. Only used if `use` is not set.
|
||||
'';
|
||||
};
|
||||
|
||||
verbose = mkOption {
|
||||
default = false;
|
||||
type = bool;
|
||||
description = ''
|
||||
Print verbose information.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "";
|
||||
type = lines;
|
||||
description = ''
|
||||
Extra configuration. Contents will be added verbatim to the configuration file.
|
||||
|
||||
::: {.note}
|
||||
`daemon` should not be added here because it does not work great with the systemd-timer approach the service uses.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
zones = mkOption {
|
||||
default = [];
|
||||
description = ''
|
||||
Config per zone.
|
||||
'';
|
||||
type = with lib.types; listOf (submodule {
|
||||
options = rec {
|
||||
disable = mkOption {
|
||||
default = false;
|
||||
type = bool;
|
||||
description = ''
|
||||
Disable zone
|
||||
'';
|
||||
};
|
||||
|
||||
domains = mkOption {
|
||||
default = [ "" ];
|
||||
type = listOf str;
|
||||
description = ''
|
||||
Domain name(s) to synchronize.
|
||||
'';
|
||||
};
|
||||
|
||||
username = mkOption {
|
||||
# For `nsupdate` username contains the path to the nsupdate executable
|
||||
default = lib.optionalString (protocol == "nsupdate") "${pkgs.bind.dnsutils}/bin/nsupdate";
|
||||
defaultText = "";
|
||||
type = str;
|
||||
description = ''
|
||||
User name.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
default = null;
|
||||
type = nullOr str;
|
||||
description = ''
|
||||
A file containing the password or a TSIG key in named format when using the nsupdate protocol.
|
||||
'';
|
||||
};
|
||||
|
||||
protocol = mkOption {
|
||||
default = "dyndns2";
|
||||
type = str;
|
||||
description = ''
|
||||
Protocol to use with dynamic DNS provider (see https://ddclient.net/protocols.html ).
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
default = "";
|
||||
type = str;
|
||||
description = ''
|
||||
Server address.
|
||||
'';
|
||||
};
|
||||
|
||||
ssl = mkOption {
|
||||
default = true;
|
||||
type = bool;
|
||||
description = ''
|
||||
Whether to use SSL/TLS to connect to dynamic DNS provider.
|
||||
'';
|
||||
};
|
||||
|
||||
script = mkOption {
|
||||
default = "";
|
||||
type = str;
|
||||
description = ''
|
||||
script as required by some providers.
|
||||
'';
|
||||
};
|
||||
|
||||
zone = mkOption {
|
||||
default = "";
|
||||
type = str;
|
||||
description = ''
|
||||
zone as required by some providers.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "";
|
||||
type = lines;
|
||||
description = ''
|
||||
Extra configuration for zone. Contents will be added verbatim to the zone-specific config.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.ddclient-multi.enable {
|
||||
systemd.services.ddclient-multi = {
|
||||
description = "Dynamic DNS Client";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
restartTriggers = optional (cfg.configFile != null) cfg.configFile;
|
||||
path = lib.optional (lib.hasPrefix "if," cfg.use) pkgs.iproute2;
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
RuntimeDirectoryMode = "0700";
|
||||
inherit RuntimeDirectory;
|
||||
inherit StateDirectory;
|
||||
Type = "oneshot";
|
||||
ExecStartPre = [ "!${pkgs.writeShellScript "ddclient-prestart" preStart}" ];
|
||||
ExecStart = "${lib.getExe cfg.package} -file /run/${RuntimeDirectory}/ddclient.conf";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.ddclient-multi = {
|
||||
description = "Run ddclient";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.interval;
|
||||
OnUnitInactiveSec = cfg.interval;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
158
profiles/adguardhome.nix
Normal file
158
profiles/adguardhome.nix
Normal file
|
@ -0,0 +1,158 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# Ad blocking
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
services.adguardhome = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
port = 3000;
|
||||
settings = {
|
||||
http = {
|
||||
address = "0.0.0.0:3000";
|
||||
session_ttl = "720h";
|
||||
};
|
||||
users = [
|
||||
{
|
||||
name = config.homefree.system.adminUsername;
|
||||
password = "$2a$10$Tt4QvbLQxnspv2TbcLMP7ug8eJ0NqMsGyVPbpEqtmkyCVrFpvh4GS";
|
||||
# password = config.homefree.system.adminHashedPassword;
|
||||
}
|
||||
];
|
||||
auth_attempts = 5;
|
||||
block_auth_min = 15;
|
||||
theme = "auto";
|
||||
dns = {
|
||||
bind_hosts = [ "0.0.0.0" ];
|
||||
port = 53;
|
||||
anonymize_client_ip = false;
|
||||
ratelimit = 20;
|
||||
ratelimit_subnet_len_ipv4 = 24;
|
||||
ratelimit_subnet_len_ipv6 = 56;
|
||||
ratelimit_whitelist = [];
|
||||
refuse_any = true;
|
||||
upstream_dns = [
|
||||
"10.0.0.1:53530"
|
||||
# "https://dns10.quad9.net/dns-query"
|
||||
];
|
||||
bootstrap_dns = [
|
||||
"9.9.9.10"
|
||||
"149.112.112.10"
|
||||
"2620:fe::10"
|
||||
"2620:fe::fe:10"
|
||||
];
|
||||
upstream_mode = "load_balance";
|
||||
fastest_timeout = "1s";
|
||||
blocked_hosts = [
|
||||
"version.bind"
|
||||
"id.server"
|
||||
"hostname.bind"
|
||||
];
|
||||
trusted_proxies = [
|
||||
"127.0.0.0/8"
|
||||
"::1/128"
|
||||
];
|
||||
cache_size = 4194304;
|
||||
cache_ttl_min = 0;
|
||||
cache_ttl_max = 0;
|
||||
cache_optimistic = false;
|
||||
aaaa_disabled = false;
|
||||
enable_dnssec = false;
|
||||
edns_client_subnet = {
|
||||
custom_ip = "";
|
||||
enabled = false;
|
||||
use_custom = false;
|
||||
};
|
||||
max_goroutines = 300;
|
||||
handle_ddr = true;
|
||||
ipset = [];
|
||||
ipset_file = "";
|
||||
bootstrap_prefer_ipv6 = false;
|
||||
upstream_timeout = "10s";
|
||||
private_networks = [];
|
||||
use_private_ptr_resolvers = true;
|
||||
local_ptr_upstreams = [];
|
||||
use_dns64 = false;
|
||||
dns64_prefixes = [];
|
||||
serve_http3 = false;
|
||||
use_http3_upstreams = false;
|
||||
serve_plain_dns = true;
|
||||
hostsfile_enabled = true;
|
||||
};
|
||||
filters = [
|
||||
{
|
||||
enabled = true;
|
||||
url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt";
|
||||
name = "AdGuard DNS filter";
|
||||
id = 1;
|
||||
}
|
||||
{
|
||||
enabled = false;
|
||||
url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt";
|
||||
name = "AdAway Default Blocklist";
|
||||
id = 2;
|
||||
}
|
||||
];
|
||||
whitelist_filters = [];
|
||||
user_rules = [];
|
||||
dhcp = {
|
||||
enabled = false;
|
||||
};
|
||||
filtering = {
|
||||
blocking_ipv4 = "";
|
||||
blocking_ipv6 = "";
|
||||
blocked_services = {
|
||||
schedule = {
|
||||
time_zone = "Local";
|
||||
};
|
||||
ids = [];
|
||||
};
|
||||
protection_disabled_until = null;
|
||||
safe_search = {
|
||||
enabled = false;
|
||||
bing = true;
|
||||
duckduckgo = true;
|
||||
google = true;
|
||||
pixabay = true;
|
||||
yandex = true;
|
||||
youtube = true;
|
||||
};
|
||||
blocking_mode = "default";
|
||||
parental_block_host = "family-block.dns.adguard.com";
|
||||
safebrowsing_block_host = "standard-block.dns.adguard.com";
|
||||
rewrites = [];
|
||||
safebrowsing_cache_size = 1048576;
|
||||
safesearch_cache_size = 1048576;
|
||||
parental_cache_size = 1048576;
|
||||
cache_time = 30;
|
||||
filters_update_interval = 24;
|
||||
blocked_response_ttl = 10;
|
||||
filtering_enabled = true;
|
||||
parental_enabled = false;
|
||||
safebrowsing_enabled = false;
|
||||
protection_enabled = true;
|
||||
};
|
||||
clients = {
|
||||
runtime_sources = {
|
||||
whois = true;
|
||||
arp = true;
|
||||
rdns = true;
|
||||
dhcp = true;
|
||||
hosts = true;
|
||||
};
|
||||
persistent = [];
|
||||
};
|
||||
log = {
|
||||
file = "";
|
||||
max_backups = 0;
|
||||
max_size = 100;
|
||||
max_age = 3;
|
||||
compress = false;
|
||||
local_time = false;
|
||||
verbose = false;
|
||||
};
|
||||
schema_version = 28;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{ agenix, options, system, ... }:
|
||||
{ config, agenix, options, system, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
agenix.packages.${system}.default
|
||||
|
@ -9,6 +9,6 @@
|
|||
|
||||
# default path is /etc/ssh/ssh_host_rsa_key
|
||||
age.identityPaths = options.age.identityPaths.default ++ [
|
||||
"/home/homefree/.ssh/id_rsa"
|
||||
"/home/${config.system.homefree.adminUsername}/.ssh/id_rsa"
|
||||
];
|
||||
}
|
||||
|
|
76
profiles/authentik.nix
Normal file
76
profiles/authentik.nix
Normal file
|
@ -0,0 +1,76 @@
|
|||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
openldap
|
||||
];
|
||||
|
||||
services.authentik = {
|
||||
enable = true;
|
||||
# Deployed SOPS file
|
||||
environmentFile = "/run/secrets/authentik/authentik-env";
|
||||
## @TODO: make these configurable from module
|
||||
settings = {
|
||||
email = {
|
||||
host = "smtp.homefree.host";
|
||||
port = 587;
|
||||
username = "authentik@homefree.host";
|
||||
use_tls = true;
|
||||
use_ssl = false;
|
||||
from = "authentik@homefree.host";
|
||||
};
|
||||
disable_startup_analytics = true;
|
||||
avatars = "initials";
|
||||
};
|
||||
};
|
||||
|
||||
services.authentik-ldap = {
|
||||
enable = true;
|
||||
# Deployed SOPS file
|
||||
environmentFile = "/run/secrets/authentik/authentik-ldap-env";
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# 3389 # LDAP
|
||||
9000 # Web GUI
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
"authentik/authentik-env" = {
|
||||
format = "yaml";
|
||||
# @TODO: Move secrets to this folder
|
||||
sopsFile = ../secrets/authentik.yaml;
|
||||
|
||||
owner = config.homefree.system.adminUsername;
|
||||
path = "/run/secrets/authentik/authentik-env";
|
||||
restartUnits = [ "authentik.service" ];
|
||||
};
|
||||
"authentik/authentik-ldap-env" = {
|
||||
format = "yaml";
|
||||
# @TODO: Move secrets to this folder
|
||||
sopsFile = ../secrets/authentik.yaml;
|
||||
|
||||
owner = config.homefree.system.adminUsername;
|
||||
path = "/run/secrets/authentik/authentik-ldap-env";
|
||||
restartUnits = [ "authentik-ldap.service" ];
|
||||
};
|
||||
"authentik/postgres-password" = {
|
||||
format = "yaml";
|
||||
# @TODO: Move secrets to this folder
|
||||
sopsFile = ../secrets/authentik.yaml;
|
||||
};
|
||||
};
|
||||
|
||||
# # Set the authentik postgresql password
|
||||
# systemd.services.postgresql.postStart = let
|
||||
# password_file_path = config.sops.secrets."authentik/postgres-password".path;
|
||||
# in ''
|
||||
# $PSQL -tA <<'EOF'
|
||||
# DO $$
|
||||
# DECLARE password TEXT;
|
||||
# BEGIN
|
||||
# password := trim(both from replace(pg_read_file('${password_file_path}'), E'\n', '''));
|
||||
# EXECUTE format('ALTER ROLE authentik WITH PASSWORD '''%s''';', password);
|
||||
# END $$;
|
||||
# EOF
|
||||
# '';
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{ config, pkgs, inputs, system, ...}:
|
||||
{ config, homefree-inputs, pkgs, system, ...}:
|
||||
{
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
@ -11,7 +11,7 @@
|
|||
# this value at the release version of the first install of this system.
|
||||
# Before changing this value read the documentation for this option
|
||||
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||
system.stateVersion = "23.11"; # Did you read the comment?
|
||||
system.stateVersion = "24.11"; # Did you read the comment?
|
||||
|
||||
# @TODO: Could this be useful for auto-upgrading systems out there?
|
||||
# system.autoUpgrade = {
|
||||
|
@ -27,10 +27,11 @@
|
|||
# };
|
||||
|
||||
nix = {
|
||||
nixPath = [ "nixpkgs=${inputs.nixpkgs}" "nixos-config=/home/homefree/nixcfg" ];
|
||||
nixPath = [ "nixpkgs=${homefree-inputs.nixpkgs}" "nixos-config=/home/${config.homefree.system.adminUsername}/nixcfg" ];
|
||||
|
||||
# Which package collection to use system-wide.
|
||||
package = pkgs.nixFlakes;
|
||||
package = pkgs.nixVersions.stable;
|
||||
# package = pkgs.nixFlakes;
|
||||
|
||||
settings = {
|
||||
# sets up an isolated environment for each build process to improve reproducibility.
|
||||
|
@ -73,7 +74,7 @@
|
|||
keep-outputs = true
|
||||
'';
|
||||
|
||||
registry.nixpkgs.flake = inputs.nixpkgs;
|
||||
# registry.nixpkgs.flake = homefree-inputs.nixpkgs;
|
||||
|
||||
# Garbage collection - deletes all unreachable paths in Nix store.
|
||||
gc = {
|
||||
|
@ -96,14 +97,13 @@
|
|||
# User config
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
users.users.homefree = {
|
||||
users.users."${config.homefree.system.adminUsername}" = {
|
||||
isNormalUser = true;
|
||||
home = "/home/homefree";
|
||||
description = "Homefree User";
|
||||
home = "/home/${config.homefree.system.adminUsername}";
|
||||
description = "Homefree Admin";
|
||||
extraGroups = [ "wheel" ];
|
||||
# @TODO: Make this dynamic, not hard coded
|
||||
openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNvmGn1/uFnfgnv5qsec0GC04LeVB1Qy/G7WivvvUZVBBDzp8goe1DsE8M8iqnBSin56gQZDWsd50co2MbFAWuqH2HxY7OGay7P/V2q+SziTYFva85WGl84qWvYMmdB+alAFBT3L4eH5cegC5NhNp+OGsQuq32RdojgXXQt6vyZnaOypuz90k3rqV6Rt+iBTLz6VziasCLcYydwOvi9f1q6YQwGPLKaupDrV6gxvoX9bXLdopqwnXPSE/Eqczxgwc3PefvAJPSd6TOqIXvbtpv/B3Evt5SPe2gq+qASc5K0tzgra8KAe813kkpq4FuKJzHbT+EmO70wiJjru7zMEhd erahhal@nfml-erahhalQFL" ];
|
||||
hashedPassword = "$6$5.6V9H0g5F47ubUm$e0N.GXZ9eoqmvpO9MjZlCISC9IIxKKcf0xtnuFyuXSQEQlfaazrS4kBhplDB6GCsQgwpOxdrX2DmcwbMiX/h30";
|
||||
openssh.authorizedKeys.keys= config.homefree.system.authorizedKeys;
|
||||
hashedPassword = config.homefree.system.adminHashedPassword;
|
||||
};
|
||||
|
||||
security.sudo.extraRules = [
|
||||
|
@ -119,22 +119,6 @@
|
|||
|
||||
nixpkgs = {
|
||||
hostPlatform = system;
|
||||
config = {
|
||||
## Allow proprietary packages.
|
||||
# allowUnfree = true;
|
||||
## Allow broken packages.
|
||||
# allowBroken = true;
|
||||
packageOverrides = pkgs: {
|
||||
unstable = import inputs.nixpkgs-unstable {
|
||||
config = config.nixpkgs.config;
|
||||
inherit system;
|
||||
};
|
||||
trunk = import inputs.nixpkgs-trunk {
|
||||
config = config.nixpkgs.config;
|
||||
inherit system;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
@ -145,6 +129,15 @@
|
|||
# Nix mounts read-write automatically when it needs to write to it.
|
||||
boot.readOnlyNixStore = true;
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# Hardware
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
hardware.enableAllFirmware = true;
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# Services
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
@ -155,10 +148,6 @@
|
|||
# Setting to true will kill things like tmux on logout
|
||||
services.logind.killUserProcesses = false;
|
||||
|
||||
# network locator e.g. scanners and printers
|
||||
services.avahi.enable = true;
|
||||
services.avahi.nssmdns = true;
|
||||
|
||||
services.gvfs.enable = true; # SMB mounts, trash, and other functionality
|
||||
services.tumbler.enable = true; # Thumbnail support for images
|
||||
|
||||
|
@ -169,7 +158,17 @@
|
|||
services.printing.drivers = [ pkgs.brlaser ];
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh.enable = true;
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
## This doesn't work, can't SSH at all
|
||||
# AllowUsers = [
|
||||
# "*@192.168.*.*"
|
||||
# "*@10.0.0.1"
|
||||
# "erahhal@10.0.0.1"
|
||||
# ];
|
||||
};
|
||||
};
|
||||
|
||||
# This will save you money and possibly your life!
|
||||
services.thermald.enable = true;
|
||||
|
@ -182,6 +181,15 @@
|
|||
powertop.enable = true;
|
||||
};
|
||||
|
||||
# Eternal Terminal
|
||||
services.eternal-terminal.enable = true;
|
||||
# et port
|
||||
networking.firewall.allowedTCPPorts = [ 2022 ];
|
||||
environment.variables = {
|
||||
ET_NO_TELEMETRY = "1";
|
||||
};
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
# i18n
|
||||
# --------------------------------------------------------------------------------------
|
||||
|
@ -201,28 +209,15 @@
|
|||
|
||||
programs.nix-ld.enable = true;
|
||||
|
||||
programs.command-not-found.enable = true;
|
||||
programs.command-not-found.dbPath = "${inputs.nixpkgs}/programs.sqlite";
|
||||
|
||||
programs.mosh.enable = true;
|
||||
|
||||
# environment.variables.EDITOR = "neovim";
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
defaultEditor = true;
|
||||
};
|
||||
|
||||
environment.interactiveShellInit = ''
|
||||
alias vi='nvim'
|
||||
alias vim='nvim'
|
||||
'';
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
at-spi2-core
|
||||
backblaze-b2
|
||||
bashmount
|
||||
bfg-repo-cleaner
|
||||
bind
|
||||
btop
|
||||
ccze # readable parsed system logs
|
||||
cpufrequtils
|
||||
distrobox
|
||||
|
@ -238,6 +233,7 @@
|
|||
git
|
||||
git-lfs
|
||||
gnumake
|
||||
gnupg
|
||||
htop
|
||||
hwinfo
|
||||
iftop
|
||||
|
@ -254,8 +250,7 @@
|
|||
memtest86plus
|
||||
minicom
|
||||
neofetch
|
||||
neovim
|
||||
unstable.nil
|
||||
nil
|
||||
nix-index
|
||||
openssl
|
||||
# openjdk16-bootstrap
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ inputs, pkgs, system, ... }:
|
||||
{ homefree-inputs, system, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
inputs.nix-editor.packages.${system}.default
|
||||
environment.systemPackages = [
|
||||
homefree-inputs.nix-editor.packages.${system}.default
|
||||
];
|
||||
}
|
||||
|
|
36
profiles/ddclient.nix
Normal file
36
profiles/ddclient.nix
Normal file
|
@ -0,0 +1,36 @@
|
|||
{ config, inputs, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.homefree.dynamic-dns;
|
||||
in
|
||||
{
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# Dynamic DNS
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
services.ddclient-multi = {
|
||||
enable = true;
|
||||
interval = cfg.interval;
|
||||
usev4 = cfg.usev4;
|
||||
usev6 = cfg.usev6;
|
||||
verbose = true;
|
||||
zones = lib.map (zone: {
|
||||
protocol = zone.protocol;
|
||||
username = zone.username;
|
||||
zone = zone.zone;
|
||||
domains = zone.domains;
|
||||
passwordFile = zone.passwordFile;
|
||||
}) cfg.zones;
|
||||
};
|
||||
|
||||
## @TODO: Move to host config
|
||||
sops.secrets = {
|
||||
"ddclient/ddclient-password" = {
|
||||
format = "yaml";
|
||||
sopsFile = ../secrets/ddclient.yaml;
|
||||
|
||||
owner = config.homefree.system.adminUsername;
|
||||
path = "/run/secrets/ddclient/ddclient-password";
|
||||
restartUnits = [ "ddclient.service" ];
|
||||
};
|
||||
};
|
||||
}
|
96
profiles/dnsmasq.nix
Normal file
96
profiles/dnsmasq.nix
Normal file
|
@ -0,0 +1,96 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
lan-interface = config.homefree.network.lan-interface;
|
||||
wan-interface = config.homefree.network.wan-interface;
|
||||
localDomain = config.homefree.system.localDomain;
|
||||
dhcp-script = pkgs.writeShellScript "dhcp-script" ''
|
||||
# $1 = action (add, del, old)
|
||||
# $2 = MAC address
|
||||
# $3 = IP address
|
||||
# $4 = hostname
|
||||
|
||||
if [ "$1" = "add" ]; then
|
||||
${pkgs.dnsutils}/bin/nsupdate -l <<EOF
|
||||
server 127.0.0.1
|
||||
zone ${localDomain}
|
||||
update delete $4.${localDomain} A
|
||||
update add $4.${localDomain} 3600 A $3
|
||||
send
|
||||
EOF
|
||||
${pkgs.dnsutils}/bin/nsupdate -l <<EOF
|
||||
server 127.0.0.1
|
||||
update delete $4 A
|
||||
update add $4 3600 A $3
|
||||
send
|
||||
EOF
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
services.dnsmasq = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
## @TODO
|
||||
## @WARNING - changes to this do not clear out old entries from /etc/dnsmasq-conf.conf
|
||||
|
||||
## Only DHCP server on network
|
||||
dhcp-authoritative = true;
|
||||
|
||||
## Don't listen to anything on wan interface
|
||||
except-interface = wan-interface;
|
||||
|
||||
## Don't send bogus requests to internet
|
||||
bogus-priv = true;
|
||||
|
||||
## Enable Router Advertising for ipv6
|
||||
enable-ra = true;
|
||||
|
||||
## Ipv6
|
||||
## ra-param = "${lan-interface},0,0"; ## This disables router-advertisements
|
||||
ra-param = "${lan-interface},10,300";
|
||||
|
||||
## DNS servers to pass to clients
|
||||
## @TODO: Make this based on configured gateway IP
|
||||
server = [ "10.0.0.1" ];
|
||||
|
||||
## Which interfaces to bind to
|
||||
interface = [
|
||||
# "${lan-interface}.${builtins.toString vlan-lan-id}"
|
||||
# "${lan-interface}.${builtins.toString vlan-iot-id}"
|
||||
# "${lan-interface}.${builtins.toString vlan-guest-id}"
|
||||
lan-interface
|
||||
];
|
||||
|
||||
## IP ranges to hand out
|
||||
dhcp-range = [
|
||||
# "lan,10.0.0.100,10.0.0.254,255.255.255.0,8h"
|
||||
# "iot,10.2.1.100,10.2.1.254,255.255.255.0,8h"
|
||||
# "guest,10.3.1.100,10.3.1.254,255.255.255.0,8h"
|
||||
"tag:${lan-interface},::1,constructor:${lan-interface},ra-names,slaac,12h" # ipv6
|
||||
"${lan-interface},10.0.0.100,10.0.0.254,255.255.255.0,8h" # ipv4
|
||||
];
|
||||
|
||||
## Disable DNS, since Unbound is handling DNS
|
||||
port = 0;
|
||||
|
||||
cache-size = 500;
|
||||
|
||||
## Additional DHCP options
|
||||
dhcp-option = [
|
||||
"option6:dns-server,[::]" # @TODO: point this at Unbound when ipv6 is setup
|
||||
"option:dns-server,10.0.0.1"
|
||||
];
|
||||
|
||||
dhcp-host = lib.map (ip-config:
|
||||
"${ip-config.mac-address},${ip-config.hostname},${ip-config.ip},${config.homefree.network.static-ip-expiration}")
|
||||
config.homefree.network.static-ips;
|
||||
|
||||
dhcp-script = "${dhcp-script}";
|
||||
};
|
||||
};
|
||||
|
||||
## dhcpd6 is obsolete
|
||||
# services.dhcpd6 = {};
|
||||
}
|
||||
|
69
profiles/git.nix
Normal file
69
profiles/git.nix
Normal file
|
@ -0,0 +1,69 @@
|
|||
{ config, pkgs, ... }:
|
||||
{
|
||||
programs.git = {
|
||||
enable = true;
|
||||
lfs.enable = true;
|
||||
config = {
|
||||
checkout = {
|
||||
defaultRemote = "origin";
|
||||
};
|
||||
color = {
|
||||
ui = "auto";
|
||||
};
|
||||
core = {
|
||||
# Can't specify "${pkgs.neovim}/bin/nvim" because programs.neovim
|
||||
# wraps neovim-unwrapped in a special way to load plugins, so must
|
||||
# expect nvim to be in $PATH here
|
||||
editor = "nvim";
|
||||
excludesfile = "~/.gitignore_global";
|
||||
};
|
||||
delta = {
|
||||
enable = true;
|
||||
};
|
||||
# filter = {
|
||||
# lfs = {
|
||||
# clean = "${pkgs.git-lfs}/bin/git-lfs clean -- %f";
|
||||
# smudge = "${pkgs.git-lfs}/bin/git-lfs smudge --skip -- %f";
|
||||
# process = "${pkgs.git-lfs}/bin/git-lfs filter-process --skip";
|
||||
# required = true;
|
||||
# };
|
||||
# };
|
||||
push = {
|
||||
default = "simple";
|
||||
};
|
||||
rerere = {
|
||||
enabled = true;
|
||||
};
|
||||
include = {
|
||||
path = "~/.gitconfig.local";
|
||||
};
|
||||
|
||||
#==========================
|
||||
# Diff settings
|
||||
#==========================
|
||||
|
||||
pager = {
|
||||
difftool = true;
|
||||
};
|
||||
|
||||
#-------------------
|
||||
## nvim
|
||||
# - text-based
|
||||
#------------------
|
||||
diff = {
|
||||
tool = "nvimdiff";
|
||||
};
|
||||
difftool = {
|
||||
prompt = true;
|
||||
};
|
||||
merge = {
|
||||
tool = "nvimdiff";
|
||||
trustExitCode = false;
|
||||
};
|
||||
mergetool = {
|
||||
trustExitCode = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
20
profiles/gitea.nix
Normal file
20
profiles/gitea.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ config, ... }:
|
||||
{
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
database = {
|
||||
## @TODO: move to postgresql
|
||||
type = "sqlite3";
|
||||
};
|
||||
settings = {
|
||||
server = {
|
||||
HTTP_PORT = 3001;
|
||||
DOMAIN = "git.${config.homefree.system.domain}";
|
||||
MINIMUM_KEY_SIZE_CHECK = false;
|
||||
START_SSH_SERVER = true;
|
||||
SSH_PORT = 3022;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -8,30 +8,11 @@
|
|||
[ (modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "virtio_blk" ];
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "ahci" "xhci_pci" "nvme" "virtio_pci" "virtio_blk" "floppy" "sd_mod" "sr_mod" "usb_storage" "usbhid" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.kernelModules = [ "kvm-amd" "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/efi" =
|
||||
{ device = "systemd-1";
|
||||
fsType = "autofs";
|
||||
};
|
||||
|
||||
fileSystems."/home/homefree/nixcfg" =
|
||||
{ device = "mount_homefree_source";
|
||||
fsType = "virtiofs";
|
||||
options = [ "nofail" ];
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -40,4 +21,5 @@
|
|||
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
|
|
2
profiles/home-assistant/automations.nix
Normal file
2
profiles/home-assistant/automations.nix
Normal file
|
@ -0,0 +1,2 @@
|
|||
[
|
||||
]
|
413
profiles/home-assistant/default.nix
Normal file
413
profiles/home-assistant/default.nix
Normal file
|
@ -0,0 +1,413 @@
|
|||
{ config, inputs, pkgs, ... }:
|
||||
|
||||
let
|
||||
# automations = import ./automations.nix;
|
||||
scenes = import ./scenes.nix;
|
||||
scripts = import ./scripts.nix;
|
||||
groups = import ./groups.nix;
|
||||
in
|
||||
{
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# Home Assistant
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
imports = [
|
||||
# On first run, this has to be commented out, and a single user created.
|
||||
# Afterward, it can be re-included
|
||||
## @TODO: Auto-initializatin for HA
|
||||
## See: https://github.com/home-assistant/core/issues/16554
|
||||
./ldap.nix
|
||||
./trusted-networks.nix
|
||||
./weather.nix
|
||||
];
|
||||
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
|
||||
# Enable Postgres
|
||||
package = (pkgs.home-assistant.override {
|
||||
extraPackages = py: with py; [ psycopg2 ];
|
||||
}).overrideAttrs (oldAttrs: {
|
||||
doInstallCheck = false;
|
||||
});
|
||||
config.recorder.db_url = "postgresql://@/hass";
|
||||
|
||||
extraComponents = [
|
||||
# Components required to complete the onboarding
|
||||
"adguard"
|
||||
"backup"
|
||||
"brother"
|
||||
"ecobee"
|
||||
"enphase_envoy"
|
||||
"esphome"
|
||||
"flume"
|
||||
"iaqualink"
|
||||
"jellyfin"
|
||||
"litterrobot"
|
||||
"met"
|
||||
"mqtt"
|
||||
"radio_browser"
|
||||
"roborock"
|
||||
"schlage"
|
||||
"snapcast"
|
||||
"synology_dsm"
|
||||
"unifi"
|
||||
"usgs_earthquakes_feed"
|
||||
"volumio"
|
||||
"wake_on_lan"
|
||||
"yamaha_musiccast"
|
||||
"zwave_js"
|
||||
];
|
||||
|
||||
customComponents = with pkgs.home-assistant-custom-components; [
|
||||
frigate
|
||||
smartthinq-sensors
|
||||
];
|
||||
|
||||
customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
|
||||
button-card
|
||||
card-mod
|
||||
decluttering-card
|
||||
lg-webos-remote-control
|
||||
light-entity-card
|
||||
mini-graph-card
|
||||
mini-media-player
|
||||
multiple-entity-row
|
||||
mushroom
|
||||
valetudo-map-card
|
||||
];
|
||||
|
||||
config = {
|
||||
# Includes dependencies for a basic setup
|
||||
# https://www.home-assistant.io/integrations/default_config/
|
||||
default_config = {};
|
||||
|
||||
# "automation manual" = automations;
|
||||
"automation ui" = "!include automations.yaml";
|
||||
|
||||
"scene manual" = scenes;
|
||||
"scene ui" = "!include scenes.yaml";
|
||||
|
||||
"script manual" = scripts;
|
||||
"script ui" = "!include scripts.yaml";
|
||||
|
||||
"group manual" = groups;
|
||||
# "group ui" = "!include groups.yaml";
|
||||
|
||||
http = {
|
||||
# @TODO: Make this a passed-in var
|
||||
base_url = "ha.homefree.lan";
|
||||
use_x_forwarded_for = true;
|
||||
trusted_proxies = [
|
||||
# @TODO: Make this a passed-in var
|
||||
"127.0.0.1"
|
||||
"10.0.0.1"
|
||||
"10.0.2.15"
|
||||
];
|
||||
};
|
||||
|
||||
## enable with empty top level key
|
||||
wake_on_lan = {};
|
||||
|
||||
switch = [
|
||||
{
|
||||
platform = "wake_on_lan";
|
||||
mac = "B4-B2-91-52-DE-DF";
|
||||
name = "LGwebOSTV";
|
||||
host = "10.0.0.40";
|
||||
}
|
||||
{
|
||||
platform = "template";
|
||||
switches = {
|
||||
lg_tv = {
|
||||
unique_id = "lg-tv";
|
||||
friendly_name = "LG CX 65\" TV";
|
||||
value_template = "{{ is_state('media_player.lg_webos_smart_tv', 'on') }}";
|
||||
turn_on = {
|
||||
service = "switch.turn_on";
|
||||
target = {
|
||||
entity_id = "switch.lgwebostv";
|
||||
};
|
||||
};
|
||||
turn_off = {
|
||||
service = "media_player.turn_off";
|
||||
target = {
|
||||
entity_id = "media_player.lg_webos_smart_tv";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
command_line = [
|
||||
{
|
||||
switch = {
|
||||
name = "msi_desktop";
|
||||
unique_id = "msi-desktop";
|
||||
command_state = "ping -c 2 -i 1 msi-desktop.localdomain";
|
||||
## Hibernate
|
||||
# command_off = "ssh -i /run/agenix/msi-desktop-id_rsa -o 'StrictHostKeyChecking=no' erahhal@msi-desktop rundll32.exe powrprof.dll, SetSuspendState Sleep";
|
||||
command_on = "wakeonlan 2c:f0:5d:72:ac:ab";
|
||||
## Suspend
|
||||
command_off = "ssh -i /config/certs/msi_desktop-id_rsa -o ConnectTimeout=30 -o 'StrictHostKeyChecking=no' erahhal@msi-desktop.localdomain 'cd \"/mnt/c/Program Files/PSTools\"; ./psshutdown.exe -accepteula -d -t 0'";
|
||||
};
|
||||
}
|
||||
{
|
||||
switch = {
|
||||
name = "stream_vr";
|
||||
unique_id = "steam-vr";
|
||||
command_on = "ssh -i /config/certs/msi_desktop-id_rsa -o ConnectTimeout=30 -o 'StrictHostKeyChecking=no' erahhal@msi-desktop.localdomain 'cd \"/mnt/c/Program Files (x86)/Steam/steamapps/common/SteamVR/bin/win64\"; ./vrstartup.exe'";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# media_player = [
|
||||
# {
|
||||
# platform = "yamaha";
|
||||
# host = "10.0.0.41";
|
||||
# source_names = {
|
||||
# HDMI1 = "PC HDMI";
|
||||
# };
|
||||
# zone_names = {
|
||||
# Main_Zone = "Family Room";
|
||||
# };
|
||||
# }
|
||||
# ];
|
||||
|
||||
sensor = [
|
||||
# See: https://github.com/home-assistant/core/issues/64839
|
||||
{
|
||||
platform = "template";
|
||||
sensors = {
|
||||
# ZWaveJS Node Stats
|
||||
zwavejs_node_statistics = {
|
||||
friendly_name = "ZwaveJS Node Statistics";
|
||||
icon_template = ''
|
||||
{%- if states | selectattr('entity_id', 'search', '_node_status') | selectattr('state', 'in', 'dead, unknown') | list | count > 0 -%}
|
||||
mdi:emoticon-sad
|
||||
{%- elif states | selectattr('entity_id', 'search', '_node_status') | rejectattr('state', 'in', 'alive, asleep, dead, unknown') | list | count > 0 -%}
|
||||
mdi:help-circle
|
||||
{%- else -%}
|
||||
mdi:z-wave
|
||||
{%- endif -%}
|
||||
'';
|
||||
value_template = "{{ states | selectattr('entity_id', 'search', '_node_status') | list | count }}";
|
||||
attribute_templates = {
|
||||
Alive = "{{ states | selectattr('entity_id', 'search', '_node_status') | selectattr('state', 'in', 'alive') | list | count }}";
|
||||
Sleeping = "{{ states | selectattr('entity_id', 'search', '_node_status') | selectattr('state', 'in', 'asleep') | list | count }}";
|
||||
Dead = "{{ states | selectattr('entity_id', 'search', '_node_status') | selectattr('state', 'in', 'dead, unknown') | list | count }}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
# {
|
||||
# platform = "hp_ilo";
|
||||
# host = "10.0.0.9";
|
||||
# username = "Administrator";
|
||||
# # @TODO: REMOVE
|
||||
# password = "CHANGEME";
|
||||
# monitored_variables = [
|
||||
# {
|
||||
# name = "CPU fanspeed";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "%";
|
||||
# value_template = "{{ ilo_data.fans[\"Fan 1\"].speed[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Fan 2";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "%";
|
||||
# value_template = "{{ ilo_data.fans[\"Fan 2\"].speed[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Fan 3";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "%";
|
||||
# value_template = "{{ ilo_data.fans[\"Fan 3\"].speed[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Server Health";
|
||||
# sensor_type = "server_health";
|
||||
# value_template = "{{ ilo_data.health_at_a_glance }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Server Power Readings (raw)";
|
||||
# sensor_type = "server_power_readings";
|
||||
# }
|
||||
# {
|
||||
# name = "Server Power Status (raw)";
|
||||
# sensor_type = "server_power_status";
|
||||
# }
|
||||
# {
|
||||
# name = "Server health (raw)";
|
||||
# sensor_type = "server_health";
|
||||
# }
|
||||
# {
|
||||
# name = "Inlet temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"01-Inlet Ambient\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Inlet temperature (raw)";
|
||||
# sensor_type = "server_health";
|
||||
# value_template = "{{ ilo_data.temperature[\"01-Inlet Ambient\"] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "CPU 1 temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"02-CPU 1\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "P1 DIMM 1-4 temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"03-P1 DIMM 1-4\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "HD Max temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"04-HD Max\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Chipset temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"05-Chipset\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "VR P1 temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"07-VR P1\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "SuperCAP Max temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"08-Supercap Max\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "iLO Zone temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"09-iLO Zone\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "LOM Zon temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"11-LOM Zone\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "PCI 2 temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"13-PCI 2\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "PCI 1 Zone temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"14-PCI 1 Zone\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "PCI 2 Zone temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"15-PCI 2 Zone\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "System Board temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"16-System Board\"].currentreading[0] }}";
|
||||
# }
|
||||
# {
|
||||
# name = "Sys Exhaust temperature";
|
||||
# sensor_type = "server_health";
|
||||
# unit_of_measurement = "°C";
|
||||
# value_template = "{{ ilo_data.temperature[\"17-Sys Exhaust\"].currentreading[0] }}";
|
||||
# }
|
||||
# ];
|
||||
# }
|
||||
# {
|
||||
# # This includes the config necessary for a washer and dryer.
|
||||
# # Code for dishwasher and mini-washer may be commented out as-needed,
|
||||
# # and are presented only for reference purposes.
|
||||
#
|
||||
# # NOTE: YOUR ENTITY NAMES MAY BE DIFFERENT, THEN THIS WON'T WORK WITHOUT TWEAKING
|
||||
# # =================================================================================
|
||||
# # If your washer doesn't have entities named sensor.washer, sensor.washer_run_state
|
||||
# # (and similar for dryer), you have to change the names throughout here!
|
||||
#
|
||||
# # NOTE: THIS CODE EXPECTS YOUR THINQ INTEGRATION TO RETURN ENGLISH STRINGS
|
||||
# # =================================================================================
|
||||
# # if your LG account is in another region/language, this will probably break unless
|
||||
# # you take the time to change out state strings like "Standby". Do this by watching
|
||||
# # your machine's entities change states during a run, or look at its history.
|
||||
#
|
||||
# platform = "template";
|
||||
# sensors = {
|
||||
# front_load_washer_door_lock = {
|
||||
# friendly_name = "Washer Door Lock";
|
||||
# value_template = "{{ state_attr('sensor.front_load_washer','door_lock') }}";
|
||||
# };
|
||||
# front_load_washer_time_display = {
|
||||
# friendly_name = "Washer Time Display";
|
||||
# value_template = ''
|
||||
# {% if is_state('sensor.front_load_washer_run_state', '-') %}
|
||||
# {% elif is_state('sensor.front_load_washer_run_state', 'unavailable') %}
|
||||
# {% elif is_state('sensor.front_load_washer_run_state', 'Standby') %}
|
||||
# -:--
|
||||
# {% else %}
|
||||
# {{ state_attr("sensor.front_load_washer","remain_time").split(":")[:-1] | join(':') }}
|
||||
# {% endif %}
|
||||
# '';
|
||||
# };
|
||||
#
|
||||
# dryer_time_display = {
|
||||
# friendly_name = "Dryer Time Display";
|
||||
# value_template = ''
|
||||
# {% if is_state('sensor.dryer_run_state', '-') %}
|
||||
# {% elif is_state('sensor.dryer_run_state', 'unavailable') %}
|
||||
# {% elif is_state('sensor.dryer_run_state', 'Standby') %}
|
||||
# -:--
|
||||
# {% else %}
|
||||
# {{ state_attr("sensor.dryer","remain_time").split(":")[:-1] | join(':') }}
|
||||
# {% endif %}
|
||||
# '';
|
||||
# };
|
||||
#
|
||||
# blank = {
|
||||
# friendly_name = "Blank Sensor";
|
||||
# value_template = "";
|
||||
# };
|
||||
# };
|
||||
# }
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Make sure UI-based config files exist in case they haven't been created yet
|
||||
systemd.tmpfiles.rules = [
|
||||
"f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
|
||||
"f ${config.services.home-assistant.configDir}/scenes.yaml 0755 hass hass"
|
||||
"f ${config.services.home-assistant.configDir}/scripts.yaml 0755 hass hass"
|
||||
];
|
||||
|
||||
# HTTP port
|
||||
networking.firewall.allowedTCPPorts = [ 8123 ];
|
||||
|
||||
# Database
|
||||
services.postgresql = {
|
||||
ensureDatabases = [ "hass" ];
|
||||
ensureUsers = [{
|
||||
name = "hass";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
}
|
2
profiles/home-assistant/groups.nix
Normal file
2
profiles/home-assistant/groups.nix
Normal file
|
@ -0,0 +1,2 @@
|
|||
[
|
||||
]
|
63
profiles/home-assistant/ldap-auth-sh.nix
Normal file
63
profiles/home-assistant/ldap-auth-sh.nix
Normal file
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
makeWrapper,
|
||||
openldap,
|
||||
coreutils,
|
||||
gnused,
|
||||
gnugrep,
|
||||
lib,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "ldap-auth-sh";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "efficiosoft";
|
||||
repo = "ldap-auth-sh";
|
||||
rev = "93b2c00413942908139e37c7432a12bcb705ac87";
|
||||
sha256 = "1pymp6ki353aqkigr89g7hg5x1mny68m31c3inxf1zr26n5s2kz8";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/etc
|
||||
cat > $out/etc/home-assistant.cfg << 'EOF'
|
||||
CLIENT="ldapsearch"
|
||||
SERVER="ldap://localhost:3389"
|
||||
USERDN="cn=$(ldap_dn_escape "$username"),ou=users,dc=ldap,dc=goauthentik,dc=io"
|
||||
PW=$password
|
||||
|
||||
BASEDN="dc=ldap,dc=goauthentik,dc=io"
|
||||
SCOPE="subtree"
|
||||
FILTER="(&(objectClass=user)(sAMAccountName=$(ldap_dn_escape "$username")))"
|
||||
# USERNAME_PATTERN='^[a-z|A-Z|0-9|_|-|.|@]+$'
|
||||
on_auth_success() {
|
||||
# print the meta entries for use in HA
|
||||
if echo "$output" | grep -qE '^(dn|DN):: '; then
|
||||
# ldapsearch base64 encodes non-ascii
|
||||
output=$(echo "$output" | sed -n -e "s/^\(dn\|DN\)\s*::\s*\(.*\)$/\2/p" | base64 -d)
|
||||
else
|
||||
output=$(echo "$output" | sed -n -e "s/^\(dn\|DN\)\s*:\s*\(.*\)$/\2/p")
|
||||
fi
|
||||
|
||||
name=$(echo "$output" | sed -nr 's/^cn=([^,]+).*/\1/Ip')
|
||||
[ -z "$name" ] || echo "name=$name"
|
||||
}
|
||||
on_auth_failure() {
|
||||
echo "$output"
|
||||
}
|
||||
EOF
|
||||
install -D -m755 ldap-auth.sh $out/bin/ldap-auth.sh
|
||||
wrapProgram $out/bin/ldap-auth.sh \
|
||||
--prefix PATH : ${
|
||||
lib.makeBinPath [
|
||||
openldap
|
||||
coreutils
|
||||
gnused
|
||||
gnugrep
|
||||
]
|
||||
} \
|
||||
--add-flags "$out/etc/home-assistant.cfg"
|
||||
'';
|
||||
}
|
||||
|
13
profiles/home-assistant/ldap.nix
Normal file
13
profiles/home-assistant/ldap.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
ldap-auth-sh = pkgs.callPackage ./ldap-auth-sh.nix {};
|
||||
in
|
||||
{
|
||||
services.home-assistant.config.homeassistant.auth_providers = [
|
||||
{
|
||||
type = "command_line";
|
||||
command = "${ldap-auth-sh}/bin/ldap-auth.sh";
|
||||
meta = true;
|
||||
}
|
||||
];
|
||||
}
|
2
profiles/home-assistant/scenes.nix
Normal file
2
profiles/home-assistant/scenes.nix
Normal file
|
@ -0,0 +1,2 @@
|
|||
[
|
||||
]
|
2
profiles/home-assistant/scripts.nix
Normal file
2
profiles/home-assistant/scripts.nix
Normal file
|
@ -0,0 +1,2 @@
|
|||
[
|
||||
]
|
14
profiles/home-assistant/trusted-networks.nix
Normal file
14
profiles/home-assistant/trusted-networks.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
ldap-auth-sh = pkgs.callPackage ./ldap-auth-sh.nix {};
|
||||
in
|
||||
{
|
||||
services.home-assistant.config.homeassistant.auth_providers = [
|
||||
{
|
||||
type = "trusted_networks";
|
||||
trusted_networks = [
|
||||
"10.0.0.0/8"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
61
profiles/home-assistant/weather.nix
Normal file
61
profiles/home-assistant/weather.nix
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
services.home-assistant.extraComponents = [
|
||||
"openweathermap"
|
||||
];
|
||||
services.home-assistant.config = {
|
||||
conversation.intents = {
|
||||
WeatherToday = [
|
||||
"(What's|What is|How's|How is) the (weather|temperature) (like|outside) (today|right now|now|outside)"
|
||||
"(What's|What is|How's|How is) the (weather|temperature) (like|outside|right now|now|today)"
|
||||
];
|
||||
WeatherTomorrow = [
|
||||
"(What's|What is|How's|How is) the (weather|temperature) (like|outside) (tomorrow|tomorrow morning|tomorrow afternoon|tomorrow evening)"
|
||||
"(What's|What is|How's|How is) the (weather|temperature) (tomorrow|tomorrow morning|tomorrow afternoon|tomorrow evening)"
|
||||
];
|
||||
};
|
||||
intent_script = {
|
||||
WeatherToday.speech.text = ''
|
||||
The weather is currently {{ states('sensor.openweathermap_temperature') | round(0) }} degrees outside and {{ states('sensor.openweathermap_condition') }}.
|
||||
'';
|
||||
WeatherTomorrow.speech.text = ''
|
||||
Tomorrow will be {{ state_attr('weather.openweathermap', 'forecast')[1]["temperature"] | round(0) }} degrees and {{ state_attr('weather.openweathermap', 'forecast')[1]["condition"] }} with a low of {{ state_attr('weather.openweathermap', 'forecast')[1]["templow"] | round(0) }} degrees.
|
||||
'';
|
||||
};
|
||||
input_boolean.rain_notified_today = {
|
||||
name = "Rain notified today";
|
||||
icon = "mdi:weather-cloudy";
|
||||
};
|
||||
weather = { };
|
||||
automation = [
|
||||
{
|
||||
alias = "rainy/snowy day notification";
|
||||
trigger = {
|
||||
platform = "state";
|
||||
entity_id = "weather.openweathermap";
|
||||
};
|
||||
condition = {
|
||||
condition = "template";
|
||||
value_template = ''{{ states.input_boolean.rain_notified_today.state == "off" }}'';
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "python_script.weather";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
alias = "Reset rain notified today";
|
||||
trigger = {
|
||||
platform = "time";
|
||||
at = "00:07:00";
|
||||
};
|
||||
action = [
|
||||
{
|
||||
service = "input_boolean.turn_off";
|
||||
entity_id = "input_boolean.rain_notified_today";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
|
@ -1,9 +1,16 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
hostConfig = ''
|
||||
respond "Hello, world! I am being accessed from {scheme}."
|
||||
'';
|
||||
proxiedHostConfig = config.homefree.proxied-hosts;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
../apps/radicale.nix
|
||||
];
|
||||
|
||||
systemd.services.caddy = {
|
||||
after = [ "network.target" "network-online.target" "unbound.service" ];
|
||||
requires = [ "network-online.target" "unbound.service" ];
|
||||
};
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
|
@ -11,16 +18,58 @@
|
|||
## reload config while running instead of restarting. true by default.
|
||||
enableReload = true;
|
||||
|
||||
virtualHosts."localhost" = {
|
||||
extraConfig = ''
|
||||
respond "Hello, my world!"
|
||||
'';
|
||||
};
|
||||
## Temporarily set to staging
|
||||
# acmeCA = "https://acme-staging-v02.api.letsencrypt.org/directory";
|
||||
|
||||
virtualHosts = lib.listToAttrs (lib.map (entry:
|
||||
let
|
||||
http-urls = lib.flatten (lib.map (subdomain: (lib.map (domain: "http://${subdomain}.${domain}") entry.http-domains)) entry.subdomains);
|
||||
https-urls = lib.flatten (lib.map (subdomain: (lib.map (domain: "https://${subdomain}.${domain}") entry.https-domains)) entry.subdomains);
|
||||
urls = http-urls ++ https-urls;
|
||||
host-string = lib.concatStringsSep ", " urls;
|
||||
in {
|
||||
name = host-string;
|
||||
value = {
|
||||
logFormat = ''
|
||||
output file ${config.services.caddy.logDir}/access-${entry.label}.log
|
||||
'';
|
||||
## @TODO: Remove headers and check if still works
|
||||
extraConfig = ''
|
||||
# header {
|
||||
# Strict-Transport-Security "max-age=31536000; includeSubdomains"
|
||||
# X-XSS-Protection "1; mode=block"
|
||||
# X-Content-Type-Options "nosniff"
|
||||
# X-Frame-Options "SAMEORIGIN"
|
||||
# Referrer-Policy "same-origin"
|
||||
# }
|
||||
'' + (if entry.public == false then ''
|
||||
bind 10.0.0.1 192.168.2.1
|
||||
'' else ''
|
||||
bind 10.0.0.1 192.168.2.1 ${config.homefree.system.domain}
|
||||
'')
|
||||
+ (if entry.ssl == true && entry.ssl-no-verify then ''
|
||||
reverse_proxy https://${entry.host}:${toString entry.port} {
|
||||
transport http {
|
||||
tls
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
}
|
||||
'' else ''
|
||||
reverse_proxy ${if entry.ssl == true then "https" else "http"}://${entry.host}:${toString entry.port}
|
||||
'');
|
||||
};
|
||||
}
|
||||
) proxiedHostConfig);
|
||||
|
||||
## With both http and https set, caddy won't redirect http to https
|
||||
## REMOVE THIS IN PROD
|
||||
# virtualHosts."http://localhost, https://localhost, https://${config.homefree.system.domain}, https://www.${config.homefree.system.domain}" = {
|
||||
# # Nix config mangles the log name, so set it manually
|
||||
# logFormat = ''
|
||||
# output file ${config.services.caddy.logDir}/access-localhost.log
|
||||
# '';
|
||||
# extraConfig = hostConfig;
|
||||
# };
|
||||
|
||||
virtualHosts."http://radicale.homefree.lan" = {
|
||||
extraConfig = ''
|
||||
reverse_proxy :5232
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
81
profiles/lib/interactive-vm.nix
Normal file
81
profiles/lib/interactive-vm.nix
Normal file
|
@ -0,0 +1,81 @@
|
|||
{ homefreeLib, modulesPath, config, lib, ... }:
|
||||
|
||||
let
|
||||
vm_homefree = (homefreeLib.prepareHomefreeConfig config homefreeLib.devices).homefree;
|
||||
cfg_ = (lib.evalModules {
|
||||
modules = lib.singleton {
|
||||
# _file = toString input;
|
||||
imports = lib.singleton { homefree.devices = vm_homefree.devices; };
|
||||
options = {
|
||||
homefree.devices = lib.mkOption {
|
||||
type = homefreeLib.toplevel;
|
||||
};
|
||||
homefree.testMode = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}).config;
|
||||
disks = lib.attrValues cfg_.homefree.devices.disk;
|
||||
rootDisk = {
|
||||
name = "root";
|
||||
file = ''"$tmp"/${lib.escapeShellArg (builtins.head disks).name}.qcow2'';
|
||||
driveExtraOpts.cache = "writeback";
|
||||
driveExtraOpts.werror = "report";
|
||||
deviceExtraOpts.bootindex = "1";
|
||||
deviceExtraOpts.serial = "root";
|
||||
};
|
||||
otherDisks = map
|
||||
(disk: {
|
||||
name = disk.name;
|
||||
file = ''"$tmp"/${lib.escapeShellArg disk.name}.qcow2'';
|
||||
driveExtraOpts.werror = "report";
|
||||
})
|
||||
(builtins.tail disks);
|
||||
|
||||
diskoBasedConfiguration = {
|
||||
# generated from disko config
|
||||
virtualisation.fileSystems = cfg_.disko.devices._config.fileSystems;
|
||||
boot = cfg_.disko.devices._config.boot or { };
|
||||
swapDevices = cfg_.disko.devices._config.swapDevices or [ ];
|
||||
};
|
||||
|
||||
hostPkgs = config.virtualisation.host.pkgs;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/virtualisation/qemu-vm.nix")
|
||||
diskoBasedConfiguration
|
||||
];
|
||||
|
||||
disko.testMode = true;
|
||||
|
||||
disko.imageBuilder.copyNixStore = false;
|
||||
disko.imageBuilder.extraConfig = {
|
||||
disko.devices = cfg_.disko.devices;
|
||||
};
|
||||
disko.imageBuilder.imageFormat = "qcow2";
|
||||
|
||||
virtualisation.useEFIBoot = config.disko.tests.efi;
|
||||
virtualisation.memorySize = lib.mkDefault config.disko.memSize;
|
||||
virtualisation.useDefaultFilesystems = false;
|
||||
virtualisation.diskImage = null;
|
||||
virtualisation.qemu.drives = [ rootDisk ] ++ otherDisks;
|
||||
boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms
|
||||
boot.zfs.forceImportAll = true;
|
||||
boot.zfs.forceImportRoot = lib.mkForce true;
|
||||
|
||||
system.build.vmWithDisko = hostPkgs.writers.writeDashBin "disko-vm" ''
|
||||
set -efux
|
||||
export tmp=$(${hostPkgs.coreutils}/bin/mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
${lib.concatMapStringsSep "\n" (disk: ''
|
||||
${hostPkgs.qemu}/bin/qemu-img create -f qcow2 \
|
||||
-b ${config.system.build.diskoImages}/${lib.escapeShellArg disk.name}.qcow2 \
|
||||
-F qcow2 "$tmp"/${lib.escapeShellArg disk.name}.qcow2
|
||||
'') disks}
|
||||
set +f
|
||||
${config.system.build.vm}/bin/run-*-vm
|
||||
'';
|
||||
}
|
503
profiles/nixvim.nix
Normal file
503
profiles/nixvim.nix
Normal file
|
@ -0,0 +1,503 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
ripgrep
|
||||
];
|
||||
|
||||
environment.interactiveShellInit = ''
|
||||
alias vi='nvim'
|
||||
alias vim='nvim'
|
||||
'';
|
||||
|
||||
programs.nixvim = {
|
||||
enable = true;
|
||||
|
||||
defaultEditor = true;
|
||||
|
||||
## ------------------------------------------------
|
||||
## Options
|
||||
## ------------------------------------------------
|
||||
|
||||
globals = {
|
||||
mapleader = " "; # global
|
||||
maplocalleader = " "; # per buffer, e.g. can change behavior per filetype
|
||||
};
|
||||
|
||||
opts = {
|
||||
number = true; # Show line numbers
|
||||
relativenumber = true; # Show relative line numbers
|
||||
ruler = true; # displays line, column, and cursor position at bottom
|
||||
wrap = false; # don't wrap lines
|
||||
signcolumn = "yes"; # always show two column sign column on left
|
||||
cursorline = true; # Highlight line cursor sits on
|
||||
|
||||
undodir.__raw = "vim.fs.normalize('~/.local/share/nvim/undo/')";
|
||||
undofile = true;
|
||||
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Backspace settings
|
||||
# indent allow backspacing over autoindent
|
||||
# eol allow backspacing over line breaks (join lines)
|
||||
# start allow backspacing over the start of insert; CTRL-W and CTRL-U
|
||||
# 0 same as ":set backspace=" (Vi compatible)
|
||||
# 1 same as ":set backspace=indent,eol"
|
||||
# 2 same as ":set backspace=indent,eol,start"
|
||||
# -----------------------------------------------------
|
||||
|
||||
bs = "2";
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Indentation settings
|
||||
# -----------------------------------------------------
|
||||
|
||||
tabstop = 4; # number of spaces a tab counts for
|
||||
shiftwidth = 4; # control how many columns text is indented with the reindent operations (<< and >>) and automatic C-style indentation.
|
||||
expandtab = true; # Insert spaces when entering <Tab>
|
||||
softtabstop = 4; # Number of spaces that a <Tab> counts for while performing editing operations, like inserting a <Tab> or using <BS>. It "feels" like a tab though
|
||||
ai = true; # auto indent
|
||||
};
|
||||
|
||||
keymaps = [
|
||||
# -----------------------------------------------------
|
||||
# nvim-tree
|
||||
# -----------------------------------------------------
|
||||
|
||||
## Go to current buffer's file in nvim-tree
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = ",n";
|
||||
action = ":NvimTreeFindFile<CR>";
|
||||
}
|
||||
## Toggle nvim-tree visibility
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = ",m";
|
||||
action = ":NvimTreeToggle<CR>";
|
||||
}
|
||||
|
||||
# -----------------------------------------------------
|
||||
# buffer manipulation
|
||||
# -----------------------------------------------------
|
||||
|
||||
## Next Buffer
|
||||
{
|
||||
key = "<Tab>";
|
||||
action = ":bn<CR>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Previous Buffer
|
||||
{
|
||||
key = "<S-Tab>";
|
||||
action = ":bp<CR>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Close Buffer
|
||||
{
|
||||
key = "<leader><Tab>";
|
||||
action = ":bd<CR>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Force Close Buffer
|
||||
{
|
||||
key = "<leader><S-Tab>";
|
||||
action = ":bd!<CR>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## New Tab
|
||||
{
|
||||
key = "<leader>t";
|
||||
action = ":tabnew split<CR>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Telescope
|
||||
# -----------------------------------------------------
|
||||
|
||||
## Lists files in your current working directory, respects .gitignore
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>ff";
|
||||
action = "<cmd>Telescope find_files<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Finds files by filename
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<c-p>";
|
||||
action = "<cmd>Telescope find_files<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Search for a string in your current working directory and get results live as you type, respects .gitignore. (Requires ripgrep)
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fg";
|
||||
action = "<cmd>Telescope live_grep<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Search file contents
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<c-s>";
|
||||
action = "<cmd>Telescope live_grep<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists open buffers in current neovim instance
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>db";
|
||||
action = "<cmd>Telescope buffers<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists available help tags and opens a new window with the relevant help info on <cr>
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fh";
|
||||
action = "<cmd>Telescope help_tags<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists manpage entries, opens them in a help window on <cr>
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fm";
|
||||
action = "<cmd>Telescope man_pages<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists previously open files
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fp";
|
||||
action = "<cmd>Telescope oldfiles<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists previously open files, Maps to ctrl-/
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<c-_>";
|
||||
action = "<cmd>Telescope oldfiles<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists spelling suggestions for the current word under the cursor, replaces word with selected suggestion on <cr>
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fs";
|
||||
action = "<cmd>Telescope spell_suggest<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists LSP references for iword under the cursor
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fr";
|
||||
action = "<cmd>Telescope lsp_references<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists LSP incoming calls for word under the cursor
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fi";
|
||||
action = "<cmd>Telescope lsp_incoming_calls<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Lists LSP outgoing calls for word under the cursor
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fo";
|
||||
action = "<cmd>Telescope lsp_outgoing_calls<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Dynamically Lists LSP for all workspace symbols
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fw";
|
||||
action = "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<leader>fd";
|
||||
action = "<cmd>Telescope lsp_definitions<cr>";
|
||||
options = { noremap = true; };
|
||||
}
|
||||
## Other Telescope options:
|
||||
## git_files search only files in git, respects .gitignore
|
||||
## oldfiles previously opened files
|
||||
## command_history
|
||||
## search_history
|
||||
## man_pages
|
||||
## resume lists the results including multi-selections of the previous
|
||||
## picker
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Diff
|
||||
# -----------------------------------------------------
|
||||
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = ",d";
|
||||
## @TODO: This doesn't work
|
||||
action = ''
|
||||
function()
|
||||
if next(require('diffview.lib').views) == nil then
|
||||
vim.cmd('DiffviewOpen origin')
|
||||
else
|
||||
vim.cmd('DiffviewClose')
|
||||
end
|
||||
end
|
||||
'';
|
||||
options = { noremap = true; };
|
||||
}
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Bufferline
|
||||
# -----------------------------------------------------
|
||||
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<A-h>";
|
||||
action = ":BufferLineCyclePrev<CR>";
|
||||
options = { noremap = true; silent = true; };
|
||||
}
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<A-l>";
|
||||
action = ":BufferLineCycleNex<CR>";
|
||||
options = { noremap = true; silent = true; };
|
||||
}
|
||||
{
|
||||
mode = [ "n" ];
|
||||
key = "<A-c>";
|
||||
action = ":bdelete!<CR>";
|
||||
options = { noremap = true; silent = true; };
|
||||
}
|
||||
];
|
||||
|
||||
autoCmd = [
|
||||
## Close nvim on last buffer closed, not leaving neovim-tree open
|
||||
{
|
||||
event = [ "BufEnter" ];
|
||||
pattern = [ "NvimTree_*" ];
|
||||
callback = {
|
||||
__raw = ''
|
||||
function()
|
||||
local layout = vim.api.nvim_call_function("winlayout", {})
|
||||
if layout[1] == "leaf" and vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(layout[2]), "filetype") == "NvimTree" and layout[3] == nil then vim.cmd("confirm quit") end
|
||||
end
|
||||
'';
|
||||
};
|
||||
}
|
||||
## Go to same line in file next time it is open
|
||||
{
|
||||
event = [ "BufReadPost" ];
|
||||
pattern = [ "*" ];
|
||||
callback = {
|
||||
__raw = ''
|
||||
function()
|
||||
if vim.fn.line("'\"") > 1 and vim.fn.line("'\"") <= vim.fn.line("$") then
|
||||
vim.api.nvim_exec("normal! g'\"",false)
|
||||
end
|
||||
end
|
||||
'';
|
||||
};
|
||||
}
|
||||
## Highlight tabs and trailing whitespace
|
||||
{
|
||||
event = [ "BufEnter" ];
|
||||
pattern = [ "*" ];
|
||||
callback = {
|
||||
__raw = ''
|
||||
function()
|
||||
vim.cmd([[
|
||||
if exists('w:extratabs')
|
||||
call matchdelete(w:extratabs)
|
||||
unlet w:extratabs
|
||||
endif
|
||||
if exists('w:trailingwhitespace')
|
||||
call matchdelete(w:trailingwhitespace)
|
||||
unlet w:trailingwhitespace
|
||||
endif
|
||||
highlight ExtraTabs ctermbg=red guibg=red
|
||||
highlight TrailingWhitespace ctermbg=red guibg=red
|
||||
if &ft != 'help'
|
||||
let w:extratabs=matchadd('ExtraTabs', '\t\+')
|
||||
let w:trailingwhitespace=matchadd('TrailingWhitespace', '\s\+$')
|
||||
endif
|
||||
]])
|
||||
end
|
||||
'';
|
||||
};
|
||||
}
|
||||
## Trim tailing whitespace on save
|
||||
{
|
||||
event = [ "BufWritePre" ];
|
||||
pattern = [ "*" ];
|
||||
callback = {
|
||||
__raw = ''
|
||||
function()
|
||||
vim.cmd([[
|
||||
if &ft =~ 'javascript\|html\|jade\|json\|css\|less\|php\|python\|sh\|c\|cpp\|markdown\|yaml\|vim\|nix'
|
||||
:%s/\s\+$//e
|
||||
elseif expand('%:t') =~ '\.gltf$' || expand('%:t') =~ '\.glsl$'
|
||||
:%s/\s\+$//e
|
||||
endif
|
||||
]])
|
||||
end
|
||||
'';
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
## ------------------------------------------------
|
||||
## Theme
|
||||
## ------------------------------------------------
|
||||
|
||||
colorschemes.tokyonight.enable = true;
|
||||
|
||||
# colorschemes.gruvbox.enable = true;
|
||||
## Or:
|
||||
# extraPlugins = [ pkgs.vimPlugins.gruvbox ];
|
||||
# colorscheme = "gruvbox";
|
||||
|
||||
## ------------------------------------------------
|
||||
## Included Plugins
|
||||
## ------------------------------------------------
|
||||
|
||||
plugins.bufferline = {
|
||||
enable = true;
|
||||
# extraOptions = {
|
||||
settings = {
|
||||
options = {
|
||||
tabpages = true;
|
||||
sidebar_filetypes = {
|
||||
NvimTree = true;
|
||||
};
|
||||
diagnostics = "nvim_lsp";
|
||||
always_show_bufferline = true;
|
||||
};
|
||||
highlights = {
|
||||
buffer_selected = {
|
||||
# fg = "#ffffff";
|
||||
bold = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
plugins.comment.enable = true;
|
||||
|
||||
plugins.diffview = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
plugins.fugitive.enable = true;
|
||||
|
||||
plugins.gitsigns.enable = true;
|
||||
|
||||
plugins.lightline.enable = true;
|
||||
|
||||
plugins.lualine.enable = true;
|
||||
|
||||
plugins.nvim-autopairs.enable = true;
|
||||
|
||||
plugins.nvim-tree = {
|
||||
enable = true;
|
||||
extraOptions = {
|
||||
actions = {
|
||||
remove_file = {
|
||||
close_window = false;
|
||||
};
|
||||
};
|
||||
## Keep tree open if already open when opening a tab
|
||||
tab = {
|
||||
sync = {
|
||||
open = true;
|
||||
close = true;
|
||||
};
|
||||
};
|
||||
view = {
|
||||
width = 30;
|
||||
};
|
||||
renderer = {
|
||||
group_empty = true;
|
||||
};
|
||||
git = {
|
||||
enable = true;
|
||||
ignore = false;
|
||||
timeout = 500;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
plugins.rainbow-delimiters.enable = true;
|
||||
|
||||
plugins.sleuth.enable = true;
|
||||
|
||||
plugins.telescope = {
|
||||
enable = true;
|
||||
extensions.ui-select.enable = true;
|
||||
settings = {
|
||||
defaults = {
|
||||
mappings = {
|
||||
i = {
|
||||
# One instead of two esc taps to exit telescope
|
||||
"<esc>" = {
|
||||
__raw = "require('telescope.actions').close";
|
||||
};
|
||||
# Ctrl-space is used by Tmux, so remap to Ctrl-e
|
||||
"<c-e>" = {
|
||||
__raw = "require('telescope.actions').to_fuzzy_refine";
|
||||
};
|
||||
# "<c-o>" = {
|
||||
# __raw = "require('trouble.sources.telescope').open";
|
||||
# };
|
||||
};
|
||||
n = {
|
||||
# "<c-o>" = {
|
||||
# __raw = "require('trouble.sources.telescope').open";
|
||||
# };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
plugins.treesitter.enable = true;
|
||||
|
||||
plugins.tmux-navigator.enable = true;
|
||||
|
||||
plugins.trouble.enable = true;
|
||||
|
||||
# ## Needed for telescope, nvim-tree, trouble, diffview, bufferline, and other plugins
|
||||
# ## Only on unstable at the moment
|
||||
plugins.web-devicons.enable = true;
|
||||
|
||||
## ------------------------------------------------
|
||||
## Extra Plugins
|
||||
## ------------------------------------------------
|
||||
|
||||
extraPlugins = with pkgs.vimPlugins; [
|
||||
vim-nix
|
||||
{
|
||||
plugin = vim-signify;
|
||||
config = ''
|
||||
let g:signify_vcs_cmds = { 'git': 'git diff --no-color --no-ext-diff -U0 master -- %f' }
|
||||
let g:signify_priority = 1
|
||||
highlight SignColumn ctermbg=237
|
||||
'';
|
||||
}
|
||||
vim-surround
|
||||
|
||||
## focus-nvim only in unstable
|
||||
# (pkgs.vimUtils.buildVimPlugin {
|
||||
# name = "focus-nvim";
|
||||
# src = pkgs.fetchFromGitHub {
|
||||
# owner = "nvim-focus";
|
||||
# repo = "focus.nvim";
|
||||
# rev = "3841a38df972534567e85840d7ead20d3a26faa6";
|
||||
# sha256 = "sha256-mgHk4u0ab2uSUNE+7DU22IO/xS5uop9iATfFRk6l6hs=";
|
||||
# };
|
||||
# })
|
||||
];
|
||||
};
|
||||
}
|
19
profiles/postgres.nix
Normal file
19
profiles/postgres.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{ lib, pkgs, ... }:
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
# Authentik sets an older package for some reason
|
||||
package = lib.mkForce pkgs.postgresql_16;
|
||||
enableTCPIP = true;
|
||||
authentication = pkgs.lib.mkOverride 10 ''
|
||||
#type database DBuser auth-method
|
||||
local all all trust
|
||||
|
||||
#type database DBuser origin-address auth-method
|
||||
# ipv4
|
||||
host all all 127.0.0.1/32 trust
|
||||
# ipv6
|
||||
host all all ::1/128 trust
|
||||
'';
|
||||
};
|
||||
}
|
33
profiles/radvd.nix
Normal file
33
profiles/radvd.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
lan-interface = config.homefree.network.lan-interface;
|
||||
in
|
||||
{
|
||||
services.radvd = {
|
||||
enable = true;
|
||||
config = ''
|
||||
interface ${lan-interface}
|
||||
{
|
||||
AdvSendAdvert on;
|
||||
MinRtrAdvInterval 3;
|
||||
MaxRtrAdvInterval 10;
|
||||
AdvDefaultPreference low;
|
||||
AdvHomeAgentFlag off;
|
||||
prefix ::/64
|
||||
{
|
||||
AdvOnLink on;
|
||||
AdvAutonomous on;
|
||||
AdvRouterAddr off;
|
||||
AdvPreferredLifetime 120;
|
||||
AdvValidLifetime 300;
|
||||
};
|
||||
# Next line has the IPv6 address of a DNS server:
|
||||
RDNSS 2001:4860:4860::8888
|
||||
{
|
||||
AdvRDNSSLifetime 30;
|
||||
};
|
||||
};
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
@ -1,18 +1,14 @@
|
|||
{ config, inputs, pkgs, ... }:
|
||||
{ config, homefree-inputs, pkgs, ... }:
|
||||
|
||||
let
|
||||
# @TODO: How to determine interface names?
|
||||
# wan-interface = "ens5";
|
||||
wan-interface = "ens3";
|
||||
# lan-interface = "ens6";
|
||||
lan-interface = "ens5";
|
||||
wan-interface = config.homefree.network.wan-interface;
|
||||
lan-interface = config.homefree.network.lan-interface;
|
||||
wireguard-port = config.homefree.wireguard.listenPort;
|
||||
vlan-wan-id = 100;
|
||||
vlan-lan-id = 200;
|
||||
vlan-iot-id = 201;
|
||||
vlan-guest-id = 202;
|
||||
# lan-interface = "ens3";
|
||||
dns-servers = [ "1.1.1.1" "1.0.0.1" ];
|
||||
adlist = inputs.adblock-unbound.packages.${pkgs.system};
|
||||
in
|
||||
{
|
||||
|
||||
|
@ -28,21 +24,47 @@ in
|
|||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
boot.kernel.sysctl = {
|
||||
# if you use ipv4, this is all you need
|
||||
# enable ipv4 forwarding
|
||||
"net.ipv4.conf.all.forwarding" = true;
|
||||
|
||||
# If you want to use it for ipv6
|
||||
# enable ipv6 forwarding
|
||||
"net.ipv6.conf.all.forwarding" = true;
|
||||
|
||||
# source: https://github.com/mdlayher/homelab/blob/master/nixos/routnerr-2/configuration.nix#L52
|
||||
# source: https://github.com/mdlayher/homelab/blob/master/nixos/routnerr-3/configuration.nix#L46[]
|
||||
# By default, not automatically configure any IPv6 addresses.
|
||||
"net.ipv6.conf.all.accept_ra" = 0;
|
||||
"net.ipv6.conf.all.autoconf" = 0;
|
||||
"net.ipv6.conf.all.use_tempaddr" = 0;
|
||||
# "net.ipv6.conf.all.accept_ra" = 0;
|
||||
# "net.ipv6.conf.all.autoconf" = 0;
|
||||
# "net.ipv6.conf.all.use_tempaddr" = 0;
|
||||
|
||||
# On WAN, allow IPv6 autoconfiguration and tempory address use.
|
||||
"net.ipv6.conf.${wan-interface}.accept_ra" = 2;
|
||||
"net.ipv6.conf.${wan-interface}.autoconf" = 1;
|
||||
"net.ipv6.conf.${lan-interface}.accept_ra" = 2;
|
||||
"net.ipv6.conf.${lan-interface}.autoconf" = 1;
|
||||
};
|
||||
|
||||
systemd.network = {
|
||||
networks = {
|
||||
"01-${lan-interface}" = {
|
||||
name = lan-interface;
|
||||
networkConfig = {
|
||||
Description = "LAN link";
|
||||
Address = "10.0.0.1/24";
|
||||
LinkLocalAddressing = "yes";
|
||||
IPv6AcceptRA = "no";
|
||||
# Announce a prefix here and act as a router.
|
||||
IPv6SendRA = "yes";
|
||||
# Use a DHCPv6-PD delegated prefix (DHCPv6PrefixDelegation.SubnetId)
|
||||
# from the pool and assigns one /64 to this network.
|
||||
DHCPPrefixDelegation = "yes";
|
||||
};
|
||||
ipv6SendRAConfig = {
|
||||
# Currently dnsmasq manages DNS servers.
|
||||
EmitDNS = "no";
|
||||
EmitDomains = "no";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
|
@ -51,7 +73,11 @@ in
|
|||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
useDHCP = false;
|
||||
nameservers = dns-servers;
|
||||
## @TODO: Base on config for lan gateway
|
||||
nameservers = [ "10.0.0.1" ];
|
||||
|
||||
# resolvconf = {
|
||||
# };
|
||||
|
||||
## Define VLANS
|
||||
## https://www.breakds.org/post/vlan-configuration-by-examples/
|
||||
|
@ -75,16 +101,19 @@ in
|
|||
# };
|
||||
|
||||
interfaces = {
|
||||
# Don't request DHCP on the physical interfaces
|
||||
${wan-interface} = {
|
||||
# useDHCP = false;
|
||||
useDHCP = true;
|
||||
};
|
||||
${lan-interface} = {
|
||||
useDHCP = false;
|
||||
ipv4.addresses = [{
|
||||
address = "10.1.1.1";
|
||||
address = "10.0.0.1";
|
||||
prefixLength = 24;
|
||||
}];
|
||||
# ipv6.addresses = [{
|
||||
# address = "2001:DB8::";
|
||||
# prefixLength = 64;
|
||||
# }];
|
||||
};
|
||||
|
||||
# Handle the VLANs
|
||||
|
@ -93,7 +122,7 @@ in
|
|||
# };
|
||||
# lan = {
|
||||
# ipv4.addresses = [{
|
||||
# address = "10.1.1.1";
|
||||
# address = "10.0.0.1";
|
||||
# prefixLength = 24;
|
||||
# }];
|
||||
# };
|
||||
|
@ -115,7 +144,10 @@ in
|
|||
# Firewall
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
nat.enable = false;
|
||||
## @TODO: Evaluate this
|
||||
# nat.enable = false;
|
||||
|
||||
## @TODO: Evaluate this
|
||||
firewall.enable = false;
|
||||
|
||||
## @TODO: Look into nftables Nix DSL: https://github.com/chayleaf/notnft
|
||||
|
@ -125,35 +157,69 @@ in
|
|||
ruleset = ''
|
||||
flush ruleset
|
||||
|
||||
# table ip filter {
|
||||
# # allow all packets sent by the firewall machine itself
|
||||
# chain output {
|
||||
# type filter hook output priority 100; policy accept;
|
||||
# }
|
||||
#
|
||||
# # allow LAN to firewall, disallow WAN to firewall
|
||||
# chain input {
|
||||
# type filter hook input priority 0; policy accept;
|
||||
# iifname "${lan-interface}" accept
|
||||
# iifname "${wan-interface}" drop
|
||||
# }
|
||||
#
|
||||
# # allow packets from LAN to WAN, and WAN to LAN if LAN initiated the connection
|
||||
# chain forward {
|
||||
# type filter hook forward priority 0; policy drop;
|
||||
# iifname "${lan-interface}" oifname "${wan-interface}" accept
|
||||
# iifname "${wan-interface}" oifname "${lan-interface}" ct state related,established accept
|
||||
# }
|
||||
# }
|
||||
## "inet" indicates both ipv4 and ipv6
|
||||
table inet filter {
|
||||
## allow all packets sent by the firewall machine itself
|
||||
chain output {
|
||||
type filter hook output priority 100; policy accept;
|
||||
}
|
||||
|
||||
## allow LAN to firewall, disallow WAN to firewall
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
|
||||
## Allow for web traffic
|
||||
tcp dport { https } ct state new accept;
|
||||
|
||||
## Allow wireguard connections
|
||||
udp dport { ${toString wireguard-port} } ct state new accept;
|
||||
|
||||
## Allow for ipv6 route advertisements
|
||||
icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert, mld-listener-query } accept;
|
||||
|
||||
# DHCPv6
|
||||
ip6 saddr fe80::/10 ip6 daddr fe80::/10 udp sport 547 udp dport 546 accept
|
||||
|
||||
iifname { "lo" } accept comment "Allow localhost to access the router"
|
||||
iifname { "${lan-interface}" } accept comment "Allow local network to access the router"
|
||||
iifname { "wg0" } accept comment "Allow wireguard network to access the router"
|
||||
|
||||
iifname "${wan-interface}" ct state { established, related } accept comment "Allow established traffic"
|
||||
iifname "${wan-interface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
|
||||
iifname "${wan-interface}" counter drop comment "Drop all other unsolicited traffic from wan"
|
||||
}
|
||||
|
||||
## allow packets from LAN to WAN, and WAN to LAN if LAN initiated the connection
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
|
||||
## LAN-WAN
|
||||
iifname { "${lan-interface}" } oifname { "${wan-interface}" } accept comment "Allow trusted LAN to WAN"
|
||||
iifname { "${wan-interface}" } oifname { "${lan-interface}" } ct state established, related accept comment "Allow established back to LANs"
|
||||
|
||||
## @TODO: Confirm which, if any, of these are needed.
|
||||
|
||||
## Wireguard-WAN
|
||||
iifname { "wg0" } oifname { "${wan-interface}" } accept comment "Allow trusted wireguard to WAN"
|
||||
iifname { "${wan-interface}" } oifname { "wg0" } ct state established, related accept comment "Allow established back to wireguard"
|
||||
|
||||
## Wireguard-LAN
|
||||
iifname { "wg0" } oifname { "${lan-interface}" } accept comment "Allow trusted wireguard to LAN"
|
||||
iifname { "${lan-interface}" } oifname { "wg0" } ct state established, related accept comment "Allow established back to wireguard"
|
||||
}
|
||||
}
|
||||
|
||||
## only need "ip" (ipv4), not "inet" (ipv4+ipv6) as it breaks ipv6 on clients. NAT is not needed for ipv6.
|
||||
table ip nat {
|
||||
chain prerouting {
|
||||
## Lower priority number indicates higher priority
|
||||
type nat hook prerouting priority 0; policy accept;
|
||||
}
|
||||
|
||||
# for all packets to WAN, after routing, replace source address with primary IP of WAN interface
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100; policy accept;
|
||||
## This handles both wg0 and the lan interface
|
||||
oifname "${wan-interface}" masquerade
|
||||
}
|
||||
}
|
||||
|
@ -161,6 +227,27 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
# systemd.services.block-wan-traffic = {
|
||||
# wantedBy = [ "multi-user.target" ];
|
||||
# enable = true;
|
||||
# serviceConfig = {
|
||||
# User = "root";
|
||||
# Group = "root";
|
||||
# };
|
||||
# script = ''
|
||||
# IPTABLES=${pkgs.iptables}/bin/iptables
|
||||
#
|
||||
# $IPTABLES -A INPUT -i ${wan-interface} -p tcp -m tcp -m multiport --dports 80,443 -j ACCEPT
|
||||
# $IPTABLES -A INPUT -i ${wan-interface} -p tcp -m tcp -m multiport --dports ${toString config.homefree.wireguard.listenPort} -j ACCEPT
|
||||
# $IPTABLES -A INPUT -i ${wan-interface} -m conntrack -j ACCEPT --ctstate RELATED,ESTABLISHED
|
||||
# $IPTABLES -A INPUT -i ${wan-interface} -j DROP
|
||||
# # $IPTABLES -A OUTPUT -o ${wan-interface} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
# # $IPTABLES -A OUTPUT -o ${wan-interface} -j DROP
|
||||
# # $IPTABLES -A FORWARD -i ${wan-interface} -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
# # $IPTABLES -A FORWARD -i ${wan-interface} -j DROP
|
||||
# '';
|
||||
# };
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# Performance Tuning
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
@ -184,26 +271,26 @@ in
|
|||
smp2=3
|
||||
rps2=2
|
||||
|
||||
ens3_irq=$($GREP ens3 /proc/interrupts | $AWK '{ print $1+0 }')
|
||||
wan_irq=$($GREP ${wan-interface} /proc/interrupts | $AWK '{ print $1+0 }')
|
||||
|
||||
# set balancer for enp1s0
|
||||
echo $smp1 > /proc/irq/$ens3_irq/smp_affinity
|
||||
echo $smp1 > /proc/irq/$wan_irq/smp_affinity
|
||||
|
||||
# set rps for ens3
|
||||
echo $rps1 > /sys/class/net/ens3/queues/rx-0/rps_cpus
|
||||
# set rps for wan interface
|
||||
echo $rps1 > /sys/class/net/${wan-interface}/queues/rx-0/rps_cpus
|
||||
|
||||
ens5_irq=$($GREP ens5 /proc/interrupts | $AWK '{ print $1+0 }')
|
||||
lan_irq=$($GREP ${lan-interface} /proc/interrupts | $AWK '{ print $1+0 }')
|
||||
|
||||
# set balancer for enp2s0
|
||||
# echo $smp2 > /proc/irq/$ens5_irq/smp_affinity
|
||||
# echo $smp2 > /proc/irq/$lan_irq/smp_affinity
|
||||
|
||||
# set rps for ens5
|
||||
echo $rps2 > /sys/class/net/ens5/queues/rx-0/rps_cpus
|
||||
# set rps for lan interface
|
||||
echo $rps2 > /sys/class/net/${lan-interface}/queues/rx-0/rps_cpus
|
||||
'';
|
||||
};
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# DHCP
|
||||
# DHCP/DNS
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
# See: https://nixos.wiki/wiki/Systemd-resolved
|
||||
|
@ -218,134 +305,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
services.dnsmasq = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
## @TODO
|
||||
## @WARNING - changes to this do not clear out old entries from /etc/dnsmasq-conf.conf
|
||||
|
||||
## Only DHCP server on network
|
||||
dhcp-authoritative = true;
|
||||
|
||||
## Enable Router Advertising for ipv6
|
||||
enable-ra = true;
|
||||
|
||||
## DNS servers to pass to clients
|
||||
server = dns-servers;
|
||||
|
||||
## Which interfaces to bind to
|
||||
interface = [
|
||||
# "${lan-interface}.${builtins.toString vlan-lan-id}"
|
||||
# "${lan-interface}.${builtins.toString vlan-iot-id}"
|
||||
# "${lan-interface}.${builtins.toString vlan-guest-id}"
|
||||
lan-interface
|
||||
];
|
||||
|
||||
## IP ranges to hand out
|
||||
dhcp-range = [
|
||||
# "lan,10.1.1.100,10.1.1.254,255.255.255.0,8h"
|
||||
# "iot,10.2.1.100,10.2.1.254,255.255.255.0,8h"
|
||||
# "guest,10.3.1.100,10.3.1.254,255.255.255.0,8h"
|
||||
"${lan-interface},10.1.1.100,10.1.1.254,255.255.255.0,8h"
|
||||
];
|
||||
|
||||
## Disable DNS
|
||||
port = 0;
|
||||
|
||||
## Additional DHCP options
|
||||
dhcp-option = [
|
||||
"option6:dns-server,[::]" # @TODO: point this at Unbound when ipv6 is setup
|
||||
"option:dns-server,10.1.1.1"
|
||||
];
|
||||
|
||||
cache-size = 500;
|
||||
};
|
||||
};
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# DNS
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
## @TODO - Setup Unbound
|
||||
## See: https://blog.josefsson.org/2015/10/26/combining-dnsmasq-and-unbound/
|
||||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
|
||||
user = "root";
|
||||
|
||||
resolveLocalQueries = true;
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
include = [
|
||||
"\"${adlist.unbound-adblockStevenBlack}\""
|
||||
];
|
||||
interface = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
"10.1.1.1"
|
||||
];
|
||||
access-control = [
|
||||
"127.0.0.1/8 allow"
|
||||
"::1 allow"
|
||||
"10.1.1.1/8 allow"
|
||||
# @TODO: need ipv6 address
|
||||
];
|
||||
outgoing-interface = [
|
||||
## @TODO: should be WAN IP - how to get this automatically?
|
||||
"10.0.2.15"
|
||||
# @TODO: need ipv6 address
|
||||
];
|
||||
local-zone = [
|
||||
"\"homefree.lan.\" static"
|
||||
];
|
||||
local-data = [
|
||||
"\"radicale.lan. IN A 10.1.1.1\""
|
||||
];
|
||||
local-data-ptr = [
|
||||
"\"10.1.1.1 radicale.lan\""
|
||||
];
|
||||
};
|
||||
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = [
|
||||
"1.1.1.1@853#cloudflare-dns.com"
|
||||
"1.0.0.1@853#cloudflare-dns.com"
|
||||
];
|
||||
forward-tls-upstream = "yes";
|
||||
}
|
||||
# {
|
||||
# name = "example.org.";
|
||||
# forward-addr = [
|
||||
# "1.1.1.1@853#cloudflare-dns.com"
|
||||
# "1.0.0.1@853#cloudflare-dns.com"
|
||||
# ];
|
||||
# }
|
||||
];
|
||||
remote-control.control-enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# Dynamic DNS
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
||||
# @TODO: https://discourse.nixos.org/t/ddclient-options/20935
|
||||
services.ddclient = {
|
||||
enable = true;
|
||||
interval = "10m";
|
||||
# protocol = "zoneedit1";
|
||||
# username = "erahhal";
|
||||
# zone = "homefree.host";
|
||||
# passwordFile = config.age.secrets.ddclient.path;
|
||||
# verbose = true;
|
||||
configFile = config.age.secrets.ddclient-conf.path;
|
||||
};
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
# Service Discovery
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
@ -361,7 +320,7 @@ in
|
|||
];
|
||||
|
||||
# network locator e.g. scanners and printers
|
||||
nssmdns = true;
|
||||
nssmdns4 = true;
|
||||
};
|
||||
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
|
|
170
profiles/traffic-shaping.nix
Normal file
170
profiles/traffic-shaping.nix
Normal file
|
@ -0,0 +1,170 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
## @TODO: Convert to work with nftables
|
||||
## @TODO: Test with ethernet cable using the following: https://www.waveform.com/tools/bufferbloat
|
||||
|
||||
let
|
||||
wan-interface = config.homefree.network.wan-interface;
|
||||
wan-bitrate-mbps-down = config.homefree.network.wan-bitrate-mbps-down;
|
||||
wan-bitrate-mbps-down-95-percent = builtins.floor (builtins.mul wan-bitrate-mbps-down 0.95);
|
||||
wan-bitrate-mbps-down-20-percent = builtins.floor (builtins.mul wan-bitrate-mbps-down 0.20);
|
||||
in
|
||||
{
|
||||
## OPNSense Config
|
||||
## ---------------
|
||||
## Pipe
|
||||
## Name: Downstream Pipe
|
||||
## Bandwidth: 950 Mbit/s
|
||||
## Scheduler: FlowQueue-CoDel
|
||||
## CoDel enabled
|
||||
## Pipe
|
||||
## Name: Upstream Pipe
|
||||
## Bandwidth: 950 Mbit/s
|
||||
## Scheduler: FlowQueue-CoDel
|
||||
## CoDel enabled
|
||||
## Queue
|
||||
## Name: Upstream Queue
|
||||
## Pipe: Upstream Pipe
|
||||
## Weight: 1
|
||||
## Queue
|
||||
## Name: Downstream Queue
|
||||
## Pipe: Downstream Pipe
|
||||
## Weight: 1
|
||||
## Queue
|
||||
## Name: High Priority Queue
|
||||
## Pipe: Upstream Pipe
|
||||
## Weight: 10
|
||||
## Rule
|
||||
## Name: DNS High Priority
|
||||
## Sequence: 11
|
||||
## Interface: WAN
|
||||
## Protocol: UDP
|
||||
## Source: 10.0.0.1 (lan gateway)
|
||||
## Src-port: any
|
||||
## Destination: any
|
||||
## Dst-port: 53
|
||||
## Target: High Priority Queue
|
||||
## Rule
|
||||
## Name: Upstream traffic
|
||||
## Sequence: 12
|
||||
## Interface: WAN
|
||||
## Protocol: IP
|
||||
## Source: 10.0.0.0/24 (lan)
|
||||
## Src-port: any
|
||||
## Destination: any
|
||||
## Dst-port: any
|
||||
## Target: Upstream queue
|
||||
## Rule
|
||||
## Name: ACK High Priority
|
||||
## Sequence: 13
|
||||
## Interface: WAN
|
||||
## Protocol: tcp (ACK packets only)
|
||||
## Source: 10.0.0.0/24 (lan)
|
||||
## Src-port: any
|
||||
## Destination: any
|
||||
## Dst-port: any
|
||||
## Target: High Priority Queue
|
||||
## Rule
|
||||
## Name: Downstream traffic
|
||||
## Sequence: 14
|
||||
## Interface: WAN
|
||||
## Protocol: ip
|
||||
## Source: any
|
||||
## Src-port: any
|
||||
## Destination: 10.0.0.0/24 (lan)
|
||||
## Dst-port: any
|
||||
## Target: Downstream queue
|
||||
|
||||
## Disable TCP offload engine, which bypasses traffic shaper to save on CPU
|
||||
systemd.services.disable-transmit-segment-offload = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
enable = true;
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
# script = builtins.readFile ../scripts/tune_router_performance.sh;
|
||||
script = ''
|
||||
ETHTOOL=${pkgs.ethtool}/bin/ethtool
|
||||
|
||||
$ETHTOOL -K ${wan-interface} tso off
|
||||
$ETHTOOL -K ${wan-interface} gso off
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.traffic-shaper = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
enable = true;
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
Group = "root";
|
||||
};
|
||||
# script = builtins.readFile ../scripts/tune_router_performance.sh;
|
||||
script = ''
|
||||
TC=${pkgs.iproute2}/bin/tc
|
||||
IPTABLES=${pkgs.iptables}/bin/iptables
|
||||
|
||||
# CoDel Active Queue Management (AQM) algorithm
|
||||
# https://www.bufferbloat.net/projects/codel/wiki/
|
||||
|
||||
# fq_codel only supported by certain network drivers
|
||||
# https://www.bufferbloat.net/projects/bloat/wiki/BQL_enabled_drivers/
|
||||
|
||||
# Reference for rules below
|
||||
# https://wiki.archlinux.org/title/Advanced_traffic_control
|
||||
# https://www.linuxquestions.org/questions/linux-networking-3/traffic-shaping-with-tc-on-a-server-4175690429-print/
|
||||
|
||||
# Remove existing queues
|
||||
# redirect errors to /dev/null in case the qdisc doesn't exist
|
||||
$TC qdisc del dev ${wan-interface} ingress 2>/dev/null || true
|
||||
$TC qdisc del dev ${wan-interface} root 2>/dev/null || true
|
||||
|
||||
# 1) Add/Replace root qdisc of eth0 with an HTB instance,
|
||||
# specify handle so it can be referred to by other rules,
|
||||
# set default class for all unclassified traffic
|
||||
|
||||
$TC qdisc replace dev ${wan-interface} root handle 1: htb default 30
|
||||
|
||||
# 2) Create single top level class with handle 1:1 which limits
|
||||
# total traffic to slightly less than the path max
|
||||
# Limit to 95% of maximum bandwidth
|
||||
|
||||
$TC class add dev ${wan-interface} parent 1: classid 1:1 htb rate ${toString wan-bitrate-mbps-down-95-percent}mbit
|
||||
|
||||
# 3) Create child classes for different uses:
|
||||
# Class 1:10 is our outgoing highest priority path, outgoing SSH/SFTP in this example
|
||||
# Class 1:20 is our next highest priority path, web admin traffic for example
|
||||
# Class 1:30 is default and has lowest priority but highest total bandwidth - bulk web traffic for example
|
||||
|
||||
$TC class add dev ${wan-interface} parent 1:1 classid 1:10 htb rate 1mbit ceil ${toString wan-bitrate-mbps-down-20-percent}mbit prio 1
|
||||
$TC class add dev ${wan-interface} parent 1:1 classid 1:20 htb rate 1mbit ceil ${toString wan-bitrate-mbps-down-20-percent}mbit prio 2
|
||||
$TC class add dev ${wan-interface} parent 1:1 classid 1:30 htb rate 1mbit ceil ${toString wan-bitrate-mbps-down-95-percent}mbit prio 3
|
||||
|
||||
# 4) Attach a leaf qdisc to each child class
|
||||
# HTB by default attaches pfifo as leaf so this is optional.
|
||||
# fq_codel is said to be worth the effort.
|
||||
|
||||
$TC qdisc add dev ${wan-interface} parent 1:10 fq_codel
|
||||
$TC qdisc add dev ${wan-interface} parent 1:20 fq_codel
|
||||
$TC qdisc add dev ${wan-interface} parent 1:30 fq_codel
|
||||
|
||||
# 5) Add filters for priority traffic
|
||||
$TC filter add dev ${wan-interface} parent 1: handle 100 fw classid 1:10
|
||||
$TC filter add dev ${wan-interface} parent 1: handle 200 fw classid 1:20
|
||||
|
||||
# Shape traffic
|
||||
## -t mangle mangle table, used for modifying packet headers
|
||||
## -A OUTPUT Append to OUTPUT chain (OUTPUT being packets leaving the system)
|
||||
## -p tcp TCP protocol
|
||||
## --match multiport Match multiple ports
|
||||
## --dports 53 Match destination port of 53 (DNS)
|
||||
## -j MARK What to do on match. Jump to MARK (to set the netfilter mark value associated with the packet. It is only valid in the mangle table)
|
||||
## --set-mark 200 Set connection mark of 200, which matches the tc filter above
|
||||
|
||||
## DNS High Priority
|
||||
$IPTABLES -t mangle -A OUTPUT -p tcp --match multiport --dports 53 -j MARK --set-mark 100
|
||||
## ACK High Priority
|
||||
$IPTABLES -t mangle -A OUTPUT -p tcp --match tcp --tcp-flags ACK ACK -j MARK --set-mark 100
|
||||
'';
|
||||
};
|
||||
}
|
251
profiles/unbound.nix
Normal file
251
profiles/unbound.nix
Normal file
|
@ -0,0 +1,251 @@
|
|||
{ homefree-inputs, config, lib, pkgs, ... }:
|
||||
let
|
||||
adlist = homefree-inputs.adblock-unbound.packages.${pkgs.system};
|
||||
zones = [config.homefree.system.domain] ++ config.homefree.system.additionalDomains;
|
||||
preStart = ''
|
||||
touch /run/unbound/include.conf
|
||||
cat > /run/unbound/dynamic.zone<< EOF
|
||||
\$ORIGIN ${config.homefree.system.localDomain}.
|
||||
\$TTL 3600
|
||||
@ IN SOA localhost. root.localhost. (
|
||||
2023100101 ; serial
|
||||
3600 ; refresh
|
||||
1800 ; retry
|
||||
604800 ; expire
|
||||
86400 ; minimum
|
||||
)
|
||||
IN NS localhost.
|
||||
EOF
|
||||
# cp /run/unbound/dynamic.zone /tmp
|
||||
'';
|
||||
in
|
||||
{
|
||||
## See: https://blog.josefsson.org/2015/10/26/combining-dnsmasq-and-unbound/
|
||||
|
||||
## Unbound is a caching resolver, not meant to be used as authoritative.
|
||||
## nbound does support simple authoritative hosting with local-zone config.
|
||||
## For a proper authoritative DNS, look at NSD.
|
||||
|
||||
systemd.services.unbound = {
|
||||
serviceConfig = {
|
||||
ExecStartPre = [ "!${pkgs.writeShellScript "unbound-prestart" preStart}" ];
|
||||
};
|
||||
};
|
||||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
|
||||
user = "root";
|
||||
|
||||
resolveLocalQueries = true;
|
||||
|
||||
settings = {
|
||||
server = {
|
||||
include = [
|
||||
## Leave ad-blocking to AdGuard, as it can be disabled by the client
|
||||
# "\"${adlist.unbound-adblockStevenBlack}\""
|
||||
|
||||
## Include run-time config, such as WAN ip mappings
|
||||
## @TODO: Update this with ddclient scripts
|
||||
## @TODO: Remove WAN entries from bare hostname maps below
|
||||
"\"/run/unbound/include.conf\""
|
||||
];
|
||||
port = 53530;
|
||||
interface = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
"10.0.0.1"
|
||||
"192.168.2.1" # wireguard
|
||||
];
|
||||
access-control = [
|
||||
"127.0.0.1/24 allow"
|
||||
"::1 allow"
|
||||
"10.0.0.1/24 allow"
|
||||
"192.168.2.1/24 allow"
|
||||
];
|
||||
# outgoing-interface = [
|
||||
# ## @TODO: should be WAN IP - how to get this automatically?
|
||||
# "10.0.2.15"
|
||||
# # @TODO: need ipv6 address
|
||||
# ];
|
||||
local-zone = [
|
||||
"\"homefree.lan\" static"
|
||||
"\"homefree.host\" transparent"
|
||||
"\"rahh.al\" transparent"
|
||||
];
|
||||
## @TODO: Add config.homefree.network.blocked-domains as such:
|
||||
# local-zone: "example.org" always_nxdomain
|
||||
|
||||
## Record format:
|
||||
## NAME CLASS (default: IN) TYPE RDATA
|
||||
## localhost IN A 127.0.0.1
|
||||
local-data =
|
||||
[
|
||||
"\"localhost A 127.0.0.1\""
|
||||
"\"localhost AAAA ::1\""
|
||||
]
|
||||
++
|
||||
## add localhost.<zone> for all configured zones
|
||||
(lib.map (zone: "\"localhost.${zone} IN A 127.0.0.1\"") zones)
|
||||
++
|
||||
## add <hostname>.<zone> for all configured zones
|
||||
(lib.map (zone: "\"${config.homefree.system.hostName}.${zone} IN A 127.0.0.1\"") zones)
|
||||
++
|
||||
# Add DNS overrides
|
||||
(lib.map (local-data-config:
|
||||
if builtins.hasAttr "domain" local-data-config then
|
||||
"\"${local-data-config.hostname}.${local-data-config.domain} IN A ${local-data-config.ip}\""
|
||||
else
|
||||
"\"${local-data-config.hostname} IN A ${local-data-config.ip}\""
|
||||
) config.homefree.network.dns-overrides
|
||||
)
|
||||
++
|
||||
# Point proxy URLs to internal IP when on LAN
|
||||
(lib.map
|
||||
(fqn: "\"${fqn} IN A 10.0.0.1\"")
|
||||
## Flatten to single list
|
||||
## e.g. [ "hij.lmnop" "hij".xyz" "abc.lmnop" "abc.xyz" "def.lmnop" "def.xyz" ]
|
||||
(lib.flatten
|
||||
## Map across all proxy configs
|
||||
## creating list of lists
|
||||
## e.g. [ [ "hij.lmnop" "hij".xyz" ] [ "abc.lmnop" "abc.xyz" "def.lmnop" "def.xyz" ] ]
|
||||
(lib.map
|
||||
(proxy-config:
|
||||
## Flatten subdomain-domain combinations for individual proxy into single list
|
||||
## e.g. [ "abc.lmnop" "abc.xyz" "def.lmnop" "def.xyz" ]
|
||||
lib.flatten
|
||||
## Create all subdomain-domain combinations, grouped by subdomain
|
||||
## e.g. [ [ "abc.lmnop" "abc.xyz" ] [ "def.lmnop" "def.xyz" ]]
|
||||
(lib.map
|
||||
(subdomain:
|
||||
# Create <subdomain>.<domain> fqn string
|
||||
(lib.map
|
||||
(domain: "${subdomain}.${domain}")
|
||||
(proxy-config.http-domains ++ proxy-config.https-domains)
|
||||
)
|
||||
)
|
||||
proxy-config.subdomains
|
||||
)
|
||||
)
|
||||
## @TODO: Get rid of this filter
|
||||
## See: https://caddy.community/t/caddy-not-handling-requests-when-listening-on-all-interfaces-serving-a-hostname-mapped-to-an-internal-ip/26384
|
||||
# (lib.filter (proxy-config: proxy-config.public == false) config.homefree.proxied-hosts)
|
||||
config.homefree.proxied-hosts
|
||||
)
|
||||
)
|
||||
)
|
||||
++
|
||||
## router lan ip with public domains
|
||||
(lib.map (zone: "\"${config.homefree.system.hostName}.${zone} IN A 10.0.0.1\"") zones)
|
||||
++
|
||||
## router vpn ip with public domains
|
||||
(lib.map (zone: "\"${config.homefree.system.hostName}.${zone} IN A 192.168.2.1\"") zones)
|
||||
++
|
||||
## @TODO: Move to config for gateway IP
|
||||
[
|
||||
## router lan IP
|
||||
"\"${config.homefree.system.hostName} IN A 10.0.0.1\""
|
||||
## router lan IP with local domain
|
||||
"\"${config.homefree.system.hostName}.${config.homefree.system.localDomain} IN A 10.0.0.1\""
|
||||
|
||||
## router vpn IP
|
||||
"\"${config.homefree.system.hostName} IN A 192.168.2.1\""
|
||||
## router vpn IP with local domain
|
||||
"\"${config.homefree.system.hostName}.${config.homefree.system.localDomain} IN A 192.168.2.1\""
|
||||
]
|
||||
++
|
||||
## @TODO: How to configure these at runtime?
|
||||
## router wan IP with public domain
|
||||
(lib.map (zone: "\"${config.homefree.system.hostName}.${zone} IN A 104.182.229.64\"") zones)
|
||||
++
|
||||
## Bare hostname maps
|
||||
[
|
||||
## router wan IP - @TODO - THIS NEEDS TO BE DYNAMIC
|
||||
"\"${config.homefree.system.hostName} IN A 104.182.229.64\""
|
||||
## router wan ipv6 IP - @TODO - THESE ARE WRONG
|
||||
"\"${config.homefree.system.hostName} IN AAAA 2600:1700:ab00:4650:2e0:67ff:fe22:3e62\""
|
||||
## ??? @TODO - WHAT IS THIS?
|
||||
"\"${config.homefree.system.hostName} IN AAAA 2600:1700:ab00:465f:2e0:67ff:fe22:3e63\""
|
||||
]
|
||||
++
|
||||
## router wan IPv6 with public domain
|
||||
(lib.map (zone: "\"${config.homefree.system.hostName}.${zone} IN AAAA 2600:1700:ab00:4650:2e0:67ff:fe22:3e62\"") zones)
|
||||
++
|
||||
(lib.map (zone: "\"${config.homefree.system.hostName}.${zone} IN AAAA 2600:1700:ab00:465f:2e0:67ff:fe22:3e64\"") zones)
|
||||
++
|
||||
(lib.map (ip-config:
|
||||
"\"${ip-config.hostname} IN A ${ip-config.ip}\"")
|
||||
config.homefree.network.static-ips)
|
||||
++
|
||||
(lib.map (ip-config:
|
||||
"\"${ip-config.hostname}.${config.homefree.system.localDomain} IN A ${ip-config.ip}\"")
|
||||
config.homefree.network.static-ips)
|
||||
;
|
||||
|
||||
local-data-ptr = [
|
||||
"\"::1 localhost\""
|
||||
"\"127.0.0.1 localhost\""
|
||||
]
|
||||
++
|
||||
(lib.map (ip-config:
|
||||
"\"${ip-config.ip} ${ip-config.hostname}\"")
|
||||
config.homefree.network.static-ips)
|
||||
++
|
||||
(lib.map (ip-config:
|
||||
"\"${ip-config.ip} ${ip-config.hostname}.${config.homefree.system.localDomain}\"")
|
||||
config.homefree.network.static-ips)
|
||||
|
||||
## @TODO: Add caddy domains to zones, e.g.:
|
||||
## "10.0.0.1 auth.rahh.al"
|
||||
;
|
||||
|
||||
hide-identity = true;
|
||||
hide-version = true;
|
||||
|
||||
# Based on recommended settings in https://doc.pi-hole.net/guides/dns/unbound/#configure-unbound
|
||||
harden-glue = true;
|
||||
harden-dnssec-stripped = true;
|
||||
use-caps-for-id = false;
|
||||
prefetch = true;
|
||||
edns-buffer-size = 1232;
|
||||
};
|
||||
#
|
||||
# range-lan = {
|
||||
# start = "10.0.0.200";
|
||||
# end = "10.0.0.254";
|
||||
# domain = "localdomain";
|
||||
# };
|
||||
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = [
|
||||
"9.9.9.9#dns.quad9.net"
|
||||
"1.1.1.1@853#cloudflare-dns.com"
|
||||
"1.0.0.1@853#cloudflare-dns.com"
|
||||
];
|
||||
forward-tls-upstream = "yes";
|
||||
}
|
||||
# {
|
||||
# name = "example.org.";
|
||||
# forward-addr = [
|
||||
# "1.1.1.1@853#cloudflare-dns.com"
|
||||
# "1.0.0.1@853#cloudflare-dns.com"
|
||||
# ];
|
||||
# }
|
||||
];
|
||||
|
||||
## Enable dynamic updates from dnsmasq
|
||||
auth-zone = {
|
||||
name = "\"${config.homefree.system.localDomain}\"";
|
||||
master = "yes";
|
||||
allow-notify = "no";
|
||||
for-downstream = "no";
|
||||
for-upstream = "yes";
|
||||
zonefile = "\"/run/unbound/dynamic.zone\"";
|
||||
};
|
||||
|
||||
remote-control.control-enable = true;
|
||||
};
|
||||
};
|
||||
}
|
12
profiles/unifi.nix
Normal file
12
profiles/unifi.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
services.unifi = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
unifiPackage = pkgs.unifi8;
|
||||
mongodbPackage = pkgs.mongodb-7_0;
|
||||
};
|
||||
}
|
||||
|
14
profiles/vaultwarden.nix
Normal file
14
profiles/vaultwarden.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
{ ... }:
|
||||
{
|
||||
services.vaultwarden = {
|
||||
enable = true;
|
||||
dbBackend = "sqlite"; # "sqlite", "mysql", "postgresql"
|
||||
## @TODO: Setup proper backup
|
||||
backupDir = "/var/backup/vaultwarden";
|
||||
config = {
|
||||
ROCKET_ADDRESS = "10.0.0.1";
|
||||
ROCKET_PORT = 8222;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
libvirt
|
||||
virtiofsd
|
||||
];
|
||||
|
||||
systemd.mounts = [
|
||||
{
|
||||
what = "mount_homefree_source";
|
||||
where = "/home/homefree/nixcfg";
|
||||
type = "virtiofs";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
enable = true;
|
||||
}
|
||||
];
|
||||
|
||||
boot.extraModprobeConfig = "options kvm_intel nested=1";
|
||||
boot.kernelParams = [
|
||||
"intel_iommu=on"
|
||||
"cgroup_enable=freezer"
|
||||
];
|
||||
}
|
44
profiles/wireguard.nix
Normal file
44
profiles/wireguard.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ config, pkgs, ... }:
|
||||
let
|
||||
listenPort = config.homefree.wireguard.listenPort;
|
||||
in
|
||||
{
|
||||
# enable NAT
|
||||
networking.nat.enable = true;
|
||||
networking.nat.externalInterface = config.homefree.network.wan-interface;
|
||||
networking.nat.internalInterfaces = [ "wg0" ];
|
||||
networking.firewall = {
|
||||
allowedUDPPorts = [ listenPort ];
|
||||
};
|
||||
|
||||
networking.wireguard.interfaces = {
|
||||
# "wg0" is the network interface name. You can name the interface arbitrarily.
|
||||
wg0 = {
|
||||
# Determines the IP address and subnet of the server's end of the tunnel interface.
|
||||
ips = [ "192.168.2.1/24" ];
|
||||
|
||||
# The port that WireGuard listens to. Must be accessible by the client.
|
||||
listenPort = listenPort;
|
||||
|
||||
# Path to the private key file.
|
||||
#
|
||||
# Note: The private key can also be included inline via the privateKey option,
|
||||
# but this makes the private key world-readable; thus, using privateKeyFile is
|
||||
# recommended.
|
||||
privateKeyFile = "/run/secrets/wireguard/server-private-key";
|
||||
|
||||
peers = config.homefree.wireguard.peers;
|
||||
};
|
||||
};
|
||||
|
||||
## @TODO: Move to host config
|
||||
sops.secrets = {
|
||||
"wireguard/server-private-key" = {
|
||||
format = "yaml";
|
||||
sopsFile = ../secrets/wireguard.yaml;
|
||||
|
||||
owner = config.homefree.system.adminUsername;
|
||||
path = "/run/secrets/wireguard/server-private-key";
|
||||
};
|
||||
};
|
||||
}
|
10
run.sh
10
run.sh
|
@ -80,10 +80,17 @@ sudo $VIRTIOFSD --socket-path /tmp/vhostqemu --shared-dir ./ --cache auto &
|
|||
pids[1]=$!
|
||||
# -netdev tap,id=enp1s0,br=hfbr0,helper=$QEMU_BRIDGE_HELPER \
|
||||
# -device e1000,netdev=enp1s0,mac=52:53:54:55:56:01 \
|
||||
|
||||
# Port 8885: Caddy default HTTP
|
||||
# Port 8445: Caddy default HTTPS
|
||||
# Port 8123: Home Assistant
|
||||
# Port 8222: Vaultwarden
|
||||
# Port 9000: Authentik
|
||||
sudo -E qemu-kvm \
|
||||
$GUI_FLAG \
|
||||
-cpu host \
|
||||
-enable-kvm \
|
||||
-display gtk,show-cursor=on \
|
||||
-chardev socket,id=char0,path=/tmp/vhostqemu \
|
||||
-device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=mount_homefree_source \
|
||||
-object memory-backend-file,id=mem,size=8G,mem-path=/dev/shm,share=on \
|
||||
|
@ -94,7 +101,7 @@ sudo -E qemu-kvm \
|
|||
-smp 4 \
|
||||
-m 8G \
|
||||
-net nic \
|
||||
-net user,hostfwd=tcp::2223-:22,hostfwd=tcp::8445-:443,hostfwd=tcp::8885-:80 \
|
||||
-net user,hostfwd=tcp::2223-:22,hostfwd=tcp::8445-:443,hostfwd=tcp::8885-:80,hostfwd=tcp::8123-:8123,hostfwd=tcp::8222-:8222,hostfwd=tcp::9000-:9000 \
|
||||
-netdev bridge,br=hfbr0,id=hn1,helper=$QEMU_BRIDGE_HELPER \
|
||||
-device virtio-net,netdev=hn1,mac=e6:c8:ff:09:76:88 \
|
||||
&
|
||||
|
@ -105,6 +112,7 @@ sudo -E qemu-kvm \
|
|||
$GUI_FLAG \
|
||||
-cpu host \
|
||||
-enable-kvm \
|
||||
-display gtk,show-cursor=on \
|
||||
-drive file=$OVMF_CODE,if=pflash,format=raw,unit=0,readonly=on \
|
||||
-drive file=./build/OVMF_VARS.fd,if=pflash,format=raw,unit=1 \
|
||||
-hda ./build/lan-client.qcow2 \
|
||||
|
|
4
scripts/generate-server-pgp-key.sh
Executable file
4
scripts/generate-server-pgp-key.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
ssh-keygen -R "[localhost]:2223"
|
||||
ssh -o StrictHostKeychecking=no -p 2223 homefree@localhost "sudo cat /etc/ssh/ssh_host_rsa_key" | nix-shell -p ssh-to-pgp --run "ssh-to-pgp -o homefree-server.asc"
|
7
scripts/generate-user-pgp-key.sh
Executable file
7
scripts/generate-user-pgp-key.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Adds to ~/.gnupg/pubring.kbx
|
||||
# List with: gpg -k
|
||||
nix-shell -p gnupg -p ssh-to-pgp --run "ssh-to-pgp -private-key -i $HOME/.ssh/id_rsa | gpg --import --quiet"
|
||||
# Exports public key from private key
|
||||
# nix-shell -p ssh-to-pgp --run "ssh-to-pgp -i $HOME/.ssh/id_rsa -o $USER.asc"
|
28
scripts/homefree-server.asc
Normal file
28
scripts/homefree-server.asc
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsFNBAAAAAABEADLkq41ZqnTM4Ak5nDDodYsm7VthYyBbzw+uzLgnvJY/TDfse5V
|
||||
s9GZPz5YSNEUiWQ3P3jQgbfY8P6Kvlr++TLcj8i5EkKRGo1ItO2yWDnT8hd3f9Hi
|
||||
nlBzDHd8aQVzJ4CE2EZo6oSFXrX8Pazp9z/KaLm5LLEcwWZ1JBFTn6vAB6M1tRji
|
||||
lgLptLER7sKPb9DHjMo0aVv8Vh9tDXk6nuzS+/3u5z17DT+89tsI8paiNrj4dame
|
||||
Dhg/uT3ko8n8kUFcwLch98taWLYT1y6/e+qCLVXosfIWVTD55U2e+gKu+aSGQ3+8
|
||||
43j2nIoycmzhj/tQY8Pcz2EQaPwsB2Hp+tnxNBDrETXKSDdLASfmJBNFeQTGnagE
|
||||
26nu+by/qCNWMC7XJzBvUBVqPH9X6242O4lbD1+c2iIM/T66+9je+rnG/YfxnJ10
|
||||
5fnMFuGwSzFnCGgWxV3VwEK931GySDs+lNbVA5HTDwD/33JQz9t5hEDIogTWp6UN
|
||||
QQyU5Uj2jMyRFrGi2As7kmQ+NvuhYIJ5ZXWpGX5PCFt6Fy1H0l1IXQkcwEeMNZLv
|
||||
Y14jpy5vrp4iRakRq9z5EGHyrHsUb9xpWc8kbwTuy0Xw3xQE4OnQujGhgS1dU3qK
|
||||
W2zvNn2iWGy4CkhxcJxFAjP1JLOUVd6L1lUPef0IIPlfSBf8y7/ZpW5lGwARAQAB
|
||||
zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT
|
||||
AQgAFgUCAAAAAAkQSRgIZw+lWbICGw8CGQEAAEQ5EACTqTJJbLXWAMfLGkAkp1OH
|
||||
hi7H2I3guHRiHFpVzqF/mu3PcAiCk5ITX2W7LUOjXCkPpUwSpdSq3BqUbOs1oCya
|
||||
EapHl9pkb5EyvnVcsF+fNLETw7WrFWX1Q6+5nrVDUfL+cjsAoGaljWArxI1gsPx5
|
||||
+Hbz8TgcE7cXA7pTaQO7bOMVahk0O8GFbMrK/62KfZvw9drCzkF+t/3SsEen19kz
|
||||
Uuxozf2IpVMabyFm6DUVtfmIizcQOe6TINDvdTm3P1gqlWEmkwDnwUZ0cvdn4GRs
|
||||
RM29RQv90npa8g4CPWK+Yq8ooUFuOtZBczMrObguQfIbW5q14MCoS6DEl+sK4MdL
|
||||
EmITwW9awhrEBARPHlxRifmG9N9Pry75eJ8ve1Lgo2I8JM2WW9E6gtZn3vaEfjtc
|
||||
/7XB0i1h9U4J4uGP/5eSS6U9rbDusaaF+3a1A4wqqG5P0UFmdGAgribwcAWmC6Cu
|
||||
cORoNmhR07mAbGDZfLN1epdsICVxxLq2VM+G4ihSWLeT0VvOqcqOg23ym1qSj9Yg
|
||||
Rtg696dq5MRr1WN25xyGLzlDbEdUq/6FWgR5Vp1NcARmo+3sa+c5U5hY47OgfFKm
|
||||
TUNbaHQjmlyLeKQs3/W3hE4lW+NzJ3OfPu3SlLErPGQ/qXi+6zCnjrQe7DUovpUw
|
||||
IOtP32FUg8jiuEv1HPU7lA==
|
||||
=iAZK
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
51
secrets/authentik.yaml
Normal file
51
secrets/authentik.yaml
Normal file
|
@ -0,0 +1,51 @@
|
|||
authentik:
|
||||
postgres-password: ENC[AES256_GCM,data:LqZbIvmQ7D4Wi18Tb9U=,iv:gMHkdS2xcccK3iBjUnU11EE+n5WJDALmBYvi/IgWbyo=,tag:8/QutMS/EIPFywaU84HPjA==,type:str]
|
||||
authentik-env: ENC[AES256_GCM,data:6Hs8FldGKG6AZHMAe0KX94CwXGWu2mrEDkCif6q9uYSdYwFTwneV5uyjkoOIgMI8/x5GEBNsMTc+NbuVtQSTaajA+RqJVNwsrSGDmNdSyLLSPAN7MhjpNSOezkjBsuQJVFRuPEjUjRZus06yy2vxPUc4hWygGyC8JwByKp+iD+GhTr05evDbeQYaNjRphZjU2gcpEUAbjA07XMJZgKo+smD/SVpIVRLluqYUD4s6C5Av41n68LLTCYCeu3tPrXXrV7cUVVwiDzcNPwewQN3oBK08fQmAhscuVbr5TTQALhgSAN/VvUo+KTR7eHJR2XkxcS2U4iDAbcL7pXGl8c8iXUH/4tqHqqSfJQI09CQ8yoTpwxfpTU1jyaDKnJ59wD/xNkF69CiK85zZy4u/3abDpNuW9sLYah906XyporFJw8M0iYgP4MEo7HGID0XVyIsdjr6Z21PI4Bv/OJDOr8aihSlSaomM8G5hZLxgQp0gwfI0Z7arVlq0/0wlDeWxOrn9V1GaBKxjcw41JpEWFQIa/S8JA9wy,iv:lZfm4LFPrk5Sa4kSPN5hTQv8ii2rd7EAsrevDjFwCgg=,tag:tqCNiQXPZskLwRz9s+Ad+w==,type:str]
|
||||
authentik-ldap-env: ENC[AES256_GCM,data:obxbXZPDdlKRIAkZCPkUF6NweaVC+8do7oPe9CdrKpAuDuK14WAwiwlFgN/uOokLS1990P3yeF/dsHghSCY4P0vYwI9obqtPOXf8P+Pyo29sgSBwgbkMlYmLzlSWC5OuDejlDY9vwbRXKMPnk26PdozzMsE/U0IvBg4nX17OGUqV1aV/Ve4G5+4=,iv:IGGMQ2mIVAONdQyY8U3QF5RoxY5I7Hjdrohp7zut4Sg=,tag:+IXNEQFB848UOmNgwH5jpg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2024-09-20T03:22:05Z"
|
||||
mac: ENC[AES256_GCM,data:EqC7gfouu7FQXZy2ZLEx0940lrTq1HWVbVwCnNC/x3S0ForK47ByrSqboHBYap2XP4HMJ+B7xYNH9jKkg3q5aL0CCaGA/6XcWLSRDa2u4bxvhCgV+bqoRUMZVeXGK7lhB+z4mzhzwM0LbnRL/ZzDiXylJlRn4rW+hQM1YY5Likw=,iv:V5B9n7MVl1e/RNDcqJr2Sf5gL9OwN+GtbluyFMe66Lc=,tag:4lOcJ6YxZVmzCynKGrSWNw==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-11-13T23:45:26Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQEMAwXRN+4RS6LCAQf/fI9eHGnRrnWNMjXEayMydMDaB6JLr0eKZOdiLKr5Bsb1
|
||||
F2Yaliq/rhMIj9YgOAHIjitRZICkhUmaq3Ce6NKYigSTH6YG6xOhRS5m/W5PIXVZ
|
||||
VyrLiEyptEjyL3FqUOBcf3aEEDDuvR5H/wojOd79M5emfBlcaShBHTRyVG9lcOKM
|
||||
el4AlVIHK7qVQ73VyhAiFFH8r0wPJCIetHotCU6lGLDUyMSu1ny4SFfyK6LYT3Pk
|
||||
lznTRvQdJB2Nl4jyaP7F/D7TzF9aGNuzZKCTSBwzVCNM9K7UXgMkk5EKgTtmZshp
|
||||
TEAqzpeS6sLGyyeObCwOQEFu8RdVH0hFTh+rXKgundRmAQkCEPYvyEH9OJjl6aQV
|
||||
hP1myCWkMasnnQQ2YNBiznvzLUL0AcJle1uLrhjiCJml0amkj5bo/7HvjoEfJyKT
|
||||
zmepSVIHXJ31rXOZMZFRZF57+Pi4JBHKKvjxKsRhUhSX8JOgxBq6
|
||||
=p3oE
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 06321D7F20335A7E08595BA905D137EE114BA2C2
|
||||
- created_at: "2024-11-13T23:45:26Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAxkAiCHAcpg+ARAAnvW2+Tu4/W+bPkeoBAyi3HdBtfmLOJ1h+3UbqN9P21Wz
|
||||
5BDth/8B6JD93OXeL/1ZCnXUWuR4Bi0+r1a+8XdXfyp5LyyEbDfHY+ALOwIdEupI
|
||||
+XX/axzs91Flmqp/qdjwu+9RNCN6+VG4Tn1AYGjCKVfN9TRsmDIgeeoc2+oO8+SL
|
||||
zG3uve7EeVovI0eYMroqCHNwD5iRUY/BCR6N4ihBAzawF/DKkW2tX4L2bRTBUZdy
|
||||
Tp7QAWm5Z6MjbNyEi9sjKhXcc2fGmDZrwtfdwOfdxIA6VwZW6DPWU+Y09XlZbTP1
|
||||
phSgTdASGD1NcePHb3CZ4b71AMQi077abF4gJWaVF0IZvUi66i/Kc5R1XoSxBgMk
|
||||
UTMxVC0ml9ZsUC4PBK8f4ALihok/wU1Qtg0KXKHMOOe4UlIyaaqwUwumRHZhhx8p
|
||||
EMIv7gTl97+HlRK4dXu5DQKUxd9UsY2TokoCWOAumTOcw4U6AklJ870T3uBieoYf
|
||||
znOO7yTv5XSnPvvHvmSYlpJDuEhZsqs7LsDiddPBpNFKDhdIWpLObRkNr1cStSHb
|
||||
S5qGAczdcM4AjUG+W2ClUAbBx5a7QwF9WtEDQok6y+SIcuMfS+3IeTK7XaN3GQyP
|
||||
HfF7UzAHzTu5Q5JhfpHbauOOKCkTmF4sKPfx9yIeGE75sb/SovMXw0Ik0EcAcmbU
|
||||
ZgEJAhBplpG4gl1nvD0kE/gfK6hcYITXfbsi0zbMxK5IMR4k3443sOZ2lIV29DSz
|
||||
gbBTO1kY0JmT0lKw9AQy+XWgSm9J8KUsyZdlrOuDyuUJ4HyccNL7Kne7fxxIA9KG
|
||||
mBegvVG/aw==
|
||||
=YNXS
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 0BC4F8FF51F3167F06683FFB19008821C072983E
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
Binary file not shown.
49
secrets/ddclient.yaml
Normal file
49
secrets/ddclient.yaml
Normal file
|
@ -0,0 +1,49 @@
|
|||
ddclient:
|
||||
ddclient-password: ENC[AES256_GCM,data:dAYjEwzbJSSTLpTaDBdC7k9IyYjIx7YKgOr4wewpfJc=,iv:s5cUiHl4QBtxYJin0iFtuba1FWCdxCNej7igyd12ayw=,tag:3Zzd5Tmo44sD800rjlWEKg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2024-10-26T19:47:13Z"
|
||||
mac: ENC[AES256_GCM,data:4Z20ynsDSJKXyeXkc/QnW6oqRZ1LCsQYrZhKG2Bv0S+e8SANFGUuGUCTszU2MXvjDVyQFmd2m8PsXJ7ATHBZr1oLLXcGZE82Yk01Vyl0GlgfmVFmaTEqPvGX/iug4QE9O+w2P7S22vhFrXuyz8FA1VUzy4ae8zw3MKfl/kIFdWA=,iv:cYh1Z3KR3cMZUolF9Y9Z39DSVI0k/bWUX+EgO3p2YDU=,tag:e5hR9pilQ7Yh095Plp6oRw==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-11-13T23:45:29Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQEMAwXRN+4RS6LCAQgAqAeI1oNLpmJgDaDx1fzOpUIEDAzNyw2f/OHYX6mnK9g5
|
||||
wXcRE5gMmrzTShLXmldwhNeQHoOc1F4kusZsMSpU3Rpj3L4OhhHb3KhWQ7iVfn6d
|
||||
XMzWSHMsKvmpjcPRxbt7utuh80XqRhUJeW704ScwGSrejCTMfUFZr3X3C2cICVoc
|
||||
eMj7AohgJ6PD/pJhsW6Ln+CINXC0ed+6mH1kg76cp1RmZ7rtYbnIyGeC74qxNjGT
|
||||
JQa4bw3Ywj+y8H3K7/FGay44ZQ6Y+fja9FsRGMq4ZReOLs0eT0YGb2CibhLzZUJM
|
||||
IxU42wp3DTKb+oF/0lZsTFisQ5yvYjHOsT0qH2kS6dRmAQkCEGzhyzQarGgqOx0h
|
||||
E2/NiPZ7KdOq2YjhVv2hKTqQuKHZ0mrteZXB0rMltYdNkHykeazYRmwaw/gGI5ap
|
||||
EqC48Jm+gp0BxgIH46gchl/uZVTzmS2KyPmUNYkGqXAi7WjkYASi
|
||||
=zCFi
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 06321D7F20335A7E08595BA905D137EE114BA2C2
|
||||
- created_at: "2024-11-13T23:45:29Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAxkAiCHAcpg+ARAAmIN8Tt0Ea0Y6i1vaECocyWeLAXrwXAXGcp4UevAFE22i
|
||||
WFnPFDpKWFyUwSSDvXJ45rFdPtLOM4KdyPHaEunryx9bSpWFohuil5nxK0QM+mvX
|
||||
Mfrs92mRs0ZUdDdBAzVZZXfzeb3hywKhCHS3wobWW28/35y4xt9HGxtoWUS+L3WX
|
||||
63NpFkgG07JeZ6AtVTxdGcdogFD4jKOU7HAZZbc8GO4rvZg+0+8kBiU5DJbjE0Rb
|
||||
i2l70+AO14qw9NH5dM07RFnBcrwMMAifr1Q3K7FTSYIT5XYV3yGLe7timWUJtJt5
|
||||
vrJteROcYuMlCU9VUHfo4acHZcksEHpqC2aH8HCN2m5lTExnmOufQqaRkSVPd9U4
|
||||
rde6Qg0gS3LzaQs4hcMPtYSLeeO7Pt8QrNXtERKhQ1WVSt2L0z0w7QFVgwqFtKeH
|
||||
S0tFZDg9nEqlf85Nxjo0bZIOkiamCzhNOLPE1KNqXTcxM/QpXZtZNdFUJSJKJOzr
|
||||
J2w9FuQYyhHl7HMKoj9jK5SJe0Xe7WINBMFIBo0ezQv9giczp/YtD1j8NS3tEa5y
|
||||
cnm/aBui3upEZnQn6XG5otOx+Yrlrb9VVCZXP/8vgFW4dpRuKaR090d3Zf4g8bHw
|
||||
2oZiGPsrjSvKPQ1ewmgs/4oSI0YvJvQfSK62a/lIHC1mrhhGPbVnm8dTfhqO7xHU
|
||||
ZgEJAhB6JfUjkcKhJFU3tmZz0kgC5qxrioOuPuzBDPuF2jhEQ3uL/FUBGsm/xSR3
|
||||
Exm8pMvqpHInzcNZVlNnJE+cN/qW5num4YkU0FWiaEWmfl0Nu1Aw7JBITF7ft93v
|
||||
SMQonXoFCQ==
|
||||
=rQsJ
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 0BC4F8FF51F3167F06683FFB19008821C072983E
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.9.1
|
50
secrets/wireguard.yaml
Normal file
50
secrets/wireguard.yaml
Normal file
|
@ -0,0 +1,50 @@
|
|||
wireguard:
|
||||
server-private-key: ENC[AES256_GCM,data:Q1zWInF562M0EUePbj6mXC4794EekBX+MGjgiuNUhYyFODI6NMZPgvUA7Wg=,iv:PEkVReP8fRD6tNXi9jfuns9BR1hAVDZDJ9XwaJm4P6M=,tag:KJxaPgZjdJ70Il3sJWJu7Q==,type:str]
|
||||
server-public-key: ENC[AES256_GCM,data:6QenG4zAJUZNmnS168SbmDSgfKr9eiFSXPDZhG6yVAtaRZnq3CHM0AHOo2U=,iv:fWckJlgDfiluOfGUXLJ5oN/PAjFfKrsnH++ABYTubbQ=,tag:bh0Ad+Q0nxNRk1ip3WyLDw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2024-11-16T04:26:17Z"
|
||||
mac: ENC[AES256_GCM,data:YkZbA5S8icRLxgxrDmeM35WRsX69bY5+IonD+4LDDGCVsOH8JA8jW7i9pxbWBdcLf4RktAGWcoBDx6KD47588AJNs1vWounw+9Q9VnfZSQbUDJzrUe0gUxNYsWhGv5E1KnCxNPWuwr3/NatYvmtHuGKTnB5k9LHfu74ijqPeBp4=,iv:FDZcKoeKy0/ruWLFCyolIcj7Glz0eP7SbADj1AcNdX4=,tag:1RZfJ0YXpBafnfI0IgZM0A==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-11-16T04:22:14Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQEMAwXRN+4RS6LCAQgApK6la0ZtWfwFHz8sIiKpX3aE6tblG+V0L+/Ju0eQPopz
|
||||
hInbCSIRdvBHV6xuYl+8KvtGfur170Gz9DVNZ6mdVudN+32GqX31l8LzCVVn/iRY
|
||||
9QHkB6wY+3IggFqAZY9XtHU5MXgtH+27i1RzGp2Z8WIxw79649hUz+DaYs71BY+k
|
||||
GV4EqN8jp6KmzMC9Omdz532sTTukyvLC3KY7gPUSRdJsrt5U+gs2n1JwoXlwIrdm
|
||||
ieVAgJE+2KaAYpHjRskH3OZBBIbj0TWhQb92FBgzYP5kYR/Mw4gu3DWBLR8nvq4m
|
||||
UHCAanV71H/GQWcZUE92b5PM6MMuNqLi/7bfBstGuNRoAQkCEMdijK/jGn9geFtl
|
||||
xlvd6DwXL0TkWC0aUT3YxEDFl/KHs3dFTXktMRO+C6TBdm8tAuYMZvHDDIne9nQE
|
||||
KWXOrt5rCsWfLF53OXttdtkoTuUnyl8mdyN8QAQ6ySmGuBrfXLxc6zM=
|
||||
=K0On
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 06321D7F20335A7E08595BA905D137EE114BA2C2
|
||||
- created_at: "2024-11-16T04:22:14Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAxkAiCHAcpg+AQ//al96/lbZoXjasxIVCbFpV4UMb9RRDdE0GN7V66hGkxnX
|
||||
Bqo5DpUuuV4cakFownILu1naIbxrppRurXWG/xa4pUyDJSEx9SS3e1qE8nKtUF7L
|
||||
FtElYaX7G+v41IpizHYMRLuBspVk8hE3OHvWcd3BfuG4BO0ckd71DFgrhkDa20sw
|
||||
499KW/SM4ccJEOESBxbntGZDYBJWDZ1M7zncz9mDhDGgd/78rPVh/I3b55hZCp0m
|
||||
Nd92IxFhIFURGjTWAnVtSdEYsHOzli4UhzDNhlgQV4mFH7UDN4KLB3YZF4+hmKqq
|
||||
Xq8amebGMwTTgs+svzrzOUPsDCgQS47VK8T+8UMIUsfkc3D7FMtiE9la+Io0A5LZ
|
||||
k6Getq2FZuqKtBlg2Ypcsj33mSMDRzvYjiIC8T2gbEiPtTb9k2vYMYKdWo2FO1nk
|
||||
HrEMtWwb8wgDPCcZRCL8LRl5IAcGWaHxFgxomaODKG5u5xHuTCpBwGkL5vHJSYyq
|
||||
a4zcK8qNJMxGhQuVUFiSS5z4M4r/py8vNNA1AI+dFKqEro1uR+msGN9YL3BWNdYu
|
||||
e7jWOAElbLa3J2nNmZk8NCuVk9Jww0dlT5Urrv07g6k//LIt2TTpU/4SCyjB34vm
|
||||
wfjvHSFJM+zSnzuDPCRLFC+ccA4TmGNVwTW/T8EbT/4jRI2mOjdQ08Ba6Jf9pCvU
|
||||
aAEJAhAqEAY20AY62A07hBZHnchG0ihYgM9k5crmgYDpYm5PQg1skoeAJS76rg9r
|
||||
HG+IqHquvY5bp8gKOoCapBxb1XRh9w6xdiXpMqFd0oZxzq9XZGvyqm0KByhfWpMO
|
||||
tRV5IxAvcAAH
|
||||
=bEBX
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 0BC4F8FF51F3167F06683FFB19008821C072983E
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.9.1
|
1
version.nix
Normal file
1
version.nix
Normal file
|
@ -0,0 +1 @@
|
|||
{ version = "0.0.1"; released = false; }
|
Loading…
Add table
Reference in a new issue