Author SHA1 Message Date
klaatu 68faf6b124 chore: update flake.lock 2026-05-17
buildbot/nix-eval Build done. (1 warning)
buildbot/nix-build gitea:greg/nixos#checks.x86_64-linux.pkg-gcc-tune Build done.
buildbot/nix-build Build done.
2026-05-17 00:03:17 +00:00
142 changed files with 2381 additions and 1840 deletions
-51
View File
@@ -1,51 +0,0 @@
name: Update zims pin
"on":
schedule:
- cron: "0 2 1 * *" # 0200 on the first of every month
workflow_dispatch:
jobs:
update-flake-lock:
runs-on: nix-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Update flake.lock
run: nix run .#zim-updater -- --output pkgs/zim/blobs.json
- name: Create PR if changed
env:
GITEA_TOKEN: ${{ secrets.KLAATU_TOKEN }}
GITEA_URL: https://src.thehellings.com
REPO: greg/nixos
run: |
if git diff --quiet pkgs/zim/blobs.json; then
echo "blobs.json unchanged, nothing to do"
exit 0
fi
BRANCH="auto/update-zims-$(date +%Y%m%d)"
git config user.email "klaatu@thehellings.com"
git config user.name "klaatu"
git checkout -b "$BRANCH"
git add pkgs/zim/blobs.json
git commit -m "chore: update zim blobs.json $(date +%Y-%m-%d)"
# Push branch using token auth
git remote set-url origin "https://klaatu:${GITEA_TOKEN}@${GITEA_URL#https://}/${REPO}.git"
git push origin "$BRANCH"
# Create PR via Gitea API
curl -s -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${GITEA_URL}/api/v1/repos/${REPO}/pulls" \
-d "{
\"title\": \"chore: update zims $(date +%Y-%m-%d)\",
\"head\": \"$BRANCH\",
\"base\": \"main\",
\"body\": \"Automated monthly zims update.\\n\\nGenerated by Gitea Actions.\",
\"assignees\": [\"greg\"]
}"
+12
View File
@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIByDCCAW+gAwIBAgIRANS+dPEH5Vqug7OWhCMmcx4wCgYIKoZIzj0EAwIwLjER
MA8GA1UEChMISGVsbGluZ3MxGTAXBgNVBAMTEEhlbGxpbmdzIFJvb3QgQ0EwHhcN
MjQwMjIwMjEyNzIxWhcNMzQwMjE3MjEyNzIxWjA2MREwDwYDVQQKEwhIZWxsaW5n
czEhMB8GA1UEAxMYSGVsbGluZ3MgSW50ZXJtZWRpYXRlIENBMFkwEwYHKoZIzj0C
AQYIKoZIzj0DAQcDQgAErZUhPfx5MpNbNVyqHDrIgUGnb6Hitl8hXlpH+kgjBzCi
7I/+TQnl9Tc0VVNOFOYLOfBi7hV3/QudUtLGk0FKeaNmMGQwDgYDVR0PAQH/BAQD
AgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFMZR8LDd+hNy+TmtEHvt
zRzXboh2MB8GA1UdIwQYMBaAFAlH11TwIFGB/K75qZ3e0S+fN3JUMAoGCCqGSM49
BAMCA0cAMEQCIBxHK6r8pMX5hrTwYKRfMmRIt44m0KtNejA2T5t09hs+AiBfvmHb
LfoE4qoC6NgpvXorAbx+O7xkem/9svF0Ob+RsA==
-----END CERTIFICATE-----
+11
View File
@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBoTCCAUagAwIBAgIRAL/1mvE8+73nRFGsvzaaVSAwCgYIKoZIzj0EAwIwLjER
MA8GA1UEChMISGVsbGluZ3MxGTAXBgNVBAMTEEhlbGxpbmdzIFJvb3QgQ0EwHhcN
MjQwMjIwMjEyNzIwWhcNMzQwMjE3MjEyNzIwWjAuMREwDwYDVQQKEwhIZWxsaW5n
czEZMBcGA1UEAxMQSGVsbGluZ3MgUm9vdCBDQTBZMBMGByqGSM49AgEGCCqGSM49
AwEHA0IABEgNBjlT/7gmzNp9vKJvGPJn9/IizuMGVpucdrN9+J1u1ABkLNRzj5p2
g7s3e/BG+EJnnTf/2tuq3p/wPqmQkdujRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNV
HRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBQJR9dU8CBRgfyu+amd3tEvnzdyVDAK
BggqhkjOPQQDAgNJADBGAiEA/uBclcFCOpkEgAeBAVurktYB82sMdIyyDGHcjlwi
pvkCIQC2kuZ/nXRjibeIebQIVTBskQ1LxlLxnx7zNSjtr3kFfQ==
-----END CERTIFICATE-----
+54
View File
@@ -0,0 +1,54 @@
services:
attic:
container_name: attic
image: ghcr.io/zhaofengli/attic:latest
command: ["-f", "/attic/server.toml"]
restart: unless-stopped
ports:
- 8080:8080
networks:
attic:
pgattic:
volumes:
- /mnt/all/configs/attic/server.toml:/attic/server.toml
- /mnt/all/containers/attic/data:/attic/storage
env_file:
- stack.env
depends_on:
pgattic:
condition: service_healthy
healthcheck:
test:
[
"CMD-SHELL",
"wget --no-verbose --tries=1 --spider http://attic:8080 || exit 1",
]
interval: 15s
timeout: 10s
retries: 10
start_period: 15s
deploy:
resources:
reservations:
cpus: 1.0
pgattic:
container_name: pgattic
image: postgres:17.6-alpine
restart: unless-stopped
ports: []
networks:
pgattic:
volumes:
- /mnt/all/containers/attic/postgres:/var/lib/postgresql/data
env_file:
- stack.env
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
networks:
attic:
pgattic:
+9
View File
@@ -0,0 +1,9 @@
services:
pinchflat:
image: ghcr.io/kieraneglin/pinchflat:latest
ports:
- "8945:8945"
volumes:
- "/mnt/all/configs/pinchflat:/config"
- "/mnt/all/video/yt:/downloads"
restart: unless-stopped
+19
View File
@@ -0,0 +1,19 @@
# Demo of rest-server with prometheus and grafana
version: "2"
services:
restserver:
image: "restic/rest-server:0.14.0"
volumes:
- /mnt/all/backups:/data
- /mnt/all/configs/certs:/certs
environment:
OPTIONS: >-
--tls
--tls-cert /certs/nas1.shire-zebra.ts.net.crt
--tls-key /certs/nas1.shire-zebra.ts.net.key
--path /data
--prometheus
--debug
ports:
- "30248:8000"
+4 -34
View File
@@ -1,6 +1,5 @@
{
pkgs,
pkgs',
top,
...
}:
@@ -32,51 +31,22 @@ let
};
in
{
environment = {
launchDaemons = {
"limit.maxfiles.plist" = {
enable = true;
text = ''
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>524288</string>
<string>524288</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
'';
};
};
systemPackages = with pkgs; [
environment.systemPackages = with pkgs; [
agenix
pkgs'.hms
procps # Includes tools like `watch`, `kill`, and `ps`
hms
];
};
fonts.packages = with pkgs; [
dejavu_fonts
nerd-fonts.hack
];
#launchd.daemons.darwin-builder = builder;
launchd.daemons.darwin-builder = builder;
nix = {
#buildMachines = [ { systems = ["aarch64-linux"]; sshUser = "builder"; sshKey = "/etc/nix/builder_ed25519"; hostName = "localhost:31022"; protocol = "ssh-ng"; }];
enable = true;
gc.interval.Hour = 3;
#linux-builder.enable = true;
linux-builder.enable = true;
settings.auto-optimise-store = false; # Darwin bugs?
};
-1
View File
@@ -19,7 +19,6 @@ let
specialArgs = {
inherit metadata top;
inherit (top) self;
pkgs' = top.self.packages.${system};
};
modules = [
{
+1 -1
View File
@@ -11,7 +11,6 @@ in
enable = true;
brews = [
"bitwarden-cli"
"colima"
"direnv"
"github-mcp-server"
{
@@ -38,6 +37,7 @@ in
"notion"
"notunes"
"onlyoffice"
"podman-desktop"
"tabby"
"zed"
];
Generated
+87 -136
View File
@@ -31,11 +31,11 @@
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1783833875,
"narHash": "sha256-G+hRtNJ/Nnr6VFMQp2UZdx/ckJDR/RJoK0Fy/yx1/YY=",
"lastModified": 1778391342,
"narHash": "sha256-7FVIfUHdQEB6HM+gUPLJVaL7ABrqlnMxS/pO+vNvjd8=",
"owner": "nix-community",
"repo": "buildbot-nix",
"rev": "147af587241e2af85399402da60a4f44fdb1e5d7",
"rev": "0bedd1aafd1653858d5f1e0f08eba3d7ec397dff",
"type": "github"
},
"original": {
@@ -53,11 +53,11 @@
"stable": "stable"
},
"locked": {
"lastModified": 1783909498,
"narHash": "sha256-T9OfLPLuh1Bf1xojlpWXwooJ6IXapxvb8GM0p3YNy8g=",
"lastModified": 1762034856,
"narHash": "sha256-QVey3iP3UEoiFVXgypyjTvCrsIlA4ecx6Acaz5C8/PQ=",
"owner": "zhaofengli",
"repo": "colmena",
"rev": "76ba0daa542880b730faec81f4e87efcaa63bc57",
"rev": "349b035a5027f23d88eeb3bc41085d7ee29f18ed",
"type": "github"
},
"original": {
@@ -95,11 +95,11 @@
]
},
"locked": {
"lastModified": 1784362797,
"narHash": "sha256-EP9b9b+OXDxHBPefFwMYCIaLq0fn3UkmrbfzbLUT7kQ=",
"lastModified": 1777780666,
"narHash": "sha256-8wURyQMdDkGUarSTKOGdCuFfYiwa3HbzwscUfn3STDE=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "b4cccbd4bc299c1f71ae185b79c3cf99aa82805c",
"rev": "8c62fba0854ba15c8917aed18894dbccb48a3777",
"type": "github"
},
"original": {
@@ -112,11 +112,11 @@
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
@@ -162,11 +162,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1782949081,
"narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"type": "github"
},
"original": {
@@ -183,11 +183,11 @@
]
},
"locked": {
"lastModified": 1782949081,
"narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=",
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"type": "github"
},
"original": {
@@ -218,15 +218,12 @@
}
},
"flake-utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
@@ -242,11 +239,11 @@
]
},
"locked": {
"lastModified": 1784407317,
"narHash": "sha256-iZrxHToDJWnvt+5LGAtvuQMTy1NZYlNEKbKaVtBJNcc=",
"lastModified": 1778954430,
"narHash": "sha256-oaNyOr05lblaQdtbkbN1wO0b2KLIL2O1LkmwDgdQp4I=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "39411a8e12a5526d992e65bc7e3dc9a4414d6713",
"rev": "26aaab785b0bab4af60a2c42b22760fa906ef22a",
"type": "github"
},
"original": {
@@ -281,14 +278,14 @@
"inputs": {
"flake-compat": "flake-compat_2",
"nixpkgs": "nixpkgs_2",
"systems": "systems_3"
"systems": "systems_2"
},
"locked": {
"lastModified": 1784344393,
"narHash": "sha256-yAo2ZzSIdeBZg7cOKUpQxwflL+DRYN+1DMObZk2lP2Q=",
"lastModified": 1778039471,
"narHash": "sha256-Arjg44jFcpSqOKK05EIxbKIjhfjou/EGF12COFU+9QA=",
"owner": "Infinidoge",
"repo": "nix-minecraft",
"rev": "7297d14c52ec8ef39c6aeff2c1818541fd030473",
"rev": "87611ef4788116de05f851920c5958f0c37d5b05",
"type": "github"
},
"original": {
@@ -303,11 +300,11 @@
"treefmt-nix": "treefmt-nix_2"
},
"locked": {
"lastModified": 1784016977,
"narHash": "sha256-TydDba3YD2u15uS0L+PDs7lMqPopnzWggljTKDqOCSw=",
"lastModified": 1778839878,
"narHash": "sha256-S2nSP6YWUz8I2uRZuAY93FoAAUa9TiZetLzjBv1n5vk=",
"owner": "Mic92",
"repo": "niks3",
"rev": "b306808bf381e7e66e33de1e9446a1be0935f4e3",
"rev": "c29f3641de064545d75f00318cd45bea2b4ea1d0",
"type": "github"
},
"original": {
@@ -324,11 +321,11 @@
]
},
"locked": {
"lastModified": 1737420293,
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
"lastModified": 1729742964,
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
"type": "github"
},
"original": {
@@ -338,15 +335,12 @@
}
},
"nix-hardware": {
"inputs": {
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1784310968,
"narHash": "sha256-rkSPTePrKqs4dg+i7ZFCq93+HrClac6oSwXX927SVjA=",
"lastModified": 1778945272,
"narHash": "sha256-Aipz0UiBhE2a1FYJrNc2y+5vKWo5QVkhmaIJk3/ls+g=",
"owner": "nixos",
"repo": "nixos-hardware",
"rev": "779c32a00155994c86cde8213a8dd4df139d4355",
"rev": "379c1f274f0fa354d012f0600806de54e79f29b5",
"type": "github"
},
"original": {
@@ -357,11 +351,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1783224372,
"narHash": "sha256-8i/87eeoqiGE4yOTjwSA3Eh/ziJRQEmd/unYU+K27sk=",
"lastModified": 1750134718,
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d407951447dcd00442e97087bf374aad70c04cea",
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c",
"type": "github"
},
"original": {
@@ -373,11 +367,11 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1782614948,
"narHash": "sha256-ePjCwr1sNm9NYUqywL7QfK3JnlS015msC+eBu2zKlp8=",
"lastModified": 1777168982,
"narHash": "sha256-GOkGPcboWE9BmGCRMLX3worL4EMnsnG8MyKmXNeYuhQ=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "db3f255737b94216eb71cce308e2912cf6bc2d7c",
"rev": "f5901329dade4a6ea039af1433fb087bd9c1fe14",
"type": "github"
},
"original": {
@@ -388,11 +382,11 @@
},
"nixpkgs-lib_2": {
"locked": {
"lastModified": 1783821755,
"narHash": "sha256-eMPX9S6MKPyUnaOgeRfrG7OKUiAlc1AlcRinMbSB0WA=",
"lastModified": 1778379128,
"narHash": "sha256-+yjPmoKsTqe/FQHriXzIfI0ELuEt3+1LXc0BE8nU/Yc=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "228ab8523d81526e57a6ca342e1a919fb6d246a8",
"rev": "e361b0ff94723bc94283566dc2a13a46f07eaf5c",
"type": "github"
},
"original": {
@@ -419,11 +413,11 @@
},
"nixpkgs_3": {
"locked": {
"lastModified": 1783978241,
"narHash": "sha256-7kK0Y/fIV2NTKArkd/eZGaFg+dEmgP8KDRsGK2vB5M4=",
"lastModified": 1778491576,
"narHash": "sha256-9YOHDS9ANGbRmf3DSQ9UCvas3CyYNIBwBkKGQZTLXGY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a8b81d3cc8d35af7bc98694696bea61ad4f8fca7",
"rev": "1174f92bf37f1a5914be77e1b44482d6fbc75ecc",
"type": "github"
},
"original": {
@@ -435,40 +429,11 @@
},
"nixpkgs_4": {
"locked": {
"lastModified": 1767892417,
"narHash": "sha256-8bW3q88CEg2u4hSP66Vf4lpbLonHz7hqDNBMcCY7E9U=",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"type": "tarball",
"url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre924538.3497aa5c9457/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
"url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1783915482,
"narHash": "sha256-FmieJB8/OUvNxbkboi7+IGfIuSXY3nF/hZQm8kD0r50=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6cdc7fc76e8bf7fde9fa43a849fcaaa70e230dee",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_6": {
"locked": {
"lastModified": 1784356753,
"narHash": "sha256-12KrbMiWLcf8m7pCvAtZh1ZrgF85ZXDXvfR/fWTKy84=",
"lastModified": 1778869304,
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "61b7c44c4073f0b827768aff0049561b5110ea5a",
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
"type": "github"
},
"original": {
@@ -478,7 +443,7 @@
"type": "github"
}
},
"nixpkgs_7": {
"nixpkgs_5": {
"locked": {
"lastModified": 1777207419,
"narHash": "sha256-V3bmPWAajDiC+1ClDOp55gianW2EyRJSJOyu1RUQibc=",
@@ -496,16 +461,16 @@
},
"nixunstable": {
"locked": {
"lastModified": 1784700541,
"narHash": "sha256-LcCdjhqwjFVrFTNW6tHm3KNYRrD1TA6bYRea30yIIjw=",
"owner": "geri1701",
"lastModified": 1778869304,
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "3c598184d1f70c5d0beeea8b95d01ab0179e4ef7",
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
"type": "github"
},
"original": {
"owner": "geri1701",
"ref": "lego-v5-acme-spike",
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
@@ -513,15 +478,17 @@
"nixvimunstable": {
"inputs": {
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs_5",
"systems": "systems_4"
"nixpkgs": [
"nixunstable"
],
"systems": "systems_3"
},
"locked": {
"lastModified": 1784057377,
"narHash": "sha256-yycNej5//EsRbV10moBoh+/63vXEwZD1ZFEiRm6C9rQ=",
"lastModified": 1778906310,
"narHash": "sha256-LqASEJRtLuKRBJd9051T1KMAEaYvsVrc6m64jhD6xbw=",
"owner": "nix-community",
"repo": "nixvim",
"rev": "07180a087e4a00720dc0731cbcd8dec796974381",
"rev": "06cace835d7ee727852ac789e3dcd42fc2fd360e",
"type": "github"
},
"original": {
@@ -534,14 +501,14 @@
"nurpkgs": {
"inputs": {
"flake-parts": "flake-parts_3",
"nixpkgs": "nixpkgs_6"
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1784417922,
"narHash": "sha256-19XZ56wJXArMKxjY25pKXkNp/FrYHGoo+HuQtW6teSM=",
"lastModified": 1778975705,
"narHash": "sha256-DweZZ/JO7AxbQ9+caW8Jt8L5MtjMvVWpKDS+MAiWN8E=",
"owner": "nix-community",
"repo": "NUR",
"rev": "2c806d314605495dd7fd75b5950003a062e2b47a",
"rev": "25081c3d50352c88e7502e2a1c76fda8560b2b41",
"type": "github"
},
"original": {
@@ -571,16 +538,16 @@
},
"stable": {
"locked": {
"lastModified": 1783625654,
"narHash": "sha256-pI1244/PJfTyKhlAr2QYQC55vR6UQdnGA0rJUgtO2IQ=",
"lastModified": 1750133334,
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a0230bd8d5cbd13893b2263918d396a2c7dd0407",
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-26.05",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
@@ -630,22 +597,6 @@
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1774449309,
"narHash": "sha256-brhZ8DmuGtzkCYHJg4HEd602amKm89Y9ytsFZ5uWD1w=",
"owner": "nix-systems",
"repo": "default",
"rev": "c29398b59d2048c4ab79345812849c9bd15e9150",
"type": "github"
},
"original": {
"owner": "nix-systems",
"ref": "future-26.11",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
@@ -654,11 +605,11 @@
]
},
"locked": {
"lastModified": 1780220602,
"narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=",
"lastModified": 1775636079,
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "db947814a175b7ca6ded66e21383d938df01c227",
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
"type": "github"
},
"original": {
@@ -675,11 +626,11 @@
]
},
"locked": {
"lastModified": 1780220602,
"narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=",
"lastModified": 1775636079,
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "db947814a175b7ca6ded66e21383d938df01c227",
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
"type": "github"
},
"original": {
@@ -690,14 +641,14 @@
},
"vsext": {
"inputs": {
"nixpkgs": "nixpkgs_7"
"nixpkgs": "nixpkgs_5"
},
"locked": {
"lastModified": 1784343266,
"narHash": "sha256-EGkegdTz2n6ESyih8s3dUuPyJQWlYfPp7U41J05g8PY=",
"lastModified": 1778902753,
"narHash": "sha256-4tgJmu6sc6F6y+igJfh+kG0t2U1T2cDwfhz5hC0W2Tg=",
"owner": "nix-community",
"repo": "nix-vscode-extensions",
"rev": "472a3e862c76c64ac3ad75a24d332cb5cdd5f1bb",
"rev": "5df06838c483ad33aa5fb1448b9ba9de665930a1",
"type": "github"
},
"original": {
@@ -714,11 +665,11 @@
]
},
"locked": {
"lastModified": 1784058842,
"narHash": "sha256-3u3tvbCIAid3Mv7RrJx13jusIEQC/HeKYhO/SUSxR3A=",
"lastModified": 1777732699,
"narHash": "sha256-2uX/XtOWZ/oy2rerRynVhqVA//ZXZ3Fo60PikLHEPQc=",
"owner": "nix-community",
"repo": "NixOS-WSL",
"rev": "24c8dc8e0f2170e1a377be24dfadc7d9d21dc1ad",
"rev": "5482f113fd31ebac131d1ebeb2ae90bf0d5e41f5",
"type": "github"
},
"original": {
+7 -9
View File
@@ -27,9 +27,11 @@
niks3.url = "github:Mic92/niks3";
nix-hardware.url = "github:nixos/nixos-hardware";
nixpkgs-lib.url = "github:nix-community/nixpkgs.lib";
nixvimunstable.url = "github:nix-community/nixvim/main";
#nixunstable.url = "github:nixos/nixpkgs/nixos-unstable";
nixunstable.url = "github:geri1701/nixpkgs/lego-v5-acme-spike";
nixvimunstable = {
url = "github:nix-community/nixvim/main";
inputs.nixpkgs.follows = "nixunstable";
};
nixunstable.url = "github:nixos/nixpkgs/nixos-unstable";
nurpkgs.url = "github:nix-community/NUR";
vsext.url = "github:nix-community/nix-vscode-extensions";
wsl = {
@@ -63,10 +65,7 @@
config = {
allowUnfree = true;
allowUnfreePredicate = _: true;
permittedInsecurePackages = [
"ventoy-1.1.05"
"electron-39.8.10"
];
permittedInsecurePackages = [ "ventoy-1.1.05" ];
};
}
);
@@ -87,7 +86,6 @@
self
top
;
pkgs' = top.self.packages.x86_64-linux;
};
};
}
@@ -101,7 +99,7 @@
{
deployment = {
inherit (v) tags;
targetHost = if (v ? "connectAddr") then v.connectAddr else v.nebulaIp;
targetHost = v.ts;
targetUser = "greg";
};
}
-1
View File
@@ -20,4 +20,3 @@ builds:
# to build at home
- homeConfigurations."gregory.hellings-mbp"
- homeConfigurations.gregs-MacBook-Pro-16-inch-Nov-2024
- homeConfigurations.ivr
+12 -46
View File
@@ -1,5 +1,5 @@
# vim: set filetype=nushell :
let servers = [isaiah jeremiah zeke genesis hosea]
let servers = [isaiah jeremiah zeke genesis]
def par-map [ items: list, c: closure ] {
let results = $items | par-each -k $c
@@ -12,55 +12,15 @@ def --env unlock [] {
}
}
def nebulaIps [] {
open /etc/nixos/network.json | get hosts | items { |h, e| $e.nebulaIp? } | where $it != null | sort
}
def localIps [] {
open /etc/nixos/network.json | get hosts | items { |h, e| $e.ip? } | where $it != null | sort
}
def genNebulaCert [ --ips: string, --name: string ] {
let public = $'~/SynologyDrive/nebula/($name).key.pub' | path expand
let private = $'~/SynologyDrive/nebula/($name).key' | path expand
let cert = $'/etc/nixos/secrets/nebula/($name).crt'
let ca_cert = '~/SynologyDrive/nebula/ca.crt' | path expand
let ca_key = '~/SynologyDrive/nebula/ca.key' | path expand
# Generate public key if there isn't one already
if ( not ($public | path exists) ) {
nebula-cert keygen -out-key $private -out-pub $public
}
# Clear old cert if there is one
if ( $cert | path exists) {
rm $cert
}
# Create and sign certs
(nebula-cert sign
-ca-crt $ca_cert
-ca-key $ca_key
-name $name
-networks $ips
-out-crt $cert
-in-pub $public
)
# Agenix update
cd /etc/nixos/secrets
cat $private | agenix -e $'nebula/($name).key.age'
}
def rebuild [ $target: string = "switch" ] {
def rebuild [] {
if (uname | get operating-system) == "Darwin" {
sudo darwin-rebuild $target
sudo darwin-rebuild switch
} else {
let hostname = uname | get nodename
let build = ^nom build --keep-going $"/etc/nixos#nixosConfigurations.($hostname).config.system.build.toplevel"
if $env.LAST_EXIT_CODE == 0 {
nvd diff /run/current-system result
run0 result/bin/switch-to-configuration $target
run0 result/bin/switch-to-configuration switch
} else {
print "Error during build"
}
@@ -75,8 +35,7 @@ def deploy [ $host: string, $build: string = "" ] {
if $buildhost == "linode" or $buildhost == "genesis" {
$buildhost = "isaiah"
}
colmena apply --on $host
#nixos-rebuild switch --sudo --use-substitutes --target-host $host --build-host $buildhost
nixos-rebuild switch --sudo --use-substitutes --target-host $host --build-host $buildhost
}
def ff [ $file: string ] {
@@ -110,6 +69,13 @@ def dc [ $cmd: string = "sh" ] {
}
}
def claude [ ] {
unlock
$env.GITLAB_TOKEN = ^bw get item 7d3da4e9-5f9a-49d0-8e14-b39c010a4001 | from json | get fields | find claudeapi | get value
#$env.ANTHROPIC_API_KEY = ^bw get item e122fd08-3506-4f21-9c6a-b42b00fe5be1 | from json | get login.password
^claude
}
if ("/usr/local/bin" | path exists) {
$env.PATH = $env.PATH | append "/usr/local/bin"
}
+24 -25
View File
@@ -13,25 +13,24 @@
includes = [ "config.local" ];
enableDefaultConfig = false;
settings =
matchBlocks =
let
nas = {
User = "admin";
user = "admin";
};
owned = {
User = "greg";
user = "greg";
};
in
{
inherit nas;
"*" = {
DynamicForward = [ "10240" ];
ForwardAgent = "yes";
dynamicForwards = [ { port = 10240; } ];
serverAliveInterval = 60;
extraOptions = {
LogLevel = "error";
ServerAliveInterval = 60;
SetEnv = {
TERM = "xterm-256color";
SetEnv = "TERM=xterm-256color";
};
};
@@ -42,46 +41,46 @@
"chronicles.thehellings.lan" = lib.hm.dag.entryBefore [ "*.thehellings.lan" ] nas;
gh = {
User = "git";
Hostname = "github.com";
user = "git";
hostname = "github.com";
};
"src" = {
User = "git";
Hostname = "jeremiah.shire-zebra.ts.net";
Port = 32222;
user = "git";
hostname = "jeremiah.shire-zebra.ts.net";
port = 32222;
};
srcpub = {
User = "git";
Hostname = "src.thehellings.com";
Port = 2222;
user = "git";
hostname = "src.thehellings.com";
port = 2222;
};
ivr = {
User = "git";
Hostname = "gitlab.com";
user = "git";
hostname = "gitlab.com";
};
"ivr.thehellings.lan" = lib.hm.dag.entryBefore [ "ivr" ] {
User = "gregory.hellings";
user = "gregory.hellings";
};
"*.thehellings.lan" = owned;
"10.42.*" = owned;
"host.crosswire.org crosswire" = {
Hostname = "host.crosswire.org";
User = "ghellings";
hostname = "host.crosswire.org";
user = "ghellings";
};
fedpeople = {
Hostname = "fedorapeople.org";
User = "greghellings";
hostname = "fedorapeople.org";
user = "greghellings";
};
"src.fedoraproject.org pkgs.fedoraproject.org" = {
User = "greghellings";
user = "greghellings";
};
"127.*" = {
"127.*".extraOptions = {
PubkeyAcceptedAlgorithms = "+ssh-rsa";
HostkeyAlgorithms = "+ssh-rsa";
};
+1
View File
@@ -8,6 +8,7 @@
home.packages =
with pkgs;
[
attic-client
dig
jqp
kubernetes-helm
-1
View File
@@ -1 +0,0 @@
{...}: {}
+1 -14
View File
@@ -1,4 +1,4 @@
{ lib, pkgs, ... }:
{ pkgs, ... }:
{
greg = {
@@ -23,12 +23,8 @@
mattermost-desktop
minio-client
mumble
nebula
nix-index
adoptopenjdk-icedtea-web
pre-commit
prismlauncher
rclone
restic
restic-browser
tea
@@ -40,13 +36,4 @@
settings.SKIP_HOST_UPDATE = true;
};
};
xdg.desktopEntries = {
prismlauncher = {
name = "Prism Launcher - Minecraft";
actions.minecraft = {
name = "Minecraft";
exec = lib.getExe pkgs.prismlauncher;
};
};
};
}
+3 -9
View File
@@ -1,6 +1,5 @@
{
pkgs,
pkgs',
lib,
username,
...
@@ -21,7 +20,6 @@
claude-code
direnv
home-manager
pkgs'.dockerCompat
python3Packages.ipython
just
glab
@@ -38,22 +36,18 @@
".pip/pip.conf".text = ''
[global]
retries = 1
index-url = https://pypi.python.org/
index-url = https://pypi.python.org/simple
extra-index-url =
https://pypidev.ivrtechnology.com/
https://pypidev.ivrtechnology.com/simple/
'';
".config/uv/uv.toml".text = ''
index-strategy = "unsafe-first-match"
[[index]]
url = "https://pypidev.ivrtechnology.com/"
url = "https://pypidev.ivrtechnology.com/simple/"
name = "pypidev"
ignore-error-codes = [403]
'';
};
sessionVariables = {
BW_GITLAB_ITEM = "7d3da4e9-5f9a-49d0-8e14-b39c010a4001";
BW_ANTHROPIC_ITEM = "e122fd08-3506-4f21-9c6a-b42b00fe5be1";
};
username = username;
homeDirectory = "/Users/${username}";
};
+4
View File
@@ -0,0 +1,4 @@
{ ... }:
{
}
+1 -8
View File
@@ -1,6 +1,5 @@
{
pkgs,
pkgs',
lib,
...
}:
@@ -27,17 +26,12 @@ in
ansible
awscli2
cargo
clippy
direnv
docker
docker-compose
docker-buildx
go
home-manager
just
mcp-grafana
nil
nixVersions.stable
podman
poetry
pre-commit
(pulumi.withPackages (
@@ -51,7 +45,6 @@ in
))
python
rustc
rustfmt
terraform
];
};
-1
View File
@@ -30,7 +30,6 @@ let
modules = [
{
nixpkgs.hostPlatform = system;
networking.hostName = name;
}
# Imported ones
top.agenix.nixosModules.default
+5 -1
View File
@@ -9,9 +9,13 @@
{
imports = [
./hardware-configuration.nix
top.nix-hardware.nixosModules.framework-intel-core-ultra-series1
top.nix-hardware.nixosModules.framework-11th-gen-intel
];
age.secrets = {
compose-attic.file = ../../../secrets/compose/attic.env.age;
};
boot = {
loader = {
systemd-boot = {
+2 -3
View File
@@ -62,7 +62,6 @@
serverProperties = {
allow-flight = true;
motd = "Maya's Minecraft World";
online-mode = true;
};
whitelist = { };
@@ -129,8 +128,8 @@
# Better storage engines
# https://www.curseforge.com/minecraft/mc-mods/refined-storage
refined-storage = pkgs.fetchurl {
url = "https://mediafilez.forgecdn.net/files/8086/588/refinedstorage-fabric-3.0.0.jar";
hash = "sha256-LuOF0aYQon78AQeD5fQ8OXHCnekfa+PNKpH7cqimFNs=";
url = "https://mediafilez.forgecdn.net/files/8032/790/refinedstorage-fabric-3.0.0-beta.8.jar";
hash = "sha256-XY5I+sw5JlWnKK/hPUOJsk2gnmqH4Iygq+aooN27NJY=";
};
# https://www.curseforge.com/minecraft/mc-mods/storage-drawers
#storagedrawers = pkgs.fetchurl {
+5 -11
View File
@@ -22,7 +22,6 @@ let
#"1.0.0.1" # Cloudflare
#"149.112.112.112" # Quad 9
metadata.infra.gw # Currently using our UniFi router for DNS as well
"100.100.100.100"
];
in
{
@@ -77,7 +76,7 @@ in
};
};
firewall = {
enable = true;
enable = false;
allowedUDPPorts = [
dhcpPort
dnsPort
@@ -88,7 +87,7 @@ in
80
];
};
nftables.enable = true;
nftables.enable = false;
};
environment.etc."hosts.d/local".text = extraHosts;
@@ -116,21 +115,16 @@ in
"@\tIN\tSOA\t${config.networking.hostName}\tgreg@thehellings.com (1 1m 1m 1m 1m)"
"\tIN\tNS\t${config.networking.hostName}"
];
makeHost =
host:
[ "${host.name}\tIN\tA\t${host.address}" ]
++ lib.map (a: "${a}\tIN\tA\t${host.address}") (
if builtins.hasAttr "aliases" host then host.aliases else [ ]
);
makeHost = host: "${host.name}\tIN\tA\t${host.address}";
in
pkgs.writeText "${domain}" (
builtins.concatStringsSep "\n" (preamble ++ (lib.flatten (lib.map makeHost hosts)) ++ [ "" ])
builtins.concatStringsSep "\n" (preamble ++ (lib.map makeHost hosts) ++ [ "" ])
);
in
lib.mapAttrs
(domain: net: {
master = true;
file = makeZoneFile (lib'.hostsByNet net (metadata.hosts // metadata.external)) domain;
file = makeZoneFile (lib'.hostsByNet net metadata.hosts) domain;
})
{
"shire-zebra.ts.net" = "tailscale";
+70
View File
@@ -0,0 +1,70 @@
{
lib,
metadata,
pkgs,
...
}:
let
ips = lib.filterAttrs (_k: v: v ? "ip" && v.ip != null) metadata.hosts;
tps = lib.filterAttrs (_k: v: v ? "ts" && v.ts != null) metadata.hosts;
get = field: set: lib.mapAttrsToList (_k: v: v.${field}) set;
getTS = get "ts" tps;
getIP = get "ip" ips;
whitelists = builtins.concatStringsSep "," (
[
"localhost"
"127.0.0.1"
]
++ getTS
++ getIP
);
in
{
services = {
prowlarr = {
enable = true;
dataDir = "/arr/prowlarr";
openFirewall = true;
};
radarr = {
enable = true;
openFirewall = true;
};
transmission = {
enable = true;
openPeerPorts = true;
openRPCPort = true;
package = pkgs.transmission_4;
settings = {
download-dir = "/arr/transmission/downloads";
rpc-bind-address = "0.0.0.0";
rpc-host-whitelist = whitelists;
rpc-host-whitelist-enabled = false;
rpc-whitelist = whitelists;
rpc-whitelist-enabled = false;
watch-dir-enabled = true;
watch-dir = "/arr/transmission/incoming";
};
};
};
systemd.mounts =
let
nfs = name: {
what = "nas1.shire-zebra.ts.net:/mnt/all/${name}";
type = "nfs";
name = "${name}.mount";
where = "/${name}";
requires = [ "tailscaled-autoconnect.service" ];
after = [ "tailscaled-autoconnect.service" ];
wantedBy = [ "multi-user.target" ];
mountConfig.Options = "_netdev,noexec,timeo=50,retrans=5,soft";
};
in
[
(nfs "arr")
(nfs "music")
(nfs "photos")
(nfs "video")
];
}
+2 -20
View File
@@ -18,6 +18,7 @@ in
{
imports = [
# Include the results of the hardware scan.
./arr.nix
./hardware-configuration.nix
top.niks3.nixosModules.niks3
];
@@ -185,7 +186,7 @@ in
s3 = {
accessKeyFile = config.age.secrets.niks3-access-key-id.path;
bucket = "niks3";
endpoint = "nas1.shire-zebra.ts.net:30188";
endpoint = "nas1.shire-zebra.ts.net:9000";
secretKeyFile = config.age.secrets.niks3-secret-access-key.path;
useSSL = false;
};
@@ -199,25 +200,6 @@ in
};
};
systemd.mounts =
let
nfs = name: {
what = "nas1.shire-zebra.ts.net:/mnt/all/${name}";
type = "nfs";
name = "${name}.mount";
where = "/${name}";
requires = [ "tailscaled-autoconnect.service" ];
after = [ "tailscaled-autoconnect.service" ];
wantedBy = [ "multi-user.target" ];
mountConfig.Options = "_netdev,noexec,timeo=50,retrans=5,soft";
};
in
[
(nfs "music")
(nfs "photos")
(nfs "video")
];
# After first deploy: create a Grafana service account + API token for Klaatu
# via the Grafana UI, then encrypt it: agenix -e secrets/grafana-api-token.age
age.secrets.grafana-api-token = {
+11
View File
@@ -0,0 +1,11 @@
{ ... }:
{
# Bootloader.
boot = {
loader.grub = {
enable = true;
device = "/dev/sda";
};
};
}
+28
View File
@@ -0,0 +1,28 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
./boot.nix
./filesystem.nix
./location.nix
./networking.nix
./wiki.nix
];
# Define a user account. Don't forget to set a password with passwd.
users.users.greg = {
isNormalUser = true;
description = "Gregory Hellings";
extraGroups = [
"networkmanager"
"wheel"
];
packages = with pkgs; [ ];
};
}
+13
View File
@@ -0,0 +1,13 @@
{ ... }:
let
in
{
fileSystems."serve" = {
#device = "10.42.1.4:/volume1/icdm-mysql/";
#fsType = "nfs";
device = "/dev/sdb1";
fsType = "auto";
mountPoint = "/srv";
};
}
@@ -0,0 +1,53 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot.initrd.availableKernelModules = [
"xhci_pci"
"ehci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/dab0d455-e25e-4445-8fa4-5320047d7e7b";
fsType = "btrfs";
options = [ "subvol=@" ];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/5aedbb07-5761-423b-909d-2560405eae32";
fsType = "ext4";
};
fileSystems."/var" = {
device = "/dev/disk/by-uuid/57968536-c29d-417d-997e-85223d1d1f65";
fsType = "btrfs";
};
swapDevices = [ { device = "/dev/disk/by-uuid/09691dce-375a-43c6-8d40-4498d20a6d9a"; } ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp2s0.useDHCP = lib.mkDefault true;
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
+15
View File
@@ -0,0 +1,15 @@
{ ... }:
{
# Set your time zone.
time.timeZone = "America/Chicago";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
# Configure keymap in X11
services.xserver.xkb = {
layout = "us";
variant = "";
};
}
+63
View File
@@ -0,0 +1,63 @@
{ ... }:
let
dnsHosts = builtins.concatStringsSep "\n" [ "wiki.icdm.lan 10.42.101.1" ];
in
{
# If we have to do proxying in Bayonnais, we can start to work on that here
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
networking = {
hostName = "icdm-root";
useDHCP = false;
defaultGateway = "10.42.1.1";
nameservers = [
"100.100.100.100"
"10.42.1.2"
];
enableIPv6 = false;
interfaces = {
eno1.ipv4.addresses = [
{
address = "10.42.101.1";
prefixLength = 16;
}
{
address = "10.77.1.2";
prefixLength = 16;
}
];
};
# Allow traffic through
firewall = {
enable = true;
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [
53
67
];
};
extraHosts = "${dnsHosts}";
};
services.dnsmasq = {
enable = true;
settings = {
domain = "icdm.lan";
dhcp-range = [ "eno1,10.77.1.10,10.77.1.255,255.255.0.0,12h" ];
dhcp-option = [
"eno1,option:router,10.77.1.1"
"eno1,option:dns-server,10.77.1.2,1.1.1.1"
"eno1,option:domain-search,icdm.lan"
];
expand-hosts = true;
log-dhcp = true;
log-queries = true;
# Upstream servers
server = [
"1.1.1.1"
"8.8.4.4"
];
};
};
}
+17
View File
@@ -0,0 +1,17 @@
{ pkgs, ... }:
let
wikiHost = "wiki.icdm.lan";
kiwixport = 8080;
in
{
services.kiwix-serve = {
enable = true;
port = kiwixport;
library = {
inherit (pkgs) zim;
};
};
greg.proxies."${wikiHost}".target = "http://localhost:${toString kiwixport}";
networking.firewall.allowedTCPPorts = [ 80 ];
}
-4
View File
@@ -47,10 +47,6 @@
enable = true;
extraLabels = [ "bare-metal:host" ];
};
vmdev = {
enable = true;
host = "libvirt";
};
};
networking = {
+2 -3
View File
@@ -88,7 +88,6 @@ in
priority = 254;
};
nebula.enable = true;
proxies."buildbot.nebula.thehellings.com".target = "http://buildbot.nebula.thehellings.com:8010/";
tailscale = {
enable = true;
tags = [ "home" ];
@@ -143,7 +142,7 @@ in
updateOutputs = false;
};
};
domain = "buildbot.nebula.thehellings.com:8010";
domain = "${config.networking.hostName}.shire-zebra.ts.net";
evalMaxMemorySize = 8192;
evalWorkerCount = 4;
gitea = {
@@ -156,7 +155,7 @@ in
webhookSecretFile = config.age.secrets.gitea-webhookSecret.path;
};
showTrace = true;
#webhookBaseUrl = "http://${config.networking.hostName}.nebula.thehellings.com:8010";
#webhookBaseUrl = "http://${config.networking.hostName}.shire-zebra.ts.net:8010";
workersFile = config.age.secrets.gitea-buildbotWorkersFile.path;
};
worker = {
-76
View File
@@ -1,76 +0,0 @@
{
config,
metadata,
modulesPath,
pkgs,
...
}:
{
imports = [ "${modulesPath}/virtualisation/proxmox-image.nix" ];
greg = {
home = true;
nebula.enable = true;
proxies =
let
tgt = {
target = "http://localhost:${config.services.uptime-kuma.settings.PORT}";
genAliases = false;
};
in
{
"kuma.nebula.thehellings.com" = tgt;
"kuma.thehellings.lan" = tgt;
"kuma.shire-zebra.ts.net" = tgt;
};
};
nix.settings = {
sandbox = false;
};
networking = {
defaultGateway = metadata.infra.gw;
nameservers = [ metadata.infra.dns ];
interfaces.ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = metadata.hosts."${config.networking.hostName}".ip;
prefixLength = 16;
}
];
};
};
proxmox.cloudInit.enable = false;
services = {
fstrim.enable = true;
mysql = {
enable = true;
ensureDatabases = [
config.services.uptime-kuma.settings.UPTIME_KUMA_DB_NAME
];
ensureUsers = [
{
name = config.services.uptime-kuma.settings.UPTIME_KUMA_DB_USERNAME;
ensurePermissions = {
"uptimekuma.*" = "ALL PRIVILEGES";
};
}
];
package = pkgs.mariadb;
};
openssh = {
enable = true;
openFirewall = true;
};
uptime-kuma = {
enable = true;
settings = {
PORT = "3001"; # Default, but this allows us to explicitly use it elsewhere
UPTIME_KUMA_DB_TYPE = "mariadb";
UPTIME_KUMA_DB_SOCKET = "/run/mysqld/mysqld.sock";
UPTIME_KUMA_DB_NAME = "uptimekuma";
UPTIME_KUMA_DB_USERNAME = "uptimekuma";
UPTIME_KUMA_DB_PASSWORD = "uptimekuma";
};
};
};
}
+18 -305
View File
@@ -1,70 +1,34 @@
{
config,
lib,
metadata,
pkgs,
pkgs',
lib,
config,
...
}:
let
homepage = "127.0.0.1:30080";
nextcloudPort = 8080;
sshPort = 2222;
in
{
imports = [
./git.nix
./hardware-configuration.nix
./podman.nix
./matrix.nix
./nextcloud.nix
./nginx.nix
./postgres.nix
];
age.secrets = {
acme.file = ../../../secrets/acme.age;
nextcloudadmin = {
file = ../../../secrets/nextcloudadmin.age;
owner = "nextcloud";
};
};
environment.systemPackages = with pkgs; [
bind
graphviz
nix-du
pgloader
podman-compose
pkgs'.upgrade-pg-cluster
];
greg = {
backup.jobs = {
nextcloud-bkup = {
src = "/var/lib/nextcloud";
dest = "nextcloud-backup";
pre = lib.getExe (
pkgs.writeShellApplication {
name = "nextcloud-backup-pre";
runtimeInputs = [ config.services.nextcloud.occ ];
text = "nextcloud-occ maintenance:mode --on";
}
);
post = lib.getExe (
pkgs.writeShellApplication {
name = "nextcloud-backup-post";
runtimeInputs = [ config.services.nextcloud.occ ];
text = "nextcloud-occ maintenance:mode --off";
}
);
};
greg-postgresql-backup = {
src = config.services.postgresqlBackup.location;
dest = "linode-postgres";
};
};
gitea-runner = {
enable = true;
labels = [
extraLabels = [
"vps:host"
"blog:host"
"nixos-linode:host"
];
};
home = false;
@@ -72,29 +36,20 @@ in
nebula = {
enable = true;
isLighthouse = true;
unsafeRoutes = [
{
route = "10.42.0.0/16";
via = metadata.hosts.genesis.nebulaIp;
}
];
};
proxies."immich.thehellings.com" = {
genAliases = false;
target = "http://localhost:${builtins.toString config.services.immich-public-proxy.port}";
ssl = true;
};
tailscale.enable = true;
};
networking = {
domain = "thehellings.com";
firewall.allowedTCPPorts = [
sshPort
80
443
];
hostName = "linode";
nameservers = [
"10.157.0.2"
"100.96.198.104"
];
networkmanager.enable = lib.mkForce false;
hostName = "linode";
domain = "thehellings.com";
nameservers = [ "100.88.91.27" ];
};
programs.ssh.extraConfig = lib.strings.concatStringsSep "\n" [
@@ -105,252 +60,10 @@ in
" UserKnownHostsFile /dev/null"
];
security.acme = {
acceptTerms = true;
defaults = {
dnsPropagationCheck = false;
dnsResolver = "92.123.95.3:53,92.123.94.3:53,92.123.94.2:53,92.123.95.4:53,92.123.95.2:53";
email = "greg.hellings@gmail.com";
extraLegoRunFlags = [ "--ipv4only" ]; # Force IPv4 only
#server = "https://acme-staging-v02.api.letsencrypt.org/directory";
};
certs."thehellings.com" = {
dnsProvider = "linode";
environmentFile = config.age.secrets.acme.path;
extraDomainNames = [
"*.thehellings.com"
];
};
};
services = {
anubis = {
instances = {
git = {
enable = true;
settings = {
BIND = "/run/anubis/anubis-git/anubis.sock";
COOKIE_DOMAIN = "thehellings.com";
SERVE_ROBOTS_TXT = true;
SLOG_LEVEL = "DEBUG";
TARGET = "http://git.k3s.thehellings.lan";
};
};
};
};
haproxy = {
enable = true;
config = ''
global
nbthread 4
maxconn 80
log /dev/log local0
defaults
timeout connect 500s
timeout client 500s
timeout server 1h
listen gitsshd
bind *:${toString sshPort}
timeout client 1h
mode tcp
server git-isaiah isaiah.thehellings.lan:32222
server git-jeremiah jeremiah.thehellings.lan:32222
server git-zeke zeke.thehellings.lan:32222
frontend https
bind *:80
bind *:443 ssl crt ${config.security.acme.certs."thehellings.com".directory}/full.pem
http-request redirect scheme https unless { ssl_fc }
http-request add-header X-Forwarded-Proto https
http-response replace-header ^Set-Cookie:\ (.*) Set-Cookie \1;\ Secure
option http-server-close
option http-keep-alive
#option httplog
#declare capture response len 80
#http-response capture res.hdr(Location) id 0
use_backend git if { hdr(host) -i src.thehellings.com }
use_backend git if { req_ssl_sni -i src.thehellings.com }
use_backend next if { hdr(host) -i next.thehellings.com }
use_backend next if { req_ssl_sni -i next.thehellings.com }
use_backend matrix if { hdr(host) -i matrix.thehellings.com }
use_backend matrix if { req_ssl_sni -i matrix.thehellings.com }
use_backend immich if { hdr(host) -i immich.thehellings.com }
use_backend immich if { req_ssl_sni -i immich.thehellings.com }
use_backend web if { hdr(host) -i thehellings.com }
use_backend web if { req_ssl_sni -i thehellings.com }
backend git
mode http
balance roundrobin
option accept-unsafe-violations-in-http-response
retries 3
option forwardfor
http-request set-header Host git.k3s.thehellings.lan
server git-isaiah isaiah.thehellings.lan:80
server git-jeremiah jeremiah.thehellings.lan:80
server git-zeke zeke.thehellings.lan:80
backend immich
mode http
balance roundrobin
option accept-unsafe-violations-in-http-response
retries 3
option forwardfor
server immich-proxy 127.0.0.1:${builtins.toString config.services.immich-public-proxy.port}
backend matrix
mode http
balance roundrobin
option accept-unsafe-violations-in-http-response
retries 3
option forwardfor
http-request set-header Host matrix.k3s.thehellings.lan
server git-isaiah isaiah.thehellings.lan:80
server git-jeremiah jeremiah.thehellings.lan:80
server git-zeke zeke.thehellings.lan:80
backend web
mode http
balance roundrobin
option accept-unsafe-violations-in-http-response
retries 3
option forwardfor
server web-container ${homepage}
backend next
log global
mode http
balance roundrobin
option accept-unsafe-violations-in-http-response
retries 3
option forwardfor
#http-response replace-value Location http://localhost:${builtins.toString nextcloudPort}/(.*) https://next.thehellings.com/\2
server nextcloud 127.0.0.1:${builtins.toString nextcloudPort}
'';
};
immich-public-proxy = {
enable = true;
immichUrl = "http://immich.k3s.thehellings.lan";
immichUrl = "https://immich.shire-zebra.ts.net";
};
logrotate = {
enable = true;
settings = {
postgresBackup = {
enable = true;
files = "${config.services.postgresqlBackup.location}/*.gz";
};
postgresLog = {
enable = true;
files = "/var/lib/postgresql/*/log/*.log";
compress = true;
compresscmd = "${pkgs.xz}/bin/xz";
};
};
};
nextcloud = {
enable = true;
package = pkgs.nextcloud33;
appstoreEnable = true;
hostName = "localhost";
https = false;
config = {
adminpassFile = config.age.secrets.nextcloudadmin.path;
adminuser = "greg";
dbhost = "/run/postgresql";
dbtype = "pgsql";
};
settings = {
default_phone_region = "US";
overwriteprotocol = "http";
trusted_domains = [ "next.thehellings.com" ];
trusted_proxies = [
"localhost"
"127.0.0.1"
];
};
};
# Move to :8080 so that we can run haproxy as the primary HTTP service
nginx.virtualHosts."${config.services.nextcloud.hostName}".listen = [
{
addr = "127.0.0.1";
port = nextcloudPort;
}
];
openssh.settings.PasswordAuthentication = false;
postgresql = {
enable = true;
package = pkgs.postgresql_15;
checkConfig = true;
ensureDatabases = [ "nextcloud" ];
#initialScript = pkgs.writeText "create-matrix-db.sql" ''
# CREATE ROLE "matrix-synapse" WITH LOGIN;
# CREATE DATABASE "synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 LC_COLLATE = "C" LC_CTYPE = "C";
# GRANT ALL PRIVILEGES ON DATABASE "synapse" TO "matrix-synapse";
#''; # These are done manually in order to set the LC_COLLATE values properly
ensureUsers = [
{
name = "nextcloud";
ensureDBOwnership = true;
}
];
settings = {
log_connections = true;
log_statement = "all";
logging_collector = true;
log_filename = "postgresql.log";
};
identMap = ''
root root postgres
'';
};
postgresqlBackup = {
enable = true;
databases = [ "nextcloud" ];
};
};
systemd.services = {
haproxy = {
after = [
"nextcloud.service"
"network-online.target"
];
wants = [
"nextcloud.service"
"network-online.target"
];
};
};
users.users.haproxy.extraGroups = [ config.security.acme.certs."thehellings.com".group ];
# Actually serve the content from here
virtualisation.oci-containers = {
backend = "podman";
containers."homepage" = {
image = "src.thehellings.com/greg/homepage:latest";
ports = [ "${homepage}:80" ];
};
};
virtualisation.podman = {
enable = true;
dockerCompat = true;
dockerSocket.enable = true;
};
}
+122
View File
@@ -0,0 +1,122 @@
{ ... }:
let
srcDomain = "src.thehellings.com";
sshPort = 2222;
in
{
greg.proxies."${srcDomain}" = {
target = "https://gitea.shire-zebra.ts.net";
ssl = true;
genAliases = false;
extraConfig = ''
proxy_ssl_verify off;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
client_max_body_size 100000m;
# Ultimate AI Block List v1.7 20250924
# https://perishablepress.com/ultimate-ai-block-list/
if ($http_user_agent ~* "(openai\.com|\.ai|-ai|_ai|ai\.|ai-|ai_|ai=|AddSearchBot|Agentic|AgentQL|Agent\ 3|Agent\ API|AI\ Agent|AI\ Article\ Writer|AI\ Chat|AI\ Content\ Detector|AI\ Detection|AI\ Dungeon|AI\ Journalist|AI\ Legion)") {
return 444;
}
if ($http_user_agent ~* "(AI\ RAG|AI\ Search|AI\ SEO\ Crawler|AI\ Training|AI\ Web|AI\ Writer|AI2|AIBot|aiHitBot|AIMatrix|AISearch|AITraining|Alexa|Alice\ Yandex|AliGenie|AliyunSec|Alpha\ AI|AlphaAI|Amazon|Amelia)") {
return 444;
}
if ($http_user_agent ~* "(AndersPinkBot|AndiBot|Anonymous\ AI|Anthropic|AnyPicker|Anyword|Applebot|Aria\ AI|Aria\ Browse|Articoolo|Ask\ AI|AutoGen|AutoGLM|Automated\ Writer|AutoML|Autonomous\ RAG|AwarioRssBot|AwarioSmartBot|AWS\ Trainium|Azure)") {
return 444;
}
if ($http_user_agent ~* "(BabyAGI|BabyCatAGI|BardBot|Basic\ RAG|Bedrock|Big\ Sur|Bigsur|Botsonic|Brightbot|Browser\ MCP\ Agent|Browser\ Use|Bytebot|ByteDance|Bytespider|CarynAI|CatBoost|CC-Crawler|CCBot|Chai|Character)") {
return 444;
}
if ($http_user_agent ~* "(Charstar\ AI|Chatbot|ChatGLM|Chatsonic|ChatUser|Chinchilla|Claude|ClearScope|Clearview|Cognitive\ AI|Cohere|Common\ Crawl|CommonCrawl|Content\ Harmony|Content\ King|Content\ Optimizer|Content\ Samurai|ContentAtScale|ContentBot|Contentedge)") {
return 444;
}
if ($http_user_agent ~* "(ContentShake|Conversion\ AI|Copilot|CopyAI|Copymatic|Copyscape|CoreWeave|Corrective\ RAG|Cotoyogi|CRAB|Crawl4AI|CrawlQ\ AI|Crawlspace|Crew\ AI|CrewAI|Crushon\ AI|DALL-E|DarkBard|DataFor|DataProvider)") {
return 444;
}
if ($http_user_agent ~* "(Datenbank\ Crawler|DeepAI|Deep\ AI|DeepL|DeepMind|Deep\ Research|DeepResearch|DeepSeek|Devin|Diffbot|Doubao\ AI|DuckAssistBot|DuckDuckGo\ Chat|DuckDuckGo-Enhanced|Echobot|Echobox|Elixir|FacebookBot|FacebookExternalHit|Factset)") {
return 444;
}
if ($http_user_agent ~* "(Falcon|FIRE-1|Firebase|Firecrawl|Flux|Flyriver|Frase\ AI|FriendlyCrawler|Gato|Gemini|Gemma|Gen\ AI|GenAI|Generative|Genspark|Gentoo-chat|Ghostwriter|GigaChat|GLM|GodMode)") {
return 444;
}
if ($http_user_agent ~* "(Goose|GPT|Grammarly|Grendizer|Grok|GT\ Bot|GTBot|GTP|Hemingway\ Editor|Hetzner|Hugging|Hunyuan|Hybrid\ Search\ RAG|Hypotenuse\ AI|iAsk|ICC-Crawler|ImageGen|ImagesiftBot|img2dataset|imgproxy)") {
return 444;
}
if ($http_user_agent ~* "(INK\ Editor|INKforall|Instructor|IntelliSeek|Inferkit|ISSCyberRiskCrawler|Janitor\ AI|Jasper|Jenni\ AI|Julius\ AI|Kafkai|Kaggle|Kangaroo|Keyword\ Density\ AI|Kimi|Knowledge|KomoBot|Kruti|LangChain|Le\ Chat)") {
return 444;
}
if ($http_user_agent ~* "(Lensa|Lightpanda|LinerBot|LLaMA|LLM|Local\ RAG\ Agent|Lovable|Magistral|magpie-crawler|Manus|MarketMuse|Meltwater|Meta-AI|Meta-External|Meta-Webindexer|Meta\ AI|MetaAI|MetaTagBot|Middleware|Midjourney)") {
return 444;
}
if ($http_user_agent ~* "(Mini\ AGI|MiniMax|Mintlify|Mistral|Mixtral|model-training|Monica|Narrative|NeevaBot|netEstate|Neural\ Text|NeuralSEO|NinjaAI|NodeZero|Nova\ Act|NovaAct|OAI-SearchBot|OAI\ SearchBot|OASIS|Olivia)") {
return 444;
}
if ($http_user_agent ~* "(Omgili|Open\ AI|Open\ Interpreter|OpenAGI|OpenAI|OpenBot|OpenPi|OpenRouter|OpenText\ AI|Operator|Outwrite|Page\ Analyzer\ AI|PanguBot|Panscient|Paperlibot|Paraphraser\.io|peer39_crawler|Perflexity|Perplexity|Petal)") {
return 444;
}
if ($http_user_agent ~* "(Phind|PiplBot|PoeBot|PoeSearchBot|ProWritingAid|Proximic|Puppeteer|Python\ AI|Qualified|Quark|QuillBot|Qopywriter|Qwen|RAG\ Agent|RAG\ Azure\ AI|RAG\ Chatbot|RAG\ Database|RAG\ IS|RAG\ Pipeline|RAG\ Search)") {
return 444;
}
if ($http_user_agent ~* "(RAG\ with|RAG-|RAG_|Raptor|React\ Agent|Redis\ AI\ RAG|RobotSpider|Rytr|SaplingAI|SBIntuitionsBot|Scala|Scalenut|Scrap|ScriptBook|Seekr|SEObot|SEO\ Content\ Machine|SEO\ Robot|SemrushBot|Sentibot)") {
return 444;
}
if ($http_user_agent ~* "(Serper|ShapBot|Sidetrade|Simplified\ AI|Sitefinity|Skydancer|SlickWrite|SmartBot|Sonic|Sora|Spider/2|SpiderCreator|Spin\ Rewrite|Spinbot|Stability|StableDiffusionBot|Sudowrite|SummalyBot|Super\ Agent|Superagent)") {
return 444;
}
if ($http_user_agent ~* "(SuperAGI|Surfer\ AI|TerraCotta|Text\ Blaze|TextCortex|Thinkbot|Thordata|TikTokSpider|Timpibot|Tinybird|Together\ AI|Traefik|TurnitinBot|uAgents|VelenPublicWebCrawler|Venus\ Chub\ AI|Vidnami\ AI|Vision\ RAG|WebSurfer|WebText)") {
return 444;
}
if ($http_user_agent ~* "(Webzio|WeChat|Whisper|WordAI|Wordtune|WPBot|Writecream|WriterZen|Writescope|Writesonic|xAI|xBot|YaML|YandexAdditional|YouBot|Zendesk|Zero|Zhipu|Zhuque\ AI|Zimm)") {
return 444;
}
'';
};
#greg.proxies."registry.thehellings.com" = {
#target = "https://gitea.shire-zebra.ts.net:5000";
#ssl = true;
#genAliases = false;
#extraConfig = ''
#proxy_set_header X-Forwarded-Proto https;
#proxy_set_header X-Forwarded-Ssl on;
#client_max_body_size 25000m;
#'';
#};
networking.firewall.allowedTCPPorts = [ sshPort ];
systemd.services = {
haproxy = {
after = [
"network-online.target"
];
wants = [
"network-online.target"
];
};
};
services.haproxy = {
enable = true;
config = ''
global
daemon
maxconn 20
defaults
timeout connect 500s
timeout client 500s
timeout server 1h
listen gitsshd
bind *:${toString sshPort}
timeout client 1h
mode tcp
server git-isaiah isaiah.shire-zebra.ts.net:32222
server git-jeremiah jeremiah.shire-zebra.ts.net:32222
server git-zeke zeke.shire-zebra.ts.net:32222
'';
};
}
+88
View File
@@ -0,0 +1,88 @@
# Registration of new users is disabled for the public, but I can create
# them by the following commands:
# nix run nixpkgs.matrix-synapse
# register_new_matrix_user -k "B9EoPr2WV9hzwc7uL2Sx1JmvCeKDEOGCpB0uginQcQtEH4wzRtkSIdo7lltrjSQa" http://localhost:8448
{ config, lib, ... }:
let
domain = "${config.networking.domain}";
fqdn = "matrix.${domain}";
in
{
services.nginx = {
virtualHosts = {
# Server the '.well-known' files to find the Matrix API server
"${domain}" = {
enableACME = true;
forceSSL = true;
# This is needed so that servers contacting hellings.com can find
# the actual application server at matrix.thehellings.com
locations."= /.well-known/matrix/server".extraConfig =
let
server = {
"m.server" = "${fqdn}:443";
};
in
''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
locations."= /.well-known/matrix/client".extraConfig =
let
client = {
"m.homeserver" = {
"base_url" = "https://${fqdn}";
};
"m.identity_server" = {
"base_url" = "https://vector.im";
};
};
in
''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
# Reverse proxy in front of the actual Matrix server
"${fqdn}" = {
enableACME = true;
forceSSL = true;
extraConfig = ''
error_log /var/log/nginx/debug.log debug;
'';
# Not the appropriate place for the chat client
locations =
(builtins.listToAttrs (
builtins.map
(
val:
lib.nameValuePair "/_${val}" {
proxyPass = "https://matrix.shire-zebra.ts.net";
}
)
[
"matrix"
"synapse"
"dendrite"
]
))
// {
"/".extraConfig = "return 404;";
};
};
};
};
# Open networking ports for the server
networking.firewall = {
enable = true;
allowedTCPPorts = [
80
443
];
};
}
+58
View File
@@ -0,0 +1,58 @@
{
config,
lib,
pkgs,
...
}:
{
age.secrets.nextcloudadmin = {
file = ../../../secrets/nextcloudadmin.age;
owner = "nextcloud";
};
services.nextcloud = {
enable = true;
package = pkgs.nextcloud33;
appstoreEnable = true;
hostName = "next.${config.networking.domain}";
https = true;
config = {
adminpassFile = config.age.secrets.nextcloudadmin.path;
adminuser = "greg";
dbhost = "/run/postgresql";
dbtype = "pgsql";
};
settings = {
default_phone_region = "US";
overwriteprotocol = "https";
};
};
services.nginx.virtualHosts."next.thehellings.com" = {
forceSSL = true;
enableACME = true;
};
# Otherwise nginx errors looking for the nextcloud sock file
systemd.services.nginx.after = [ "nextcloud.service" ];
greg.backup.jobs.nextcloud-bkup = {
src = "/var/lib/nextcloud";
dest = "nextcloud-backup";
pre = lib.getExe (
pkgs.writeShellApplication {
name = "nextcloud-backup-pre";
runtimeInputs = [ config.services.nextcloud.occ ];
text = "nextcloud-occ maintenance:mode --on";
}
);
post = lib.getExe (
pkgs.writeShellApplication {
name = "nextcloud-backup-post";
runtimeInputs = [ config.services.nextcloud.occ ];
text = "nextcloud-occ maintenance:mode --off";
}
);
};
}
+43
View File
@@ -0,0 +1,43 @@
{ ... }:
let
homepage = "127.0.0.1:30080";
in
{
security.acme = {
acceptTerms = true;
defaults.email = "greg.hellings@gmail.com";
};
services.nginx = {
enable = true;
clientMaxBodySize = "25000m"; # To help with uploading container images
# If there are recommended settings, let's use them!
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
};
# Actually serve the content from here
virtualisation.podman.enable = true;
virtualisation.oci-containers = {
backend = "podman";
containers."homepage" = {
image = "registry.thehellings.com:443/greg/homepage/gregs-homepage:latest";
ports = [ "${homepage}:80" ];
};
};
greg.proxies = {
"thehellings.com" = {
target = "http://${homepage}/";
ssl = true;
genAliases = false;
};
"doubles.thehellings.com" = {
target = "http://localhost:8081";
ssl = true;
genAliases = false;
};
};
}
+13
View File
@@ -0,0 +1,13 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
podman-compose
];
virtualisation.podman = {
enable = true;
dockerCompat = true;
dockerSocket.enable = true;
};
}
+63
View File
@@ -0,0 +1,63 @@
{
config,
pkgs,
pkgs',
...
}:
{
environment.systemPackages = [ pkgs'.upgrade-pg-cluster ];
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
checkConfig = true;
ensureDatabases = [ "nextcloud" ];
#initialScript = pkgs.writeText "create-matrix-db.sql" ''
# CREATE ROLE "matrix-synapse" WITH LOGIN;
# CREATE DATABASE "synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 LC_COLLATE = "C" LC_CTYPE = "C";
# GRANT ALL PRIVILEGES ON DATABASE "synapse" TO "matrix-synapse";
#''; # These are done manually in order to set the LC_COLLATE values properly
ensureUsers = [
{
name = "nextcloud";
ensureDBOwnership = true;
}
];
settings = {
log_connections = true;
log_statement = "all";
logging_collector = true;
log_filename = "postgresql.log";
};
identMap = ''
root root postgres
'';
};
services.postgresqlBackup = {
enable = true;
databases = [ "nextcloud" ];
};
services.logrotate = {
enable = true;
settings = {
postgresBackup = {
enable = true;
files = "${config.services.postgresqlBackup.location}/*.gz";
};
postgresLog = {
enable = true;
files = "/var/lib/postgresql/*/log/*.log";
compress = true;
compresscmd = "${pkgs.xz}/bin/xz";
};
};
};
greg.backup.jobs.greg-postgresql-backup = {
src = config.services.postgresqlBackup.location;
dest = "linode-postgres";
};
}
@@ -0,0 +1,60 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ pkgs, ... }:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
];
# Bootloader.
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
environment.systemPackages = with pkgs; [
];
greg = {
home = true;
tailscale = {
enable = true;
tags = [ "home" ];
};
};
networking = {
hostName = "proxmoxtemplate"; # Define your hostname.
# defaultGateway = {
# address = " 10.42.1.2";
# interface = "enp6s18";
# };
# interfaces = {
# enp6s18 = {
# ipv4.addresses = [
# {
# address = "10.42.1.8";
# prefixLength = 16;
# }
# ];
# };
# };
nameservers = [ "10.42.1.5" ];
};
services.qemuGuest.enable = true;
system.stateVersion = "24.11"; # Did you read the comment?
# Define a user account. Don't forget to set a password with passwd.
users.users.greg = {
isNormalUser = true;
description = "Greg Hellings";
extraGroups = [ "wheel" ];
packages = with pkgs; [ ];
};
}
@@ -0,0 +1,50 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"uhci_hcd"
"ehci_pci"
"ahci"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/507251f1-efe7-448d-8de8-91ee582a9afb";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/7115-EFA6";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp6s18.useDHCP = lib.mkDefault true;
}
+6 -4
View File
@@ -32,10 +32,6 @@
enable = true;
tags = [ "home" ];
};
vmdev = {
enable = true;
host = "vbox";
};
};
hardware = {
@@ -75,4 +71,10 @@
users.users.greg.extraGroups = [
"podman"
];
# virtualisation.virtualbox.host = {
# enableExtensionPack = true;
# headless = true;
# enableWebService = true;
# };
}
-1
View File
@@ -15,7 +15,6 @@
(name: value: {
inherit name;
address = builtins.getAttr netAttr value;
aliases = lib.optionals (builtins.hasAttr "aliases" value) (builtins.getAttr "aliases" value);
})
(
lib.filterAttrs (
+79
View File
@@ -0,0 +1,79 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: donetick-config
namespace: donetick
data:
# Value pulled from
# https://github.com/donetick/donetick/blob/main/config/selfhosted.yaml
selfhosted.yaml: |-
name: "selfhosted"
is_done_tick_dot_com: false
is_user_creation_disabled: false
telegram:
token: ""
pushover:
token: ""
database:
type: "sqlite"
migration: true
# these are only required for postgres
host: "secret"
port: 5432
user: "secret"
password: "secret"
name: "secret"
jwt:
secret: "This is really a secure JWT secret now!"
session_time: 168h
max_refresh: 168h
server:
port: 2021
read_timeout: 10s
write_timeout: 10s
rate_period: 60s
rate_limit: 300
cors_allow_origins:
- "http://localhost:5173"
- "http://localhost:7926"
# the below are required for the android app to work
- "https://localhost"
- "capacitor://localhost"
serve_frontend: true
logging:
level: "info"
encoding: "json"
development: false
scheduler_jobs:
due_job: 30m
overdue_job: 3h
pre_due_job: 3h
email:
host:
port:
key:
email:
appHost:
oauth2:
client_id:
client_secret:
auth_url:
token_url:
user_info_url:
redirect_url:
name:
# Real-time configuration
realtime:
enabled: true
sse_enabled: true
heartbeat_interval: 60s
connection_timeout: 120s
max_connections: 1000
max_connections_per_user: 5
event_queue_size: 2048
cleanup_interval: 2m
stale_threshold: 5m
enable_compression: true
enable_stats: true
allowed_origins:
- "*"
+38
View File
@@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: donetick
namespace: donetick
spec:
replicas: 1
selector:
matchLabels:
app: donetick
template:
metadata:
labels:
app: donetick
spec:
containers:
- name: donetick
image: donetick/donetick
ports:
- containerPort: 2021
name: http
env:
- name: DT_ENV
value: "selfhosted"
- name: DT_SQLITE_PATH
value: "/data/donetick.db"
volumeMounts:
- name: config
mountPath: /config
- name: data
mountPath: /data
volumes:
- name: config
configMap:
name: donetick-config
- name: data
persistentVolumeClaim:
claimName: donetick-data
+15
View File
@@ -0,0 +1,15 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: donetick-tailscale
namespace: donetick
spec:
ingressClassName: tailscale
defaultBackend:
service:
name: donetick
port:
number: 2021
tls:
- hosts:
- todo
+9
View File
@@ -0,0 +1,9 @@
namespace: donetick
resources:
- namespace.yaml
- configmap.yaml
- pvc.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: donetick
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: donetick-data
namespace: donetick
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
+13
View File
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: donetick
namespace: donetick
spec:
selector:
app: donetick
ports:
- name: http
port: 2021
targetPort: 2021
protocol: TCP
+56
View File
@@ -0,0 +1,56 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: gitea
spec:
interval: "24h"
url: https://dl.gitea.com/charts/
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: gitea-runner
namespace: gitea-runner
spec:
interval: 10m
chart:
spec:
chart: actions
version: "0.0.4"
sourceRef:
kind: HelmRepository
name: gitea
interval: "1h"
values:
rbac:
create: true
serviceAccount:
create: true
gitea:
instanceURL: https://src.thehellings.com
runnerToken:
existingSecret: gitea-runner
existingSecretKey: token
imagePullSecrets:
- name: image-pull-secrets
config:
runner:
labels:
# Ubuntu
- "ubuntu-22.04:docker://ubuntu:22.04"
- "ubuntu-24.04:docker://ubuntu:24.04"
- "ubuntu-24.10:docker://ubuntu:24.10"
# Fedora
- "fedora-41:docker://fedora:41"
- "fedora-42:docker://fedora:42"
# CentOS Stream
- "centos-stream-9:docker://quay.io/centos/centos:stream9"
- "centos-stream-10:docker://quay.io/centos/centos:stream10"
# Nix
- "nix:docker://nixos/nix:latest"
# ci-images (internal registry: src.thehellings.com/greg)
- "ci-builder:docker://src.thehellings.com/greg/builder:latest"
- "ci-vm-test:docker://src.thehellings.com/greg/vm-test:latest"
- "ci-sword:docker://src.thehellings.com/greg/sword-container-builder:latest"
- "ci-bitwarden:docker://src.thehellings.com/greg/bitwarden:latest"
- "ci-immich:docker://src.thehellings.com/greg/immich:latest"
@@ -0,0 +1,6 @@
namespace: gitea-runner
resources:
- namespace.yaml
- secrets.yaml
- chart.yaml
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: gitea-runner
+18
View File
@@ -0,0 +1,18 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: gitea-runner
namespace: gitea-runner
spec:
refreshInterval: 1h
secretStoreRef:
name: bitwarden-login
kind: ClusterSecretStore
target:
name: gitea-runner
creationPolicy: Owner
data:
- secretKey: token
remoteRef:
key: 11419680-5338-4f19-bdd9-b422007046af
property: password
+10 -10
View File
@@ -15,7 +15,7 @@ spec:
chart:
spec:
chart: gitea
version: "12.7.0"
version: "12.5.3"
sourceRef:
kind: HelmRepository
name: gitea-repository
@@ -35,7 +35,7 @@ spec:
storageClass: longhorn-default
image:
tag: "1.27.1"
tag: "1.25.5"
replicaCount: 1
@@ -66,8 +66,8 @@ spec:
APP_NAME: "Gitea: Greg's Cup of Git"
RUN_MODE: dev
server:
DOMAIN: "shire-zebra.ts.net"
ROOT_URL: "https://gitea.shire-zebra.ts.net"
DOMAIN: "thehellings.com"
ROOT_URL: "https://src.thehellings.com"
SSH_PORT: "2222"
database:
DB_TYPE: postgres
@@ -85,15 +85,15 @@ spec:
DISABLE_REGISTRATION: "true"
storage:
STORAGE_TYPE: minio
MINIO_ENDPOINT: "nas1.shire-zebra.ts.net:30188"
MINIO_ENDPOINT: "nas1.shire-zebra.ts.net:9000"
MINIO_BUCKET: gitea
MINIO_LOCATION: garage
MINIO_LOCATION: us-east-1
# MINIO_ACCESS_KEY_ID: ""
# MINIO_SECRET_ACCESS_KEY: ""
MINIO_USE_SSL: "false"
MINIO_INSECURE_SKIP_VERIFY: "true"
security:
ALLOWED_HOST_LIST: loopback,private,*.shire-zebra.ts.net,*.nebula.thehellings.com,*.thehellings.lan
webhook:
ALLOWED_HOST_LIST: loopback,private,*.shire-zebra.ts.net
metrics:
enabled: false
@@ -102,8 +102,8 @@ spec:
persistence:
enabled: true
create: false
claimName: gitea-new
storageClass: longhorn-default
size: "50Gi"
# I will manage my Postgres externally
postgresql:
+7 -7
View File
@@ -18,12 +18,12 @@ spec:
volumes:
- name: gitea-data
persistentVolumeClaim:
claimName: gitea-new
claimName: gitea-shared-storage
- name: dump-staging
emptyDir: {}
initContainers:
- name: gitea-dump
image: "gitea/gitea:1.27.1"
image: "gitea/gitea:1.25.4"
command:
- /bin/sh
- "-c"
@@ -51,12 +51,12 @@ spec:
- |
set -e
# Configure mc alias for MinIO
mc alias set nas1 http://nas1.shire-zebra.ts.net:30188 \
mc alias set nas1 http://nas1.shire-zebra.ts.net:9000 \
"${MINIO_ACCESS_KEY}" "${MINIO_SECRET_KEY}"
# Upload dump to backup-gitea bucket
DUMP_FILE=$(ls /dump-staging/gitea-dump-*.zip | head -1)
mc cp "${DUMP_FILE}" "nas1/gitea-backup/$(basename ${DUMP_FILE})"
echo "Uploaded $(basename ${DUMP_FILE}) to gitea-backup"
mc cp "${DUMP_FILE}" "nas1/backup-gitea/$(basename ${DUMP_FILE})"
echo "Uploaded $(basename ${DUMP_FILE}) to backup-gitea"
# Set 30-day lifecycle on the bucket (idempotent)
mc ilm rule add --expire-days 30 nas1/backup-gitea 2>/dev/null || true
volumeMounts:
@@ -69,10 +69,10 @@ spec:
- name: MINIO_ACCESS_KEY
valueFrom:
secretKeyRef:
name: gitea-backup
name: gitea-config
key: minio_key
- name: MINIO_SECRET_KEY
valueFrom:
secretKeyRef:
name: gitea-backup
name: gitea-config
key: minio_secret
-17
View File
@@ -12,20 +12,3 @@ spec:
tls:
- hosts:
- gitea
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitea-direct
spec:
rules:
- host: git.k3s.thehellings.lan
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea-release-http
port:
name: http
+11 -29
View File
@@ -1,32 +1,5 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: gitea-backup
spec:
target:
name: gitea-backup
deletionPolicy: Delete
template:
type: Opaque
data:
minio_key: "{{ .minio_key }}"
minio_secret: "{{ .minio_secret }}"
secretStoreRef:
name: bitwarden-login
kind: ClusterSecretStore
data:
# MinIO credentials
- secretKey: minio_key
remoteRef:
key: dfb2f0c8-110d-4e96-83a7-b49c001c0897
property: username
- secretKey: minio_secret
remoteRef:
key: dfb2f0c8-110d-4e96-83a7-b49c001c0897
property: password
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: gitea-config
spec:
@@ -48,14 +21,23 @@ spec:
name: bitwarden-login
kind: ClusterSecretStore
data:
# MinIO credentials
- secretKey: minio_key
remoteRef:
key: dcbcf704-7dce-48d7-bbd1-b3a801875b3d
property: username
- secretKey: minio_secret
remoteRef:
key: dcbcf704-7dce-48d7-bbd1-b3a801875b3d
property: password
# MinIO credentials for NAS1
- secretKey: minio_nas1_key
remoteRef:
key: 33e8e4e0-eb90-484c-9ec9-b3a8018077a3
key: c4c66ab3-2ade-4086-9c0d-b3a80172b1ba
property: username
- secretKey: minio_nas1_secret
remoteRef:
key: 33e8e4e0-eb90-484c-9ec9-b3a8018077a3
key: c4c66ab3-2ade-4086-9c0d-b3a80172b1ba
property: password
# Postgres credentials
- secretKey: dbuser
+1 -5
View File
@@ -27,7 +27,7 @@ spec:
chart:
spec:
chart: longhorn
version: "1.11.3"
version: "1.11.1"
sourceRef:
kind: HelmRepository
name: longhorn
@@ -141,10 +141,6 @@ spec:
number: 80
- <<: *host
host: longhorn.kubernetes
- <<: *host
host: longhorn.k3s.nebula.thehellings.com
- <<: *host
host: longhorn.k3s.thehellings.lan
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
+6 -6
View File
@@ -33,24 +33,24 @@ spec:
access-key: "{{ .minio_key }}"
secret-key: "{{ .minio_secret }}"
rclone.conf: |
[garage]
[nas1minio]
type = s3
provider = Minio
endpoint = http://nas1.shire-zebra.ts.net:30188
endpoint = http://nas1.shire-zebra.ts.net:9000
access_key_id = {{ .minio_key }}
secret_access_key = {{ .minio_secret }}
region = garage
region = us-east-1
secretStoreRef:
name: bitwarden-login
kind: ClusterSecretStore
data:
- secretKey: minio_key
remoteRef:
key: 8fce2750-aa62-4892-b90c-b49c001f494b
key: c4c66ab3-2ade-4086-9c0d-b3a80172b1ba
property: username
- secretKey: minio_secret
remoteRef:
key: 8fce2750-aa62-4892-b90c-b49c001f494b
key: c4c66ab3-2ade-4086-9c0d-b3a80172b1ba
property: password
---
apiVersion: v1
@@ -128,7 +128,7 @@ spec:
--progress \
--transfers 4 \
--checkers 8 \
/staging garage:immich
/staging nas1minio:immich
volumeMounts:
- name: staging
mountPath: /staging
+1 -1
View File
@@ -32,7 +32,7 @@ spec:
containers:
main:
image:
tag: v3.1.0
tag: v2.7.5
env:
DB_HOSTNAME: immich-rw
DB_DATABASE_NAME: immich
-4
View File
@@ -22,10 +22,6 @@ spec:
name: immich-server
port:
name: http
- <<: *host
host: immich.k3s.nebula.thehellings.com
- <<: *host
host: immich.k3s.thehellings.lan
---
apiVersion: networking.k8s.io/v1
kind: Ingress
+3
View File
@@ -10,4 +10,7 @@ resources:
- immich
- monitoring
- pinchflat
- smokeping
- uptimekuma
- donetick
- gitea
-2
View File
@@ -19,7 +19,6 @@ spec:
kind: HelmRepository
name: mariadb-operator
interval: "1h"
version: "26.3.0"
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
@@ -34,7 +33,6 @@ spec:
kind: HelmRepository
name: mariadb-operator
interval: "1h"
version: "26.3.0"
dependsOn:
- name: mariadb-operator-crds
- name: longhorn
@@ -11,7 +11,6 @@ spec:
kind: HelmRepository
name: mariadb-operator
interval: "1h"
version: "26.3.0"
dependsOn:
- name: mariadb-operator-crds
- name: mariadb-operator
-17
View File
@@ -13,20 +13,3 @@ spec:
tls:
- hosts:
- matrix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: matrix-direct
spec:
rules:
- host: matrix.k3s.thehellings.lan
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dendrite
port:
number: 8008
+50
View File
@@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: smokeping
labels:
app: smokeping
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: smokeping
template:
metadata:
labels:
app: smokeping
spec:
containers:
- name: smokeping
image: docker.io/linuxserver/smokeping:2.9.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: config
mountPath: /config
- name: data
mountPath: /data
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: TZ
value: "America/Chicago"
#- name: MASTER_URL
# value: "https://ping.shire-zebra.ts.net"
# SHARED_SECRET if you want to run a cluster
# CACHE_DIR if you need to explicitly state that
restartPolicy: Always
volumes:
- name: config
persistentVolumeClaim:
claimName: smokeping-config
- name: data
persistentVolumeClaim:
claimName: smokeping-data
+14
View File
@@ -0,0 +1,14 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: smokeping-tailscale
spec:
ingressClassName: tailscale
defaultBackend:
service:
name: smokeping
port:
name: http
tls:
- hosts:
- ping
+8
View File
@@ -0,0 +1,8 @@
namespace: smokeping
resources:
- namespace.yaml
- pvc.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: smokeping
+23
View File
@@ -0,0 +1,23 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: smokeping-config
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn-default
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: smokeping-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn-default
resources:
requests:
storage: 25Gi
+15
View File
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: smokeping
labels:
app: smokeping
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: smokeping
+38
View File
@@ -0,0 +1,38 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: uptime-kuma
namespace: uptime-kuma
spec:
interval: "24h"
url: "https://helm.irsigler.cloud"
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: uptime-kuma
namespace: uptime-kuma
spec:
interval: 10m
chart:
spec:
chart: uptime-kuma
sourceRef:
kind: HelmRepository
name: uptime-kuma
interval: "1h"
dependsOn:
- name: longhorn
namespace: longhorn-system
- name: mariadb-cluster
namespace: mariadb-operator
values:
volume:
storageClassName: longhorn-default
image:
tag: "2.0.2"
externalDatabase:
enabled: true
hostname: mariadb-cluster.mariadb-operator.svc.cluster.local
database: uptimekuma
existingSecret: uptimekuma-mariadb-password
+15
View File
@@ -0,0 +1,15 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: uptime-kuma-tailscale
namespace: uptime-kuma
spec:
ingressClassName: tailscale
defaultBackend:
service:
name: uptime-kuma
port:
number: 3001
tls:
- hosts:
- kuma
+7
View File
@@ -0,0 +1,7 @@
namespace: uptimekuma
resources:
- namespace.yaml
- secrets.yaml
- chart.yaml
- ingress.yaml
+4
View File
@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: uptimekuma
+27
View File
@@ -0,0 +1,27 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: uptimekuma-mariadb-password
spec:
target:
name: uptimekuma-mariadb-password
deletionPolicy: Delete
template:
type: kubernetes.io/basic-auth
data:
username: |-
{{ .username }}
password: |-
{{ .password }}
secretStoreRef:
name: bitwarden-login
kind: ClusterSecretStore
data:
- secretKey: username
remoteRef:
key: 4df95656-9f9c-4916-8e34-b3a200376365
property: username
- secretKey: password
remoteRef:
key: 4df95656-9f9c-4916-8e34-b3a200376365
property: password
-1
View File
@@ -77,7 +77,6 @@ in
programs.firefox = {
enable = true; # (!pkgs.stdenv.hostPlatform.isDarwin);
configPath = if pkgs.stdenv.hostPlatform.isDarwin then "${config.home.homeDirectory}/Library/Application Support/Firefox" else "${config.xdg.configHome}/mozilla/firefox";
package = pkgs.firefox-bin;
policies = {
DisableAppUpdate = true;
+4 -32
View File
@@ -316,26 +316,6 @@
name = "Buildbot";
url = "http://jeremiah.shire-zebra.ts.net:8010/";
}
{
name = "Garage WebUI";
url = "http://nas1.shire-zebra.ts.net:30186/";
}
{
name = "Garage RPC";
url = "http://nas1.shire-zebra.ts.net:30187/";
}
{
name = "Garage S3 API";
url = "http://nas1.shire-zebra.ts.net:30188/";
}
{
name = "Garage S3 Web";
url = "http://nas1.shire-zebra.ts.net:30189/";
}
{
name = "Garage Admin";
url = "http://nas1.shire-zebra.ts.net:30190/";
}
];
}
{
@@ -418,25 +398,17 @@
{
name = "Media";
bookmarks = [
{
name = "Flaresolverr";
url = "http://nas1.shire-zebra.ts.net:30098";
}
{
name = "Prowlarr";
url = "http://nas1.shire-zebra.ts.net:30050/";
url = "https://hosea.shire-zebra.ts.net:9696/";
}
{
name = "Sonarr (TV)";
url = "http://nas1.shire-zebra.ts.net:30113/";
name = "Transmission";
url = "https://hosea.shire-zebra.ts.net:9091/";
}
{
name = "Radarr (Movies)";
url = "http://nas1.shire-zebra.ts.net:30025/";
}
{
name = "Deluge";
url = "http://nas1.shire-zebra.ts.net:30038/";
url = "https://hosea.shire-zebra.ts.net:7878/";
}
];
}
+2 -2
View File
@@ -62,12 +62,12 @@ in
if cfg.cache then
[
#"http://chronicles.shire-zebra.ts.net:9000/binary-cache/"
"http://niks3.nas1.shire-zebra.ts.net:30189/"
"http://nas1.shire-zebra.ts.net:9000/niks3"
#"http://nas1.shire-zebra.ts.net:8080/default"
]
else
[
"http://niks3.nas1.thehellings.lan:30189/"
"http://nas1.thehellings.lan:8080/default"
]
)
++ [
-13
View File
@@ -98,19 +98,6 @@ in
inherit labels;
inherit (cfg) name;
enable = true;
hostPackages = with pkgs; [
bash
buildah
coreutils
curl
gawk
gitMinimal
gnused
nix
nodejs
podman
wget
];
url = cfg.instanceURL;
tokenFile = config.age.secrets."gitea-runner-${host}-podman".path;
settings = {
+27
View File
@@ -1,6 +1,7 @@
{
config,
lib,
pkgs,
...
}:
@@ -17,9 +18,35 @@ with lib;
};
config = mkIf cfg {
age.secrets.attic.file = ../../secrets/attic.age;
networking.domain = "thehellings.lan";
time.timeZone = "America/Chicago";
systemd.services.attic-client = {
enable = true;
description = "Attic client watch-store service";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
Restart = "on-failure";
RestartSec = "5s";
};
preStart = ''
set -x
mkdir -p $XDG_CONFIG_HOME/attic
cp ${config.age.secrets.attic.path} $XDG_CONFIG_HOME/attic/config.toml
'';
script = "${pkgs.attic-client}/bin/attic watch-store --ignore-upstream-cache-filter default";
environment = {
XDG_CONFIG_HOME = "/var/lib/attic-client";
};
};
systemd.tmpfiles.rules = [
"d /var/lib/attic-client 0755 root root -"
];
# Open Prometheus exporter ports on LAN-connected hosts only.
# NOT in baseline.nix to avoid exposing these on internet-facing hosts (e.g. linode).
networking.firewall.allowedTCPPorts = [
+2 -6
View File
@@ -14,7 +14,6 @@ let
url = "https://github.com/fluxcd/flux2/releases/download/v2.7.2/install.yaml";
sha256 = "sha256-Qs1qJmgZm8q9xZsORjT/N/wzpbWVVODXtzDpjnAYMuQ=";
};
keepaliveIp = "10.42.5.1";
in
{
options.greg = {
@@ -96,7 +95,6 @@ in
"--supervisor-metrics=true"
"--tls-san ${config.networking.hostName}.thehellings.lan"
"--tls-san ${config.networking.hostName}.shire-zebra.ts.net"
"--tls-san ${keepaliveIp}"
];
manifests = {
cert-manager.source = cert-manager;
@@ -112,14 +110,13 @@ in
keepalived = {
enable = true;
openFirewall = true;
vrrpInstances = {
kubernetes = {
vrrpInstances.kubernetes = {
interface = cfg.vipInterface;
priority = cfg.priority;
state = if (config.networking.hostName == "isaiah") then "MASTER" else "BACKUP";
virtualIps = [
{
addr = "${keepaliveIp}/16";
addr = "10.42.5.1/16";
dev = cfg.vipInterface;
}
];
@@ -129,7 +126,6 @@ in
'';
};
};
};
openiscsi = {
enable = true;
name = "${config.networking.hostName}-initiatorhost";
+2 -13
View File
@@ -23,13 +23,6 @@ with lib;
type = types.str;
description = "Kernel module type to install - amd, intel, etc";
};
host = mkOption {
type = types.enum [
"libvirt"
"vbox"
];
description = "Which VM hosting type to configure";
};
};
};
@@ -42,6 +35,7 @@ with lib;
nixos-generators
packer
swtpm
virt-manager
virtio-win
xorriso
];
@@ -50,7 +44,7 @@ with lib;
# Enable the virtualisation services
virtualisation = {
libvirtd = mkIf (cfg.host == "libvirt") {
libvirtd = {
enable = true;
onBoot = "ignore"; # Do not auto-restart VMs on boot, unless they are marked autostart
qemu = {
@@ -60,11 +54,6 @@ with lib;
};
};
};
virtualbox.host = mkIf (cfg.host == "vbox") {
enable = true;
enableExtensionPack = true;
headless = true;
};
};
boot.extraModprobeConfig = "options kvm_${cfg.system} nested=1";
+37 -74
View File
@@ -9,9 +9,11 @@
"tailscale": "100.64.0.0/10"
},
"hosts": {
"builder2": {
"ip": "10.42.1.17",
"system": "x86_64-linux"
"chronicles": {
"ip": "10.42.1.4",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEBecZUva9OnZuXLaBun6/1ITo5f9p0YMLPD+q0egLRS",
"external": true,
"ts": "100.119.228.115"
},
"exodus": {
"ip": null,
@@ -28,15 +30,6 @@
"tags": ["router", "server"],
"nebulaIp": "10.157.0.2"
},
"gregory.hellings-mbp": {
"external": true,
"system": "aarch64-darwin",
"user": "gregory.hellings"
},
"gregs-MacBook-Pro-16-inch-Nov-2024": {
"external": true,
"system": "aarch64-darwin"
},
"hosea": {
"ip": "10.42.1.7",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKLIwkTTXA56sUlUjEulXXZRvZy5H4a5ZwgKWLlpkQDz",
@@ -45,6 +38,10 @@
"tags": ["server"],
"nebulaIp": "10.157.0.3"
},
"icdm-root": {
"external": true,
"system": "x86_64-linux"
},
"isaiah": {
"builder": true,
"ip": "10.42.1.6",
@@ -59,12 +56,12 @@
"external": true,
"system": "x86_64-linux"
},
"ivr": {
"gregory.hellings-mbp": {
"external": true,
"system": "aarch64-darwin"
"system": "aarch64-darwin",
"user": "gregory.hellings"
},
"jeremiah": {
"aliases": ["buildbot"],
"builder": true,
"ip": "10.42.1.8",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOjQjXq9WYU2Ki27BR9WwJ4ZruS/lJXbjC1b0Q42Adi0",
@@ -74,19 +71,20 @@
"tags": ["builder", "kube", "server"],
"nebulaIp": "10.157.0.5"
},
"kuma": {
"ip": "10.42.1.19",
"nebulaIp": "10.157.0.8",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIhr+LmYMOk4Hixxew2FiAvL8sycgQvnhK8PBGjfnkJb",
"system": "x86_64-linux",
"tags": ["server"]
"joel": {
"external": true,
"ip": "10.42.0.4",
"ts": null
},
"gregs-MacBook-Pro-16-inch-Nov-2024": {
"external": true,
"system": "aarch64-darwin"
},
"lithic": {
"external": true,
"system": "aarch64-darwin"
},
"linode": {
"connectAddr": "thehellings.com",
"ip": null,
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMv9Zud3kZOl86gtmkn+uj3D4kiXWDPtyUL02VVLNR4Q",
"ts": "100.109.86.8",
@@ -94,6 +92,10 @@
"tags": ["public", "server"],
"nebulaIp": "10.157.0.1"
},
"ivr": {
"external": true,
"system": "aarch64-darwin"
},
"MacBook-Pro.local": {
"external": true,
"system": "aarch64-darwin"
@@ -102,10 +104,23 @@
"external": true,
"system": "aarch64-darwin"
},
"nas1": {
"external": true,
"ip": "10.42.1.14",
"ts": "100.114.187.61"
},
"nixos": {
"external": true,
"system": "x86_64-linux"
},
"printer": {
"external": true,
"ip": "10.42.1.3"
},
"proxmoxtemplate": {
"external": true,
"system": "x86_64-linux"
},
"wsl": {
"external": true,
"system": "aarch64-linux"
@@ -120,57 +135,5 @@
"tags": ["builder", "kube", "server"],
"nebulaIp": "10.157.0.6"
}
},
"external": {
"chronicles": {
"ip": "10.42.1.4",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEBecZUva9OnZuXLaBun6/1ITo5f9p0YMLPD+q0egLRS",
"ts": "100.119.228.115",
"aliases": ["s3"]
},
"hermes": {
"ip": "10.42.1.18",
"mac": "BC:24:11:E4:72:AB",
"nebulaIp": "10.157.0.8",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILFYyzz/9i5rXprCQj9IL1ulrbQ6E9BOSeOcvf4D/b0G",
"tags": ["server"]
},
"joel": {
"ip": "10.42.0.4"
},
"k3s": {
"aliases": ["*.k3s"],
"ip": "10.42.5.1",
"nebulaIp": "10.157.100.1"
},
"nas1": {
"aliases": ["*.nas1"],
"ip": "10.42.1.14",
"ts": "100.114.187.61"
},
"printer": {
"ip": "10.42.1.3"
},
"pve2": {
"ip": "10.42.1.15"
},
"pve2bmc": {
"ip": "10.42.6.2",
"mac": "00:25:90:4b:34:e8"
},
"pve3": {
"ip": "10.42.1.16"
},
"pve3bmc": {
"ip": "10.42.6.3",
"mac": "00:25:90:4a:dc:2e"
},
"pve4": {
"ip": "10.42.1.17"
},
"pve4bmc": {
"ip": "10.42.6.4",
"mac": "00:25:90:4a:d8:2e"
}
}
}
-10
View File
@@ -16,15 +16,6 @@ let
adblock_update = c ./adblock_update.nix { };
brew = c ./homebrew.nix { };
create_ssl = c ./create_ssl.nix { };
dockerCompat =
pkgs.runCommand "docker-compat"
{
nativeBuildInputs = [ ];
}
''
mkdir -p $out/bin
ln -s ${pkgs.podman}/bin/podman $out/bin/docker
'';
gcc-tune = c ./gcc-tune.nix { };
#gen-build = c ./gen-build { };
hms = c ./hms { };
@@ -32,7 +23,6 @@ let
inject = c ./inject.nix { };
setup-ssh = c ./setup-ssh { };
upgrade-pg-cluster = c ./upgrade-pg-cluster.nix { };
zim-updater = c ./zim/updater.nix { };
};
x86Linux = {
qemu-hook = c ./qemu-hook.nix { };
+28 -28
View File
@@ -2,18 +2,18 @@
"en": {
"gutenberg": {
"name": "gutenberg_en_all",
"version": "2025-11",
"hash": "sha256-AWd8jVVKHKssv9AgrJnryn3Wx0084NE/JmorpgPfryg="
"version": "2023-08",
"hash": "sha256-OXmdHdsLZcW4nCUQsy7sMpUssS8NV7ztkCgS/nsISuw="
},
"phet": {
"name": "phet_en_all",
"version": "2026-05",
"hash": "sha256-zAAq/X5rjQUiYmjMpBtWP5z3J2ZHJMmIxFKnxLAhOlA="
"version": "2025-03",
"hash": "sha256-ARuUzU2o17J2/ZedHc2acXl33dtHCbQJEb72UQUEm1Y="
},
"wikibooks": {
"name": "wikibooks_en_all_maxi",
"version": "2026-04",
"hash": "sha256-wt7Zr+RkfCsFrOudMCYBADacu6IvPQDkZ6Y0VG2j9hA="
"version": "2025-10",
"hash": "sha256-ONBh/ze1Fv2Ffm5b9vDzYS/i2cWSa4pM4MLZnozr2n8="
},
"wikipedia": {
"name": "wikipedia_en_all_maxi",
@@ -22,40 +22,40 @@
},
"wikisource": {
"name": "wikisource_en_all_maxi",
"version": "2026-05",
"hash": "sha256-OA4b+U8mxpcX3fst6hrMyctucYTQOlG/b4qZDiVlcf4="
"version": "2025-11",
"hash": "sha256-p1Jio+PMTZVSLIDIOBeMG3acXJg83CwQM7zIWDUyozM="
},
"wikiversity": {
"name": "wikiversity_en_all_maxi",
"version": "2026-05",
"hash": "sha256-8mZ1CSUcF4QnDIyN0M2KedQ4pcSUCmzHBlOm93MYpCE="
"version": "2025-11",
"hash": "sha256-IG/gAUdc/vHRrIWGHhw8vMJdLWwqrNbfh+SiclQRIAI="
},
"wiktionary": {
"name": "wiktionary_en_all_nopic",
"version": "2026-05",
"hash": "sha256-Dwiz+viVQt0zb077R9KQRgtUtxG9ixA/DeXAkCdD4rM="
"version": "2025-09",
"hash": "sha256-Ghcb60qeGaSJtTKQkJoMx/XucX7Lt1XY145lD3gHlMg="
}
},
"fr": {
"gutenberg": {
"name": "gutenberg_fr_all",
"version": "2026-01",
"hash": "sha256-sGn1TeKwBK0+Er5YOJWq6g0itEm4gIGvKxv/PW0DIao="
"version": "2025-10",
"hash": "sha256-gLHxLXJNwwcxM/mZHtoJ8ojbGQ1fugxgni/+RXccwhU="
},
"phet": {
"name": "phet_fr_all",
"version": "2026-05",
"hash": "sha256-bJmchFnaPcofE/hy3ZcRggMT9osHqXwLbwMLJ+cpF28="
"version": "2025-03",
"hash": "sha256-CSboZNTIowLLhp1u9wkxH8xmu3LvQNx5q493AOYJRIc="
},
"wikibooks": {
"name": "wikibooks_fr_all_maxi",
"version": "2026-07",
"hash": "sha256-csI+E5UFGi42BLGWWHxQhVr5KSihCFc53KGKwo557Ck="
"version": "2025-09",
"hash": "sha256-KHCc/73L5Bd9iZ47SRV6vpI8fVM1v9hk1TpEvTro2uo="
},
"wikipedia": {
"name": "wikipedia_fr_all_maxi",
"version": "2026-05",
"hash": "sha256-YUAbGzYYr+c2RQqGjHIF9XL1kNsxDgRKnHK1H7/PtDE="
"version": "2025-06",
"hash": "sha256-ve7Mbh96/ObNbV/KVNYZpfLN+HdWlJ7C5LItEdVkRH0="
},
"wikisource": {
"name": "wikisource_fr_all_maxi",
@@ -64,25 +64,25 @@
},
"wikiversity": {
"name": "wikiversity_fr_all_maxi",
"version": "2026-05",
"hash": "sha256-nVDHtkWIOJkoiGixnA1zVR1QS58thjc12FJyagK3Ec0="
"version": "2025-09",
"hash": "sha256-55fdtw/cRezq6nkRp6wuwkukBiqsQKdwh9QWVAgFcBI="
},
"wiktionary": {
"name": "wiktionary_fr_all_nopic",
"version": "2026-05",
"hash": "sha256-7UXByW2IIL0hec8RPT39jpg5IEGvRMD47hc4Y4vFkJs="
"version": "2025-11",
"hash": "sha256-P0CJptee5rDzccxyRDBzyRLuuFOcaLsJYi6DkBFUfIc="
}
},
"ht": {
"phet": {
"name": "phet_ht_all",
"version": "2026-05",
"hash": "sha256-GiJ1jllhioyMYidQ7+Lcbdd9JN2yf04ZQgnO8XaGAqY="
"version": "2025-03",
"hash": "sha256-bHrPzE8H7ptrP6r5wPlXSsXNlTiKxJ9KatABC4kwx+s="
},
"wikipedia": {
"name": "wikipedia_ht_all_maxi",
"version": "2026-07",
"hash": "sha256-InS9cMRaIv9ArlKVwKUypz56m4DgSR7Tl6XpSTMzH+o="
"version": "2026-04",
"hash": "sha256-qUX0pKxIyNsWX4V6kNIsP4Z9nc6TDhwdDR0MmpDOQFs="
}
}
}
+111 -166
View File
@@ -9,7 +9,7 @@ import (
"net/http"
"os"
"os/exec"
"reflect"
"path/filepath"
"regexp"
"sort"
"strings"
@@ -17,144 +17,27 @@ import (
const BASE = "https://download.kiwix.org/zim"
// ///////////////////////////////////////////////////////////////////////////
// //////////////// THE BLOB ITSELF /////////////////////////////////////////
// ///////////////////////////////////////////////////////////////////////////
type Blobs struct {
En Language `json:"en"`
Fr Language `json:"fr"`
Ht Language `json:"ht"`
dirty bool
}
func (b *Blobs) Populate() {
done := make(chan bool)
waitFor := 0
// Launch self-populating efforts
blobType := reflect.Indirect(reflect.ValueOf(b)).Type()
for f := range blobType.Fields() {
if f.IsExported() {
//fmt.Printf("%s:\tBeginning population efforts\n", f.Name)
waitFor += 1
go reflect.Indirect(reflect.ValueOf(b)).
FieldByName(f.Name).
Addr().
Interface().
(*Language).
Populate(strings.ToLower(f.Name), done)
}
}
// Wait until all languages are completed
for d := range done {
waitFor -= 1
if waitFor == 0 {
fmt.Println("Completed waiting for all languages")
close(done)
break
}
b.dirty = b.dirty || d
func getTypes() []string {
return []string{
"phet",
"wikipedia",
"wiktionary",
"wikiversity",
"wikisource",
"wikibooks",
"gutenberg",
"ted",
}
}
/////////////////////////////////////////////////////////////////////////////
//////////////////////// The Language ///////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
type Language struct {
Gutenberg *Zim `json:"gutenberg,omitempty"`
Phet *Zim `json:"phet,omitempty"`
Ted *Zim `json:"ted,omitempty"`
Wikibooks *Zim `json:"wikibooks,omitempty"`
Wikipedia *Zim `json:"wikipedia,omitempty"`
Wikisource *Zim `json:"wikisource,omitempty"`
Wikiversity *Zim `json:"wikiversity,omitempty"`
Wiktionary *Zim `json:"wiktionary,omitempty"`
dirty bool
}
func (l *Language) Populate(code string, done chan bool) {
childDone := make(chan bool)
waitFor := 0
languageType := reflect.Indirect(reflect.ValueOf(l)).Type()
l.dirty = false
for f := range languageType.Fields() {
if f.IsExported() {
ptrPtrZim := reflect.Indirect(reflect.ValueOf(l)).
FieldByName(f.Name)
if ptrPtrZim.IsValid() && !ptrPtrZim.IsNil() {
waitFor += 1
go reflect.Indirect(ptrPtrZim).
Addr().
Interface().
(*Zim).
Populate(strings.ToLower(f.Name), code, childDone)
} else {
// TODO: Figure out how to set a value over the nil pointer
// of the field, so we can auto-detect when these are available
// in the future
// waitFor += 1
//z := &Zim{Name: f.Name, Version: "1999-01-01", Hash: ""}
//ptrPtrZim.Set(reflect.ValueOf(z))
//go z.Populate(strings.ToLower(f.Name), code, childDone)
}
}
}
// Wait until children are all done
for d := range childDone {
waitFor -= 1
if waitFor == 0 {
close(childDone)
break
}
l.dirty = l.dirty || d
}
//fmt.Printf("%s\tFinished populate\n", code)
done <- l.dirty
}
// ///////////////////////////////////////////////////////////////////////////
// ////////////////////// A Single Zim ///////////////////////////////////////
// ///////////////////////////////////////////////////////////////////////////
type Zim struct {
Name string `json:"name"`
Version string `json:"version"`
Hash string `json:"hash"`
dirty bool
}
func (z *Zim) Populate(category string, language string, done chan bool) {
//fmt.Printf("%s:%s\tBeginning populate for\n", language, category)
// Look for a possible Zim file
links := getLinks(getPage(category))
link, err := getName(links, category, language)
if err != nil {
fmt.Printf("%s:%s\tNo zim found\n", language, category)
done <- false
return
}
//fmt.Printf("%s:%s\tFound link: %s\n", category, language, link)
// Extract name and version
re := regexp.MustCompilePOSIX("^([a-zA-Z_]+)_([0-9-]+)\\.zim$")
match := re.FindStringSubmatch(link)
if len(match) != 3 {
fmt.Printf("%s:%s Matches: %s", language, category, match)
os.Exit(1)
}
// Check if the name and version mismatch
if match[1] == z.Name && match[2] == z.Version {
fmt.Printf("Skipping existing hash: %s\n", link)
done <- false
} else {
z.Name = match[1]
z.Version = match[2]
// Fetch the Zim file, if it differs from what we currently have
z.UpdateHash(category)
done <- true
func getLanguages() []string {
return []string{
"ht",
"en",
"fr",
}
}
// Helper function to fetch the HTML of a given type page
func getPage(t string) string {
page, err := http.Get(fmt.Sprintf("%s/%s/", BASE, t))
if err != nil {
@@ -165,7 +48,6 @@ func getPage(t string) string {
return string(pageBytes)
}
// Helper function to parse out all the links from the page
func getLinks(page string) []string {
ret := []string{}
@@ -178,7 +60,6 @@ func getLinks(page string) []string {
return ret
}
// Helper function to get the most likely link for this particular entry
func getName(links []string, t, lang string) (string, error) {
candidates := []string{}
prefix := fmt.Sprintf("%s_%s_all", t, lang)
@@ -198,39 +79,44 @@ func getName(links []string, t, lang string) (string, error) {
}
}
// Helper function to get the hash value from the resulting link
func (z *Zim) UpdateHash(category string) error {
file := fmt.Sprintf("%s_%s.zim", z.Name, z.Version)
// First fetch the file into our local Nix store
fmt.Printf("Fetching hash: %s\n", file)
cmd := exec.Command("nix-prefetch-url", fmt.Sprintf("%s/%s/%s", BASE, category, file))
func getHash(ch chan result, file, category, language string) {
// TODO: Only call this if the file doesn't already have a hash
// in the existing file
fmt.Printf("Fetching hash for %s\n", file)
cmd := exec.Command( "nix-prefetch-url", fmt.Sprintf("%s/%s/%s", BASE, category, file))
out, err := cmd.Output()
if err != nil {
fmt.Printf("%s: ERROR fetching hash: %v\n", file, err)
fmt.Printf("Error fetching hash for %s (category: %s, language: %s): %v\n", file, category, language, err)
if exitErr, ok := err.(*exec.ExitError); ok {
fmt.Printf("Command stderr: %s\n", string(exitErr.Stderr))
}
return errors.New("Error fetching file")
ch <- result{category, language, ""}
return
}
hash := strings.TrimSpace(string(out))
fmt.Printf("%s: Successfully fetched raw hash\n", file)
fmt.Printf("%s: Hash is: %s\n", file, hash)
fmt.Printf("Successfully fetched hash for %s (category: %s, language: %s)\n", file, category, language)
ch <- result{category, language, hash}
}
// Then, convert the hash to SRI
cmd2 := exec.Command("nix", "hash", "convert", "--to", "sri", hash, "--hash-algo", "sha256")
out2, err2 := cmd2.Output()
if err2 != nil {
fmt.Printf("%s: Error converting hash to SRI: %v\n", file, err)
if exitErr, ok := err.(*exec.ExitError); ok {
fmt.Printf("%s: Command stderr: %s\n", file, string(exitErr.Stderr))
func outputIsValid(o map[string]map[string]Zim) bool {
for a := range o {
for b := range o[a] {
if o[a][b].Hash == "" {
return false
}
return errors.New("Error fetching file")
}
z.Hash = strings.TrimSpace(string(out2))
z.dirty = true
fmt.Printf("%s: Successfully convert hash to SRI: %s", file, out2)
return nil
}
return true
}
type result struct {
category, language, hash string
}
type Zim struct {
Name string `json:"name"`
Version string `json:"version"`
Hash string `json:"hash"`
}
func main() {
@@ -239,31 +125,90 @@ func main() {
// Determine the output file path
var outputPath string
if *outputFile != "" {
outputPath = *outputFile
} else {
// Get the directory where updater.go is located
execPath, err := os.Executable()
if err != nil {
// Fallback to current directory if we can't determine executable path
outputPath = "blobs.json"
} else {
dir := filepath.Dir(execPath)
outputPath = filepath.Join(dir, "blobs.json")
}
}
fmt.Println("Writing file to ", outputPath)
// Read existing cache if it exists
var blobs Blobs
cached := make(map[string]map[string]Zim)
if data, err := os.ReadFile(outputPath); err == nil {
if err := json.Unmarshal(data, &blobs); err != nil {
if err := json.Unmarshal(data, &cached); err != nil {
fmt.Printf("Warning: could not parse existing cache file: %v\n", err)
} else {
fmt.Printf("Loaded existing cache from %s\n", outputPath)
}
} else {
fmt.Printf("Error reading file: %s", err)
os.Exit(1)
}
blobs.Populate()
ret, err := json.MarshalIndent(&blobs, "", " ")
output := make(map[string]map[string]Zim)
comms := make(chan result)
pendingHashes := 0
for _, t := range getTypes() {
page := getPage(t)
links := getLinks(page)
for _, lang := range getLanguages() {
if file, err := getName(links, t, lang); err == nil {
if _, ok := output[lang]; !ok {
output[lang] = make(map[string]Zim)
}
// Check if this file already exists in cache with same name
if cachedLang, ok := cached[lang]; ok {
if cachedEntry, ok := cachedLang[t]; ok && cachedEntry.Name == file {
// Reuse cached hash
fmt.Printf("Using cached hash for %s (category: %s, language: %s)\n", file, t, lang)
output[lang][t] = cachedEntry
continue
}
}
// File is new or name has changed, fetch hash
output[lang][t] = Zim{file, ""}
pendingHashes++
go getHash(comms, file, t, lang)
}
}
}
// Only wait for results if we actually spawned goroutines
if pendingHashes > 0 {
hashesReceived := 0
for r := range comms {
if entry, ok := output[r.language][r.category]; ok {
entry.Hash = r.hash
output[r.language][r.category] = entry
}
hashesReceived++
if hashesReceived >= pendingHashes {
close(comms)
break
}
}
}
// Verify all hashes are present
if !outputIsValid(output) {
fmt.Println("Warning: Some hashes are missing from the output")
}
ret, err := json.MarshalIndent(output, "", " ")
if err != nil {
fmt.Printf("Error marshaling JSON: %v\n", err)
os.Exit(1)
}
err = os.WriteFile(outputPath, []byte(fmt.Sprintf("%s\n", ret)), 0644)
err = os.WriteFile(outputPath, ret, 0644)
if err != nil {
fmt.Printf("Error writing to file %s: %v\n", outputPath, err)
os.Exit(1)
BIN
View File
Binary file not shown.
+37
View File
@@ -0,0 +1,37 @@
age-encryption.org/v1
-> ssh-ed25519 87huqg LKhlbZI1BygDI8E4kkzhw0/Y1BfWnzekf/URa/Bma30
uT7QzE8DPX8j3us7oNRKwu6hPUFpQosbcMRmMNgS/Gw
-> ssh-ed25519 8UnW5Q dDAJI5EnPMIhs5H21wLT84GWhkROEJRXE1QVp1aOH38
qZJt4Kip5qVZl9QoIFEXgrhtrlQEpbkfLarCgaHugj8
-> ssh-ed25519 UFfTmg kbrSoge204JvRPBszhAfMewPM4oHg0HkF52BNeb9kx8
E4ASRdn0pjF//GiFCjmRlgXRS2wiJxIXDFSjldMtTdQ
-> ssh-ed25519 xNtnoA 7b9/Z/qUEmRnFCiCYzVGJVvxvV8onjZemSg6sllaDyA
bQosZIGbaSsUqFO2JuRpIhm3FJd79JyYS43A9+zr+1w
-> ssh-ed25519 aY2AXA m4gIzzAX8pkBHHzsSykIy24E6Kru/I4uNnjihKH3JHg
S18CWIY5wNcR5PVkCqbjp1FJRrGxco6fdoykQeHhyX0
-> ssh-ed25519 AQhf1g LBmvyUbKRLKtPGIEqt+NwOSrtGwlFt2zqgdmRDHu9n8
zb8OnKRsJBEkH6eJ76mlKvJmtZ8NvVwVS9/0tsZlMUk
-> ssh-ed25519 mOmPfg TuPbRMlX9eRATxSbv6v88TtzGhOKWn5FOkIg4xR6FH0
NLNzJM/9r2jZ70Y2r5Hsc36gcRTSPw40Aabn/H7OE+4
-> ssh-ed25519 YJiRbw bVMyOOgBcFFRNulym46YwKAIPlOkbQhmQAo9kl4dRx8
5W2fIxGXCXbzULOismGg4NxE+VQ8LDEbODlJ0OpFMiI
-> ssh-ed25519 Nl/5yA ydFS0bVjjDzymhQFaBJ3YqDREQDpVO6VzgS2MBtuOUo
tNzj/85BiYe6th2N6A9ZkMSPKduwAIe/qnf2NVJiHOg
-> ssh-ed25519 GdLgCQ wmfT7bCzwnkwEtn2mRnElIM75MmdRw+33MhSegSHJWk
YHrCYB1wF1njNjzpIy3hKZ9l1cj7m5yicLuj71TvKr8
-> ssh-ed25519 tOH/HQ z5/GMQOtkpMWwWdMXqxmf12MM84xkgXL/OLliq3RHh0
mVhBt+uc7z/YkoIAyXTqBgv00cJOrZ0bsBP0lD9S24c
-> ssh-ed25519 FpzvfQ D8N5JQ+3rGdSZIPmzlZqO5VpS90v6r99WMXtyUqCGiw
A2SSvI4H5TRY13R/iOa60bCdc0zR6lUAHJVHfAUR5mQ
-> ssh-ed25519 2UotMw eaM1Kkzw53Oq8lW0BFn3rqWFcTQaTz9jcDsULDg/fwU
3QVYFrhKnvwWDpIdsyTp0amontUXePko8z8PeUub9EE
-> ssh-ed25519 kdPvzQ 08LE8a24S5cvuK9DVWD2ta0GjJMNzUidmgYT4RfhQDA
cRFH8vOr2y1/C9F2wZWV2deUxUpoL34IFRyOBHPYifI
-> ssh-ed25519 onmXpg J5MKGIovNwv4FyTN4ofExlHV8qYzU/J9O3MI4tZYcTo
iagT0Ypo8gTwvGpV66XNuNPedefx2S72q9hyeB2Rz/w
-> ssh-ed25519 CnhD0g se/N4hrYxOiukByYzsIhxToceXNuBO7J7VmM4muJ3Dk
cW+WW8iWjj3eXDqDO8aEON1ZH/+6AXQGAEXkLRbL3AI
-> ssh-ed25519 4ep2UA uyjvubY39oSGeCNsX3/VIdM5CzNBlrnRpkF+YN5MBCo
xiNuksI7olV5Db392Vjz/7uDNDIssGmI9bez6vSOXTk
--- VsGbd8K7JzHe/eoYUeTMwcg/GrY9SXVzNxL4HZ23tKQ
£_÷t/¢ªØËVÎÞ}7J'%?™Á‰Å0“¤¼^õ¿-„ÏÛ„äu4¥ù‹íäóü0!®ÝîËðMÜÅ·
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

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