Compare commits

...

53 Commits

Author SHA1 Message Date
c02dafd0d1 big restructure, getting there prayers for rebuild 2025-10-13 21:29:04 -05:00
9128bf3d66 qbit permissions up 2025-10-13 20:53:00 -05:00
042787770e trashy! 2025-10-13 20:06:47 -05:00
afb451d3cc lfrc symlink 2025-10-13 20:05:19 -05:00
1d1a13d9ce add lf 2025-10-13 18:40:20 -05:00
ba38794ef4 add basic stat monitoring to backup script 2025-10-13 17:35:54 -05:00
30302af17b add stats to backups 2025-10-13 17:27:13 -05:00
2f627902f3 update "${services}" 2025-10-13 16:25:33 -05:00
3b2460f97a add formatter 2025-10-13 15:54:29 -05:00
c73adbe26f keymaps! 2025-10-13 15:37:40 -05:00
59476285df update vim config 2025-10-13 15:17:04 -05:00
68ee7894a0 add nvf 2025-10-13 15:04:14 -05:00
dc5c5038b9 zsh test fin 2025-10-13 12:02:49 -05:00
61e8436dd9 update proxy config 2025-10-12 22:24:09 -05:00
cae85ef2e6 tls insecure 2025-10-12 21:22:14 -05:00
6226177c08 troubleshooting certs 2025-10-12 20:13:51 -05:00
593449d0c3 troubleshooting 2025-10-12 20:12:53 -05:00
c1e56790c5 finallyy? 2025-10-12 20:11:00 -05:00
3acd59d938 i fixed it 2025-10-12 20:00:31 -05:00
758ab5beb1 fix backup script to fucking work bro exit 0 my ass and add mode selector 2025-10-12 19:19:23 -05:00
39c108b3ee add podman compose 2025-10-12 19:01:52 -05:00
cd55d1d7cf troubleshoot suwayomi 2025-10-12 18:21:26 -05:00
f76c6862ba add suwayomi 2025-10-12 16:41:29 -05:00
abcad5c9f2 adding yacreader 2025-10-12 16:09:41 -05:00
b89c6a14cc add uptime kuma integration 2025-10-12 15:35:14 -05:00
86582c0dcc add uptime kuma integration 2025-10-12 15:30:36 -05:00
460d79c107 add status monitor to glance 2025-10-12 15:05:08 -05:00
394d12a7b2 clean up glance and try and add minecraft monitor 2025-10-12 14:55:09 -05:00
2cc42a5800 I think get it working lmao 2025-10-12 14:16:31 -05:00
4c6f6ee68d troubleshoot key site 2025-10-12 14:14:46 -05:00
15d82a44fb caddy testing 2025-10-12 14:13:09 -05:00
5168f5fc3e removed nginx and altered caddy (build script changes too) 2025-10-12 13:57:35 -05:00
d58262a043 rm nginx, adjust caddy for testing, redo rebuild script 2025-10-12 13:44:28 -05:00
2db7081bfc 355 current 2025-10-12 12:06:38 25.05.20251006.20c4598 6.12.50 * 2025-10-12 12:21:38 -05:00
bad309eb60 355 current 2025-10-12 12:06:38 25.05.20251006.20c4598 6.12.50 * 2025-10-12 12:09:54 -05:00
6ca3f8fedc 354 current 2025-10-12 12:04:23 25.05.20251006.20c4598 6.12.50 * 2025-10-12 12:06:40 -05:00
cd4cd68e96 353 current 2025-10-12 12:02:06 25.05.20251006.20c4598 6.12.50 * 2025-10-12 12:04:25 -05:00
f6379435b8 352 current 2025-10-12 12:00:03 25.05.20251006.20c4598 6.12.50 * 2025-10-12 12:02:08 -05:00
36213c47c9 351 current 2025-10-12 11:59:13 25.05.20251006.20c4598 6.12.50 * 2025-10-12 12:00:06 -05:00
ff096a520a 350 current 2025-10-12 11:58:18 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:59:16 -05:00
00ab2ae68c 349 current 2025-10-12 11:50:40 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:58:20 -05:00
b4bf817c5e 348 current 2025-10-12 11:49:03 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:50:42 -05:00
2b3b12b6a1 347 current 2025-10-12 11:48:00 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:49:06 -05:00
87ed8a6337 346 current 2025-10-12 11:43:32 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:48:03 -05:00
c2a543f83b 346 current 2025-10-12 11:43:32 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:46:50 -05:00
fcbf908b15 345 current 2025-10-12 11:39:59 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:43:35 -05:00
1657efcae7 344 current 2025-10-12 10:51:52 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:40:02 -05:00
ee51577189 344 current 2025-10-12 10:51:52 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:38:46 -05:00
6609922170 344 current 2025-10-12 10:51:52 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:37:58 -05:00
35be9990ba 344 current 2025-10-12 10:51:52 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:37:17 -05:00
cacb342117 344 current 2025-10-12 10:51:52 25.05.20251006.20c4598 6.12.50 * 2025-10-12 11:36:56 -05:00
23384e35ed 343 current 2025-10-12 10:50:02 25.05.20251006.20c4598 6.12.50 * 2025-10-12 10:51:56 -05:00
0897deae29 342 current 2025-10-12 10:45:09 25.05.20251006.20c4598 6.12.50 * 2025-10-12 10:50:05 -05:00
51 changed files with 1472 additions and 1677 deletions

View File

@@ -1,173 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# --- SUDO CHECK ---
if [ "$EUID" -ne 0 ]; then
echo "This script requires root privileges. Re-running with sudo..."
exec sudo "$0" "$@"
fi
# --- HANDLE -k OPTION FOR KEY FILE ---
BORG_PASSPHRASE=""
while getopts "k:" opt; do
case "$opt" in
k)
BORG_PASSPHRASE=$(<"$OPTARG")
if [ -z "$BORG_PASSPHRASE" ]; then
echo "Error: The key file is empty."
exit 1
fi
echo "Using passphrase from key file: $OPTARG"
;;
*)
echo "Usage: $0 [-k passphrase_file] <repo>"
exit 1
;;
esac
done
shift $((OPTIND - 1))
# --- FALLBACK TO /run/secrets/borg_passwd IF NO KEY FILE ---
if [ -z "$BORG_PASSPHRASE" ]; then
if [ -f "/run/secrets/borg_passwd" ]; then
BORG_PASSPHRASE=$(<"/run/secrets/borg_passwd")
echo "Using passphrase from /run/secrets/borg_passwd"
else
# Prompt user for passphrase if neither -k nor /run/secrets/borg_passwd is available
read -s -p "Enter Borg repository passphrase: " BORG_PASSPHRASE
echo
fi
fi
export BORG_PASSPHRASE
# --- DEFAULT REPO ---
REPO="${1:-/holocron/backups}"
# --- CHECK REQUIRED COMMANDS ---
for cmd in borg fzf find tree cp mkdir; do
command -v "$cmd" >/dev/null || { echo "Error: '$cmd' is required but not installed."; exit 1; }
done
# --- LIST ARCHIVES (sorted, newest last) ---
mapfile -t archives < <(borg list --format="{archive}{NL}" "$REPO" | sort)
if [ ${#archives[@]} -eq 0 ]; then
echo "No archives found in $REPO"
exit 1
fi
# --- FZF ARCHIVE SELECT ---
selected=$(printf '%s\n' "${archives[@]}" | fzf --prompt="Select archive: " --height=40% --border --reverse)
if [ -z "$selected" ]; then
echo "No archive selected."
exit 1
fi
echo "Selected archive: $selected"
# --- GENERATE A UNIQUE, SHORTER MOUNT POINT ---
MOUNT_POINT="/tmp/borg-mount-${selected}-$(uuidgen | sha256sum | head -c 6)"
mkdir -p "$MOUNT_POINT"
# --- MOUNT ARCHIVE ---
echo "Mounting '$selected' to $MOUNT_POINT..."
borg mount "$REPO::$selected" "$MOUNT_POINT"
if [ ! -d "$MOUNT_POINT" ]; then
echo "Error: mount failed."
exit 1
fi
# --- LIST FILES AND DIRECTORIES ---
echo "Scanning files and directories..."
if command -v fd >/dev/null 2>&1; then
# List files and directories using fd (can handle both files and dirs)
files=$(fd --type f --type d . "$MOUNT_POINT" | sort)
else
# Fall back to find if fd is not available
files=$(find "$MOUNT_POINT" -type f -o -type d | sort)
fi
if [ -z "$files" ]; then
echo "No files or directories found in archive."
borg umount "$MOUNT_POINT"
rm -rf "$MOUNT_POINT"
exit 1
fi
# --- HIERARCHICAL FZF FILE/DIRECTORY SELECTION (REVERSED) ---
# We reverse the order of files to display the latest (newest) files/folders at the top.
selected_files=$(printf '%s\n' "$files" | sed "s|$MOUNT_POINT/||" | tac | fzf \
--multi \
--height=50% \
--border \
--prompt="Select files or directories to restore: " \
--preview "tree -C -L 5 $MOUNT_POINT/$(dirname {})" \
--preview-window=right:50% \
--delimiter='/' \
--with-nth=1..)
if [ -z "$selected_files" ]; then
echo "No files or directories selected. Exiting."
borg umount "$MOUNT_POINT"
rm -rf "$MOUNT_POINT"
exit 0
fi
# --- SUMMARY OF SELECTED FILES/DIRECTORIES ---
echo "Selected files and directories:"
for file in $selected_files; do
echo " $file"
done
# --- OPTIONS MENU (concise) ---
# Default to option 1 if no input is given
echo "Select restore destination: 1) Restore to ./${selected}_restore 2) Restore to original dirs 3) Quit"
read -p "Enter your choice (1/2/3) [default: 1]: " choice
# Default to option 1 if user presses Enter without providing input
choice="${choice:-1}"
# --- SET RESTORE DESTINATION BASED ON USER CHOICE ---
case "$choice" in
1)
DEST="./${selected}_restore"
;;
2)
DEST="$MOUNT_POINT"
;;
3)
echo "Quitting. No files restored."
borg umount "$MOUNT_POINT"
rm -rf "$MOUNT_POINT"
exit 0
;;
*)
echo "Invalid choice. Exiting."
borg umount "$MOUNT_POINT"
rm -rf "$MOUNT_POINT"
exit 1
;;
esac
mkdir -p "$DEST"
# --- RESTORE FILES AND DIRECTORIES ---
echo "Restoring selected files and directories..."
while IFS= read -r file; do
# Path is already stripped of /tmp, so no need for further modification
dest_path="$DEST/$file"
mkdir -p "$(dirname "$dest_path")"
# If it's a directory, we use cp -r to ensure the directory structure is restored
if [ -d "$MOUNT_POINT/$file" ]; then
cp -r "$MOUNT_POINT/$file" "$dest_path"
else
cp -a "$MOUNT_POINT/$file" "$dest_path"
fi
echo "Restored: $file"
done <<< "$selected_files"
# --- CLEANUP ---
borg umount "$MOUNT_POINT"
rm -rf "$MOUNT_POINT"
echo "Restore complete."

View File

@@ -1,64 +0,0 @@
#!/usr/bin/env bash
# borg-browser.sh — fzf-based Borg archive browser with passphrase prompt
[ "$EUID" -ne 0 ] && { echo "Please run as root."; exec sudo "$0" "$@"; }
REPO="/holocron/backups"
# Prompt once for Borg passphrase
read -rs -p "Borg passphrase: " BORG_PASSPHRASE
echo
export BORG_PASSPHRASE
# Pick an archive
ARCHIVE=$(borg list --short "$REPO" | fzf --prompt="Select archive: ") || {
unset BORG_PASSPHRASE
exit
}
[ -z "$ARCHIVE" ] && { unset BORG_PASSPHRASE; exit; }
# Function to browse directories hierarchically
browse_borg_dir() {
local prefix="$1"
while true; do
# Get immediate children of the current path
ITEMS=$(borg list --format='{path}{NL}' "$REPO::$ARCHIVE" \
| awk -v p="$prefix" -F/ '
BEGIN{n=split(p,a,"/")}
index($0,p)==1 && NF>n {
if (NF==n+1) print $NF;
else print $(n+1)"/";
}' \
| sort -u)
[ -z "$ITEMS" ] && { echo "No items found in $prefix"; return; }
SELECTION=$(echo -e "../\n$ITEMS" | fzf --prompt="${prefix:-/}> ")
case "$SELECTION" in
"../")
prefix="${prefix%/*}"
prefix="${prefix%/}"
;;
"")
return
;;
*/)
prefix="${prefix:+$prefix/}${SELECTION%/}"
;;
*)
local fullpath="${prefix:+$prefix/}$SELECTION"
echo "Selected file: $fullpath"
read -rp "Extract it here? [y/N]: " yn
if [[ $yn =~ ^[Yy]$ ]]; then
borg extract "$REPO::$ARCHIVE" "$fullpath"
fi
return
;;
esac
done
}
browse_borg_dir ""
unset BORG_PASSPHRASE

View File

@@ -17,6 +17,10 @@ TARGET=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-m|--media)
OWNER=":media"
shift
;;
-o|--owner)
OWNER="$2"
shift 2

View File

@@ -1,26 +1,44 @@
#!/usr/bin/env bash
set -e
pushd ~/.nix
# nvim flake.nix
# alejandra . &>/dev/null
# git diff -U0 *.nix
set -euo pipefail
# add generation comment to flake.nix
gen=$(nixos-rebuild list-generations | grep current)
if sed -n '3p' flake.nix | grep -q '^# generation:'; then
# replace the comment on line 3
sed -i "3s/^# generation:.*/# generation: $gen/" flake.nix
else
# insert comment on line 3
sed -i "3i# generation: $gen" flake.nix
#echo "searching generations"
# your hostname (flake target)
hostname="$(hostname)"
#old_gen=$(nixos-rebuild list-generations | grep current | awk '{print $1}')
#gen=$((old_gen + 1))
#echo "gen $old_gen --> gen $gen"
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
nix_dir="$HOME/.nix"
logfile="$nix_dir/.nixos-switch-log"
pushd "$nix_dir" >/dev/null
# function to get current nixos generation
#get_current_generation() {
# nixos-rebuild list-generations
#}
echo "diffs:"
git diff
echo ""
echo "files:"
git status --short
read -rp "commit message: " commit_msg
echo "rebuilding nixos with flake.nix..."
if ! sudo nixos-rebuild switch --flake .#"$hostname" 2>&1 | tee "$logfile"; then
echo "rebuild failed; exited with no commit"
exit 1
fi
#if sed -n '3p' flake.nix | grep -q '^# generation:'; then
# # replace the comment on line 3
# sed -i "3s|^# generation:.*|# generation: $gen, timestamp: $timestamp|" flake.nix
#else
# # insert comment on line 3
# sed -i "3i# generation: $gen, timestamp: $timestamp" flake.nix
#fi
echo "committing..."
git add $nix_dir
git commit -m "$commit_msg"
echo "flake rebuild and commit fin"
git diff -U0 $(find . -name '*.nix')
echo "nixos rebuilding..."
#sudo nixos-rebuild switch --flake ~/.nix#snowbelle &>.nixos-switch-log || (
# cat .nixos-switch-log | grep --color error && false)
sudo nixos-rebuild switch --flake ~/.nix#snowbelle 2>&1 | tee .nixos-switch-log | grep --color=always -E "error|$" && true
git commit -am "$gen"
popd

26
bin/rebuild_legacy.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
pushd ~/.nix
# nvim flake.nix
# alejandra . &>/dev/null
# git diff -U0 *.nix
# add generation comment to flake.nix
gen=$(nixos-rebuild list-generations | grep current)
if sed -n '3p' flake.nix | grep -q '^# generation:'; then
# replace the comment on line 3
sed -i "3s/^# generation:.*/# generation: $gen/" flake.nix
else
# insert comment on line 3
sed -i "3i# generation: $gen" flake.nix
fi
git diff -U0 $(find . -name '*.nix')
echo "nixos rebuilding..."
#sudo nixos-rebuild switch --flake ~/.nix#snowbelle &>.nixos-switch-log || (
# cat .nixos-switch-log | grep --color error && false)
sudo nixos-rebuild switch --flake ~/.nix#snowbelle 2>&1 | tee .nixos-switch-log | grep --color=always -E "error|$" && true
git commit -am "$gen"
popd

110
flake.lock generated
View File

@@ -1,5 +1,42 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1751685974,
"narHash": "sha256-NKw96t+BgHIYzHUjkTK95FqYRVKB8DHpVhefWSz/kTw=",
"ref": "refs/heads/main",
"rev": "549f2762aebeff29a2e5ece7a7dc0f955281a1d1",
"revCount": 92,
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nvf",
"nixpkgs"
]
},
"locked": {
"lastModified": 1759362264,
"narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "758cf7296bee11f1706a574c77d072b8a7baa881",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
@@ -21,13 +58,28 @@
"type": "github"
}
},
"mnw": {
"locked": {
"lastModified": 1758834834,
"narHash": "sha256-Y7IvY4F8vajZyp3WGf+KaiIVwondEkMFkt92Cr9NZmg=",
"owner": "Gerg-L",
"repo": "mnw",
"rev": "cfbc7d1cc832e318d0863a5fc91d940a96034001",
"type": "github"
},
"original": {
"owner": "Gerg-L",
"repo": "mnw",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1759735786,
"narHash": "sha256-a0+h02lyP2KwSNrZz4wLJTu9ikujNsTWIC874Bv7IJ0=",
"lastModified": 1760139962,
"narHash": "sha256-4xggC56Rub3WInz5eD7EZWXuLXpNvJiUPahGtMkwtuc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "20c4598c84a671783f741e02bf05cbfaf4907cff",
"rev": "7e297ddff44a3cc93673bb38d0374df8d0ad73e4",
"type": "github"
},
"original": {
@@ -38,11 +90,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1759831965,
"narHash": "sha256-vgPm2xjOmKdZ0xKA6yLXPJpjOtQPHfaZDRtH+47XEBo=",
"lastModified": 1760284886,
"narHash": "sha256-TK9Kr0BYBQ/1P5kAsnNQhmWWKgmZXwUQr4ZMjCzWf2c=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c9b6fb798541223bbb396d287d16f43520250518",
"rev": "cf3f5c4def3c7b5f1fc012b3d839575dbe552d43",
"type": "github"
},
"original": {
@@ -51,11 +103,36 @@
"type": "indirect"
}
},
"nvf": {
"inputs": {
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"mnw": "mnw",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1760153667,
"narHash": "sha256-F7KmXT/Izse6Q6CkD5GCImoGPaDJxl03Kd7eD+eY/bU=",
"owner": "NotAShelf",
"repo": "nvf",
"rev": "9df9d51fd9fc8f9a8fc377f984ea3b7ae796172d",
"type": "github"
},
"original": {
"owner": "NotAShelf",
"repo": "nvf",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
"nvf": "nvf",
"sops-nix": "sops-nix",
"vpn-confinement": "vpn-confinement"
}
@@ -67,11 +144,11 @@
]
},
"locked": {
"lastModified": 1759635238,
"narHash": "sha256-UvzKi02LMFP74csFfwLPAZ0mrE7k6EiYaKecplyX9Qk=",
"lastModified": 1760240450,
"narHash": "sha256-sa9bS9jSyc4vH0jSWrUsPGdqtMvDwmkLg971ntWOo2U=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "6e5a38e08a2c31ae687504196a230ae00ea95133",
"rev": "41fd1f7570c89f645ee0ada0be4e2d3c4b169549",
"type": "github"
},
"original": {
@@ -80,6 +157,21 @@
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"vpn-confinement": {
"locked": {
"lastModified": 1759956062,

View File

@@ -1,6 +1,6 @@
# flake for blakes nixos config
# define new devices in outputs
# generation: 341 current 2025-10-12 10:38:28 25.05.20251006.20c4598 6.12.50 *
# generation: 378, timestamp: 2025-10-12 19:57:35
{
description = "blakes nix config";
inputs = {
@@ -17,6 +17,10 @@
vpn-confinement = {
url = "github:Maroka-chan/VPN-Confinement";
};
nvf = {
url = "github:NotAShelf/nvf";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, nixpkgs-unstable, ... }@inputs:
let

View File

@@ -25,30 +25,31 @@ in
tailscale.enable = true;
nvidia.enable = true;
};
homelab = {
enable = true;
fileshare = {
zfs.enable = true;
smb.enable = true;
nfs.enable = true;
nginx-proxy.enable = true;
};
homelab.enable = true;
services = {
jellyfin.enable = true;
audiobookshelf.enable = true;
vaultwarden.enable = true;
gitea.enable = true;
glance.enable = true;
qbittorrent.enable = true;
immich.enable = true;
hass.enable = true;
zigbee2mqtt.enable = true;
mosquitto.enable = true;
jellyfin.enable = true;
audiobookshelf.enable = true;
yacreader.enable = true;
qbittorrent.enable = true;
sonarr.enable = true;
radarr.enable = true;
bazarr.enable = true;
prowlarr.enable = true;
flaresolverr.enable = true;
bazarr.enable = true;
radarr.enable = true;
sonarr.enable = true;
zigbee2mqtt.enable = true;
mosquitto.enable = true;
caddy.enable = true;
uptime-kuma.enable = true;
vaultwarden.enable = true;
};
gameservers = {
minecraft_recpro.enable = true;
@@ -111,6 +112,7 @@ in
curl
fzf
fd
alejandra
tree
vim
lf

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [ "media" ];
};
@@ -58,8 +58,8 @@ in
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
user = service;
group = service;
listenPort = cfg.port;
};
@@ -71,14 +71,12 @@ in
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -48,7 +48,7 @@ in
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
group = "${service}";
group = service;
};
# enable the ${service} service
@@ -60,21 +60,19 @@ in
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
User = "${service}";
Group = "${service}";
User = service;
Group = service;
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
};
}

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [ "media" ];
};
@@ -66,21 +66,19 @@ in
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
User = "${service}";
Group = "${service}";
User = service;
Group = service;
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [ "media" ];
};
@@ -58,8 +58,8 @@ in
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
user = service;
group = service;
dataDir = cfg.data_dir;
settings = {
server.port = cfg.port;
@@ -69,21 +69,19 @@ in
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
# User = service;
# Group = service;
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [ "media" ];
};
@@ -58,8 +58,8 @@ in
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
user = service;
group = service;
dataDir = cfg.data_dir;
settings = {
server.port = cfg.port;
@@ -74,14 +74,12 @@ in
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -0,0 +1,101 @@
{ pkgs, config, lib, ... }:
let
service = "audiobookshelf";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7101;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "abs.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
# home = cfg.data_dir;
createHome = true;
group = service;
extraGroups = [ "media" ];
};
# enable the ${service} service
services.${service} = {
enable = true;
openFirewall = true;
user = service;
group = service;
# dataDir = cfg.data_dir;
host = "0.0.0.0";
port = cfg.port;
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = service;
# Group = service;
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "abs.${homelab.public_domain}" ];
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port} {
}
'';
};
# add to glance public service
modules.services.glance.links.mediastack = [{
title = service;
url = "https://abs.${homelab.public_domain}";
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}"; }];
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -0,0 +1,98 @@
{ pkgs, config, lib, ... }:
let
service = "caddy";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = {};
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = service;
extraGroups = [];
};
# enable the ${service} service
services.${service} = {
enable = true;
user = service;
group = service;
dataDir = cfg.data_dir;
email = "me@blakedheld.xyz";
globalConfig = ''
auto_https ignore_loaded_certs
'';
virtualHosts."key.${homelab.public_domain}" = {
extraConfig = ''
root * /var/www/keys
file_server
'';
};
};
# enable acme for auto ssl certs with lets encrypt
security.acme = {
acceptTerms = true;
defaults.email = "me@blakedheld.xyz";
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
};
# open firewall
networking.firewall.allowedTCPPorts = [ 80 443 ];
sops.secrets = {
"ssl_blakedheld_crt" = {
owner = "caddy";
group = "caddy";
path = "/etc/ssl/blakedheld.xyz.crt";
};
"ssl_blakedheld_key" = {
owner = "caddy";
group = "caddy";
path = "/etc/ssl/blakedheld.xyz.key";
};
"klefki_pub.asc" = {
owner = "caddy";
group = "caddy";
path = "/var/www/keys/klefki_pub.asc";
};
};
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -39,11 +39,27 @@ in
};
};
# the order determines the order in glance :3
imports = [
./services
./shares/nfs.nix
./shares/smb.nix
./shares/zfs.nix
./fileshare
./caddy
./home/zigbee2mqtt
./vaultwarden
./gitea
./home/homeassistant
./immich
./arr/bazarr
./arr/prowlarr
./arr/radarr
./qbittorrent
./arr/sonarr
./yacreader
./audiobookshelf
./jellyfin
./arr/flaresolverr
./home/mosquitto
./uptime-kuma
./glance
];
config = lib.mkIf cfg.enable {

View File

@@ -0,0 +1,13 @@
{
pkgs,
config,
lib,
...
}: {
# services show up in glance in reverse import order lmao
imports = [
./shares/nfs.nix
./shares/smb.nix
./shares/zfs.nix
];
}

View File

@@ -1,14 +1,17 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
# define nfs exports
let
cfg = config.modules.homelab.nfs;
cfg = config.modules.fileshare.nfs;
nfs_exports = ''
/holocron/vault *(rw,sync,no_subtree_check,no_root_squash)
/holocron/media *(ro,sync,no_subtree_check)
'';
in
{
#/holocron/vault *(rw,sync,no_subtree_check,no_root_squash)
in {
options.modules.homelab.nfs = {
enable = lib.mkEnableOption "enables nfs";
};

View File

@@ -1,8 +1,12 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
# define smb shares
let
cfg = config.modules.homelab.smb;
cfg = config.modules.fileshare.smb;
smb_shares = {
vault = {
path = "/holocron/vault";
@@ -17,8 +21,7 @@ let
guestOk = false;
};
};
in
{
in {
options.modules.homelab.smb = {
enable = lib.mkEnableOption "enables smb";
};

View File

@@ -1,9 +1,11 @@
{ pkgs, config, lib, ... }:
let
cfg = config.modules.homelab.zfs;
in
{
pkgs,
config,
lib,
...
}: let
cfg = config.modules.fileshare.zfs;
in {
options.modules.homelab.zfs = {
enable = lib.mkEnableOption "enables zfs";
};
@@ -31,5 +33,4 @@ in
options = ["nofail"];
};
};
}

View File

@@ -56,7 +56,7 @@ in
shell = pkgs.bash;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [];
};
@@ -69,7 +69,8 @@ in
appName = "gitea";
settings = {
server = {
DOMAIN = "https://git.blakedheld.xyz";
ROOT_URL = "https://git.blakedheld.xyz";
DOMAIN = "git.blakedheld.xyz";
HTTP_PORT = cfg.port;
SSH_PORT = cfg.ssh_port;
START_SSH_SERVER = true;
@@ -90,41 +91,15 @@ in
# open firewall
networking.firewall.allowedTCPPorts = [ cfg.port cfg.ssh_port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "git.${homelab.public_domain}" ];
extraConfig = ''
client_max_body_size 512M;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy localhost:${toString cfg.port} {
}
'';
};
};
# external reverse proxy entry
services.nginx.virtualHosts."git.blakedheld.xyz" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
extraConfig = ''
client_max_body_size 512M;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
'';
};
};
# add to glance
modules.services.glance.links.services = [{
@@ -134,10 +109,11 @@ in
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}"; }];
# manage secrets with sops
sops.secrets = {
"${service}_database_password" = {
owner = "${service}";
group = "${service}";
owner = service;
group = service;
};
};

View File

@@ -0,0 +1,306 @@
{
pkgs,
config,
lib,
...
}:
/*
this is a wrapper module for glance that allows you to
to pass monitor entries in with nix, all declaratively!
| <8yy> |
V V
# add to glance
modules.services.glance.links.mediastack = [{
title = service;
url = "https://${cfg.url}";
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}";
allow-insecure = true; }];
*/
let
service = "glance";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
uptimekuma_url = "localhost:7901";
uptimekuma_page = "glance";
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7700;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
links = {
services = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [ ];
description = "list of links for ${service}";
};
mediastack = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [ ];
description = "list of links for ${service}";
};
system = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [ ];
description = "list of links for ${service}";
};
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = {
gid = lib.mkForce cfg.ids;
};
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = service;
extraGroups = [ ];
};
services.${service} = {
enable = true;
openFirewall = true;
settings = {
server = {
host = "0.0.0.0";
port = cfg.port;
assets-path = "${cfg.data_dir}/assets";
};
# theme = {custom-css-file = "/assets/user.css";};
auth = {
secret-key = "+mYVAc1uO85hUUz5Ij6Lpelv1RqiLlneYqZD5Jv45buoF2+LZtIt2okRrbFCppiRQbqXkGoRMtSI0bROg4uFUw==";
users = {
blake = {
password-hash = "$2a$10$RwPCkcto35DCp4vNTDpH6.G3TpecPJ/zUL1jI93uzr.lg6v233Sie";
};
};
};
branding = {
logo-url = "/assets/icons/snowbelle.png";
favicon-url = "/assets/icons/favicon.ico";
};
pages = [
{
name = "snowbelle";
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{
type = "calendar";
first-day-of-week = "monday";
}
{
type = "server-stats";
servers = [
{
type = "local";
name = "snowbelle";
}
];
}
{
type = "clock";
hour-format = "24h";
timezones = [
{
timezone = "America/Chicago";
label = "HTX";
}
{
timezone = "America/Denver";
label = "AF";
}
];
}
{
type = "twitch-channels";
channels = [
"mang0"
"SaltSSBM"
"thewaffle77"
"ironmouse"
"linustech"
];
}
];
}
{
size = "full";
widgets = [
{
type = "search";
autofocus = true;
search-engine = "https://www.ecosia.org/search?q={QUERY}";
new-tab = true;
bangs = [
{
title = "YouTube";
shortcut = "!y";
url = "https://www.youtube.com/results?search_query={QUERY}";
}
{
title = "Google";
shortcut = "!g";
url = "https://www.google.com/search?q={QUERY}";
}
{
title = "Github";
shortcut = "!gh";
url = "https://github.com/search?q={QUERY}&type=repositories";
}
];
}
{
type = "monitor";
cache = "1m";
title = "services";
sites = cfg.links.services;
}
{
type = "monitor";
cache = "1m";
title = "mediastack";
sites = cfg.links.mediastack;
}
{
type = "monitor";
cache = "1m";
title = "system";
sites = cfg.links.system;
}
{
type = "custom-api";
title = "recpro";
url = "https://api.mcstatus.io/v2/status/java/mc.recoil.pro";
cache = "5s";
template = "<div style=\"display:flex; align-items:center; gap:12px;\">\n <div style=\"width:40px; height:40px; flex-shrink:0; border-radius:4px; display:flex; justify-content:center; align-items:center; overflow:hidden;\">\n {{ if .JSON.Bool \"online\" }}\n <img src=\"{{ .JSON.String \"icon\" | safeURL }}\" width=\"64\" height=\"64\" style=\"object-fit:contain;\">\n {{ else }}\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" style=\"width:32px; height:32px; opacity:0.5;\">\n <path fill-rule=\"evenodd\" d=\"M1 5.25A2.25 2.25 0 0 1 3.25 3h13.5A2.25 2.25 0 0 1 19 5.25v9.5A2.25 2.25 0 0 1 16.75 17H3.25A2.25 2.25 0 0 1 1 14.75v-9.5Zm1.5 5.81v3.69c0 .414.336.75.75.75h13.5a.75.75 0 0 0 .75-.75v-2.69l-2.22-2.219a.75.75 0 0 0-1.06 0l-1.91 1.909.47.47a.75.75 0 1 1-1.06 1.06L6.53 8.091a.75.75 0 0 0-1.06 0l-2.97 2.97ZM12 7a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\" clip-rule=\"evenodd\" />\n </svg>\n {{ end }}\n </div>\n\n <div style=\"flex-grow:1; min-width:0;\">\n <a class=\"size-h4 block text-truncate color-highlight\">\n {{ .JSON.String \"host\" }}\n {{ if .JSON.Bool \"online\" }}\n <span\n style=\"width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-positive); display: inline-block; vertical-align: middle;\"\n data-popover-type=\"text\"\n data-popover-text=\"Online\"\n ></span>\n {{ else }}\n <span\n style=\"width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-negative); display: inline-block; vertical-align: middle;\"\n data-popover-type=\"text\"\n data-popover-text=\"Offline\"\n ></span>\n {{ end }}\n </a>\n\n <ul class=\"list-horizontal-text\">\n <li>\n {{ if .JSON.Bool \"online\" }}\n <span>{{ .JSON.String \"version.name_clean\" }}</span>\n {{ else }}\n <span>Offline</span>\n {{ end }}\n </li>\n {{ if .JSON.Bool \"online\" }}\n <li data-popover-type=\"html\">\n <div data-popover-html>\n {{ range .JSON.Array \"players.list\" }}{{ .String \"name_clean\" }}<br>{{ end }}\n </div>\n <p style=\"display:inline-flex;align-items:center;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-6\" style=\"height:1em;vertical-align:middle;margin-right:0.5em;\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n {{ .JSON.Int \"players.online\" | formatNumber }}/{{ .JSON.Int \"players.max\" | formatNumber }} players\n </p>\n </li>\n {{ else }}\n <li>\n <p style=\"display:inline-flex;align-items:center;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-6\" style=\"height:1em;vertical-align:middle;margin-right:0.5em;opacity:0.5;\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n 0 players\n </p>\n </li>\n {{ end }}\n </ul>\n </div>\n</div>";
}
];
}
{
size = "small";
widgets = [
{
type = "weather";
location = "Pearland, Texas, United States";
units = "imperial";
hour-format = "24h";
}
{
type = "markets";
markets = [
{
symbol = "SPY";
name = "S&P 500";
}
{
symbol = "XMR-USD";
name = "Monero";
}
{
symbol = "NVDA";
name = "NVIDIA";
}
{
symbol = "AAPL";
name = "Apple";
}
{
symbol = "MSFT";
name = "Microsoft";
}
];
}
{
type = "releases";
cache = "1d";
repositories = [
"glanceapp/glance"
"go-gitea/gitea"
"immich-app/immich"
"syncthing/syncthing"
];
}
];
}
];
}
];
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
User = service;
Group = service;
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
# serverAliases = [ "${homelab.public_domain}" ];
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to backups
modules.system.backups.baks = {
${service} = {
paths = [ cfg.data_dir ];
};
};
# add to udr to glance
modules.services.glance.links.system = [{
title = "bebe";
url = "https://bebe.lan";
error-url = "https://10.10.0.1";
check-url = "https://10.10.0.1";
icon = "di:unifi";
allow-insecure = true; }];
};
}

View File

@@ -87,37 +87,13 @@ in
# open firewall
networking.firewall.allowedTCPPorts = [ cfg.port 8123 ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "${service}.${homelab.public_domain}" ];
extraConfig = ''
proxy_buffering off;
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
extraConfig =
"proxy_set_header Upgrade $http_upgrade;" +
"proxy_set_header Connection upgrade;"
;
};
};
# external reverse proxy entry
services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
extraConfig = ''
proxy_buffering off;
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
extraConfig =
"proxy_set_header Upgrade $http_upgrade;" +
"proxy_set_header Connection upgrade;"
;
};
};
# add to glance
@@ -137,9 +113,6 @@ in
# here lies my tough, and I mean fucking tough, swing at
# getting this to work bare metal, ggs ill see you again
# - didnt take long

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [];
};
@@ -73,8 +73,8 @@ in
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
User = "${service}";
Group = "${service}";
User = service;
Group = service;
};
# open firewall
@@ -82,8 +82,8 @@ in
sops.secrets = {
"${service}_hashed_passwd" = {
owner = "${service}";
group = "${service}";
owner = service;
group = service;
};
};

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [];
};
@@ -87,38 +87,20 @@ in
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
User = "${service}";
Group = "${service}";
User = service;
Group = service;
};
# # open firewall
networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "z2m.${homelab.public_domain}" ];
extraConfig = ''
proxy_buffering off;
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
};
locations."/api" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}/api";
extraConfig = ''
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
'';
};
};
# add to glance
@@ -131,8 +113,8 @@ in
sops.secrets = {
"mosquitto_passwd.yaml" = {
owner = "${service}";
group = "${service}";
owner = service;
group = service;
};
};

View File

@@ -18,7 +18,7 @@ in
};
url = lib.mkOption {
type = lib.types.str;
default = "$=photos.${homelab.base_domain}";
default = "photos.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [ "video" "render" ];
};
@@ -59,8 +59,8 @@ in
enable = true;
package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.immich;
openFirewall = true;
user = "${service}";
group = "${service}";
user = service;
group = service;
mediaLocation = cfg.data_dir;
host = "0.0.0.0";
port = cfg.port;
@@ -75,25 +75,13 @@ in
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
proxyWebsockets = true;
};
};
# external reverse proxy entry
services.nginx.virtualHosts."photos.blakedheld.xyz" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
proxyWebsockets = true;
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "photos.${homelab.public_domain}" ];
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -50,7 +50,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [ "media" "video" "render" ];
};
@@ -58,8 +58,8 @@ in
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
user = service;
group = service;
dataDir = cfg.data_dir;
};
@@ -71,23 +71,13 @@ in
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# external reverse proxy entry
services.nginx.virtualHosts."media.blakedheld.xyz" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "media.${homelab.public_domain}" ];
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -50,8 +50,10 @@ in
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# ensure media dirs existence
systemd.tmpfiles.rules = [
"d /holocron/media/downloads 2775 qbittorrent media -"
];
# declare ${service} user
users.users.${service} = {
@@ -60,16 +62,15 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [ "media" ];
group = "media";
};
# enable the qbittorrent service
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
user = service;
group = lib.mkForce "media"; # override for permissions
profileDir = cfg.data_dir;
webuiPort = cfg.port;
# torrentingPort = cfg.torrenting_port;
@@ -109,14 +110,12 @@ in
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -0,0 +1,127 @@
{
pkgs,
config,
lib,
...
}:
let
service = "";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = <port>;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${service}.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = {
gid = lib.mkForce cfg.ids;
};
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = service;
extraGroups = [ "media" ];
};
# enable the ${service} service
services.${service} = {
enable = true;
openFirewall = true;
user = service;
group = service;
dataDir = cfg.data_dir;
settings = {
server.port = cfg.port;
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = service;
# Group = service;
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "${service}.${homelab.public_domain}" ];
extraConfig = ''
tls /etc/ssl/blakedheld.xyz.crt /etc/ssl/blakedheld.xyz.key
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
#---------------------------------------------------------------------------
# # add to glance (public service)
# modules.services.glance.links.<category> = [{
# title = service;
# url = "https://${service}.${homelab.public_domain}";
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
# icon = "di:${service}"; }];
#---------------------------------------------------------------------------
# # add to glance (local service)
# modules.services.glance.links.<category> = [{
# title = service;
# url = "https://${cfg.url}";
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
# icon = "di:${service}"; }];
#---------------------------------------------------------------------------
#
# sops.secrets = {
# "${service}_" = {
# owner = ;
# group = ;
# };
# };
# add to backups
modules.system.backups.baks = {
${service} = {
paths = [ cfg.data_dir ];
};
};
};
}

View File

@@ -1,5 +1,31 @@
{ pkgs, config, lib, ... }:
/*
no longer in use, replaced by caddy if
wanting to use again here is the boilerplate
for whatt o put in for each service
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# external reverse proxy entry
services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
*/
let
cfg = config.modules.homelab.nginx-proxy;
sec = config.sops.secrets;

View File

@@ -1,128 +0,0 @@
{ pkgs, config, lib, ... }:
let
service = "audiobookshelf";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7101;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "abs.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
# home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [ "media" ];
};
# enable the ${service} service
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
# dataDir = cfg.data_dir;
host = "0.0.0.0";
port = cfg.port;
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
extraConfig = ''
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
client_max_body_size 10240M;
'';
};
};
# external reverse proxy entry
services.nginx.virtualHosts."$abs.blakedheld.xyz" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# add to glance public service
modules.services.glance.links.mediastack = [{
title = service;
url = "https://abs.${homelab.public_domain}";
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}"; }];
#
# sops.secrets = {
# "${service}_" = {
# owner = "${service}";
# group = "${service}";
# };
# };
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -5,33 +5,8 @@
# services show up in glance in reverse import order lmao
imports = [
./home/zigbee2mqtt
./vaultwarden
./gitea
./home/homeassistant
./immich
./arr/prowlarr
./arr/bazarr
./arr/radarr
./arr/sonarr
./audiobookshelf
./qbittorrent
./jellyfin
./nginx-proxy
./arr/flaresolverr
./home/mosquitto
./uptime-kuma
./glance
];
# add to udr to glance
modules.services.glance.links.system = [{
title = "bebe";
url = "https://bebe.lan";
error-url = "https://10.10.0.1";
check-url = "https://10.10.0.1";
icon = "di:unifi";
allow-insecure = true; }];

View File

@@ -1,129 +0,0 @@
{ pkgs, config, lib, ... }:
let
service = "";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = <port>;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${service}.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [ "media" ];
};
# enable the ${service} service
services.${service} = {
enable = true;
openFirewall = true;
user = "${service}";
group = "${service}";
dataDir = cfg.data_dir;
settings = {
server.port = cfg.port;
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# uncomment for service hosted publicly
#---------------------------------------------------------------------------
# # external reverse proxy entry
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
# forceSSL = true;
# sslCertificate = sec."ssl_blakedheld_crt".path;
# sslCertificateKey = sec."ssl_blakedheld_key".path;
# locations."/" = {
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
# };
# };
#
# # add to glance public service
# modules.services.glance.links.<category> = [{
# title = service;
# url = "https://${service}.${homelab.public_domain}";
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
# icon = "di:${service}"; }];
#---------------------------------------------------------------------------
# # add to glance local service
# modules.services.glance.links.<category> = [{
# title = service;
# url = "https://${cfg.url}";
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
# icon = "di:${service}"; }];
#
# sops.secrets = {
# "${service}_" = {
# owner = "${service}";
# group = "${service}";
# };
# };
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -1,257 +0,0 @@
{ pkgs, config, lib, ... }:
/*
this is a wrapper module for glance that allows you to
to pass monitor entries in with nix, all declaratively!
| <8yy> |
V V
# add to glance
modules.services.glance.links.mediastack = [{
title = service;
url = "https://${cfg.url}";
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}";
allow-insecure = true; }];
*/
let
service = "glance";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7700;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
links = {
services = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [];
description = "list of links for ${service}";
};
mediastack = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [];
description = "list of links for ${service}";
};
system = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [];
description = "list of links for ${service}";
};
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [];
};
services.${service} = {
enable = true;
openFirewall = true;
settings = {
server = {
host = "0.0.0.0";
port = cfg.port;
};
pages = [
{
name = "violet";
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{ type = "calendar"; first-day-of-week = "monday"; }
{ type = "server-stats"; servers = [ { type = "local"; name = "violet"; } ]; }
{
type = "clock";
hour-format = "24h";
timezones = [
{ timezone = "America/Chicago"; label = "HTX"; }
{ timezone = "America/Denver"; label = "AF"; }
];
}
{ type = "twitch-channels"; channels = [ "mang0" "SaltSSBM" "thewaffle77" "ironmouse" "linustech" ]; }
];
}
{
size = "full";
widgets = [
{
type = "search";
autofocus = true;
search-engine = "https://www.ecosia.org/search?q={QUERY}";
new-tab = true;
bangs = [
{ title = "YouTube"; shortcut = "!y"; url = "https://www.youtube.com/results?search_query={QUERY}"; }
{ title = "Google"; shortcut = "!g"; url = "https://www.google.com/search?q={QUERY}"; }
{ title = "Github"; shortcut = "!gh"; url = "https://github.com/search?q={QUERY}&type=repositories"; }
];
}
{
type = "monitor";
cache = "1m";
title = "services";
sites = cfg.links.services;
# sites = [
# { title = "jellyfin"; url = "https://media.blakedheld.xyz"; icon = "di:jellyfin"; }
# { title = "audiobookshelf"; url = "https://audiobooks.blakedheld.xyz"; icon = "di:audiobookshelf"; }
# { title = "yacreader"; url = "http://10.10.0.30:3434"; icon = "/assets/icons/yacreader.png"; }
# { title = "sonarr"; url = "http://10.10.0.30:3636"; icon = "di:sonarr"; }
# { title = "qbittorrent"; url = "http://10.10.0.40:3333"; icon = "di:qbittorrent"; }
# { title = "radarr"; url = "http://10.10.0.30:3737"; icon = "di:radarr"; }
# { title = "kiwix"; url = "http://10.10.0.30:5050"; icon = "di:kiwix"; }
# { title = "prowlarr"; url = "http://10.10.0.30:3535"; icon = "di:prowlarr"; }
# { title = "bazarr"; url = "http://10.10.0.30:3838"; icon = "di:bazarr"; }
# ];
}
{
type = "monitor";
cache = "1m";
title = "mediastack";
sites = cfg.links.mediastack;
# [
# { title = "immich"; url = "https://pics.blakedheld.xyz"; icon = "di:immich"; }
# { title = "vaultwarden"; url = "https://pass.blakedheld.xyz"; icon = "di:vaultwarden"; }
# { title = "gitea"; url = "https://git.blakedheld.xyz"; icon = "di:gitea"; }
# { title = "home assistant"; url = "https://home.blakedheld.xyz"; icon = "di:home-assistant"; }
# { title = "zigbee2mqtt"; url = "http://10.10.0.30:4142"; icon = "di:zigbee2mqtt"; }
# { title = "syncthing"; url = "http://10.10.0.20:2222"; icon = "di:syncthing"; }
# { title = "archivebox"; url = "http://10.10.0.30:5656"; icon = "sh:archivebox"; }
# { title = "copyparty"; url = "http://10.10.0.20:3923"; icon = "sh:copyparty"; }
# ];
}
{
type = "monitor";
cache = "1m";
title = "system";
sites = cfg.links.system;
# [
# { title = "proxmox"; url = "http://10.10.0.10:8006"; icon = "di:proxmox"; allow-insecure = true; }
# { title = "nginx"; url = "http://10.10.0.30:8080"; icon = "di:nginx"; }
# { title = "uptime kuma"; url = "http://10.10.0.30:8181"; icon = "di:uptime-kuma"; }
# { title = "tn holocron"; url = "https://10.10.0.20"; icon = "di:truenas"; allow-insecure = true; }
# { title = "bebe"; url = "https://10.10.0.1"; icon = "di:unifi"; allow-insecure = true; }
# ];
}
];
}
{
size = "small";
widgets = [
{ type = "weather"; location = "Pearland, Texas, United States"; units = "imperial"; hour-format = "24h"; }
{
type = "markets";
markets = [
{ symbol = "SPY"; name = "S&P 500"; }
{ symbol = "XMR-USD"; name = "Monero"; }
{ symbol = "NVDA"; name = "NVIDIA"; }
{ symbol = "AAPL"; name = "Apple"; }
{ symbol = "MSFT"; name = "Microsoft"; }
];
}
{
type = "releases";
cache = "1d";
repositories = [
"glanceapp/glance"
"go-gitea/gitea"
"immich-app/immich"
"syncthing/syncthing"
];
}
];
}
];
}
];
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# # external reverse proxy entry
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
# forceSSL = true;
# sslCertificate = sec."ssl_blakedheld_crt".path;
# sslCertificateKey = sec."ssl_blakedheld_key".path;
# locations."/" = {
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
# };
# };
#
# sops.secrets = {
# "${service}_" = {
# owner = "${service}";
# group = "${service}";
# };
# };
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -1,230 +0,0 @@
{ pkgs, config, lib, ... }:
let
service = "glance";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7700;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
pages = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule {
options.description = lib.mkOption { type = lib.types.str; };
options.url = lib.mkOption { type = lib.types.str; };
options.icon = lib.mkOption { type = lib.types.str; };
options.category = lib.mkOption { type = lib.types.str; };
});
default = {};
description = "configure the service for use in ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [];
};
services.${service} = {
enable = true;
openFirewall = true;
settings = {
server = {
host = "0.0.0.0";
port = cfg.port;
};
pages = [
{
name = "violet";
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{ type = "calendar"; first-day-of-week = "monday"; }
{ type = "server-stats"; servers = [ { type = "local"; name = "violet"; } ]; }
{
type = "clock";
hour-format = "24h";
timezones = [
{ timezone = "America/Chicago"; label = "HTX"; }
{ timezone = "America/Denver"; label = "AF"; }
];
}
{ type = "twitch-channels"; channels = [ "mang0" "SaltSSBM" "thewaffle77" "ironmouse" "linustech" ]; }
];
}
{
size = "full";
widgets = [
{
type = "search";
autofocus = true;
search-engine = "https://www.ecosia.org/search?q={QUERY}";
new-tab = true;
bangs = [
{ title = "YouTube"; shortcut = "!y"; url = "https://www.youtube.com/results?search_query={QUERY}"; }
{ title = "Google"; shortcut = "!g"; url = "https://www.google.com/search?q={QUERY}"; }
{ title = "Github"; shortcut = "!gh"; url = "https://github.com/search?q={QUERY}&type=repositories"; }
];
}
{
type = "monitor";
cache = "1m";
title = "mediastack";
sites = [
{ title = "jellyfin"; url = "https://media.blakedheld.xyz"; icon = "di:jellyfin"; }
{ title = "audiobookshelf"; url = "https://audiobooks.blakedheld.xyz"; icon = "di:audiobookshelf"; }
{ title = "yacreader"; url = "http://10.10.0.30:3434"; icon = "/assets/icons/yacreader.png"; }
{ title = "sonarr"; url = "http://10.10.0.30:3636"; icon = "di:sonarr"; }
{ title = "qbittorrent"; url = "http://10.10.0.40:3333"; icon = "di:qbittorrent"; }
{ title = "radarr"; url = "http://10.10.0.30:3737"; icon = "di:radarr"; }
{ title = "kiwix"; url = "http://10.10.0.30:5050"; icon = "di:kiwix"; }
{ title = "prowlarr"; url = "http://10.10.0.30:3535"; icon = "di:prowlarr"; }
{ title = "bazarr"; url = "http://10.10.0.30:3838"; icon = "di:bazarr"; }
];
}
{
type = "monitor";
cache = "1m";
title = "services";
sites = [
{ title = "immich"; url = "https://pics.blakedheld.xyz"; icon = "di:immich"; }
{ title = "vaultwarden"; url = "https://pass.blakedheld.xyz"; icon = "di:vaultwarden"; }
{ title = "gitea"; url = "https://git.blakedheld.xyz"; icon = "di:gitea"; }
{ title = "home assistant"; url = "https://home.blakedheld.xyz"; icon = "di:home-assistant"; }
{ title = "zigbee2mqtt"; url = "http://10.10.0.30:4142"; icon = "di:zigbee2mqtt"; }
{ title = "syncthing"; url = "http://10.10.0.20:2222"; icon = "di:syncthing"; }
{ title = "archivebox"; url = "http://10.10.0.30:5656"; icon = "sh:archivebox"; }
{ title = "copyparty"; url = "http://10.10.0.20:3923"; icon = "sh:copyparty"; }
];
}
{
type = "monitor";
cache = "1m";
title = "system";
sites = [
{ title = "proxmox"; url = "http://10.10.0.10:8006"; icon = "di:proxmox"; allow-insecure = true; }
{ title = "nginx"; url = "http://10.10.0.30:8080"; icon = "di:nginx"; }
{ title = "uptime kuma"; url = "http://10.10.0.30:8181"; icon = "di:uptime-kuma"; }
{ title = "tn holocron"; url = "https://10.10.0.20"; icon = "di:truenas"; allow-insecure = true; }
{ title = "bebe"; url = "https://10.10.0.1"; icon = "di:unifi"; allow-insecure = true; }
];
}
];
}
{
size = "small";
widgets = [
{ type = "weather"; location = "Pearland, Texas, United States"; units = "imperial"; hour-format = "24h"; }
{
type = "markets";
markets = [
{ symbol = "SPY"; name = "S&P 500"; }
{ symbol = "XMR-USD"; name = "Monero"; }
{ symbol = "NVDA"; name = "NVIDIA"; }
{ symbol = "AAPL"; name = "Apple"; }
{ symbol = "MSFT"; name = "Microsoft"; }
];
}
{
type = "releases";
cache = "1d";
repositories = [
"glanceapp/glance"
"go-gitea/gitea"
"immich-app/immich"
"syncthing/syncthing"
];
}
];
}
];
}
];
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# # external reverse proxy entry
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
# forceSSL = true;
# sslCertificate = sec."ssl_blakedheld_crt".path;
# sslCertificateKey = sec."ssl_blakedheld_key".path;
# locations."/" = {
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
# };
# };
#
# sops.secrets = {
# "${service}_" = {
# owner = "${service}";
# group = "${service}";
# };
# };
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -1,230 +0,0 @@
{ pkgs, config, lib, ... }:
let
service = "glance";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7700;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
pages = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule {
options.description = lib.mkOption { type = lib.types.str; };
options.url = lib.mkOption { type = lib.types.str; };
options.icon = lib.mkOption { type = lib.types.str; };
options.category = lib.mkOption { type = lib.types.str; };
});
default = {};
description = "configure the service for use in ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [];
};
services.${service} = {
enable = true;
openFirewall = true;
settings = {
server = {
host = "0.0.0.0";
port = cfg.port;
};
pages = [
{
name = "violet";
hide-desktop-navigation = true;
columns = [
{
size = "small";
widgets = [
{ type = "calendar"; first-day-of-week = "monday"; }
{ type = "server-stats"; servers = [ { type = "local"; name = "violet"; } ]; }
{
type = "clock";
hour-format = "24h";
timezones = [
{ timezone = "America/Chicago"; label = "HTX"; }
{ timezone = "America/Denver"; label = "AF"; }
];
}
{ type = "twitch-channels"; channels = [ "mang0" "SaltSSBM" "thewaffle77" "ironmouse" "linustech" ]; }
];
}
{
size = "full";
widgets = [
{
type = "search";
autofocus = true;
search-engine = "https://www.ecosia.org/search?q={QUERY}";
new-tab = true;
bangs = [
{ title = "YouTube"; shortcut = "!y"; url = "https://www.youtube.com/results?search_query={QUERY}"; }
{ title = "Google"; shortcut = "!g"; url = "https://www.google.com/search?q={QUERY}"; }
{ title = "Github"; shortcut = "!gh"; url = "https://github.com/search?q={QUERY}&type=repositories"; }
];
}
{
type = "monitor";
cache = "1m";
title = "mediastack";
sites = [
{ title = "jellyfin"; url = "https://media.blakedheld.xyz"; icon = "di:jellyfin"; }
{ title = "audiobookshelf"; url = "https://audiobooks.blakedheld.xyz"; icon = "di:audiobookshelf"; }
{ title = "yacreader"; url = "http://10.10.0.30:3434"; icon = "/assets/icons/yacreader.png"; }
{ title = "sonarr"; url = "http://10.10.0.30:3636"; icon = "di:sonarr"; }
{ title = "qbittorrent"; url = "http://10.10.0.40:3333"; icon = "di:qbittorrent"; }
{ title = "radarr"; url = "http://10.10.0.30:3737"; icon = "di:radarr"; }
{ title = "kiwix"; url = "http://10.10.0.30:5050"; icon = "di:kiwix"; }
{ title = "prowlarr"; url = "http://10.10.0.30:3535"; icon = "di:prowlarr"; }
{ title = "bazarr"; url = "http://10.10.0.30:3838"; icon = "di:bazarr"; }
];
}
{
type = "monitor";
cache = "1m";
title = "services";
sites = [
{ title = "immich"; url = "https://pics.blakedheld.xyz"; icon = "di:immich"; }
{ title = "vaultwarden"; url = "https://pass.blakedheld.xyz"; icon = "di:vaultwarden"; }
{ title = "gitea"; url = "https://git.blakedheld.xyz"; icon = "di:gitea"; }
{ title = "home assistant"; url = "https://home.blakedheld.xyz"; icon = "di:home-assistant"; }
{ title = "zigbee2mqtt"; url = "http://10.10.0.30:4142"; icon = "di:zigbee2mqtt"; }
{ title = "syncthing"; url = "http://10.10.0.20:2222"; icon = "di:syncthing"; }
{ title = "archivebox"; url = "http://10.10.0.30:5656"; icon = "sh:archivebox"; }
{ title = "copyparty"; url = "http://10.10.0.20:3923"; icon = "sh:copyparty"; }
];
}
{
type = "monitor";
cache = "1m";
title = "system";
sites = [
{ title = "proxmox"; url = "http://10.10.0.10:8006"; icon = "di:proxmox"; allow-insecure = true; }
{ title = "nginx"; url = "http://10.10.0.30:8080"; icon = "di:nginx"; }
{ title = "uptime kuma"; url = "http://10.10.0.30:8181"; icon = "di:uptime-kuma"; }
{ title = "tn holocron"; url = "https://10.10.0.20"; icon = "di:truenas"; allow-insecure = true; }
{ title = "bebe"; url = "https://10.10.0.1"; icon = "di:unifi"; allow-insecure = true; }
];
}
];
}
{
size = "small";
widgets = [
{ type = "weather"; location = "Pearland, Texas, United States"; units = "imperial"; hour-format = "24h"; }
{
type = "markets";
markets = [
{ symbol = "SPY"; name = "S&P 500"; }
{ symbol = "XMR-USD"; name = "Monero"; }
{ symbol = "NVDA"; name = "NVIDIA"; }
{ symbol = "AAPL"; name = "Apple"; }
{ symbol = "MSFT"; name = "Microsoft"; }
];
}
{
type = "releases";
cache = "1d";
repositories = [
"glanceapp/glance"
"go-gitea/gitea"
"immich-app/immich"
"syncthing/syncthing"
];
}
];
}
];
}
];
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# # external reverse proxy entry
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
# forceSSL = true;
# sslCertificate = sec."ssl_blakedheld_crt".path;
# sslCertificateKey = sec."ssl_blakedheld_key".path;
# locations."/" = {
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
# };
# };
#
# sops.secrets = {
# "${service}_" = {
# owner = "${service}";
# group = "${service}";
# };
# };
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -67,31 +67,18 @@ in
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
# User = "${service}";
# Group = "${service}";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
};
# # external reverse proxy entry
# services.nginx.virtualHosts."up.blakedheld.xyz" = {
# forceSSL = true;
# sslCertificate = sec."ssl_blakedheld_crt".path;
# sslCertificateKey = sec."ssl_blakedheld_key".path;
# locations."/" = {
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
# };
# };
# add to glance
modules.services.glance.links.system = [{
@@ -101,14 +88,9 @@ in
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}"; }];
# sops.secrets = {
# "${service}_" = {
# owner = "${service}";
# group = "${service}";
# };
# };
# add to backups
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -51,7 +51,7 @@ in
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
group = service;
extraGroups = [];
};
@@ -84,23 +84,13 @@ in
# open firewall
networking.firewall.allowedTCPPorts = [ cfg.port ];
# internal reverse proxy entry
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
};
# external reverse proxy entry
services.nginx.virtualHosts."pass.blakedheld.xyz" = {
forceSSL = true;
sslCertificate = sec."ssl_blakedheld_crt".path;
sslCertificateKey = sec."ssl_blakedheld_key".path;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString cfg.port}";
};
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "pass.${homelab.public_domain}" ];
extraConfig = ''
tls /etc/ssl/blakedheld.xyz.crt /etc/ssl/blakedheld.xyz.key
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance

View File

@@ -0,0 +1,105 @@
{ pkgs, config, lib, ... }:
let
service = "yacreader";
cfg = config.modules.services.${service};
sec = config.sops.secrets;
homelab = config.modules.homelab;
in
{
options.modules.services.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7102;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "manga.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# install the binary
environment.systemPackages = with pkgs; [ yacreader ];
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = service;
extraGroups = [ "media" ];
};
# enable the ${service} service
systemd.services.${service} = {
description = "${service} library server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
UMask = lib.mkForce "0007";
User = service;
Group = service;
Restart = "always";
RestartSec = "5s";
Type = "simple";
ExecStart = "${pkgs.yacreader}/bin/YACReaderLibraryServer start --port ${toString cfg.port}";
WorkingDirectory = "/var/lib/yacreader";
TimeoutStopSec = "20s";
};
};
# open firewall
networking.firewall.allowedTCPPorts = [ cfg.port ];
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
extraConfig = ''
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
reverse_proxy 127.0.0.1:${toString cfg.port} {
}
'';
};
# add to glance local service
modules.services.glance.links.mediastack = [{
title = service;
url = "https://${cfg.url}";
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:yac-reader"; }];
# add to backups
modules.system.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}

View File

@@ -27,9 +27,6 @@ in
default = {};
description = "backup jobs, nested attribute sets should be <bak_name> = paths [<list_of_paths>]";
};
paths = lib.mkOption {
type = lib.types.list;
};
repo = lib.mkOption {
type = lib.types.path;
default = "/holocron/borg";
@@ -40,6 +37,11 @@ in
default = sec."borg_passwd".path;
description = "borg repository passphrase file";
};
mode = lib.mkOption {
type = lib.types.str;
default = "split"; # "all"
description = "choice between creating one archive of all paths or one archive per service";
};
};
config = lib.mkIf (cfg.enable && cfg.baks != {}) {
@@ -52,11 +54,12 @@ in
# EnvironmentFile = config.modules.system.backups.passphraseFile;
# the actual script borg is using
ExecStart = pkgs.writeShellScript "borg-backup" ''
backup() {
set -euo pipefail
export BORG_PASSPHRASE="$(cat ${cfg.passwd_file})"
export BORG_REPO="${cfg.repo}"
timestamp="$(date +'%Y-%m-%d_%H:%M:%S')"
mode=sep
mode=${cfg.mode}
# init repo in needed
if ! borg info "$BORG_REPO" >/dev/null 2>&1; then
@@ -68,7 +71,7 @@ in
echo "starting backup at $timestamp"
if [ "$mode" = "sep" ]; then
if [ "$mode" = "split" ]; then
# loop for each backup
${lib.concatStringsSep "\n\n" (lib.mapAttrsToList (bak_name: bak_paths:
''
@@ -77,23 +80,23 @@ in
echo "backing up: ${lib.concatStringsSep " " bak_paths.paths} $archive"
borg create \
--verbose \
--filter AME \
# --filter AME \
--list \
--stats \
--show-rc \
--compression lzma,9 \
--compression lz4 \
"$BORG_REPO::$archive" \
${lib.concatStringsSep " " bak_paths.paths}
echo "pruning old backups for ${bak_name}..."
borg prune -v --list "$BORG_REPO" \
--prefix "${bak_name}-" \
--glob-archives "*-${bak_name}" \
--keep-daily=7 \
--keep-weekly=52 \
--keep-monthly=-1
echo "backup run complete at \"$BORG_REPO::$archive\""
exit 0
''
) cfg.baks)}
exit 0
else
# flatten all paths from cfg.baks into one big list
all_paths="${
@@ -113,13 +116,23 @@ in
echo "pruning old backups for ${toString config.networking.hostName}..."
borg prune -v --list "$BORG_REPO" \
--prefix "${toString config.networking.hostName}" \
--glob-archives "*-${toString config.networking.hostName}" \
--keep-daily=7 \
--keep-weekly=52 \
--keep-monthly=-1
echo "backup run complete at \"$BORG_REPO::${toString config.networking.hostName}\""
exit 0
fi
}
start_time=$(date +%s)
backup
end_time=$(date +%s)
exec_time=$((end_time - start_time))
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1"%"}')
echo ""
echo "backup stats:"
echo "exec time: $exec_time"
echo "cpu usage: $cpu_usage"
'';
};
};

View File

@@ -9,6 +9,10 @@ in
};
config = lib.mkIf cfg.enable {
# install the binary for compose
environment.systemPackages = with pkgs; [ podman-compose ];
virtualisation = {
oci-containers.backend = "podman";
podman = {

View File

@@ -1,10 +1,12 @@
{ pkgs, config, lib, ... }:
let
{
pkgs,
config,
lib,
...
}: let
cfg = config.modules.system.tailscale;
authkey_file = config.sops.secrets."tailscale_authkey".path;
in
{
in {
options.modules.system.tailscale = {
enable = lib.mkEnableOption "enables tailscale";
};
@@ -20,6 +22,10 @@ in
];
};
# network config
networking.firewall.trustedInterfaces = ["tailscale0"];
networking.firewall.allowedUDPPorts = [config.services.tailscale.port];
# declare authkey secrets
sops.secrets = {
"tailscale_authkey" = {

View File

@@ -20,7 +20,7 @@ in
# create blake user
users.users.${cfg.username} = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" "docker" "media" "minecraft" ]; # Enable sudo for the user.
extraGroups = [ "wheel" "networkmanager" "docker" "media" "podman" "minecraft" ]; # Enable sudo for the user.
uid = 1000;
shell = pkgs.zsh;
group = "blake";

View File

@@ -1,9 +0,0 @@
# general
set forcekitty
set chafasixel
preview glow .md {{
glow -s "dark" < "$f"
}}

View File

@@ -32,6 +32,7 @@ alias src='source $HOME/.config/zsh/.zshrc'
# config editing
alias cfh='nvim $HOME/.config/hypr/hyprland.conf'
alias cfl='nvim $HOME/.config/lf/lfrc'
# navigation
setopt autocd
@@ -95,6 +96,8 @@ alias stat='sudo systemctl status'
alias restart='sudo systemctl restart'
alias start='sudo systemctl start'
alias stop='sudo systemctl stop'
alias jou='sudo journalctl -xeu'
alias live='sudo journalctl -o short-iso -n 50 -fu'
# shortcuts
alias chil='nvim ~/documents/holocron/tech/devices/yveltal/chilton'

View File

@@ -0,0 +1,5 @@
# general
set forcekitty
set chafasixel

View File

@@ -0,0 +1,21 @@
{
pkgs,
config,
...
}: {
# just using the normal lfrc
programs.lf = {
enable = false;
};
# install it to userspace
home.packages = with pkgs; [lf ctpv trashy];
# link configs
xdg.configFile."lf/lfrc" = {
source = config.lib.file.mkOutOfStoreSymlink "/home/blake/.nix/users/blake/dots/lf/lfrc";
};
xdg.configFile."ctpv/config" = {
source = config.lib.file.mkOutOfStoreSymlink "/home/blake/.nix/users/blake/dots/lf/ctpv_config";
};
}

View File

@@ -21,6 +21,10 @@ set ignorecase true
# --- mappings ---
# shortcuts
map gb cd /holocron
map gn cd ~/.nix
# navigation
map [ half-up
map ] half-down
@@ -104,7 +108,7 @@ cmd mkfile %{{
# make backup
cmd mkbak %{{
for x in $fx; do
cp $x $x.bak
cp -r $x $x.bak
done
}}

View File

@@ -0,0 +1,188 @@
{
pkgs,
config,
lib,
inputs,
...
}:
{
imports = [
inputs.nvf.homeManagerModules.default
];
programs.nvf = {
enable = true;
settings = {
vim = {
globals = {
mapleader = " ";
maplocalleader = " ";
};
vimAlias = true;
lsp.enable = true;
statusline.lualine.enable = true;
telescope.enable = true;
autocomplete.nvim-cmp.enable = true;
autopairs.nvim-autopairs.enable = true;
keymaps = [
# visual line movement (insert mode)
{
key = "<Up>";
mode = [ "i" ];
action = "<C-o>gk";
desc = "Visual Line Up (Insert)";
}
{
key = "<Down>";
mode = [ "i" ];
action = "<C-o>gj";
desc = "Visual Line Down (Insert)";
}
# visual line movement (normal/visual)
{
key = "<Up>";
mode = [
"n"
"v"
];
action = "g<Up>";
desc = "Visual Line Up";
}
{
key = "<Down>";
mode = [
"n"
"v"
];
action = "g<Down>";
desc = "Visual Line Down";
}
# lsp
#{ key = "gd"; mode = [ "n" ]; action = "<cmd>lua vim.lsp.buf.definition()<CR>"; desc = "Go to definition"; }
#{ key = "K"; mode = [ "n" ]; action = "<cmd>lua vim.lsp.buf.hover()<CR>"; desc = "Hover info"; }
#{ key = "<leader>f"; mode = [ "n" ]; action = "<cmd>lua vim.lsp.buf.format({ async = true })<CR>"; desc = "Format buffer"; }
{
key = "gd";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.lsp.buf.definition()<CR>";
desc = "Go to definition";
}
# Hover info
{
key = "K";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.lsp.buf.hover()<CR>";
desc = "Hover info";
}
# Format buffer (Alejandra for Nix)
{
key = "<leader>F";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.lsp.buf.format({ async = true })<CR>";
desc = "Format buffer";
}
# Code actions / quickfix
{
key = "<leader>a";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.lsp.buf.code_action()<CR>";
desc = "Code action";
}
# Rename symbol
{
key = "<leader>r";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.lsp.buf.rename()<CR>";
desc = "Rename symbol";
}
# Diagnostics
{
key = "<leader>e";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.diagnostic.open_float()<CR>";
desc = "Show diagnostic";
}
{
key = "[d";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.diagnostic.goto_prev()<CR>";
desc = "Previous diagnostic";
}
{
key = "]d";
mode = [ "n" ];
silent = true;
action = "<cmd>lua vim.diagnostic.goto_next()<CR>";
desc = "Next diagnostic";
}
];
options = {
clipboard = "unnamedplus";
# line numbers
number = true;
numberwidth = 2;
relativenumber = true;
# tabs and indentation
tabstop = 2;
shiftwidth = 2;
softtabstop = -1;
expandtab = true;
smarttab = true;
autoindent = true;
# search
ignorecase = true;
smartcase = true;
# files and backups
backup = false;
writebackup = false;
undofile = true;
swapfile = true;
# wrapping
wrap = true;
linebreak = true;
breakindent = true;
termguicolors = true;
autoread = true;
};
languages = {
enableTreesitter = true;
nix = {
enable = true;
format = {
enable = true;
type = "alejandra";
#type = "nixfmt";
};
};
markdown.enable = true;
rust.enable = true;
lua.enable = true;
};
};
};
};
}

View File

@@ -1,20 +1,25 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, inputs, ... }:
{
imports = [
./dots/neovim
./dots/lf
];
# general config
home.username = "blake";
home.homeDirectory = "/home/blake";
home.stateVersion = "25.05";
# stand alone packages
home.packages = with pkgs; [
git
lf
ripgrep
btop
p7zip
ctpv
imagemagick
sops
usbutils
trashy
];
@@ -22,6 +27,7 @@
home.sessionVariables.ZDOTDIR = "$HOME/.config/zsh";
programs.zsh = {
enable = true;
# dotDir = ".config/zsh";
};
# link dotfiles
xdg.configFile."zsh" = {
@@ -29,30 +35,6 @@
recursive = true;
};
# setup neovim
programs.neovim = {
enable = true;
};
# link dotfiles
xdg.configFile."nvim" = {
source = config.lib.file.mkOutOfStoreSymlink "/home/blake/.nix/users/blake/dotfiles/nvim";
recursive = true;
};
# setup lf
programs.lf = {
enable = false;
};
# link dotfiles
xdg.configFile."lf" = {
source = config.lib.file.mkOutOfStoreSymlink "/home/blake/.nix/users/blake/dotfiles/lf";
recursive = true;
};
xdg.configFile."ctpv" = {
source = config.lib.file.mkOutOfStoreSymlink "/home/blake/.nix/users/blake/dotfiles/ctpv";
recursive = true;
};
programs.gpg = {
enable = true;
};
@@ -96,5 +78,4 @@
};
home.stateVersion = "25.05";
}