Compare commits
1 commit
master
...
generic-de
Author | SHA1 | Date | |
---|---|---|---|
748948bfbf |
61 changed files with 2012 additions and 1894 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,3 @@
|
|||
.direnv
|
||||
.pre-commit-config.yaml
|
||||
result
|
||||
.manifests
|
||||
|
|
108
README.md
108
README.md
|
@ -5,82 +5,74 @@ We use [Kubenix](https://kubenix.org/) to write Kubernetes deployments in Nix!
|
|||
## Images used
|
||||
|
||||
Legend:
|
||||
|
||||
- ✨: Image built with Nix (including
|
||||
[NixNG](https://github.com/nix-community/NixNG))
|
||||
- ✨: Image built with Nix (including [NixNG](https://github.com/nix-community/NixNG))
|
||||
- ✅: Official image or trusted publisher
|
||||
- 🫤: Unofficial image
|
||||
|
||||
| Status | Image | Comments |
|
||||
| ------ | ---------------------------------------------- | --------------------------------------------------------- |
|
||||
| ✨ | `nixng-blog` | |
|
||||
| ✨ | `nixng-dnsmasq` | |
|
||||
| ✨ | `nixng-attic` | |
|
||||
| ✨ | `nixng-ntfy-sh` | |
|
||||
| ✨ | `nixng-radicale` | |
|
||||
| ✨ | `nixng-jellyseerr` | |
|
||||
| ✨ | `nixng-radarr` | |
|
||||
| ✨ | `nixng-sonarr` | |
|
||||
| ✨ | `nixng-bazarr` | |
|
||||
| ✨ | `nixng-prowlarr` | |
|
||||
| ✨ | `nixng-deluge` | |
|
||||
| ✨ | `nixng-mealie` | |
|
||||
| ✨ | `nixng-atuin` | |
|
||||
| ✅ | `jellyfin/jellyfin` | |
|
||||
| ✅ | `postgres:14` | Database for Atuin |
|
||||
| ✅ | `ghcr.io/paperless-ngx/paperless-ngx` | |
|
||||
| ✅ | `docker.io/library/redis:7` | Database for Paperless-ngx |
|
||||
| ✅ | `nextcloud` | |
|
||||
| ✅ | `postgres:15` | Database for Attic, Nextcloud, Paperless-ngx and Hedgedoc |
|
||||
| ✅ | `inbucket/inbucket` | |
|
||||
| ✅ | `lscr.io/linuxserver/syncthing` | |
|
||||
| ✅ | `codeberg.org/forgejo/forgejo` | |
|
||||
| ✅ | `ghcr.io/immich-app/immich-server` | |
|
||||
| ✅ | `ghcr.io/immich-app/immich-machine-learning` | |
|
||||
| ✅ | `docker.io/redis:6.2-alpine` | Database for Immich |
|
||||
| ✅ | `docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0` | Database for Immich |
|
||||
| ✅ | `tombursch/kitchenowl` | |
|
||||
| ✅ | `freshrss/freshrss` | |
|
||||
| ✅ | `ubuntu/bind9` | |
|
||||
| ✅ | `quay.io/hedgedoc/hedgedoc` | |
|
||||
| 🫤 | `teddysun/kms` | |
|
||||
| 🫤 | `mpepping/cyberchef` | |
|
||||
| Status | Image | Comments |
|
||||
| --- | --- | --- |
|
||||
| ✨ | `nixng-blog` | |
|
||||
| ✨ | `nixng-dnsmasq` | |
|
||||
| ✨ | `nixng-attic` | |
|
||||
| ✨ | `nixng-ntfy-sh` | |
|
||||
| ✨ | `nixng-radicale` | |
|
||||
| ✨ | `nixng-jellyseerr` | |
|
||||
| ✨ | `nixng-radarr` | |
|
||||
| ✨ | `nixng-sonarr` | |
|
||||
| ✨ | `nixng-bazarr` | |
|
||||
| ✨ | `nixng-prowlarr` | |
|
||||
| ✅ | `jellyfin/jellyfin` | |
|
||||
| ✅ | `linuxserver/deluge` | |
|
||||
| ✅ | `ghcr.io/atuinsh/atuin` | |
|
||||
| ✅ | `postgres:14` | Database for Atuin |
|
||||
| ✅ | `ghcr.io/paperless-ngx/paperless-ngx` | |
|
||||
| ✅ | `docker.io/library/redis:7` | Database for Paperless-ngx |
|
||||
| ✅ | `nextcloud` | |
|
||||
| ✅ | `postgres:15` | Database for Attic, Nextcloud, Paperless-ngx and Hedgedoc |
|
||||
| ✅ | `inbucket/inbucket` | |
|
||||
| ✅ | `lscr.io/linuxserver/syncthing` | |
|
||||
| ✅ | `codeberg.org/forgejo/forgejo` | |
|
||||
| ✅ | `pihole/pihole` | |
|
||||
| ✅ | `ghcr.io/immich-app/immich-server` | |
|
||||
| ✅ | `ghcr.io/immich-app/immich-machine-learning` | |
|
||||
| ✅ | `docker.io/redis:6.2-alpine` | Database for Immich |
|
||||
| ✅ | `docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0` | Database for Immich |
|
||||
| ✅ | `tombursch/kitchenowl` | |
|
||||
| ✅ | `freshrss/freshrss` | |
|
||||
| ✅ | `ubuntu/bind9` | |
|
||||
| ✅ | `quay.io/hedgedoc/hedgedoc` | |
|
||||
| 🫤 | `itzg/minecraft-server` | |
|
||||
| 🫤 | `teddysun/kms` | |
|
||||
| 🫤 | `mpepping/cyberchef` | |
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
- [dns.nix](https://github.com/kirelagin/dns.nix): A Nix DSL for defining DNS
|
||||
zones
|
||||
- [flake-utils](https://github.com/numtide/flake-utils): Handy utilities to
|
||||
develop Nix flakes
|
||||
- [kubenix](https://kubenix.org/): Declare and deploy Kubernetes resources using
|
||||
Nix
|
||||
- [dns.nix](https://github.com/kirelagin/dns.nix): A Nix DSL for defining DNS zones
|
||||
- [flake-utils](https://github.com/numtide/flake-utils): Handy utilities to develop Nix flakes
|
||||
- [kubenix](https://kubenix.org/): Declare and deploy Kubernetes resources using Nix
|
||||
- [nixhelm](https://github.com/farcaller/nixhelm): Nix-digestible Helm charts
|
||||
- [sops-nix](https://github.com/Mic92/sops-nix): Sops secret management for Nix
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To deploy to the Kubernetes cluster, first make sure you have an admin account
|
||||
on the cluster. You can generate this using
|
||||
`nix run '.#gen-k3s-cert' <username> <servername> ~/.kube`, assuming you have
|
||||
SSH access to the master node. This puts a private key, signed certificate and a
|
||||
kubeconfig in the kubeconfig directory
|
||||
To deploy to the Kubernetes cluster, first make sure you have an admin account on the cluster.
|
||||
You can generate this using `nix run '.#gen-k3s-cert' <username> <servername> ~/.kube`, assuming you have SSH access to the master node.
|
||||
This puts a private key, signed certificate and a kubeconfig in the kubeconfig directory
|
||||
|
||||
## Bootstrapping
|
||||
|
||||
We are now ready to deploy to the Kubernetes cluster. Deployments are done
|
||||
through an experimental Kubernetes feature called
|
||||
[ApplySets](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-to-delete-objects).
|
||||
We are now ready to deploy to the Kubernetes cluster.
|
||||
Deployments are done through an experimental Kubernetes feature called [ApplySets](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-to-delete-objects).
|
||||
Each applyset is responsible for a set number of resources within a namespace.
|
||||
|
||||
If the cluster has not been initialized yet, we must bootstrap it first. Run
|
||||
these deployments:
|
||||
|
||||
If the cluster has not been initialized yet, we must bootstrap it first.
|
||||
Run these deployments:
|
||||
- `nix run '.#bootstrap-default-deploy'`
|
||||
- `nix run '.#bootstrap-kube-system-deploy'`
|
||||
|
||||
## Deployment
|
||||
|
||||
Now the cluster has been initialized and we can deploy applications. To explore
|
||||
which applications we can deploy, run `nix flake show`. Then, for each
|
||||
application, run `nix run '.#<application>-deploy'`. Or, if you're lazy:
|
||||
`nix flake show --json | jq -r '.packages."x86_64-linux"|keys[]' | grep -- -deploy | xargs -I{} nix run ".#{}"`.
|
||||
Now the cluster has been initialized and we can deploy applications.
|
||||
To explore which applications we can deploy, run `nix flake show`.
|
||||
Then, for each application, run `nix run '.#<application>-deploy'`.
|
||||
Or, if you're lazy: `nix flake show --json | jq -r '.packages."x86_64-linux"|keys[]' | grep -- -deploy | xargs -I{} nix run ".#{}"`.
|
||||
|
|
|
@ -2,31 +2,11 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
CREATE_LOCAL_GCROOT=false
|
||||
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--help)
|
||||
echo "Use --create-local-gcroot to create local GC root"
|
||||
exit 0
|
||||
;;
|
||||
--create-local-gcroot)
|
||||
CREATE_LOCAL_GCROOT=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
first_server="${SERVERS%% *}"
|
||||
previous_manifest=$(
|
||||
envsubst <<EOF | ssh -T "root@$first_server"
|
||||
if [[ -f "$GCROOTDIR/$NAME.yml" ]]; then
|
||||
cat "$GCROOTDIR/$NAME.yml"
|
||||
fi
|
||||
previous_manifest=$(ssh -T "root@$first_server" << EOF
|
||||
if [[ -f "$GCROOTDIR/${NAME}.yml" ]]; then
|
||||
cat "$GCROOTDIR/${NAME}.yml"
|
||||
fi
|
||||
EOF
|
||||
)
|
||||
|
||||
|
@ -34,35 +14,30 @@ set +e
|
|||
if [ -z "$previous_manifest" ]; then
|
||||
echo No previous manifest found!
|
||||
else
|
||||
$DYFF between <(echo "$previous_manifest") "$MANIFEST" \
|
||||
$DYFF between <(echo $previous_manifest) $MANIFEST \
|
||||
--exclude-regexp metadata.labels.kubenix/hash \
|
||||
--exclude-regexp labels.kubenix/hash \
|
||||
--set-exit-code
|
||||
--set-exit-code
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
set -e
|
||||
|
||||
read -r -p "Continue? " _
|
||||
read -r -p "Continue? " response
|
||||
|
||||
echo Uploading closure...
|
||||
for server in $SERVERS; do
|
||||
echo Uploading closure to "$server"...
|
||||
nix copy --to "ssh://root@$server" "$MANIFEST"
|
||||
echo Uploading closure to $server...
|
||||
nix copy --to "ssh://root@$server.dmz" $MANIFEST
|
||||
ssh "root@$server.dmz" "mkdir -p $GCROOTDIR && ln -sf $MANIFEST $GCROOTDIR/${NAME}.yml"
|
||||
done
|
||||
|
||||
echo Applying Kubernetes manifest...
|
||||
export KUBECTL_APPLYSET=true
|
||||
vals eval -fail-on-missing-key-in-map <"$MANIFEST" |
|
||||
kubectl apply -f - \
|
||||
--prune \
|
||||
--applyset applyset-"$NAME" \
|
||||
--namespace "$NAMESPACE"
|
||||
|
||||
echo Creating GC roots
|
||||
for server in $SERVERS; do
|
||||
ssh "root@$server" "mkdir -p $GCROOTDIR && ln -sf $MANIFEST $GCROOTDIR/${NAME}.yml"
|
||||
done
|
||||
|
||||
if $CREATE_LOCAL_GCROOT; then
|
||||
mkdir -p ./.manifests
|
||||
ln -sf "$MANIFEST" "./.manifests/${NAME}.yml"
|
||||
fi
|
||||
vals eval -fail-on-missing-key-in-map <$MANIFEST | \
|
||||
kubectl apply -f - \
|
||||
--prune \
|
||||
--applyset applyset-$NAME \
|
||||
--namespace $NAMESPACE
|
||||
|
|
|
@ -69,6 +69,11 @@
|
|||
namespace = "syncthing";
|
||||
};
|
||||
|
||||
pihole = {
|
||||
module.pihole.enable = true;
|
||||
namespace = "dns";
|
||||
};
|
||||
|
||||
immich = {
|
||||
module.immich.enable = true;
|
||||
namespace = "immich";
|
||||
|
@ -104,6 +109,11 @@
|
|||
namespace = "kube-system";
|
||||
};
|
||||
|
||||
minecraft = {
|
||||
module.minecraft.enable = true;
|
||||
namespace = "minecraft";
|
||||
};
|
||||
|
||||
tailscale = {
|
||||
module.tailscale.enable = true;
|
||||
namespace = "tailscale";
|
||||
|
@ -113,14 +123,4 @@
|
|||
module.ntfy.enable = true;
|
||||
namespace = "ntfy";
|
||||
};
|
||||
|
||||
authentik = {
|
||||
module.authentik.enable = true;
|
||||
namespace = "authentik";
|
||||
};
|
||||
|
||||
mealie = {
|
||||
module.mealie.enable = true;
|
||||
namespace = "mealie";
|
||||
};
|
||||
}
|
||||
|
|
98
docs/longhorn.md
Normal file
98
docs/longhorn.md
Normal file
|
@ -0,0 +1,98 @@
|
|||
# Longhorn notes
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
```
|
||||
Multi-Attach error for volume "prowlarr" Volume is already exclusively attached to one node and can't be attached to another
|
||||
```
|
||||
|
||||
I solved the above problem like this:
|
||||
```
|
||||
❯ kubectl get volumeattachments | grep prowlarr
|
||||
csi-f13ee1f46a4acc0d7e4abe8a3c993c7e043e9a55cd7573bda3499085654b493a driver.longhorn.io prowlarr lewis true 3m38s
|
||||
❯ kubectl delete volumeattachments csi-f13ee1f46a4acc0d7e4abe8a3c993c7e043e9a55cd7573bda3499085654b493a
|
||||
❯ kubectl rollout restart -n media deployment prowlarr
|
||||
```
|
||||
|
||||
```
|
||||
driver name driver.longhorn.io not found in the list of registered CSI drivers
|
||||
```
|
||||
|
||||
I solved this by restarting k3s:
|
||||
```
|
||||
systemctl restart k3s
|
||||
```
|
||||
|
||||
## Migration from NFS to Longhorn
|
||||
|
||||
1. Delete the workload, and delete the PVC and PVC using NFS.
|
||||
2. Create Longhorn volumes as described below.
|
||||
3. Copy NFS data from lewis.dmz to local disk.
|
||||
4. Spin up a temporary pod and mount the Longhorn volume(s) in it:
|
||||
```nix
|
||||
{
|
||||
pods.testje.spec = {
|
||||
containers.testje = {
|
||||
image = "nginx";
|
||||
|
||||
volumeMounts = [
|
||||
{
|
||||
name = "uploads";
|
||||
mountPath = "/hedgedoc/public/uploads";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
volumes = {
|
||||
uploads.persistentVolumeClaim.claimName = "hedgedoc-uploads";
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
5. Use `kubectl cp` to copy the data from the local disk to the pod.
|
||||
6. Delete the temporary pod.
|
||||
7. Be sure to set the group ownership of the mount to the correct GID.
|
||||
7. Create the workload with updated volume mounts.
|
||||
8. Delete the data from local disk.
|
||||
|
||||
## Creation of new Longhorn volumes
|
||||
|
||||
While it seems handy to use a K8s StorageClass for Longhorn, we do *not* want to use that.
|
||||
If you use a StorageClass, a PV and Longhorn volume will be automatically provisioned.
|
||||
These will have the name `pvc-<UID of PVC>`, where the UID of the PVC is random.
|
||||
This makes it hard to restore a backup to a Longhorn volume with the correct name.
|
||||
|
||||
Instead, we want to manually create the Longhorn volumes via the web UI.
|
||||
Then, we can create the PV and PVC as usual using our K8s provisioning tool (e.g. Kubectl/Kubenix).
|
||||
|
||||
Follow these actions to create a Volume:
|
||||
1. Using the Longhorn web UI, create a new Longhorn volume, keeping the following in mind:
|
||||
- The size can be some more than what we expect to reasonable use. We use storage-overprovisioning, so the total size of volumes can exceed real disk size.
|
||||
- The number of replicas should be 2.
|
||||
2. Enable the "backup-nfs" recurring job for the Longhorn volume.
|
||||
3. Disable the "default" recurring job group for the Longhorn volume.
|
||||
4. Create the PV, PVC and workload as usual.
|
||||
|
||||
## Disaster recovery using Longhorn backups
|
||||
|
||||
Backing up Longhorn volumes is very easy, but restoring them is more tricky.
|
||||
We consider here the case when all our machines are wiped, and all we have left is Longhorn backups.
|
||||
To restore a backup, perform the following actions:
|
||||
1. Restore the latest snapshot in the relevant Longhorn backup, keeping the following in mind:
|
||||
- The name should remain the same (i.e. the one chosen at Longhorn volume creation).
|
||||
- The number of replicas should be 2.
|
||||
- Disable recurring jobs.
|
||||
2. Enable the "backup-nfs" recurring job for the Longhorn volume.
|
||||
3. Disable the "default" recurring job group for the Longhorn volume.
|
||||
4. Create the PV, PVC and workload as usual.
|
||||
|
||||
## Recovering Longhorn volumes without a Kubernetes cluster
|
||||
|
||||
1. Navigate to the Longhorn backupstore location (`/mnt/longhorn/persistent/longhorn-backup/backupstore/volumes` for us).
|
||||
2. Find the directory for the desired volume: `ls **/**`.
|
||||
3. Determine the last backup for the volume: `cat volume.cfg | jq '.LastBackupName'`.
|
||||
4. Find the blocks and the order that form the volume: `cat backups/<name>.cfg | jq '.Blocks'`.
|
||||
5. Extract each block using lz4: `lz4 -d blocks/XX/YY/XXYY.blk block`.
|
||||
6. Append the blocks to form the file system: `cat block1 block2 block3 > volume.img`
|
||||
7. Lastly we need to fix the size of the image. We can simply append zero's to the end until the file is long enough so `fsck.ext4` does not complain anymore.
|
||||
8. Mount the image: `mount -o loop volume.img /mnt/volume`.
|
734
flake.lock
generated
734
flake.lock
generated
|
@ -6,11 +6,11 @@
|
|||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1749306247,
|
||||
"narHash": "sha256-4IKXo51HPvYB8t3FC7QBhQZGXANCgMrEvdgvBjv2SIk=",
|
||||
"lastModified": 1735508994,
|
||||
"narHash": "sha256-SMMX3irZ4Y+0QEAq0mOYEnJIYRe3YnXHrkCSRvdxHxU=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "ba47dfab6c5e8f3b91db61789cfd4b7b88ce6b02",
|
||||
"revCount": 27,
|
||||
"rev": "433c1ef4b5874e2c4782be7322604d17182035ab",
|
||||
"revCount": 23,
|
||||
"type": "git",
|
||||
"url": "https://git.kun.is/pim/blog"
|
||||
},
|
||||
|
@ -19,6 +19,47 @@
|
|||
"url": "https://git.kun.is/pim/blog"
|
||||
}
|
||||
},
|
||||
"deploy-rs": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_4",
|
||||
"nixpkgs": "nixpkgs_4",
|
||||
"utils": "utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1727447169,
|
||||
"narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=",
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729712798,
|
||||
"narHash": "sha256-a+Aakkb+amHw4biOZ0iMo8xYl37uUL48YEXIC5PYJ/8=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "09a776702b004fdf9c41a024e1299d575ee18a7d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"dns": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
|
@ -27,11 +68,33 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1737653493,
|
||||
"narHash": "sha256-qTbv8Pm9WWF63M5Fj0Od9E54/lsbMSQUBHw/s30eFok=",
|
||||
"lastModified": 1733919067,
|
||||
"narHash": "sha256-ZsL5pKwEDhcZhVJh+3IwgHus7kSW/N8qOlBscwB6BCI=",
|
||||
"owner": "kirelagin",
|
||||
"repo": "dns.nix",
|
||||
"rev": "96e548ae8bd44883afc5bddb9dacd0502542276d",
|
||||
"rev": "a23f43f9762aa96d3e35c8eeefa7610bd0cdf456",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "kirelagin",
|
||||
"repo": "dns.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"dns_2": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_5",
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726867691,
|
||||
"narHash": "sha256-IK3r16N9pizf53AipOmrcrcyjVsPJwC4PI5hIqEyKwQ=",
|
||||
"owner": "kirelagin",
|
||||
"repo": "dns.nix",
|
||||
"rev": "a3196708a56dee76186a9415c187473b94e6cbae",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -88,6 +151,70 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_4": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_5": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_6": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_7": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
|
@ -109,6 +236,28 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts_2": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"servers",
|
||||
"nix-snapshotter",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1704152458,
|
||||
"narHash": "sha256-DS+dGw7SKygIWf9w4eNBUZsK+4Ug27NwEWmn2tnbycg=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "88a2cd8166694ba0b6cb374700799cec53aef527",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1614513358,
|
||||
|
@ -147,11 +296,11 @@
|
|||
"systems": "systems_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -163,6 +312,39 @@
|
|||
"inputs": {
|
||||
"systems": "systems_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_5": {
|
||||
"locked": {
|
||||
"lastModified": 1614513358,
|
||||
"narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5466c5bbece17adaab2d82fae80b46e807611bf3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_6": {
|
||||
"inputs": {
|
||||
"systems": "systems_8"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726560853,
|
||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
||||
|
@ -201,14 +383,39 @@
|
|||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1747372754,
|
||||
"narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
|
||||
"lastModified": 1734797603,
|
||||
"narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
|
||||
"rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks_2": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_5",
|
||||
"gitignore": "gitignore_2",
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs-unstable"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730302582,
|
||||
"narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -238,6 +445,28 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"globset": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
|
@ -304,14 +533,38 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kubenix_2": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_6",
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs-unstable"
|
||||
],
|
||||
"systems": "systems_9",
|
||||
"treefmt": "treefmt_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717788185,
|
||||
"narHash": "sha256-Uc6QSQqJa2lyv/1W4StwoKrjtq7cFjlKNhdrtanToGo=",
|
||||
"owner": "pizzapim",
|
||||
"repo": "kubenix",
|
||||
"rev": "a9590abe23a2f7577bc3271d90955e9ccc2923fe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "pizzapim",
|
||||
"repo": "kubenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nginx": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1748296742,
|
||||
"narHash": "sha256-E67DlHlrwomNSnRdjcnyOGhACtFbMz2jwm/glxeOxbg=",
|
||||
"lastModified": 1735301654,
|
||||
"narHash": "sha256-PHcSyHYyPUwPAls0BgtnGu2e936vhxW2nt7bQxDyGAQ=",
|
||||
"owner": "nginx",
|
||||
"repo": "nginx",
|
||||
"rev": "5b8a5c08ce28639e788734b2528faad70baa113c",
|
||||
"rev": "e3a9b6ad08a86e799a3d77da3f2fc507d3c9699e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -329,11 +582,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729742964,
|
||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||
"lastModified": 1703863825,
|
||||
"narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||
"rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -344,11 +597,11 @@
|
|||
},
|
||||
"nix-kube-generators": {
|
||||
"locked": {
|
||||
"lastModified": 1729269463,
|
||||
"narHash": "sha256-8jDDpC99fYl5CSHjZyPwb5PK7nQSknhkpfe8+DXI910=",
|
||||
"lastModified": 1708155396,
|
||||
"narHash": "sha256-A/BIeJjiRS7sBYP6tFJa/WHDPHe7DGTCkSEKXttYeAQ=",
|
||||
"owner": "farcaller",
|
||||
"repo": "nix-kube-generators",
|
||||
"rev": "2be4f3cb99e179d9f94e6c8723862421437f8efb",
|
||||
"rev": "14dbd5e5b40615937900f71d9a9851b59b4d9a88",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -380,6 +633,29 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-snapshotter_2": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_7",
|
||||
"flake-parts": "flake-parts_2",
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs-unstable"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729627456,
|
||||
"narHash": "sha256-TCZdXCmnqCPsd3PjLv/LDSKJhTspLliL0DE+c/XP9BY=",
|
||||
"owner": "pdtpartners",
|
||||
"repo": "nix-snapshotter",
|
||||
"rev": "f2957822a3748c91e678657a1cfd009b0440bbfd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "pdtpartners",
|
||||
"repo": "nix-snapshotter",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixhelm": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_3",
|
||||
|
@ -391,11 +667,11 @@
|
|||
"poetry2nix": "poetry2nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1748482293,
|
||||
"narHash": "sha256-Q3lyAFjJeR2d5kmiiSmb8ni121siv/ByjD2ueg2hUQA=",
|
||||
"lastModified": 1735607967,
|
||||
"narHash": "sha256-hdOdhQskvxyPPrf4w/k484xfVEVsqktHjwS0noTRRCw=",
|
||||
"owner": "farcaller",
|
||||
"repo": "nixhelm",
|
||||
"rev": "0ecf1ebc80e65ff8bc37e8c852cac6cc149aea6e",
|
||||
"rev": "6ce9cfd0e06bbf609af333069b3c4e84cd739755",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -412,19 +688,73 @@
|
|||
"treefmt-nix": "treefmt-nix_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1746371274,
|
||||
"narHash": "sha256-7X65+TP0luFpQsA6KV80R05qnWp7NxMaIDryFfJ4MqI=",
|
||||
"owner": "nix-community",
|
||||
"lastModified": 1735726395,
|
||||
"narHash": "sha256-rwhsZuwJzJ825Et7YI73G7+wHiPLFfx3SOnozWZfLJ0=",
|
||||
"owner": "pizzapim",
|
||||
"repo": "NixNG",
|
||||
"rev": "ea02c5dd1f2e80ee7acc47f75ec3439ed480dd6f",
|
||||
"rev": "dbbbb22d8feed064455a8653a0450b3da5a31424",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"owner": "pizzapim",
|
||||
"ref": "kubernetes",
|
||||
"repo": "NixNG",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixng_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1726571270,
|
||||
"narHash": "sha256-LEug48WOL+mmFYtKM57e/oudgjBk2Km5zIP3p27hF8I=",
|
||||
"owner": "pizzapim",
|
||||
"repo": "NixNG",
|
||||
"rev": "9538892da603608f0176d07d33b1265e038c0adf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "pizzapim",
|
||||
"ref": "dnsmasq",
|
||||
"repo": "NixNG",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-facter-modules": {
|
||||
"locked": {
|
||||
"lastModified": 1730737399,
|
||||
"narHash": "sha256-PzJrTMhHb9f46uMxmRD4GjnyVuNqxeyEvxaq7OierUQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "nixos-facter-modules",
|
||||
"rev": "c22b916f629fee6941a2976c62247b0bec68082b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "nixos-facter-modules",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1729742320,
|
||||
"narHash": "sha256-u3Of8xRkN//me8PU+RucKA59/6RNy4B2jcGAF36P4jI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "e8a2f6d5513fe7b7d15701b2d05404ffdc3b6dda",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "master",
|
||||
"repo": "nixos-hardware",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1714076141,
|
||||
|
@ -441,13 +771,45 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-bazarr": {
|
||||
"locked": {
|
||||
"lastModified": 1735086895,
|
||||
"narHash": "sha256-893hOoQn5t9g0r57N0D8/G5WC4pPaNlprjAYO0TWRxc=",
|
||||
"owner": "r-ryantm",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "89e79d58769436a8cfd0d80ae28012d51134f2f3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "r-ryantm",
|
||||
"ref": "auto-update/bazarr",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-jellyseerr": {
|
||||
"locked": {
|
||||
"lastModified": 1735406088,
|
||||
"narHash": "sha256-Cwah5iXhOJ3cbrPYG5oeSyhQ7F7BsAabHTeezD4elh0=",
|
||||
"owner": "coonce",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "25569750ccc0c692128e667a77585d6d27ff7e57",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "coonce",
|
||||
"ref": "jellyseerr",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-master": {
|
||||
"locked": {
|
||||
"lastModified": 1748523262,
|
||||
"narHash": "sha256-QGBY1wNWqtrT/9LYPcrie4e7EC44/CXGljkM2N/puWg=",
|
||||
"lastModified": 1735935963,
|
||||
"narHash": "sha256-i6xTJb3sb4BeWypD/DjAmslDzGXZUGU1OFJliaKFuuc=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9e0df1205d7c2acb4504a25091ee603fd1dd9865",
|
||||
"rev": "20166d17f391d2e11311baaa74344381fa44e4a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -457,6 +819,86 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-radicale": {
|
||||
"locked": {
|
||||
"lastModified": 1735496163,
|
||||
"narHash": "sha256-oqUP98g0eqfzCDA/i88qRIBq4BIyxEk9um7dfNGiw+I=",
|
||||
"owner": "erictapen",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e14050d0c94dc929543f7e4502fda8539d36536f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "erictapen",
|
||||
"ref": "radicale",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1730741070,
|
||||
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1720386169,
|
||||
"narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "194846768975b7ad2c4988bdb82572c00222c0d7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable_3": {
|
||||
"locked": {
|
||||
"lastModified": 1729357638,
|
||||
"narHash": "sha256-66RHecx+zohbZwJVEPF7uuwHeqf8rykZTMCTqIrOew4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "bb8c2cf7ea0dd2e18a52746b2c3a5b0c73b93c22",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1729818716,
|
||||
"narHash": "sha256-XRfkUsxLzFkMn3Tpstio1gNOIQ+2PZPCKbifJ2IXxlw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "062c4f59744fcffa2e5aa3ef443dc8b4d1674ed6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1726871744,
|
||||
|
@ -475,11 +917,11 @@
|
|||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1748370509,
|
||||
"narHash": "sha256-QlL8slIgc16W5UaI3w7xHQEP+Qmv/6vSNTpoZrrSlbk=",
|
||||
"lastModified": 1735471104,
|
||||
"narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4faa5f5321320e49a78ae7848582f684d64783e9",
|
||||
"rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -491,11 +933,43 @@
|
|||
},
|
||||
"nixpkgs_4": {
|
||||
"locked": {
|
||||
"lastModified": 1747958103,
|
||||
"narHash": "sha256-qmmFCrfBwSHoWw7cVK4Aj+fns+c54EBP8cGqp/yK410=",
|
||||
"lastModified": 1702272962,
|
||||
"narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_5": {
|
||||
"locked": {
|
||||
"lastModified": 1726871744,
|
||||
"narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "fe51d34885f7b5e3e7b59572796e1bcb427eccb1",
|
||||
"rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_6": {
|
||||
"locked": {
|
||||
"lastModified": 1733097829,
|
||||
"narHash": "sha256-9hbb1rqGelllb4kVUCZ307G2k3/UhmA8PPGBoyuWaSw=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2c15aa59df0017ca140d9ba302412298ab4bf22a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -517,11 +991,11 @@
|
|||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1738741221,
|
||||
"narHash": "sha256-UiTOA89yQV5YNlO1ZAp4IqJUGWOnTyBC83netvt8rQE=",
|
||||
"lastModified": 1718285706,
|
||||
"narHash": "sha256-DScsBM+kZvxOva7QegfdtleebMXh30XPxDQr/1IGKYo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "poetry2nix",
|
||||
"rev": "be1fe795035d3d36359ca9135b26dcc5321b31fb",
|
||||
"rev": "a5be1bbbe0af0266147a88e0ec43b18c722f2bb9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -542,8 +1016,67 @@
|
|||
"nixhelm": "nixhelm",
|
||||
"nixng": "nixng",
|
||||
"nixpkgs": "nixpkgs_3",
|
||||
"nixpkgs-bazarr": "nixpkgs-bazarr",
|
||||
"nixpkgs-jellyseerr": "nixpkgs-jellyseerr",
|
||||
"nixpkgs-master": "nixpkgs-master",
|
||||
"nixpkgs-radicale": "nixpkgs-radicale",
|
||||
"servers": "servers",
|
||||
"treefmt-nix": "treefmt-nix_4"
|
||||
}
|
||||
},
|
||||
"servers": {
|
||||
"inputs": {
|
||||
"deploy-rs": "deploy-rs",
|
||||
"disko": "disko",
|
||||
"dns": "dns_2",
|
||||
"flake-utils": "flake-utils_6",
|
||||
"git-hooks": "git-hooks_2",
|
||||
"kubenix": "kubenix_2",
|
||||
"nix-snapshotter": "nix-snapshotter_2",
|
||||
"nixng": "nixng_2",
|
||||
"nixos-facter-modules": "nixos-facter-modules",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"sops-nix": "sops-nix",
|
||||
"treefmt-nix": "treefmt-nix_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733068232,
|
||||
"narHash": "sha256-iZJ/cq07OVk2TQy6UV9JaXgLARQqJedmuPIHTtgVeeo=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "68b79e086c4cc6b850ba12c60f3a978d18bd41b1",
|
||||
"revCount": 495,
|
||||
"type": "git",
|
||||
"url": "https://git.kun.is/home/nixos-servers"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.kun.is/home/nixos-servers"
|
||||
}
|
||||
},
|
||||
"sops-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729775275,
|
||||
"narHash": "sha256-J2vtHq9sw1wWm0aTMXpEEAzsVCUMZDTEe5kiBYccpLE=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "78a0e634fc8981d6b564f08b6715c69a755c4c7d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
|
@ -621,6 +1154,20 @@
|
|||
}
|
||||
},
|
||||
"systems_6": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "systems",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"systems_7": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
|
@ -635,6 +1182,35 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_8": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_9": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "systems",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"treefmt": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -665,11 +1241,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1730120726,
|
||||
"narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=",
|
||||
"lastModified": 1717850719,
|
||||
"narHash": "sha256-npYqVg+Wk4oxnWrnVG7416fpfrlRhp/lQ6wQ4DHI8YE=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "9ef337e492a5555d8e17a51c911ff1f02635be15",
|
||||
"rev": "4fc1c45a5f50169f9f29f6a98a438fb910b834ed",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -698,14 +1274,14 @@
|
|||
},
|
||||
"treefmt-nix_3": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_4"
|
||||
"nixpkgs": "nixpkgs_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1748243702,
|
||||
"narHash": "sha256-9YzfeN8CB6SzNPyPm2XjRRqSixDopTapaRsnTpXUEY8=",
|
||||
"lastModified": 1730025913,
|
||||
"narHash": "sha256-Y9NtFmP8ciLyRsopcCx1tyoaaStKeq+EndwtGCgww7I=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "1f3f7b784643d488ba4bf315638b2b0a4c5fb007",
|
||||
"rev": "bae131e525cc8718da22fbeb8d8c7c43c4ea502a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -713,6 +1289,64 @@
|
|||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix_4": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_6"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1735649548,
|
||||
"narHash": "sha256-/4pTzlmABhx26AOTYvFN1OTCxJJL/LBUB49giqoMhJA=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "597705118f16d1dcd0fef99707700d13b2b324d7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"servers",
|
||||
"kubenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1688026376,
|
||||
"narHash": "sha256-qJmkr9BWDpqblk4E9/rCsAEl39y2n4Ycw6KRopvpUcY=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "df3f32b0cc253dfc7009b7317e8f0e7ccd70b1cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_7"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701680307,
|
||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
|
11
flake.nix
11
flake.nix
|
@ -7,6 +7,9 @@
|
|||
flake-utils.url = "github:numtide/flake-utils";
|
||||
treefmt-nix.url = "github:numtide/treefmt-nix";
|
||||
blog.url = "git+https://git.kun.is/pim/blog";
|
||||
nixpkgs-jellyseerr.url = "github:coonce/nixpkgs?ref=jellyseerr";
|
||||
nixpkgs-bazarr.url = "github:r-ryantm/nixpkgs?ref=auto-update/bazarr";
|
||||
nixpkgs-radicale.url = "github:erictapen/nixpkgs?ref=radicale";
|
||||
|
||||
git-hooks = {
|
||||
url = "github:cachix/git-hooks.nix";
|
||||
|
@ -28,8 +31,13 @@
|
|||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
servers = {
|
||||
url = "git+https://git.kun.is/home/nixos-servers";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
nixng = {
|
||||
url = "github:nix-community/NixNG";
|
||||
url = "github:pizzapim/NixNG/kubernetes";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
|
@ -52,6 +60,5 @@
|
|||
./formatter.nix
|
||||
./shell.nix
|
||||
./nixng-configurations
|
||||
./nixng-modules
|
||||
];
|
||||
}
|
||||
|
|
55
globals.nix
55
globals.nix
|
@ -1,25 +1,29 @@
|
|||
_: {
|
||||
{servers, ...}: let
|
||||
globals = {
|
||||
images = {
|
||||
jellyfin = "jellyfin/jellyfin:10.10.7";
|
||||
jellyfin = "jellyfin/jellyfin:10.10.3";
|
||||
deluge = "linuxserver/deluge:2.1.1";
|
||||
atuin = "ghcr.io/atuinsh/atuin:18.3.0";
|
||||
postgres14 = "postgres:14";
|
||||
kms = "teddysun/kms:latest";
|
||||
paperless = "ghcr.io/paperless-ngx/paperless-ngx:2.16.2";
|
||||
paperless = "ghcr.io/paperless-ngx/paperless-ngx:2.13.5";
|
||||
redis7 = "docker.io/library/redis:7";
|
||||
nextcloud = "nextcloud:30.0.6";
|
||||
nextcloud = "nextcloud:30.0.2";
|
||||
postgres15 = "postgres:15";
|
||||
inbucket = "inbucket/inbucket:edge";
|
||||
syncthing = "lscr.io/linuxserver/syncthing:1.29.6";
|
||||
forgejo = "codeberg.org/forgejo/forgejo:11.0.1";
|
||||
immich = "ghcr.io/immich-app/immich-server:v1.134.0";
|
||||
immich-machine-learning = "ghcr.io/immich-app/immich-machine-learning:v1.134.0";
|
||||
immich-redis = "docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1";
|
||||
immich-postgres = "ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0";
|
||||
kitchenowl = "tombursch/kitchenowl:v0.6.15";
|
||||
syncthing = "lscr.io/linuxserver/syncthing:1.28.0";
|
||||
forgejo = "codeberg.org/forgejo/forgejo:9.0.2";
|
||||
pihole = "pihole/pihole:2024.07.0";
|
||||
immich = "ghcr.io/immich-app/immich-server:v1.122.3";
|
||||
immich-machine-learning = "ghcr.io/immich-app/immich-machine-learning:v1.122.3";
|
||||
immich-redis = "docker.io/redis:6.2-alpine@sha256:eaba718fecd1196d88533de7ba49bf903ad33664a92debb24660a922ecd9cac8";
|
||||
immich-postgres = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0";
|
||||
kitchenowl = "tombursch/kitchenowl:v0.6.4";
|
||||
cyberchef = "mpepping/cyberchef:latest";
|
||||
freshrss = "freshrss/freshrss:1.26.3";
|
||||
freshrss = "freshrss/freshrss:1.24.3";
|
||||
bind9 = "ubuntu/bind9:9.18-22.04_beta";
|
||||
hedgedoc = "quay.io/hedgedoc/hedgedoc:1.10.3";
|
||||
hedgedoc = "quay.io/hedgedoc/hedgedoc:1.10.0";
|
||||
minecraft = "itzg/minecraft-server:latest";
|
||||
};
|
||||
|
||||
nodeLabels = {
|
||||
|
@ -31,28 +35,7 @@ _: {
|
|||
hasMedia = "true";
|
||||
};
|
||||
};
|
||||
|
||||
routerPublicIPv4 = "89.220.7.89";
|
||||
bind9Ipv6 = "2a0d:6e00:1a77:30::134";
|
||||
|
||||
# Load balancer IPv4
|
||||
traefikIPv4 = "192.168.30.128";
|
||||
kmsIPv4 = "192.168.30.129";
|
||||
inbucketIPv4 = "192.168.30.130";
|
||||
gitIPv4 = "192.168.30.132";
|
||||
delugeIPv4 = "192.168.30.133";
|
||||
bind9IPv4 = "192.168.30.134";
|
||||
dnsmasqIPv4 = "192.168.30.135";
|
||||
jellyseerrIPv4 = "192.168.30.137";
|
||||
syncthingIPv4 = "192.168.30.138";
|
||||
radarrIPv4 = "192.168.30.140";
|
||||
prowlarrIPv4 = "192.168.30.141";
|
||||
sonarrIPv4 = "192.168.30.142";
|
||||
bazarrIPv4 = "192.168.30.143";
|
||||
paperlessIPv4 = "192.168.30.144";
|
||||
radicaleIPv4 = "192.168.30.145";
|
||||
freshrssIPv4 = "192.168.30.146";
|
||||
immichIPv4 = "192.168.30.147";
|
||||
nextcloudIPv4 = "192.168.30.148";
|
||||
};
|
||||
in {
|
||||
globals = globals // servers.globals;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ inputs @ {
|
|||
flake-utils.lib.eachDefaultSystem
|
||||
(system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (pkgs) lib;
|
||||
lib = pkgs.lib;
|
||||
deployScript = (pkgs.writeScriptBin "applyset-deploy.sh" (builtins.readFile ./applyset-deploy.sh)).overrideAttrs (old: {
|
||||
buildCommand = "${old.buildCommand}\npatchShebangs $out";
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ flake-utils.lib.eachDefaultSystem
|
|||
pkgs.symlinkJoin
|
||||
{
|
||||
name = "applyset-deploy.sh";
|
||||
paths = [deployScript pkgs.vals pkgs.kubectl pkgs.gettext];
|
||||
paths = [deployScript pkgs.vals pkgs.kubectl];
|
||||
buildInputs = [pkgs.makeWrapper];
|
||||
passthru.manifest = result;
|
||||
meta.mainProgram = "applyset-deploy.sh";
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
self,
|
||||
utils,
|
||||
lib,
|
||||
config,
|
||||
|
@ -40,8 +41,6 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.attic = {
|
||||
image = utils.mkNixNGImage "attic";
|
||||
ports.web.containerPort = 8080;
|
||||
|
@ -67,12 +66,8 @@
|
|||
};
|
||||
|
||||
volumes = {
|
||||
data.persistentVolumeClaim.claimName = "data";
|
||||
server.secret.secretName = "server";
|
||||
|
||||
data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/attic";
|
||||
type = "Directory";
|
||||
};
|
||||
};
|
||||
|
||||
securityContext = {
|
||||
|
@ -96,8 +91,6 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.postgres = {
|
||||
image = globals.images.postgres15;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
|
@ -122,10 +115,7 @@
|
|||
];
|
||||
};
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/attic-db";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "database";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -167,6 +157,18 @@
|
|||
portName = "web";
|
||||
};
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim = {
|
||||
data = {
|
||||
volumeName = "attic";
|
||||
storage = "15Gi";
|
||||
};
|
||||
|
||||
database = {
|
||||
volumeName = "attic-db";
|
||||
storage = "150Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
config,
|
||||
utils,
|
||||
globals,
|
||||
lib,
|
||||
...
|
||||
|
@ -30,22 +29,35 @@
|
|||
metadata.labels.app = "atuin";
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.database.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/atuin-db";
|
||||
type = "Directory";
|
||||
volumes = {
|
||||
data.persistentVolumeClaim.claimName = "data";
|
||||
database.persistentVolumeClaim.claimName = "database";
|
||||
};
|
||||
|
||||
containers = {
|
||||
atuin = {
|
||||
image = utils.mkNixNGImage "atuin";
|
||||
image = globals.images.atuin;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
ports.web.containerPort = 8888;
|
||||
args = ["server" "start"];
|
||||
|
||||
env.ATUIN_DB_URI.valueFrom.secretKeyRef = {
|
||||
name = "database";
|
||||
key = "databaseURL";
|
||||
env = {
|
||||
ATUIN_HOST.value = "0.0.0.0";
|
||||
ATUIN_PORT.value = "8888";
|
||||
ATUIN_OPEN_REGISTRATION.value = "false";
|
||||
|
||||
ATUIN_DB_URI.valueFrom.secretKeyRef = {
|
||||
name = "database";
|
||||
key = "databaseURL";
|
||||
};
|
||||
};
|
||||
|
||||
volumeMounts = [
|
||||
{
|
||||
name = "data";
|
||||
mountPath = "/config";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
database = {
|
||||
|
@ -93,6 +105,18 @@
|
|||
portName = "web";
|
||||
};
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim = {
|
||||
data = {
|
||||
volumeName = "atuin";
|
||||
storage = "300Mi";
|
||||
};
|
||||
|
||||
database = {
|
||||
volumeName = "atuin-db";
|
||||
storage = "300Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
{
|
||||
nixhelm,
|
||||
system,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options.authentik.enable = lib.mkEnableOption "authentik";
|
||||
|
||||
config = lib.mkIf config.authentik.enable {
|
||||
kubernetes = {
|
||||
helm.releases.authentik = {
|
||||
chart = nixhelm.chartsDerivations.${system}.authentik.authentik;
|
||||
includeCRDs = true;
|
||||
namespace = "authentik";
|
||||
|
||||
values = {
|
||||
authentik = {
|
||||
email = {
|
||||
host = "mail.smtp2go.com";
|
||||
port = 2525;
|
||||
from = "Authentik authentik@kun.is";
|
||||
};
|
||||
};
|
||||
|
||||
postgresql = {
|
||||
enabled = true;
|
||||
auth.password = "ref+sops://secrets.yml#/authentik/postgresql_password";
|
||||
primary = {
|
||||
persistence.enabled = false;
|
||||
extraEnvVarsSecret = "postgresql-env";
|
||||
extraVolumes = [
|
||||
{
|
||||
name = "data";
|
||||
|
||||
hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/authentik-db";
|
||||
type = "Directory";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
redis = {
|
||||
enabled = true;
|
||||
master = {
|
||||
persistence.enabled = false;
|
||||
extraVolumes = [
|
||||
{
|
||||
name = "authentik-redis";
|
||||
hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/authentik-redis";
|
||||
type = "Directory";
|
||||
};
|
||||
}
|
||||
];
|
||||
extraVolumeMounts = [
|
||||
{
|
||||
mountPath = "/data";
|
||||
name = "authentik-redis";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
resources = let
|
||||
env = {
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD.value = "ref+sops://secrets.yml#/authentik/postgresql_password";
|
||||
AUTHENTIK_SECRET_KEY.value = "ref+sops://secrets.yml#/authentik/secret_key";
|
||||
AUTHENTIK_EMAIL__USERNAME.value = "ref+sops://secrets.yml#/smtp2go/username";
|
||||
AUTHENTIK_EMAIL__PASSWORD.value = "ref+sops://secrets.yml#/smtp2go/password";
|
||||
};
|
||||
in {
|
||||
secrets.postgresql-env.stringData = {
|
||||
POSTGRES_PASSWORD = "ref+sops://secrets.yml#/authentik/postgresql_password";
|
||||
};
|
||||
|
||||
deployments = {
|
||||
authentik-server.spec.template.spec.containers.server.env = env;
|
||||
authentik-worker.spec.template.spec.containers.worker.env = env;
|
||||
};
|
||||
|
||||
statefulSets.authentik-postgresql.spec.template.spec.nodeName = "atlas";
|
||||
statefulSets.authentik-redis-master.spec.template.spec.nodeName = "atlas";
|
||||
};
|
||||
};
|
||||
|
||||
lab = {
|
||||
ingresses.authentik = {
|
||||
host = "authentik.kun.is";
|
||||
|
||||
service = {
|
||||
name = "authentik-server";
|
||||
portName = "http";
|
||||
};
|
||||
};
|
||||
|
||||
tailscaleIngresses = {
|
||||
tailscale-authentik = {
|
||||
host = "authentik";
|
||||
service = {
|
||||
name = "authentik-server";
|
||||
portName = "http";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -117,7 +117,6 @@ in {
|
|||
bind9-udp = {
|
||||
metadata.annotations = {
|
||||
"metallb.universe.tf/loadBalancerIPs" = "${globals.bind9IPv4},${globals.bind9Ipv6}";
|
||||
# "metallb.universe.tf/loadBalancerIPs" = "${globals.bind9IPv4}";
|
||||
"metallb.universe.tf/allow-shared-ip" = "dns";
|
||||
};
|
||||
|
||||
|
@ -138,7 +137,6 @@ in {
|
|||
bind9-tcp = {
|
||||
metadata.annotations = {
|
||||
"metallb.universe.tf/loadBalancerIPs" = "${globals.bind9IPv4},${globals.bind9Ipv6}";
|
||||
# "metallb.universe.tf/loadBalancerIPs" = "${globals.bind9IPv4}";
|
||||
"metallb.universe.tf/allow-shared-ip" = "dns";
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ with dns.lib.combinators; {
|
|||
SOA = {
|
||||
nameServer = "ns1";
|
||||
adminEmail = "webmaster.kun.is";
|
||||
serial = 2024041302;
|
||||
serial = 2024041301;
|
||||
};
|
||||
|
||||
NS = [
|
||||
|
@ -24,15 +24,13 @@ with dns.lib.combinators; {
|
|||
subdomains = rec {
|
||||
"*".A = [globals.routerPublicIPv4];
|
||||
|
||||
ns1 = {
|
||||
ns = {
|
||||
A = [globals.routerPublicIPv4];
|
||||
AAAA = [];
|
||||
};
|
||||
|
||||
ns2 = {
|
||||
A = ["192.145.57.90"];
|
||||
AAAA = [];
|
||||
};
|
||||
ns1 = ns;
|
||||
ns2 = ns;
|
||||
|
||||
wg = {
|
||||
A = [globals.routerPublicIPv4];
|
||||
|
|
|
@ -15,9 +15,33 @@
|
|||
chart = nixhelm.chartsDerivations.${system}.metallb.metallb;
|
||||
includeCRDs = true;
|
||||
};
|
||||
|
||||
# argo-workflows = {
|
||||
# chart = nixhelm.chartsDerivations.${system}.argoproj.argo-workflows;
|
||||
# includeCRDs = true;
|
||||
# };
|
||||
|
||||
longhorn = {
|
||||
chart = nixhelm.chartsDerivations.${system}.longhorn.longhorn;
|
||||
includeCRDs = true;
|
||||
|
||||
values = {
|
||||
persistence.defaultClassReplicaCount = 2;
|
||||
service.ui.type = "LoadBalancer";
|
||||
|
||||
defaultSettings = {
|
||||
defaultDataPath = "/mnt/longhorn";
|
||||
storageMinimalAvailablePercentage = 0;
|
||||
allowRecurringJobWhileVolumeDetached = true;
|
||||
backupTarget = "nfs://lewis.dmz:/mnt/longhorn/persistent/longhorn-backup";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
resources = {
|
||||
services.longhorn-frontend.spec.loadBalancerIP = globals.longhornIPv4;
|
||||
|
||||
namespaces = {
|
||||
static-websites = {};
|
||||
freshrss = {};
|
||||
|
@ -35,21 +59,93 @@
|
|||
inbucket = {};
|
||||
dns = {};
|
||||
media = {};
|
||||
minecraft = {};
|
||||
tailscale = {};
|
||||
ntfy = {};
|
||||
authentik = {};
|
||||
mealie = {};
|
||||
};
|
||||
|
||||
nodes =
|
||||
builtins.mapAttrs
|
||||
(_name: labels: {
|
||||
(name: labels: {
|
||||
metadata.labels = labels;
|
||||
})
|
||||
globals.nodeLabels;
|
||||
|
||||
recurringJobs.backup-nfs.spec = {
|
||||
cron = "0 1 * * *"; # One o'clock at night
|
||||
task = "backup";
|
||||
retain = 2; # We don't need many, as we also make Borg backups.
|
||||
concurrency = 1;
|
||||
};
|
||||
|
||||
ipAddressPools.main.spec.addresses = ["192.168.30.128-192.168.30.200" "2a0d:6e00:1a77:30::2-2a0d:6e00:1a77:30:ffff:ffff:ffff:fffe"];
|
||||
l2Advertisements.main.metadata = {};
|
||||
|
||||
persistentVolumes = {
|
||||
music-syncthing.spec = {
|
||||
capacity.storage = "1Gi";
|
||||
accessModes = ["ReadWriteMany"];
|
||||
|
||||
nfs = {
|
||||
server = "lewis.dmz";
|
||||
path = "/mnt/longhorn/persistent/media/music";
|
||||
};
|
||||
};
|
||||
|
||||
media-media.spec = {
|
||||
capacity.storage = "1Gi";
|
||||
accessModes = ["ReadWriteMany"];
|
||||
|
||||
nfs = {
|
||||
server = "lewis.dmz";
|
||||
path = "/mnt/longhorn/persistent/media";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lab = {
|
||||
longhorn.persistentVolume = {
|
||||
freshrss.storage = "1Gi";
|
||||
radicale.storage = "200Mi";
|
||||
atuin.storage = "300Mi";
|
||||
atuin-db.storage = "300Mi";
|
||||
nextcloud.storage = "50Gi";
|
||||
nextcloud-db.storage = "400Mi";
|
||||
hedgedoc-uploads.storage = "50Mi";
|
||||
hedgedoc-db.storage = "100Mi";
|
||||
kitchenowl.storage = "100Mi";
|
||||
forgejo.storage = "20Gi";
|
||||
paperless-data.storage = "10Gi";
|
||||
paperless-redisdata.storage = "20Mi";
|
||||
paperless-db.storage = "150Mi";
|
||||
syncthing.storage = "400Mi";
|
||||
pihole-data.storage = "750Mi";
|
||||
pihole-dnsmasq.storage = "16Mi";
|
||||
immich.storage = "50Gi";
|
||||
immich-db.storage = "5Gi";
|
||||
attic.storage = "15Gi";
|
||||
attic-db.storage = "150Mi";
|
||||
jellyfin.storage = "5Gi";
|
||||
transmission.storage = "25Mi";
|
||||
jellyseerr.storage = "75Mi";
|
||||
radarr.storage = "300Mi";
|
||||
prowlarr.storage = "150Mi";
|
||||
sonarr.storage = "150Mi";
|
||||
bazarr.storage = "25Mi";
|
||||
minecraft.storage = "1Gi";
|
||||
ntfy.storage = "300Mi";
|
||||
deluge.storage = "500Mi";
|
||||
};
|
||||
|
||||
tailscaleIngresses.tailscale-longhorn = {
|
||||
host = "longhorn";
|
||||
|
||||
service = {
|
||||
name = "longhorn-frontend";
|
||||
portName = "http";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
imports = [
|
||||
./inbucket.nix
|
||||
./tailscale-ingress.nix
|
||||
./longhorn-volume.nix
|
||||
./ingress.nix
|
||||
./dummy-types.nix
|
||||
./dnsmasq.nix
|
||||
|
@ -19,6 +20,7 @@
|
|||
./forgejo
|
||||
./paperless.nix
|
||||
./syncthing.nix
|
||||
./pihole.nix
|
||||
./immich.nix
|
||||
./attic.nix
|
||||
./bind9
|
||||
|
@ -26,7 +28,6 @@
|
|||
./traefik.nix
|
||||
./tailscale.nix
|
||||
./ntfy.nix
|
||||
./authentik.nix
|
||||
./mealie.nix
|
||||
./minecraft.nix
|
||||
];
|
||||
}
|
||||
|
|
|
@ -32,11 +32,11 @@
|
|||
kind = "ClusterIssuer";
|
||||
};
|
||||
|
||||
middlewares = {
|
||||
attrName = "middlewares";
|
||||
group = "traefik.io";
|
||||
version = "v1alpha1";
|
||||
kind = "Middleware";
|
||||
recurringJob = {
|
||||
attrName = "recurringJobs";
|
||||
group = "longhorn.io";
|
||||
version = "v1beta1";
|
||||
kind = "RecurringJob";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,18 +7,11 @@
|
|||
"repository.pull-request".DEFAULT_MERGE_STYLE = "merge";
|
||||
"repository.signing".DEFAULT_TRUST_MODEL = "committer";
|
||||
ui.DEFAULT_THEME = "forgejo-light";
|
||||
|
||||
oauth2 = {
|
||||
ENABLED = true;
|
||||
ENABLED = false;
|
||||
JWT_SECRET = "ref+sops://secrets.yml#/forgejo/jwtSecret";
|
||||
};
|
||||
|
||||
oauth2_client = {
|
||||
ENABLE_AUTO_REGISTRATION = true;
|
||||
ACCOUNT_LINKING = "auto";
|
||||
USERNAME = "email";
|
||||
};
|
||||
|
||||
DEFAULT = {
|
||||
APP_NAME = "Forgejo: Beyond coding. We forge.";
|
||||
RUN_MODE = "prod";
|
||||
|
@ -92,11 +85,11 @@
|
|||
};
|
||||
|
||||
service = {
|
||||
DISABLE_REGISTRATION = false;
|
||||
DISABLE_REGISTRATION = true;
|
||||
REQUIRE_SIGNIN_VIEW = false;
|
||||
REGISTER_EMAIL_CONFIRM = false;
|
||||
ENABLE_NOTIFY_MAIL = false;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = false;
|
||||
ENABLE_CAPTCHA = false;
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = true;
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true;
|
||||
|
@ -105,7 +98,7 @@
|
|||
};
|
||||
|
||||
openid = {
|
||||
ENABLE_OPENID_SIGNIN = false;
|
||||
ENABLE_OPENID_SIGNIN = true;
|
||||
ENABLE_OPENID_SIGNUP = false;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
# This disables services from becoming environmental variables
|
||||
# to prevent SSH_PORT clashing with Forgejo config.
|
||||
enableServiceLinks = false;
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.forgejo = {
|
||||
image = globals.images.forgejo;
|
||||
|
@ -59,10 +58,7 @@
|
|||
};
|
||||
|
||||
volumes = {
|
||||
data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/forgejo";
|
||||
type = "Directory";
|
||||
};
|
||||
data.persistentVolumeClaim.claimName = "data";
|
||||
config.secret.secretName = "forgejo";
|
||||
};
|
||||
};
|
||||
|
@ -101,6 +97,11 @@
|
|||
portName = "web";
|
||||
};
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim.data = {
|
||||
volumeName = "forgejo";
|
||||
storage = "20Gi";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
metadata.labels.app = "freshrss";
|
||||
|
||||
spec = {
|
||||
nodeName = "atlas";
|
||||
|
||||
containers.freshrss = {
|
||||
image = globals.images.freshrss;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
|
@ -38,13 +36,6 @@
|
|||
CRON_MIN.value = "2,32";
|
||||
ADMIN_EMAIL.value = "pim@kunis.nl";
|
||||
PUBLISHED_PORT.value = "443";
|
||||
OIDC_ENABLED.value = "1";
|
||||
OIDC_PROVIDER_METADATA_URL.value = "https://authentik.kun.is/application/o/freshrss/.well-known/openid-configuration";
|
||||
OIDC_CLIENT_ID.value = "5J2L7Ufq4KMayQ8qrqxHCslxHWL2SXNMKJmsbbiQ";
|
||||
OIDC_CLIENT_SECRET.value = "ref+sops://secrets.yml#/authentik/oauth2/freshrss/client_secret";
|
||||
OIDC_CLIENT_CRYPTO_KEY.value = "ref+sops://secrets.yml#/freshrss/oidc_crypto_key";
|
||||
OIDC_SCOPES.value = "openid email profile";
|
||||
OIDC_X_FORWARDED_HEADERS.value = "X-Forwarded-Port X-Forwarded-Proto X-Forwarded-Host";
|
||||
|
||||
ADMIN_PASSWORD.valueFrom.secretKeyRef = {
|
||||
name = "server";
|
||||
|
@ -65,10 +56,7 @@
|
|||
];
|
||||
};
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/freshrss";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
|
||||
securityContext = {
|
||||
fsGroup = 33;
|
||||
|
@ -95,6 +83,11 @@
|
|||
host = "freshrss";
|
||||
service.name = "server";
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim.data = {
|
||||
volumeName = "freshrss";
|
||||
storage = "1Gi";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.hedgedoc = {
|
||||
image = globals.images.hedgedoc;
|
||||
ports.web.containerPort = 3000;
|
||||
|
@ -56,17 +54,6 @@
|
|||
CMD_PROTOCOL_USESSL.value = "true";
|
||||
CMD_CSP_ENABLE.value = "false";
|
||||
|
||||
CMD_OAUTH2_PROVIDERNAME.value = "Authentik";
|
||||
CMD_OAUTH2_CLIENT_ID.value = "ZF56062l4BPnq2INv2zaO9cEiE6sAj7CrxbWhExj";
|
||||
CMD_OAUTH2_CLIENT_SECRET.value = "ref+sops://secrets.yml#/authentik/oauth2/hedgedoc/client_secret";
|
||||
CMD_OAUTH2_SCOPE.value = "openid email profile";
|
||||
CMD_OAUTH2_USER_PROFILE_URL.value = "https://authentik.kun.is/application/o/userinfo/";
|
||||
CMD_OAUTH2_TOKEN_URL.value = "https://authentik.kun.is/application/o/token/";
|
||||
CMD_OAUTH2_AUTHORIZATION_URL.value = "https://authentik.kun.is/application/o/authorize/";
|
||||
CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR.value = "preferred_username";
|
||||
CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR.value = "name";
|
||||
CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR.value = "email";
|
||||
|
||||
CMD_DB_URL.valueFrom.secretKeyRef = {
|
||||
name = "hedgedoc";
|
||||
key = "databaseURL";
|
||||
|
@ -92,12 +79,8 @@
|
|||
};
|
||||
|
||||
volumes = {
|
||||
uploads.persistentVolumeClaim.claimName = "uploads";
|
||||
config.configMap.name = "hedgedoc-config";
|
||||
|
||||
uploads.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/hedgedoc-uploads";
|
||||
type = "Directory";
|
||||
};
|
||||
};
|
||||
|
||||
securityContext = {
|
||||
|
@ -130,8 +113,6 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.postgres = {
|
||||
image = globals.images.postgres15;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
|
@ -156,10 +137,7 @@
|
|||
];
|
||||
};
|
||||
|
||||
volumes.database.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/hedgedoc-db";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.database.persistentVolumeClaim.claimName = "database";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -201,6 +179,18 @@
|
|||
portName = "web";
|
||||
};
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim = {
|
||||
uploads = {
|
||||
volumeName = "hedgedoc-uploads";
|
||||
storage = "50Mi";
|
||||
};
|
||||
|
||||
database = {
|
||||
volumeName = "hedgedoc-db";
|
||||
storage = "100Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,12 +33,7 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/immich";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
|
||||
enableServiceLinks = false;
|
||||
|
||||
|
@ -94,10 +89,7 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
volumes.cache.hostPath = {
|
||||
path = "/tmp/immich-ml-cache";
|
||||
type = "DirectoryOrCreate";
|
||||
};
|
||||
volumes.cache.persistentVolumeClaim.claimName = "cache";
|
||||
|
||||
containers.machine-learning = {
|
||||
image = globals.images.immich-machine-learning;
|
||||
|
@ -169,16 +161,13 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/immich-db";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "database";
|
||||
|
||||
containers.postgres = {
|
||||
image = globals.images.immich-postgres;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
command = ["postgres"];
|
||||
args = ["-c" "shared_preload_libraries=vectors.so" "-c" "search_path=\"$$user\", public, vectors" "-c" "logging_collector=on" "-c" "max_wal_size=2GB" "-c" "shared_buffers=512MB" "-c" "wal_compression=on"];
|
||||
ports.postgres.containerPort = 5432;
|
||||
securityContext.runAsUser = 999;
|
||||
securityContext.runAsGroup = 999;
|
||||
|
@ -259,6 +248,11 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
persistentVolumeClaims.cache.spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
resources.requests.storage = "5Gi";
|
||||
};
|
||||
};
|
||||
|
||||
lab = {
|
||||
|
@ -266,6 +260,18 @@
|
|||
host = "immich";
|
||||
service.name = "server";
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim = {
|
||||
data = {
|
||||
volumeName = "immich";
|
||||
storage = "50Gi";
|
||||
};
|
||||
|
||||
database = {
|
||||
volumeName = "immich-db";
|
||||
storage = "5Gi";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,14 +21,7 @@
|
|||
|
||||
containers.inbucket = {
|
||||
image = globals.images.inbucket;
|
||||
env = {
|
||||
INBUCKET_MAILBOXNAMING.value = "full";
|
||||
INBUCKET_SMTP_DEFAULTACCEPT.value = "false";
|
||||
INBUCKET_SMTP_ACCEPTDOMAINS.value = "kun.is";
|
||||
INBUCKET_SMTP_DEFAULTSTORE.value = "false";
|
||||
INBUCKET_SMTP_STOREDOMAINS.value = "kun.is";
|
||||
INBUCKET_STORAGE_RETENTIONPERIOD.value = "168h";
|
||||
};
|
||||
|
||||
ports = {
|
||||
web.containerPort = 9000;
|
||||
smtp.containerPort = 2500;
|
||||
|
|
|
@ -47,7 +47,7 @@ in {
|
|||
|
||||
rules = [
|
||||
{
|
||||
inherit (ingress) host;
|
||||
host = ingress.host;
|
||||
|
||||
http.paths = [
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ in {
|
|||
pathType = "Prefix";
|
||||
|
||||
backend.service = {
|
||||
inherit (ingress.service) name;
|
||||
name = ingress.service.name;
|
||||
port.name = ingress.service.portName;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -26,28 +26,16 @@
|
|||
metadata.labels.app = "kitchenowl";
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/kitchenowl";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
|
||||
containers.kitchenowl = {
|
||||
image = globals.images.kitchenowl;
|
||||
ports.web.containerPort = 8080;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
|
||||
env = {
|
||||
FRONT_URL.value = "https://boodschappen.kun.is";
|
||||
OIDC_ISSUER.value = "https://authentik.kun.is/application/o/kitchenowl/";
|
||||
OIDC_CLIENT_ID.value = "OptR5S9hPix9beuJWFdfNBWRBr2l0nPx7mj8FpB3";
|
||||
OIDC_CLIENT_SECRET.value = "ref+sops://secrets.yml#/authentik/oauth2/kitchenowl/client_secret";
|
||||
|
||||
JWT_SECRET_KEY.valueFrom.secretKeyRef = {
|
||||
name = "server";
|
||||
key = "jwtSecretKey";
|
||||
};
|
||||
env.JWT_SECRET_KEY.valueFrom.secretKeyRef = {
|
||||
name = "server";
|
||||
key = "jwtSecretKey";
|
||||
};
|
||||
|
||||
volumeMounts = [
|
||||
|
@ -85,6 +73,11 @@
|
|||
portName = "web";
|
||||
};
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim.data = {
|
||||
volumeName = "kitchenowl";
|
||||
storage = "100Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
157
modules/longhorn-volume.nix
Normal file
157
modules/longhorn-volume.nix
Normal file
|
@ -0,0 +1,157 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
longhornVolumeOpts = {name, ...}: {
|
||||
options = {
|
||||
storage = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
namespace = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "default";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
longhornPVOpts = {name, ...}: {
|
||||
options = {
|
||||
storage = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
longhornPVCOpts = {name, ...}: {
|
||||
options = {
|
||||
volumeName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
};
|
||||
|
||||
# TODO: ideally we take this from the longhornPV so we don't duplicate this information.
|
||||
storage = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
lab.longhornVolumes = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule longhornVolumeOpts);
|
||||
default = {};
|
||||
};
|
||||
|
||||
lab.longhorn = {
|
||||
persistentVolume = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule longhornPVOpts);
|
||||
default = {};
|
||||
};
|
||||
|
||||
persistentVolumeClaim = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule longhornPVCOpts);
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
kubernetes.resources = {
|
||||
persistentVolumes =
|
||||
lib.mergeAttrs
|
||||
(builtins.mapAttrs
|
||||
(name: longhornVolume: {
|
||||
spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
capacity.storage = longhornVolume.storage;
|
||||
persistentVolumeReclaimPolicy = "Delete";
|
||||
volumeMode = "Filesystem";
|
||||
|
||||
claimRef = {
|
||||
inherit name;
|
||||
namespace = longhornVolume.namespace;
|
||||
};
|
||||
|
||||
csi = {
|
||||
driver = "driver.longhorn.io";
|
||||
fsType = "ext4";
|
||||
volumeHandle = name;
|
||||
|
||||
volumeAttributes = {
|
||||
dataLocality = "disabled";
|
||||
fromBackup = "";
|
||||
fsType = "ext4";
|
||||
numberOfReplicas = "2";
|
||||
staleReplicaTimeout = "30";
|
||||
unmapMarkSnapChainRemoved = "ignored";
|
||||
|
||||
recurringJobSelector = lib.generators.toYAML {} [
|
||||
{
|
||||
name = "backup-nfs";
|
||||
isGroup = false;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
config.lab.longhornVolumes)
|
||||
(builtins.mapAttrs
|
||||
(name: longhornPV: {
|
||||
spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
capacity.storage = longhornPV.storage;
|
||||
persistentVolumeReclaimPolicy = "Delete";
|
||||
volumeMode = "Filesystem";
|
||||
|
||||
csi = {
|
||||
driver = "driver.longhorn.io";
|
||||
fsType = "ext4";
|
||||
volumeHandle = name;
|
||||
|
||||
volumeAttributes = {
|
||||
dataLocality = "disabled";
|
||||
fromBackup = "";
|
||||
fsType = "ext4";
|
||||
numberOfReplicas = "2";
|
||||
staleReplicaTimeout = "30";
|
||||
unmapMarkSnapChainRemoved = "ignored";
|
||||
|
||||
recurringJobSelector = lib.generators.toYAML {} [
|
||||
{
|
||||
name = "backup-nfs";
|
||||
isGroup = false;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
config.lab.longhorn.persistentVolume);
|
||||
|
||||
persistentVolumeClaims =
|
||||
lib.mergeAttrs
|
||||
(builtins.mapAttrs
|
||||
(name: longhornVolume: {
|
||||
spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
resources.requests.storage = longhornVolume.storage;
|
||||
storageClassName = "";
|
||||
};
|
||||
})
|
||||
config.lab.longhornVolumes)
|
||||
(builtins.mapAttrs
|
||||
(name: longhornPVC: {
|
||||
spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
resources.requests.storage = longhornPVC.storage;
|
||||
storageClassName = "";
|
||||
volumeName = longhornPVC.volumeName;
|
||||
};
|
||||
})
|
||||
config.lab.longhorn.persistentVolumeClaim);
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
utils,
|
||||
...
|
||||
}: {
|
||||
options.mealie.enable = lib.mkEnableOption "mealie";
|
||||
|
||||
config = lib.mkIf config.mealie.enable {
|
||||
kubernetes.resources = {
|
||||
deployments.mealie.spec = {
|
||||
selector.matchLabels.app = "mealie";
|
||||
|
||||
strategy = {
|
||||
type = "RollingUpdate";
|
||||
|
||||
rollingUpdate = {
|
||||
maxSurge = 0;
|
||||
maxUnavailable = 1;
|
||||
};
|
||||
};
|
||||
|
||||
template = {
|
||||
metadata.labels.app = "mealie";
|
||||
|
||||
spec = {
|
||||
nodeName = "atlas";
|
||||
|
||||
containers.mealie = {
|
||||
image = utils.mkNixNGImage "mealie";
|
||||
ports.web.containerPort = 8000;
|
||||
|
||||
env = {
|
||||
SMTP_USER.value = "ref+sops://secrets.yml#/smtp2go/username";
|
||||
SMTP_PASSWORD.value = "ref+sops://secrets.yml#/smtp2go/password";
|
||||
OIDC_CLIENT_SECRET.value = "ref+sops://secrets.yml#/authentik/oauth2/mealie/client_secret";
|
||||
};
|
||||
|
||||
volumeMounts = [
|
||||
{
|
||||
name = "mealie";
|
||||
mountPath = "/data";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
volumes.mealie.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/mealie";
|
||||
type = "Directory";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.mealie.spec = {
|
||||
selector.app = "mealie";
|
||||
|
||||
ports.web = {
|
||||
port = 80;
|
||||
targetPort = "web";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lab = {
|
||||
ingresses.mealie = {
|
||||
host = "mealie.kun.is";
|
||||
|
||||
service = {
|
||||
name = "mealie";
|
||||
portName = "web";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
File diff suppressed because it is too large
Load diff
59
modules/minecraft.nix
Normal file
59
modules/minecraft.nix
Normal file
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
globals,
|
||||
...
|
||||
}: {
|
||||
options.minecraft.enable = lib.mkEnableOption "minecraft";
|
||||
|
||||
config = lib.mkIf config.minecraft.enable {
|
||||
kubernetes.resources = {
|
||||
deployments.minecraft.spec = {
|
||||
selector.matchLabels.app = "minecraft";
|
||||
|
||||
template = {
|
||||
metadata.labels.app = "minecraft";
|
||||
|
||||
spec = {
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
|
||||
containers.minecraft = {
|
||||
image = globals.images.minecraft;
|
||||
ports.minecraft.containerPort = 25565;
|
||||
|
||||
env.EULA.value = "TRUE";
|
||||
|
||||
volumeMounts = [
|
||||
{
|
||||
name = "data";
|
||||
mountPath = "/data";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
securityContext = {
|
||||
fsGroup = 1000;
|
||||
fsGroupChangePolicy = "OnRootMismatch";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.minecraft.spec = {
|
||||
type = "LoadBalancer";
|
||||
loadBalancerIP = globals.minecraftIPv4;
|
||||
selector.app = "minecraft";
|
||||
|
||||
ports.minecraft = {
|
||||
port = 25565;
|
||||
targetPort = "minecraft";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lab.longhorn.persistentVolumeClaim.data = {
|
||||
volumeName = "minecraft";
|
||||
storage = "1Gi";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -33,12 +33,7 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "atlas";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/nextcloud";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
|
||||
containers.nextcloud = {
|
||||
image = globals.images.nextcloud;
|
||||
|
@ -106,8 +101,6 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "atlas";
|
||||
|
||||
containers.postgres = {
|
||||
image = globals.images.postgres15;
|
||||
imagePullPolicy = "IfNotPresent";
|
||||
|
@ -132,10 +125,7 @@
|
|||
];
|
||||
};
|
||||
|
||||
volumes.database.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/nextcloud-db";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.database.persistentVolumeClaim.claimName = "database";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -176,6 +166,18 @@
|
|||
host = "nextcloud";
|
||||
service.name = "server";
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim = {
|
||||
data = {
|
||||
volumeName = "nextcloud";
|
||||
storage = "50Gi";
|
||||
};
|
||||
|
||||
database = {
|
||||
volumeName = "nextcloud-db";
|
||||
storage = "400Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
metadata.labels.app = "ntfy";
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.ntfy = {
|
||||
image = utils.mkNixNGImage "ntfy";
|
||||
ports.web.containerPort = 80;
|
||||
|
@ -48,30 +46,26 @@
|
|||
};
|
||||
|
||||
volumes = {
|
||||
data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/ntfy";
|
||||
type = "Directory";
|
||||
};
|
||||
|
||||
cache.hostPath = {
|
||||
path = "/tmp/ntfy-cache";
|
||||
type = "DirectoryOrCreate";
|
||||
};
|
||||
|
||||
attachment-cache.hostPath = {
|
||||
path = "/tmp/ntfy-attachment-cache";
|
||||
type = "DirectoryOrCreate";
|
||||
};
|
||||
};
|
||||
|
||||
securityContext = {
|
||||
fsGroup = 407;
|
||||
fsGroupChangePolicy = "Always";
|
||||
cache.persistentVolumeClaim.claimName = "cache";
|
||||
attachment-cache.persistentVolumeClaim.claimName = "attachment-cache";
|
||||
data.persistentVolumeClaim.claimName = "data";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
persistentVolumeClaims = {
|
||||
cache.spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
resources.requests.storage = "300Mi";
|
||||
};
|
||||
|
||||
attachment-cache.spec = {
|
||||
accessModes = ["ReadWriteOnce"];
|
||||
resources.requests.storage = "500Mi";
|
||||
};
|
||||
};
|
||||
|
||||
services.ntfy.spec = {
|
||||
selector.app = "ntfy";
|
||||
|
||||
|
@ -91,6 +85,11 @@
|
|||
portName = "web";
|
||||
};
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim.data = {
|
||||
volumeName = "ntfy";
|
||||
storage = "300Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -36,12 +36,7 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/paperless-data";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
|
||||
containers.paperless = {
|
||||
image = globals.images.paperless;
|
||||
|
@ -62,25 +57,6 @@
|
|||
PAPERLESS_OCR_LANGUAGE.value = "nld";
|
||||
USERMAP_UID.value = "33";
|
||||
USERMAP_GID.value = "33";
|
||||
PAPERLESS_APPS.value = "allauth.socialaccount.providers.openid_connect";
|
||||
PAPERLESS_SOCIALACCOUNT_PROVIDERS.value = ''
|
||||
{
|
||||
"openid_connect": {
|
||||
"APPS": [
|
||||
{
|
||||
"provider_id": "authentik",
|
||||
"name": "Authentik",
|
||||
"client_id": "z5PlhxTB1eXJ9L39Ix2BfhLV72TbF3vbGJZUtyBJ",
|
||||
"secret": "ref+sops://secrets.yml#/authentik/oauth2/paperless-ngx/client_secret+",
|
||||
"settings": {
|
||||
"server_url": "https://authentik.kun.is/application/o/paperless-ngx/.well-known/openid-configuration"
|
||||
}
|
||||
}
|
||||
],
|
||||
"OAUTH_PKCE_ENABLED": "True"
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
PAPERLESS_DBPASS.valueFrom.secretKeyRef = {
|
||||
name = "database";
|
||||
|
@ -131,12 +107,7 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/paperless-redisdata";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "redisdata";
|
||||
|
||||
containers.redis = {
|
||||
image = globals.images.redis7;
|
||||
|
@ -181,13 +152,6 @@
|
|||
};
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/paperless-db";
|
||||
type = "Directory";
|
||||
};
|
||||
|
||||
containers.postgres = {
|
||||
image = globals.images.postgres15;
|
||||
ports.postgres.containerPort = 5432;
|
||||
|
@ -211,6 +175,8 @@
|
|||
}
|
||||
];
|
||||
};
|
||||
|
||||
volumes.data.persistentVolumeClaim.claimName = "database";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -263,6 +229,23 @@
|
|||
host = "paperless";
|
||||
service.name = "web";
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim = {
|
||||
data = {
|
||||
volumeName = "paperless-data";
|
||||
storage = "10Gi";
|
||||
};
|
||||
|
||||
redisdata = {
|
||||
volumeName = "paperless-redisdata";
|
||||
storage = "20Mi";
|
||||
};
|
||||
|
||||
database = {
|
||||
volumeName = "paperless-db";
|
||||
storage = "150Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
117
modules/pihole.nix
Normal file
117
modules/pihole.nix
Normal file
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
globals,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options.pihole.enable = lib.mkEnableOption "pihole";
|
||||
|
||||
config = lib.mkIf config.pihole.enable {
|
||||
kubernetes.resources = {
|
||||
secrets.pihole.stringData.webPassword = "ref+sops://secrets.yml#/pihole/password";
|
||||
|
||||
deployments.pihole.spec = {
|
||||
selector.matchLabels.app = "pihole";
|
||||
|
||||
strategy = {
|
||||
type = "RollingUpdate";
|
||||
|
||||
rollingUpdate = {
|
||||
maxSurge = 0;
|
||||
maxUnavailable = 1;
|
||||
};
|
||||
};
|
||||
|
||||
template = {
|
||||
metadata.labels.app = "pihole";
|
||||
|
||||
spec = {
|
||||
containers.pihole = {
|
||||
image = globals.images.pihole;
|
||||
|
||||
env = {
|
||||
TZ.value = "Europe/Amsterdam";
|
||||
PIHOLE_DNS_.value = "192.168.30.1";
|
||||
|
||||
WEBPASSWORD.valueFrom.secretKeyRef = {
|
||||
name = "pihole";
|
||||
key = "webPassword";
|
||||
};
|
||||
};
|
||||
|
||||
ports = {
|
||||
web.containerPort = 80;
|
||||
|
||||
dns = {
|
||||
containerPort = 53;
|
||||
protocol = "UDP";
|
||||
};
|
||||
};
|
||||
|
||||
volumeMounts = [
|
||||
{
|
||||
name = "data";
|
||||
mountPath = "/etc/pihole";
|
||||
}
|
||||
{
|
||||
name = "dnsmasq";
|
||||
mountPath = "/etc/dnsmasq.d";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
volumes = {
|
||||
data.persistentVolumeClaim.claimName = "pihole-data";
|
||||
dnsmasq.persistentVolumeClaim.claimName = "pihole-dnsmasq";
|
||||
};
|
||||
|
||||
securityContext = {
|
||||
fsGroup = 1000;
|
||||
fsGroupChangePolicy = "OnRootMismatch";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
pihole.spec = {
|
||||
type = "LoadBalancer";
|
||||
loadBalancerIP = globals.piholeIPv4;
|
||||
selector.app = "pihole";
|
||||
|
||||
ports = {
|
||||
dns = {
|
||||
protocol = "UDP";
|
||||
port = 53;
|
||||
targetPort = "dns";
|
||||
};
|
||||
|
||||
web = {
|
||||
port = 80;
|
||||
targetPort = "web";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lab = {
|
||||
longhorn.persistentVolumeClaim = {
|
||||
pihole-data = {
|
||||
volumeName = "pihole-data";
|
||||
storage = "750Mi";
|
||||
};
|
||||
|
||||
pihole-dnsmasq = {
|
||||
volumeName = "pihole-dnsmasq";
|
||||
storage = "16Mi";
|
||||
};
|
||||
};
|
||||
|
||||
tailscaleIngresses.tailscale-pihole = {
|
||||
host = "pihole";
|
||||
service.name = "pihole";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -25,8 +25,6 @@
|
|||
metadata.labels.app = "radicale";
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
|
||||
containers.radicale = {
|
||||
image = utils.mkNixNGImage "radicale";
|
||||
ports.web.containerPort = 5232;
|
||||
|
@ -40,10 +38,7 @@
|
|||
];
|
||||
};
|
||||
|
||||
volumes.data.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/radicale";
|
||||
type = "Directory";
|
||||
};
|
||||
volumes.data.persistentVolumeClaim.claimName = "data";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -65,6 +60,11 @@
|
|||
host = "radicale";
|
||||
service.name = "server";
|
||||
};
|
||||
|
||||
longhorn.persistentVolumeClaim.data = {
|
||||
volumeName = "radicale";
|
||||
storage = "200Mi";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
config = lib.mkIf config.syncthing.enable {
|
||||
kubernetes.resources = {
|
||||
serviceAccounts.syncthing = {};
|
||||
|
||||
deployments.syncthing.spec = {
|
||||
selector.matchLabels.app = "syncthing";
|
||||
|
||||
|
@ -24,7 +26,7 @@
|
|||
metadata.labels.app = "syncthing";
|
||||
|
||||
spec = {
|
||||
nodeName = "jefke";
|
||||
serviceAccountName = "syncthing";
|
||||
|
||||
containers.syncthing = {
|
||||
image = globals.images.syncthing;
|
||||
|
@ -43,22 +45,15 @@
|
|||
mountPath = "/config";
|
||||
}
|
||||
{
|
||||
name = "keepassxc";
|
||||
mountPath = "/keepassxc";
|
||||
name = "music";
|
||||
mountPath = "/music";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
volumes = {
|
||||
keepassxc.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/keepassxc";
|
||||
type = "Directory";
|
||||
};
|
||||
|
||||
config.hostPath = {
|
||||
path = "/mnt/longhorn/persistent/volumes/syncthing";
|
||||
type = "Directory";
|
||||
};
|
||||
config.persistentVolumeClaim.claimName = "config";
|
||||
music.persistentVolumeClaim.claimName = "music";
|
||||
};
|
||||
|
||||
securityContext = {
|
||||
|
@ -79,9 +74,21 @@
|
|||
targetPort = "web";
|
||||
};
|
||||
};
|
||||
|
||||
persistentVolumeClaims.music.spec = {
|
||||
accessModes = ["ReadWriteMany"];
|
||||
storageClassName = "";
|
||||
resources.requests.storage = "1Mi";
|
||||
volumeName = "music-syncthing";
|
||||
};
|
||||
};
|
||||
|
||||
lab = {
|
||||
longhorn.persistentVolumeClaim.config = {
|
||||
volumeName = "syncthing";
|
||||
storage = "400Mi";
|
||||
};
|
||||
|
||||
tailscaleIngresses.tailscale = {
|
||||
host = "syncthing";
|
||||
service.name = "syncthing";
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
pathType = "Prefix";
|
||||
|
||||
backend.service = {
|
||||
inherit (service) name;
|
||||
name = service.name;
|
||||
port.name = service.portName;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
ports = {
|
||||
localsecure = {
|
||||
port = 8444;
|
||||
expose.default = true;
|
||||
expose = true;
|
||||
exposedPort = 444;
|
||||
protocol = "TCP";
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
dinit.enable = true;
|
||||
init.services.atuin.shutdownOnExit = true;
|
||||
|
||||
services.atuin = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
open_registration = false;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,23 +1,9 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
{...}: {
|
||||
dinit.enable = true;
|
||||
|
||||
init.services.bazarr = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
init.services.bazarr.shutdownOnExit = true;
|
||||
|
||||
services.bazarr = {
|
||||
enable = true;
|
||||
configDir = "/config";
|
||||
};
|
||||
|
||||
users.groups.media = nglib.mkDefaultRec {
|
||||
gid = config.ids.gids.media;
|
||||
members = ["bazarr"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
nginx,
|
||||
blog,
|
||||
nixpkgs,
|
||||
nixpkgs-jellyseerr,
|
||||
nixpkgs-bazarr,
|
||||
nixpkgs-radicale,
|
||||
nixpkgs-master,
|
||||
...
|
||||
}:
|
||||
|
@ -20,9 +23,7 @@ flake-utils.lib.eachDefaultSystem (system: let
|
|||
bazarr = ./bazarr.nix;
|
||||
prowlarr = ./prowlarr.nix;
|
||||
blog = ./blog.nix;
|
||||
deluge = ./deluge.nix;
|
||||
mealie = ./mealie.nix;
|
||||
atuin = ./atuin.nix;
|
||||
generic-device-plugin = ./generic-device-plugin.nix;
|
||||
};
|
||||
in {
|
||||
nixngConfigurations = builtins.mapAttrs (name: configFile:
|
||||
|
@ -37,21 +38,16 @@ in {
|
|||
};
|
||||
|
||||
extraModules = [
|
||||
self.nixngModules.ids
|
||||
self.nixngModules.bazarr
|
||||
self.nixngModules.radicale
|
||||
self.nixngModules.jellyseerr
|
||||
self.nixngModules.radarr
|
||||
self.nixngModules.sonarr
|
||||
self.nixngModules.prowlarr
|
||||
self.nixngModules.deluge
|
||||
self.nixngModules.mealie
|
||||
self.nixngModules.atuin
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(_final: _prev: {
|
||||
(final: _prev: {
|
||||
# From master branch
|
||||
inherit (nixpkgs-master.legacyPackages.${system}) jellyseerr radicale bazarr;
|
||||
prowlarr = nixpkgs-master.legacyPackages.${system}.prowlarr;
|
||||
|
||||
# From forks
|
||||
bazarr = nixpkgs-bazarr.legacyPackages.${system}.bazarr;
|
||||
jellyseerr = nixpkgs-jellyseerr.legacyPackages.${system}.jellyseerr;
|
||||
radicale = nixpkgs-radicale.legacyPackages.${system}.radicale;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
config,
|
||||
nglib,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
dinit.enable = true;
|
||||
init.services = {
|
||||
deluged = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
|
||||
deluge-web = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
};
|
||||
|
||||
services.deluge = {
|
||||
enable = true;
|
||||
configDir = "/config";
|
||||
web.enable = true;
|
||||
};
|
||||
|
||||
users.groups.media = nglib.mkDefaultRec {
|
||||
gid = config.ids.gids.media;
|
||||
members = ["deluge"];
|
||||
};
|
||||
}
|
10
nixng-configurations/generic-device-plugin.nix
Normal file
10
nixng-configurations/generic-device-plugin.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{globals, ...}: {
|
||||
dinit.enable = true;
|
||||
init.services.generic-device-plugin.shutdownOnExit = true;
|
||||
|
||||
services.generic-device-plugin = {
|
||||
enable = true;
|
||||
settings = {
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,22 +1,9 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
nglib,
|
||||
...
|
||||
}: {
|
||||
{...}: {
|
||||
dinit.enable = true;
|
||||
init.services.jellyseerr = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
init.services.jellyseerr.shutdownOnExit = true;
|
||||
|
||||
services.jellyseerr = {
|
||||
enable = true;
|
||||
configDir = "/app/config";
|
||||
};
|
||||
|
||||
users.groups.media = nglib.mkDefaultRec {
|
||||
gid = config.ids.gids.media;
|
||||
members = ["jellyseerr"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
dinit.enable = true;
|
||||
init.services.mealie.shutdownOnExit = true;
|
||||
|
||||
services.mealie = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
DATA_DIR = "/data";
|
||||
BASE_URL = "https://mealie.kun.is";
|
||||
ALLOW_SIGNUP = "False";
|
||||
SMTP_HOST = "mail.smtp2go.com";
|
||||
SMTP_PORT = "2525";
|
||||
SMTP_FROM_NAME = "Mealie";
|
||||
SMTP_AUTH_STRATEGY = "ssl";
|
||||
SMTP_FROM_EMAIL = "mealie@kun.is";
|
||||
OIDC_AUTH_ENABLED = "True";
|
||||
OIDC_CONFIGURATION_URL = "https://authentik.kun.is/application/o/mealie/.well-known/openid-configuration";
|
||||
OIDC_CLIENT_ID = "lvkHoIPacUXjY4jr9YyEQC7YyhccOH0atbpOiKmG";
|
||||
OIDC_AUTO_REDIRECT = "True";
|
||||
OIDC_PROVIDER_NAME = "Authentik";
|
||||
OIDC_REMEMBER_ME = "True";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{...}: {
|
||||
dinit.enable = true;
|
||||
init.services.ntfy-sh.shutdownOnExit = true;
|
||||
|
||||
|
|
|
@ -1,22 +1,9 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
{...}: {
|
||||
dinit.enable = true;
|
||||
init.services.prowlarr = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
init.services.prowlarr.shutdownOnExit = true;
|
||||
|
||||
services.prowlarr = {
|
||||
enable = true;
|
||||
dataDir = "/config";
|
||||
};
|
||||
|
||||
users.groups.media = nglib.mkDefaultRec {
|
||||
gid = config.ids.gids.media;
|
||||
members = ["prowlarr"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,22 +1,9 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
{...}: {
|
||||
dinit.enable = true;
|
||||
init.services.radarr = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
init.services.radarr.shutdownOnExit = true;
|
||||
|
||||
services.radarr = {
|
||||
enable = true;
|
||||
dataDir = "/config";
|
||||
};
|
||||
|
||||
users.groups.media = nglib.mkDefaultRec {
|
||||
gid = config.ids.gids.media;
|
||||
members = ["radarr"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,22 +1,9 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
nglib,
|
||||
...
|
||||
}: {
|
||||
{...}: {
|
||||
dinit.enable = true;
|
||||
init.services.sonarr = {
|
||||
shutdownOnExit = true;
|
||||
group = lib.mkForce "media";
|
||||
};
|
||||
init.services.sonarr.shutdownOnExit = true;
|
||||
|
||||
services.sonarr = {
|
||||
enable = true;
|
||||
dataDir = "/config";
|
||||
};
|
||||
|
||||
users.groups.media = nglib.mkDefaultRec {
|
||||
gid = config.ids.gids.media;
|
||||
members = ["sonarr"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.atuin;
|
||||
cfgInit = config.init.services.atuin;
|
||||
settingsFormat = pkgs.formats.toml {};
|
||||
in {
|
||||
options.services.atuin = {
|
||||
enable = lib.mkEnableOption "atuin";
|
||||
package = lib.mkPackageOption pkgs "atuin" {};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options = {
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "The host to listen on";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8888;
|
||||
description = "The TCP port to listen on";
|
||||
};
|
||||
|
||||
open_registration = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "If true, accept new user registrations";
|
||||
};
|
||||
|
||||
db_uri = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = "A valid PostgreSQL URI, for saving history";
|
||||
};
|
||||
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "A path to prepend to all the routes of the server";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.atuin = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "atuin";
|
||||
group = lib.mkDefault "atuin";
|
||||
|
||||
script = pkgs.writeShellScript "atuin-run" ''
|
||||
${lib.getExe cfg.package} server start
|
||||
'';
|
||||
};
|
||||
|
||||
environment = {
|
||||
systemPackages = [cfg.package];
|
||||
|
||||
variables.ATUIN_CONFIG_DIR = let
|
||||
settingsFile = settingsFormat.generate "server.toml" (lib.filterAttrs (_: v: v != null) cfg.settings);
|
||||
in
|
||||
toString (pkgs.writeTextDir "server.toml" (builtins.readFile settingsFile));
|
||||
};
|
||||
|
||||
users.users.${cfgInit.user} = nglib.mkDefaultRec {
|
||||
description = "atuin";
|
||||
inherit (cfgInit) group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.atuin;
|
||||
};
|
||||
|
||||
users.groups.${cfgInit.group} = nglib.mkDefaultRec {gid = config.ids.gids.atuin;};
|
||||
};
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.bazarr;
|
||||
cfgInit = config.init.services.bazarr;
|
||||
in {
|
||||
options.services.bazarr = {
|
||||
enable = lib.mkEnableOption "bazarr";
|
||||
package = lib.mkPackageOption pkgs "bazarr" {};
|
||||
|
||||
configDir = lib.mkOption {
|
||||
description = "Where Bazarr's configuration files are stored.";
|
||||
type = lib.types.str;
|
||||
default = "/config";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.bazarr = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "bazarr";
|
||||
group = lib.mkDefault "bazarr";
|
||||
|
||||
script = pkgs.writeShellScript "bazarr-run" ''
|
||||
umask 0002
|
||||
${lib.getExe cfg.package} \
|
||||
--no-update \
|
||||
--config '${cfg.configDir}'
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
users.users.${cfgInit.user} = lib.mkIf (cfgInit.user == "bazarr") (nglib.mkDefaultRec {
|
||||
description = "bazarr";
|
||||
group = cfgInit.group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.bazarr;
|
||||
});
|
||||
|
||||
users.groups.${cfgInit.group} = lib.mkIf (cfgInit.group == "bazarr") (nglib.mkDefaultRec {gid = config.ids.gids.bazarr;});
|
||||
};
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
_: {
|
||||
nixngModules = {
|
||||
bazarr = import ./bazarr.nix;
|
||||
radicale = import ./radicale.nix;
|
||||
jellyseerr = import ./jellyseerr.nix;
|
||||
radarr = import ./radarr.nix;
|
||||
sonarr = import ./sonarr.nix;
|
||||
prowlarr = import ./prowlarr.nix;
|
||||
ids = import ./ids.nix;
|
||||
deluge = import ./deluge.nix;
|
||||
mealie = import ./mealie.nix;
|
||||
atuin = import ./atuin.nix;
|
||||
};
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.deluge;
|
||||
cfgInit = config.init.services.deluged;
|
||||
in {
|
||||
options.services.deluge = {
|
||||
enable = lib.mkEnableOption "deluge";
|
||||
package = lib.mkPackageOption pkgs "deluge-2_x" {};
|
||||
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/deluge";
|
||||
|
||||
description = ''
|
||||
Directory for Deluge's run-time configuration
|
||||
'';
|
||||
};
|
||||
|
||||
web = {
|
||||
enable = lib.mkEnableOption "Deluge web daemon";
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8112;
|
||||
description = ''
|
||||
Deluge web UI port
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services = {
|
||||
deluged = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "deluge";
|
||||
group = lib.mkDefault "deluge";
|
||||
tmpfiles = with nglib.nottmpfiles.dsl; [(d cfg.configDir "-" cfgInit.user cfgInit.group _ _)];
|
||||
|
||||
script = pkgs.writeShellScript "deluged-run" ''
|
||||
# TODO: make init-level option?
|
||||
umask 0002
|
||||
${cfg.package}/bin/deluged \
|
||||
--do-not-daemonize \
|
||||
--config ${cfg.configDir}
|
||||
'';
|
||||
};
|
||||
|
||||
deluge-web = {
|
||||
enabled = cfg.web.enable;
|
||||
dependencies = ["deluged"];
|
||||
user = lib.mkDefault "deluge";
|
||||
group = lib.mkDefault "deluge";
|
||||
|
||||
script = pkgs.writeShellScript "deluge-web-run" ''
|
||||
${cfg.package}/bin/deluge-web \
|
||||
--do-not-daemonize \
|
||||
--port ${toString cfg.web.port} \
|
||||
--config ${cfg.configDir}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment = {
|
||||
systemPackages = [cfg.package];
|
||||
variables.PYTHON_EGG_CACHE = "${config.users.users.${cfgInit.user}.home}/.cache";
|
||||
};
|
||||
|
||||
users.users.${cfgInit.user} = lib.mkIf (cfgInit.user == "deluge") (nglib.mkDefaultRec {
|
||||
description = "deluge";
|
||||
inherit (cfgInit) group;
|
||||
createHome = true;
|
||||
home = "/home/deluge";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.deluge;
|
||||
});
|
||||
|
||||
users.groups.${cfgInit.group} = lib.mkIf (cfgInit.group == "deluge") (nglib.mkDefaultRec {gid = config.ids.gids.deluge;});
|
||||
};
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
ids = {
|
||||
uids = {
|
||||
radicale = 408;
|
||||
jellyseerr = 409;
|
||||
radarr = 410;
|
||||
sonarr = 411;
|
||||
bazarr = 412;
|
||||
prowlarr = 413;
|
||||
deluge = 414;
|
||||
mealie = 415;
|
||||
atuin = 416;
|
||||
};
|
||||
|
||||
gids = {
|
||||
media = 51;
|
||||
radicale = 408;
|
||||
jellyseerr = 409;
|
||||
radarr = 410;
|
||||
sonarr = 411;
|
||||
bazarr = 412;
|
||||
prowlarr = 413;
|
||||
deluge = 414;
|
||||
mealie = 415;
|
||||
atuin = 416;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.jellyseerr;
|
||||
cfgInit = config.init.services.jellyseerr;
|
||||
in {
|
||||
options.services.jellyseerr = {
|
||||
enable = lib.mkEnableOption "jellyseerr";
|
||||
package = lib.mkPackageOption pkgs "jellyseerr" {};
|
||||
|
||||
port = lib.mkOption {
|
||||
description = ''
|
||||
The port Jellyseerr should listen on.
|
||||
'';
|
||||
type = lib.types.port;
|
||||
example = 8080;
|
||||
default = 5055;
|
||||
};
|
||||
|
||||
configDir = lib.mkOption {
|
||||
description = ''
|
||||
The directory to save run-time configuration.
|
||||
'';
|
||||
type = lib.types.str;
|
||||
example = "/jellyseerr";
|
||||
default = "/var/lib/jellyseerr";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.jellyseerr = {
|
||||
enabled = true;
|
||||
script = pkgs.writeShellScript "jellyseerr-run" ''
|
||||
umask 0002
|
||||
${lib.getExe cfg.package}
|
||||
'';
|
||||
user = lib.mkDefault "jellyseerr";
|
||||
group = lib.mkDefault "jellyseerr";
|
||||
};
|
||||
|
||||
environment = {
|
||||
systemPackages = [cfg.package];
|
||||
|
||||
variables = {
|
||||
PORT = builtins.toString cfg.port;
|
||||
CONFIG_DIRECTORY = cfg.configDir;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.${cfgInit.user} = lib.mkIf (cfgInit.user == "jellyseerr") (nglib.mkDefaultRec {
|
||||
description = "jellyseerr";
|
||||
group = cfgInit.group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.jellyseerr;
|
||||
});
|
||||
|
||||
users.groups.${cfgInit.group} = lib.mkIf (cfgInit.group == "jellyseerr") (nglib.mkDefaultRec {gid = config.ids.gids.jellyseerr;});
|
||||
};
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.mealie;
|
||||
cfgInit = config.init.services.mealie;
|
||||
in {
|
||||
options.services.mealie = {
|
||||
enable = lib.mkEnableOption "mealie";
|
||||
package = lib.mkPackageOption pkgs "mealie" {};
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = with lib.types; attrsOf str;
|
||||
|
||||
options = {
|
||||
PRODUCTION = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "true";
|
||||
};
|
||||
|
||||
DATA_DIR = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
DB_ENGINE = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = "sqlite";
|
||||
};
|
||||
|
||||
ALEMBIC_CONFIG_FILE = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = "${cfg.package}/alembic.ini";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
description = ''
|
||||
Configuration of the Mealie service.
|
||||
|
||||
See [the Mealie documentation](https://nightly.mealie.io/documentation/getting-started/installation/backend-config/) for available options and default values.
|
||||
'';
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.mealie = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "mealie";
|
||||
group = lib.mkDefault "mealie";
|
||||
|
||||
tmpfiles = with nglib.nottmpfiles.dsl; lib.optional (cfg.settings.DATA_DIR != null) (d "${cfg.settings.DATA_DIR}" "-" cfgInit.user cfgInit.group "-" _);
|
||||
|
||||
execStart =
|
||||
pkgs.writeShellScript "mealie-run"
|
||||
(let
|
||||
# Mealie can only be configured via environmental variables.
|
||||
# With this, we don't accidentally overwrite env variables set by the user.
|
||||
extraEnvLines = lib.mapAttrsToList (key: value: ''export ${key}=''${${key}:=${value}}'') cfg.settings;
|
||||
in ''
|
||||
${lib.concatStringsSep "\n" extraEnvLines}
|
||||
${cfg.package}/libexec/init_db
|
||||
|
||||
${lib.getExe cfg.package} -b 0.0.0.0:8000
|
||||
'');
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
users.users.${cfgInit.user} = nglib.mkDefaultRec {
|
||||
description = "mealie";
|
||||
inherit (cfgInit) group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.mealie;
|
||||
};
|
||||
|
||||
users.groups.${cfgInit.group} = nglib.mkDefaultRec {gid = config.ids.gids.mealie;};
|
||||
};
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.prowlarr;
|
||||
cfgInit = config.init.services.prowlarr;
|
||||
in {
|
||||
options.services.prowlarr = {
|
||||
enable = lib.mkEnableOption "prowlarr";
|
||||
package = lib.mkPackageOption pkgs "prowlarr" {};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
description = "Directory to store Prowlarr's data";
|
||||
type = lib.types.str;
|
||||
default = "/config";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.prowlarr = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "prowlarr";
|
||||
group = lib.mkDefault "prowlarr";
|
||||
|
||||
script = pkgs.writeShellScript "prowlarr-run" ''
|
||||
${lib.getExe cfg.package} \
|
||||
-nobrowser \
|
||||
-data=${cfg.dataDir}
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
users.users.${cfgInit.user} = lib.mkIf (cfgInit.user == "prowlarr") (nglib.mkDefaultRec {
|
||||
description = "prowlarr";
|
||||
group = cfgInit.group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.prowlarr;
|
||||
});
|
||||
|
||||
users.groups.${cfgInit.group} = lib.mkIf (cfgInit.group == "prowlarr") (nglib.mkDefaultRec {gid = config.ids.gids.prowlarr;});
|
||||
};
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
nglib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.radarr;
|
||||
cfgInit = config.init.services.radarr;
|
||||
in {
|
||||
options.services.radarr = {
|
||||
enable = lib.mkEnableOption "radarr";
|
||||
package = lib.mkPackageOption pkgs "radarr" {};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/radarr/.config/Radarr";
|
||||
description = "The directory where Radarr stores its data files.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.radarr = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "radarr";
|
||||
group = lib.mkDefault "radarr";
|
||||
|
||||
script = pkgs.writeShellScript "radarr-run.sh" ''
|
||||
umask 0002
|
||||
${lib.getExe cfg.package} -nobrowser -data='${cfg.dataDir}'
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
users.users.${cfgInit.user} = lib.mkIf (cfgInit.user == "radarr") (nglib.mkDefaultRec {
|
||||
description = "radarr";
|
||||
inherit (cfgInit) group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.radarr;
|
||||
});
|
||||
|
||||
users.groups.${cfgInit.group} = lib.mkIf (cfgInit.group == "radarr") (nglib.mkDefaultRec {gid = config.ids.gids.radarr;});
|
||||
};
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
nglib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.radicale;
|
||||
cfgInit = config.init.services.radicale;
|
||||
|
||||
settingsFormat = pkgs.formats.ini {
|
||||
listToValue = lib.concatMapStringsSep ", " (lib.generators.mkValueStringDefault {});
|
||||
};
|
||||
in {
|
||||
options.services.radicale = {
|
||||
enable = lib.mkEnableOption "radicale";
|
||||
package = lib.mkPackageOption pkgs "radicale" {};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = {};
|
||||
|
||||
description = ''
|
||||
Configuration for Radicale. See
|
||||
<https://radicale.org/v3.html#configuration>.
|
||||
'';
|
||||
|
||||
example = lib.literalExpression ''
|
||||
server = {
|
||||
hosts = [ "0.0.0.0:5232" "[::]:5232" ];
|
||||
};
|
||||
auth = {
|
||||
type = "htpasswd";
|
||||
htpasswd_filename = "/etc/radicale/users";
|
||||
htpasswd_encryption = "bcrypt";
|
||||
};
|
||||
storage = {
|
||||
filesystem_folder = "/var/lib/radicale/collections";
|
||||
};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (let
|
||||
configFile = settingsFormat.generate "radicale.ini" cfg.settings;
|
||||
in {
|
||||
init.services.radicale = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "radicale";
|
||||
group = lib.mkDefault "radicale";
|
||||
|
||||
script = pkgs.writeShellScript "radicale-run" ''
|
||||
${cfg.package}/bin/radicale \
|
||||
--config ${configFile}
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
users.users.${cfgInit.user} = nglib.mkDefaultRec {
|
||||
description = "radicale";
|
||||
group = cfgInit.group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.radicale;
|
||||
};
|
||||
|
||||
users.groups.${cfgInit.group} = nglib.mkDefaultRec {gid = config.ids.gids.radicale;};
|
||||
});
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
nglib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.sonarr;
|
||||
cfgInit = config.init.services.sonarr;
|
||||
in {
|
||||
options.services.sonarr = {
|
||||
enable = lib.mkEnableOption "sonarr";
|
||||
package = lib.mkPackageOption pkgs "sonarr" {};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/sonarr/.config/NzbDrone";
|
||||
description = "The directory where Sonarr stores its data files.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
init.services.sonarr = {
|
||||
enabled = true;
|
||||
user = lib.mkDefault "sonarr";
|
||||
group = lib.mkDefault "sonarr";
|
||||
tmpfiles = with nglib.nottmpfiles.dsl; [(e "${cfg.dataDir}/logs" "-" cfgInit.user cfgInit.group "7d" _)];
|
||||
|
||||
script = pkgs.writeShellScript "sonarr-run" ''
|
||||
umask 0002
|
||||
${lib.getExe cfg.package} -nobrowser -data=${cfg.dataDir}
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = [cfg.package];
|
||||
|
||||
users.users.${cfgInit.user} = lib.mkIf (cfgInit.user == "sonarr") (nglib.mkDefaultRec {
|
||||
description = "sonarr";
|
||||
inherit (cfgInit) group;
|
||||
createHome = false;
|
||||
home = "/var/empty";
|
||||
useDefaultShell = true;
|
||||
uid = config.ids.uids.sonarr;
|
||||
});
|
||||
|
||||
users.groups.${cfgInit.group} = lib.mkIf (cfgInit.group == "sonarr") (nglib.mkDefaultRec {gid = config.ids.gids.sonarr;});
|
||||
};
|
||||
}
|
|
@ -13,11 +13,6 @@ if [ -z "$username" ] || [ -z "$host" ]
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$output_path" ]; then
|
||||
echo "Output directory $output_path does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a temporary directory
|
||||
temp=$(mktemp -d)
|
||||
|
||||
|
|
36
secrets.yml
36
secrets.yml
|
@ -1,14 +1,11 @@
|
|||
freshrss:
|
||||
password: ENC[AES256_GCM,data:ECDPrW+VgO8PY9p2fLIreRETNiRL5ZGnu/PMC7aNj8KaWfyNYL+l3w==,iv:srR/r1EtOpC/CKKrCDKcTLVdMFPAYIJIB1CCg8mS0UU=,tag:YN4PqR5uvPkVskpJWD+91g==,type:str]
|
||||
oidc_crypto_key: ENC[AES256_GCM,data:dFQKZtFVd5l8W2go6WcK76o7O7hpQWnQKXCGTf9EhSVURvWigv6zzBULie7Y4lkJCsItG8oKmIiCYSy3MhFnU3DJTUJcenm4I7NHyINjvzHOBgUVPXbYQjQhouJwOlPkdqlSKv1f38ItZKNPJebMObZj+kACKbjdik6e6yM40RM=,iv:g6Ygval2qTQwKnrliI+n/r9OxJFePT9MKYyBLU6b3UQ=,tag:kWXTbm2JIR5aL/s4OX2Tqg==,type:str]
|
||||
pihole:
|
||||
password: ENC[AES256_GCM,data:MA60825Tl6aYEFVoPgo8k5Vjb9zmIxtPLJriQV1B3P1bOKu1KK7vxQ==,iv:RGZHox8CbJiEEEjMo2k/tNbtjCPy/QY7vOuMN/YNZcg=,tag:yphrq03IKpXM/tSDBLeSgA==,type:str]
|
||||
hedgedoc:
|
||||
databaseURL: ENC[AES256_GCM,data:6+IV4TaClIGE1XVkUf7JwXzqx3EvWiIKFx9X5x7QKvQKC7bIieD1ADVeAMQmiQfibnH/YV5TgjNY8Ft+3eX881c3yD+2j7mM+O1fX6taK/BCokDnqhIwTN2qxHsu+mrPcM/Pgg5Zqy8HvUgX8jM=,iv:bCwuNk5CVgK2T5IgLebcKwxwloi6FkWMWhnxwJek1GM=,tag:UDQ0KmRDVlDh35Fjm6eaAA==,type:str]
|
||||
sessionSecret: ENC[AES256_GCM,data:7FdRjAShjjue1fFwizCgK+94mkbT4ohAPxdyn/8Z8/f2nvGWPZHO/hGexOixbRGLPewJSaMunTMeJL+IzFlGlg==,iv:iz7640b8Mlb6mNps20b+TbphWDEFUbKwKNUXc0kR5NY=,tag:fdEr1tbes1h8VCA/q+0sOw==,type:str]
|
||||
databasePassword: ENC[AES256_GCM,data:wdRhCluNx2IzgDqouAoIcG6yOWwNLOaEkpqgYEeFvJDZsMC8OUuV7Q==,iv:Csut0c+LRKWD2b4uVuQpGnwwVqnGT6Sk6T/ODlH57Bk=,tag:7bS6a18GyRifq2D6cIheaw==,type:str]
|
||||
oidc:
|
||||
client_secret:
|
||||
password: ENC[AES256_GCM,data:rLkMFkEzCF3+ejGAUliaBMpfOrxL5b3pJVvkblEFIvHupmr9DTS71L4T6/oo616E4IoCuZxqKh0FxhdWZRM4KrEk5YZMbgp9,iv:TbySrCTY+Kps4v/q5maQglm4aOzuUPch2ECBHPp4FYc=,tag:mz71m6JqIemVCypf93hkBQ==,type:str]
|
||||
digest: ENC[AES256_GCM,data:m+abt7SEXZoeOA+ioB3BmiWN09CDpCWdZ5eNRhShvuUJW7rjbSJAQ2NTZkMTnFoNv6PO6rSUD6lmStFfO/mqVUFvWXBBDMK3xK+ILcgDoZZ1Pnmr19noqTL5OxyYLAtUHRNOohsUBYlZKyv2lFNQlqxk6kOi+fUPitmmsO6BO1nrq2s=,iv:CmC0JLXuT9O29Rtu7Pp8i0h/SyaEAT0bsXQb2LRFAkk=,tag:/IL39BCMuw+bqxv2OaNwhw==,type:str]
|
||||
nextcloud:
|
||||
databasePassword: ENC[AES256_GCM,data:jRLgW96FnMEpU0T5z/iQOX/CgjpH2ZykZGd1qGFHK8o=,iv:YrY9IsrlCaiQ8BFYqu+UnOxnvvB/JN4iYfy3vMa3wcw=,tag:41iWc4iVqjdUr02O5CLu7g==,type:str]
|
||||
paperless:
|
||||
|
@ -32,29 +29,6 @@ immich:
|
|||
tailscale:
|
||||
clientID: ENC[AES256_GCM,data:O8tTyy55xP85JkbJNR5daB4=,iv:SMj83Sxh7BvPRG3l5TnnpmclO5N2treUQCCJuMy8cO8=,tag:UUSN3bsZvb09cyYN65RQDg==,type:str]
|
||||
clientSecret: ENC[AES256_GCM,data:c8E/a7McI+wGN9TFJ/yzTSkrhUlISmrNJdjDDMqAQrZ8s5wFEZ+4+h+dtwcjF9Ykj198glgny7cP3HubHVDw,iv:ifaP4NmLRQbYQtJQaMMCMaehosapZ2R3im9ew5h6f9E=,tag:XF+xB94nua8RZlkGxFDFFQ==,type:str]
|
||||
authentik:
|
||||
secret_key: ENC[AES256_GCM,data:bbEEpymADAGY/fDNMU7FfzveyK2SBUBCitQLN85tB5C5u32PRsRnOa2MDjKGU4kArnyV/WtJQXT4HJ//nMLVh53Q8BYclWYYVFourEjaajTixkZ2gkAfcMJ1mMaQG09ylrwMhLsZWbeaLFzW6dfPSQOCchvj3VhgvJSXuhNmr90=,iv:aE/DGt/yd9wL5qlWfdyT/9SIsCj7U3GcljArcGIdh9k=,tag:CVeiZITOJ71/jdLzjZjteA==,type:str]
|
||||
postgresql_password: ENC[AES256_GCM,data:4okPqDzPDnx7ZBFQV2Jtk6SEHTskRd2GVG4XLdpMQrgivKsuhQJf1QAnCWHrjmtg74xdlUy2TdPwTWGd5UiM1G90GwHSzLPSJt6X0IFMxCuq/eyYYbD9w8Wk1pVuvqoluPcjN6WoRJdCzap1QITih8B+oSkTJ/rk84xczsjah4U=,iv:r0dYWcsIqdH8FGuBd2dxAJ1AjRmk6k4QYKq0cnZITk4=,tag:errORaXgO7yJW7ERbmdtRg==,type:str]
|
||||
oauth2:
|
||||
freshrss:
|
||||
client_secret: ENC[AES256_GCM,data:e7wdwWRS8KivGkcWaMgSrUEEuOTHzj1oim+qUcLD35/DA/V6itM2XqVPhqIOXHrf6pOyYgprEv14bEx8zUvtT6iXV4fsEUEWeWTgt4NI3YULtx/t0yVDq9Zc8fN9cIqGxGeig1mcQwmm7vByq58mNJEpcfz46swjN2ATf/CPJQs=,iv:xeNgSKd+g4ne8NLw/2KQjTXSvNkqezOhMn5niuWpD38=,tag:ElOUMg0oZ+q15hCgh/Mzug==,type:str]
|
||||
hedgedoc:
|
||||
client_secret: ENC[AES256_GCM,data:hdNQzatO6Pf6mxvfO4h1XrhycKMBUHElEwacGttzByi4JDbIndAwYc2GXdwUmytPMYs/s+lVjcdHhspUFWS01DETWQfnWm/GN73GzW18uj3XyRXqt62HhMf18GvRlOWkGX+jYpUTGGoonYes2xijhD/mNCjxKk5Q+6FVFT2mdJ4=,iv:pScEX6YnoU7HelxmCes8A9vJjPdvFbqbclHYMme8OOE=,tag:FURxphI8IDMvOwB4ahD8hg==,type:str]
|
||||
paperless-ngx:
|
||||
client_secret: ENC[AES256_GCM,data:GgF+gQt8olzKUzGMDL6mh6UWDv49OPDH5tB/gboWkFd7Njc1SrSkqf71gQryOcPQ0vpXrh0nK1z6ZjMpmDEA5ohTwWymeLCgwNtJSAMHZ1VlZ2aQZr70r3KtAxKjmTiT5flUYnxS79fCF43BveSMGeAshRCvQmYCdi43sP2E4To=,iv:DzsIRPiMzxaqVrjaHMVKWgOR0asZQzWf8EE1nxRSJmk=,tag:79bo7EzVq9tvL6ap6jfV+Q==,type:str]
|
||||
forgejo:
|
||||
client_secret: ENC[AES256_GCM,data:I0LBIrsPuARFEcvu0sKhIbkEYxLhZrwpRfPls3KDARu5rnfwgbJ6AVtfMmcAIM9ISFzXykoyMXossHo1i23N90PsHdl2t580EffhJ+q/UUfCIk7/rX/6CXlcb8WHdab4ymN5r9jEsgD3mAWX55IehU96ZKGRKRhxSIowCIYRhyQ=,iv:1wQDGCDhSu0s+IqXULiHmRiKGTLRvOjwsYaNMCWfkjg=,tag:p1mwks0KP9lhbciTIv3/Dw==,type:str]
|
||||
immich:
|
||||
client_secret: ENC[AES256_GCM,data:KrsaLLsjfQsyNQzvQF/pCLj1dhi8tr/OdToY7WczvPUUQKMtSk//oxsiPike/HoVEuCUp+j7UlTfIRPF2xUcPPvw7pkcLhQhcot79aieI1ciIeLZ1Q5svsPrqDBmDY7g65jkzA9vjM9VLTsx4Dx/1vGHDqo7I12qadEQlKAuhhQ=,iv:3icAM7sVe2HlmosbP7VPbcF4SRz/mlbzdQ1gENR9TRs=,tag:O8TCN7NltNpDGoG3T8Ds1w==,type:str]
|
||||
nextcloud:
|
||||
client_secret: ENC[AES256_GCM,data:zLejYbfudK/4OquLXPYTv9YOmFpCVfg0KLNkDSDCpFrxroDUAXBCLtYXiGuYkYrD/t7LAzRt+OTq70d7ciuHhBNSLclP2U97BQoXCWscWnxQauRZ+UCABvP+DB9VPQmCwU+uKPrKQ8l51baj+MkpIDdk2lwavpONMU57Zov6N2o=,iv:aQ4bsXUXn177tCxe1kAsSMP9ynEzvDwN0hwFhrT3Nko=,tag:EFcnf6VmyFt2i4+aL56sWw==,type:str]
|
||||
kitchenowl:
|
||||
client_secret: ENC[AES256_GCM,data:x4Xsd3d3El59HKBYNV56ah314hYSRhzt46upW34cOopXNHSB3zCDrD46LUa6i8g6V5GJyrMpMfO5mv+b80JrmfHkhGUXZXuTwDNu6ijnO6ZCvC2Bdlo+T0tlkJe25OMCBseJkkC++UBrpKQQTAhyVjnPSVrGVvtY4WtdAw+X/OY=,iv:pOowIhPD7kb2F3ylFzLwNW3BhPZyzoFCGRm2+KCmhno=,tag:GxFI0w06EyGxFwj6Fv4ZLQ==,type:str]
|
||||
mealie:
|
||||
client_secret: ENC[AES256_GCM,data:VNEV8a1KZc6XVeRzyBWzuwldTmxEepPRUOEMEM3HKrDIkxcGHDuoLh5P7Ti+jS5rbmua+ET4GPcJTYXR+pO5/cMaxqFONj1D1w9541QPYZNBbTfPM/Zfu8OnzngVsCnnKEtu1bVwflUnmf7F5hHED8zJRe1F9PT/HYA6NCd4ajQ=,iv:58ysTItP8UNnQWwgWRS1dk/K/2dJv3P5wa5rGnz2P/I=,tag:vLGrFldzOey9ANW010GylA==,type:str]
|
||||
smtp2go:
|
||||
username: ENC[AES256_GCM,data:BEr7Rq7rlGvfYEpY/ZXnhM2eClnHdqU81A==,iv:dwYD5h+C5bzS9ikUgxQ51+jRQ32TtDy2PhDbd1tpS8Q=,tag:CjjLDz5n4H28qi8jWf9S4w==,type:str]
|
||||
password: ENC[AES256_GCM,data:Yys6qy6DRYo16+X+Uj9oa9otjaKBnHOtIQ==,iv:G7H9mxsODShFoVlNMwuV8O18NBG/7LTFDFdqnH83YkE=,tag:hSlYp27QMoPZwiKBqyOpKA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
|
@ -79,8 +53,8 @@ sops:
|
|||
azR0UkJyL0RwUVk4ZzdkSWptcDlWVjAK5FU9B5TBSnV3azO4eCv13T6i3dGGuI68
|
||||
UgBrVEb1/Fv+4XTjeSEhpiOaH8sNWYoNa3Aa7uTZYlHDRWga2GC7zw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-05-26T20:32:01Z"
|
||||
mac: ENC[AES256_GCM,data:si28Fu1crF2mYYCJAgN95+G8iJkn4T9wF0Itpi+5cjoSZ2ebxm2wWnVLQ9PwLIkHVF7nNbQM4fWy3eGIWWpexW6ReEc/aGJBLM0L4ho7iFaO1tzWEa5nTyz3QQH8kap1xvqEYgwH9EDkblc4gFpCUDnYbBt9lNcRCZ3JzeYoPxQ=,iv:QHsvuyCCn+9oe5ZQJi2/qDtV7Z2N4JMfqXUEqJkzKH4=,tag:2NGB4VR5bPEZmIC/lYX2VQ==,type:str]
|
||||
lastmodified: "2024-12-01T13:22:41Z"
|
||||
mac: ENC[AES256_GCM,data:6UqmxHJC4KWsiQttXFEEG1opPcrGntYj9nlD8m0iBqjc9g/SHxEogpaiYEnriGNXGw0HhRWjrd+JX29Ht4xVeiYqthYX+4rVuIuv+SI7p08hJeIBbIYrfonAJsebbSsynuy9YgyUkNZhoqjZTtuzFU/c4Dh5453RVnuQmu4PZNs=,iv:yA//mqJ0Ft63eRME8A1HBiZ/B0gcVYlS4MaP0LykooU=,tag:0NxU0lVi67N34eDhsT82kQ==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.9.4
|
||||
version: 3.9.1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue