Compare commits

..

70 Commits

Author SHA1 Message Date
John Lancaster
fbda875a6f restructuring for new nix-home flake 2025-06-16 14:05:08 -05:00
John Lancaster
83db5f51ce renamed git-hooks to silence warning 2025-06-02 09:56:35 -05:00
John Lancaster
a501d9f4b1 flake updates 2025-06-02 09:54:39 -05:00
John Lancaster
d88c8f4807 updated workspace settings 2025-04-09 22:19:57 -05:00
John Lancaster
acca27b76c changed ads aliased 2025-04-09 22:19:49 -05:00
John Lancaster
4434093128 added some utilities 2025-04-04 01:15:38 -05:00
John Lancaster
07d1bd6e06 moved gh 2025-04-04 01:04:23 -05:00
John Lancaster
1c27e2f318 renamed home-manager module for import 2025-04-04 00:52:02 -05:00
John Lancaster
e73e22d0b5 fixes for zsh 2025-04-04 00:08:52 -05:00
John Lancaster
feae94f042 flake.lock update 2025-04-03 23:57:29 -05:00
John Lancaster
dc608152f7 added some build scripts 2025-04-03 23:57:23 -05:00
John Lancaster
445e08a771 added namespaces to restic ignore 2025-04-03 23:57:00 -05:00
John Lancaster
1c9f2b54df added zsh 2025-04-03 23:56:48 -05:00
John Lancaster
2e8306c281 lots of python/ruff settings 2025-03-20 19:11:04 -05:00
John Lancaster
e522024eb9 flake update 2025-03-20 18:47:07 -05:00
John Lancaster
faa8df37fc flake.lock update 2025-03-11 23:27:56 -05:00
John Lancaster
229ab0ea80 added space optimization stuff 2025-03-10 21:56:30 -05:00
John Lancaster
7c55d2875c flake.lock update 2025-03-10 21:49:05 -05:00
John Lancaster
398ec0f0f3 comment 2025-03-10 21:48:58 -05:00
John Lancaster
670c1972c5 tweaked loki host in promtail, unverified 2025-03-10 21:48:53 -05:00
John Lancaster
3bd35e7a53 sops tweaks 2025-02-17 01:55:25 -06:00
John Lancaster
4e69da43c9 Update flake.lock 2025-02-17 01:45:17 -06:00
John Lancaster
11bfe1baac Update flake.lock 2025-02-17 01:44:19 -06:00
John Lancaster
bf6c231d1f added https 2025-02-17 01:13:14 -06:00
John Lancaster
f0dd952341 fleshed out restic stuff 2025-02-17 01:13:04 -06:00
John Lancaster
50a4c72a67 updated flake.lock 2025-02-17 00:37:11 -06:00
John Lancaster
cc63f0ae04 updated loki url 2025-02-17 00:37:04 -06:00
John Lancaster
47c1567a15 formatting 2025-02-17 00:36:55 -06:00
John Lancaster
bca14b7326 added restic 2025-02-17 00:36:47 -06:00
John Lancaster
895a9f18b1 flake.lock update 2025-02-15 01:46:14 -06:00
John Lancaster
108c6dec41 flake.lock update 2025-02-07 00:38:29 -06:00
John Lancaster
5fc68dc852 updated flake lock 2025-01-31 19:02:47 -06:00
John Lancaster
a327c6c6c9 added ad-test repo to workspace 2025-01-31 19:02:40 -06:00
John Lancaster
5a4bd85e11 flake.lock update 2025-01-27 17:33:22 -06:00
John Lancaster
c57176dff5 updated lock file 2025-01-25 09:58:50 -06:00
John Lancaster
9725b50d70 changed PS1 2025-01-25 09:51:41 -06:00
John Lancaster
2c4b842446 added gdbm to packages 2025-01-25 09:51:25 -06:00
John Lancaster
550150fdd2 added ad-nb command from inside the devenv shell 2024-12-29 18:31:54 -06:00
John Lancaster
5ce8581135 workspace update 2024-12-29 18:19:54 -06:00
John Lancaster
04e5776d02 safer link 2024-12-29 18:14:00 -06:00
John Lancaster
ae002a4370 added crontab for auto updating 2024-12-29 16:57:36 -06:00
John Lancaster
2f219876ba changed python version and added gdbm for namespaces 2024-12-29 16:33:01 -06:00
John Lancaster
f93614daf8 readme tweak 2024-12-29 16:32:34 -06:00
John Lancaster
a9247ba1a5 improved startup script 2024-12-29 15:41:55 -06:00
John Lancaster
f662da1ad2 renamed file 2024-12-29 15:22:10 -06:00
John Lancaster
52c7e3d9c4 opened up sops regex 2024-12-29 15:07:12 -06:00
John Lancaster
75baa6744c secrets updates 2024-12-29 14:50:35 -06:00
John Lancaster
1020239659 readme updates 2024-12-29 14:34:20 -06:00
John Lancaster
a647982b37 enabled services 2024-12-29 14:30:01 -06:00
John Lancaster
44a817e5ab readme update 2024-12-29 14:25:57 -06:00
John Lancaster
fd2563549d bootstrap instructions 2024-12-29 14:21:36 -06:00
John Lancaster
3a004e9251 comment 2024-12-29 14:14:51 -06:00
John Lancaster
b8cba0a5b2 fixed services 2024-12-29 14:12:53 -06:00
John Lancaster
2687c755a3 readme update 2024-12-29 13:59:37 -06:00
John Lancaster
f6c72142ef sops-ad 2024-12-29 13:59:31 -06:00
John Lancaster
321b5f7e3c home dir updates 2024-12-29 13:47:27 -06:00
John Lancaster
a8c4b75eb1 pruned 2024-12-29 13:31:55 -06:00
John Lancaster
26307a04d1 moved option to home manager 2024-12-29 13:31:48 -06:00
John Lancaster
f2d91f4e36 added user home setup 2024-12-29 13:30:38 -06:00
John Lancaster
e8aee82c00 more notes 2024-12-29 13:30:30 -06:00
John Lancaster
4a9bee71ae workspace updates 2024-12-29 10:16:11 -06:00
John Lancaster
1bad54c7a2 broke out scripts folder 2024-12-29 10:16:04 -06:00
John Lancaster
30fcca3624 more notes 2024-12-29 00:11:51 -06:00
John Lancaster
8321b440ed more objectives 2024-12-28 23:55:42 -06:00
John Lancaster
1a3dcb516a jupyter works through uv command in devenv shell 2024-12-28 23:54:16 -06:00
John Lancaster
77098ae071 fixed trailing whitespace 2024-12-18 00:57:33 -06:00
John Lancaster
e80a85c490 big refactor 2024-12-18 00:52:36 -06:00
John Lancaster
f36c1b1188 tweak 2024-12-17 01:15:35 -06:00
John Lancaster
7216a90f90 added some debug scripts 2024-12-17 01:09:22 -06:00
John Lancaster
d0544a89ff converted to flakes and implemented sops-nix for the telegraf token 2024-12-17 00:56:38 -06:00
23 changed files with 756 additions and 225 deletions

5
.gitignore vendored
View File

@@ -1,2 +1,5 @@
git.nix # git.nix
*.env *.env
.devenv
*.log

9
.sops.yaml Normal file
View File

@@ -0,0 +1,9 @@
keys:
- &1password age197d424aa7jpj2s735fl2h2s4c687y8vm44usx8wag0r2kh2v7ces4efdyn
- &lola-ad age1qf4c4asf7wcqqyd9aju8fq9dvum4ptcqr8dd6xqengsf6jx7daqqtgup30
creation_rules:
- path_regex: yaml$
key_groups:
- age:
- *1password
- *lola-ad

View File

@@ -1,15 +1,91 @@
NixOS Configuration for AppDaemon Development # NixOS Configuration for AppDaemon Development
Needs a `git.nix` file. Example below: ## Objectives
- SSH remote with VSCode
- Debugger must work
- Multiple dev versions (different branches, forks)
- Multiple config directories - deployment and test
- `devenv`-based workflow
- Shell
- Makes `uv` available
- Syncs `devenv` virtual environment
- `appdaemon`
- Build Docker
- Use flakes
- Jupyter through VSCode
- `autoreload` must work with editable install of the dev version
- could always work in a dev container
- Observation - telegraf/promtail
- Utility - portainer, watchtower
## Usage
### `nfs`
Used to rebuild the `ad-nix` system with whatever is currently symlinked to `/etc/nixos`
### `ads`
Used to enter the development shell. Be careful, as this will create a `.devenv` directory and venv wherever it's entered.
### venv
`.devenv/state/venv/bin/python`
Used in VSCode for type hints, running, and debugging
### Jupyter
- Install devenv kernel - might not be useful?
- `python -m ipykernel install --user --name devenv --display-name "Python (devenv)"`
- Run jupyter notebook on the side with a `uv run jupyter notebook` command
- Use the link with the token to connect the jupyter notebook kernel to it
## Mechanics
### SSH Connection
SSH keys are pre-authorized from `secrets/authorized_keys` which contains the public keys for desktop, laptop, and phone.
### SOPS
- `secrets/secrets.yaml` contains the encrypted keys.
- There needs to be a `~/.config/sops/age/keys.txt` file with the age secret key. This file has to be manually placed.
- `.sops.yaml` indicates to SOPS that the yaml file is encrypted with that secret key.
- `sops-ad` is a convenience script for editing the secrets.yaml file.
## Setup
### Bootstrapping
SSH in to the host as root and get into a shell with `git`.
```shell ```shell
{ ... }: nix-channel --update && nix-shell -p git
{ ```
programs.git = {
enable = true; Then build the system from the flake
extraConfig.credential.helper = "store --file ~/.git-credentials";
userName = "John Lancaster"; ```shell
userEmail = "32917998+jsl12@users.noreply.github.com"; nixos-rebuild switch --flake git+https://gitea.john-stream.com/john/ad-nix#ad-nix --impure
}; ```
}
### Secrets
During build time `/etc/ssh/ssh_host_ed25519_key` automatically gets imported as an age key. If that fingerprint is included in the `.sops.yaml` file, then `secrets/secrets.yaml` can be decrypted during the build. Otherwise `~/.config/sops/age/keys.txt` needs to already be populated.
`secrets/secrets.yaml` needs to be edited from the terminal. There's a `sops-ad` command for convenience. The following keys are required:
- `telegraf_influx_token`
`~/.config/sops/age/keys.txt` needs to be set for the `sops-ad` command to work.
### Tailscale
Needs this in the `/etc/pve/lxc/<vmid>.conf` file on the proxmox host.
```
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
``` ```

View File

@@ -1,19 +1,74 @@
{ {
"folders": [ "folders": [
{ {
"path": "/usr/src/app" "path": "/home/appdaemon/ad-lola"
}, },
{ {
"path": "/conf" "path": "/conf/lola"
}, },
{ {
"path": "/srv/appdaemon/snippets" "path": "/home/appdaemon/ad-nix"
}, },
{ {
"path": "/srv/appdaemon/ad-nix" "path": "/home/appdaemon/ad-test"
}, },
], ],
"settings": { "settings": {
"python.defaultInterpreterPath": "/usr/src/app/.venv/bin/python3" // Python
"[python]": {
"editor.autoClosingDelete": "always",
"editor.autoClosingBrackets": "always",
"editor.defaultFormatter": "charliermarsh.ruff",
// "editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports.ruff": "explicit",
// "source.fixAll": "explicit"
}
},
"python.defaultInterpreterPath": "${workspaceFolder}/.devenv/state/venv/bin/python3",
"python.autoComplete.extraPaths": ["~/ad-lola", "${fileWorkspaceFolder}/apps/room_control/src"],
"python.analysis.extraPaths": ["~/ad-lola", "${fileWorkspaceFolder}/apps/room_control/src"],
"python.analysis.autoFormatStrings": true,
"python.analysis.completeFunctionParens": true,
"python.analysis.autoImportCompletions": true,
"python.analysis.importFormat": "relative",
"python.analysis.autoIndent": true,
"python.analysis.useLibraryCodeForTypes": true,
"python.analysis.languageServerMode": "full",
"python.analysis.typeEvaluation.enableReachabilityAnalysis": true,
"python.languageServer": "Pylance",
"python.terminal.shellIntegration.enabled": true,
// Ruff settings
"ruff.enable": true,
"ruff.organizeImports": true,
"ruff.importStrategy": "fromEnvironment",
"ruff.nativeServer": true,
"ruff.configurationPreference": "filesystemFirst",
"ruff.configuration": "${workspaceFolder}/pyproject.toml",
"ruff.fixAll": true,
"ruff.lint.enable": true,
// https://docs.astral.sh/ruff/rules/
"ruff.lint.extendSelect": [
"F", "W", "I",
"E1", "E2", "E3", "E4", "E5", "E7", "E9"
],
// Notebooks
// "jupyter.askForKernelRestart": false,
"notebook.defaultFormatter": "charliermarsh.ruff",
"notebook.formatOnSave.enabled": true,
"notebook.codeActionsOnSave": {
"notebook.source.fixAll": "explicit",
"notebook.source.organizeImports": "explicit"
},
"editor.rulers": [120],
"editor.wordWrap": "on",
"editor.wordWrapColumn": 120,
// https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
// https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
} }
} }

View File

@@ -1,78 +0,0 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
devenv.url = "github:cachix/devenv";
nixpkgs-python = {
url = "github:cachix/nixpkgs-python";
inputs = { nixpkgs.follows = "nixpkgs"; };
};
};
nixConfig = {
extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
extra-substituters = "https://devenv.cachix.org";
};
outputs = { self, nixpkgs, devenv, ... } @ inputs:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
adPath = "/usr/src/app";
in
{
packages.${system} = {
devenv-up = self.devShells.${system}.default.config.procfileScript;
devenv-test = self.devShells.${system}.default.config.test;
};
devShells.${system}.default = devenv.lib.mkShell {
inherit inputs pkgs;
modules = [
({ pkgs, config, ... }: {
# This is your devenv configuration
pre-commit.hooks = {
end-of-file-fixer.enable = true;
trim-trailing-whitespace.enable = true;
};
languages.python = {
enable = true;
version = "3.12.7";
uv = {
enable = true;
sync = {
enable = true;
allExtras = true;
arguments = [ "-U" ];
};
};
};
packages = with pkgs; [
git
(writeShellScriptBin "full-build" ''
cd ${adPath}
${pkgs.uv}/bin/uv build --wheel
docker build -t acockburn/appdaemon:local-dev ${adPath}
'')
];
enterShell = ''
alias appdaemon="${pkgs.uv}/bin/uv run --frozen python -m appdaemon"
alias ad="appdaemon"
export PS1="\[\e[0;34m\](AppDaemon)\[\e[0m\] ''${PS1-}"
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
echo -e "URL: \e[34m$(${pkgs.git}/bin/git config --get remote.origin.url)\e[0m"
echo -e "Branch: \e[32m$(${pkgs.git}/bin/git rev-parse --abbrev-ref HEAD)\e[0m"
echo -e "Hash: \e[33m$(${pkgs.git}/bin/git rev-parse --short HEAD)\e[0m"
echo "AppDaemon v$(${pkgs.uv}/bin/uv pip show appdaemon | awk '/^Version:/ {print $2}') development shell started"
'';
})
];
};
};
}

View File

@@ -1,50 +1,36 @@
{ pkgs, lib, modulesPath, ... }: { pkgs, lib, userSettings, systemSettings, ... }:
let
stateVersion = "24.05";
unstable = import <nixos-unstable> {};
adHome = "/srv/appdaemon";
adNixPath = "${adHome}/ad-nix";
adPath = "/usr/src/app";
adRepo = "https://github.com/jsl12/appdaemon";
adBranch = "hass";
in
{ {
imports = [ imports = [
(modulesPath + "/virtualisation/proxmox-lxc.nix") (import ./home-manager {inherit systemSettings userSettings lib pkgs;})
(import "${builtins.fetchTarball https://github.com/nix-community/home-manager/archive/release-24.05.tar.gz}/nixos") ./nixos
(fetchTarball "https://github.com/nix-community/nixos-vscode-server/tarball/master") ./scripts
./telegraf.nix
./promtail.nix
./portainer.nix
./watchtower.nix
]; ];
system.stateVersion = systemSettings.stateVersion;
time.timeZone = "${systemSettings.timeZone}";
nix.settings.trusted-users = [ "root" "@wheel" ];
nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.download-buffer-size = 524288000; # 500MB
programs.nix-ld.enable = true;
sops.defaultSopsFile = ./secrets/encrypted_secrets.yaml;
sops.defaultSopsFormat = "yaml";
# This is needed for nix to access the secrets at build time.
# It doesn't affect for the `sops ...` command
# Optional if the system has the key age for /etc/ssh/ssh_host_ed25519_key in .sops.yaml
# sops.age.keyFile = "${userSettings.adHome}/.config/sops/age/keys.txt";
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
(pkgs.writeShellScriptBin "nrbs" "sudo nixos-rebuild switch")
(pkgs.writeShellScriptBin "nrbsu" "sudo nix-channel --update && sudo nixos-rebuild switch")
(pkgs.writeShellScriptBin "ads" ''
cd ${adPath}
nix develop --no-pure-eval ${adNixPath}/appdaemon
'')
(pkgs.writeShellScriptBin "ad-clone" ''
if [ ! -d ${adPath} ]; then
sudo git clone -b ${adBranch} ${adRepo} ${adPath}
sudo chown -R appdaemon:users $(dirname ${adPath})
else
echo "${adPath} already exists"
fi
'')
# unstable.uv
bash bash
git git
eza eza
gh sops
# appdaemon gdbm
btop
]; ];
time.timeZone = "America/Chicago";
virtualisation.docker.enable = true; virtualisation.docker.enable = true;
virtualisation.oci-containers.backend = "docker"; virtualisation.oci-containers.backend = "docker";
@@ -52,43 +38,42 @@ in
services.openssh.enable = true; services.openssh.enable = true;
services.tailscale.enable = true; services.tailscale.enable = true;
system.activationScripts.ensureDirectory = '' # services.cron = {
if [ ! -d /conf ]; then # enable = true;
mkdir /conf # systemCronJobs = [
chmod 0755 /conf # "30 2 * * * /run/current-system/sw/bin/nfsu > /etc/nixos/auto_update.log 2>&1"
chown 1000:100 /conf # ];
fi # };
'';
security.sudo-rs = { # systemd.timers."auto-update" = {
enable = true; # wantedBy = [ "timers.target" ];
execWheelOnly = false; # timerConfig = {
wheelNeedsPassword = false; # OnCalendar="*-*-* 4:00:00";
# Unit = "auto-update.service";
# };
# };
# systemd.services."auto-update" = {
# script = ''
# ${pkgs.coreutils}/bin/echo "Running auto-update"
# FLAKE=$(${pkgs.coreutils}/bin/readlink -f /etc/nixos)
# ${pkgs.coreutils}/bin/echo "FLAKE: $FLAKE"
# ${pkgs.nix}/bin/nix flake update --flake $FLAKE --impure
# ${pkgs.git}/bin/git -C $FLAKE add "$FLAKE/flake.lock" > /dev/null 2>&1
# ${pkgs.sudo}/bin/sudo ${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --flake $FLAKE#${systemSettings.hostName} --impure
# '';
# serviceConfig = {
# Type = "oneshot";
# User = "${userSettings.userName}";
# };
# };
# https://nixos.wiki/wiki/Storage_optimization
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
}; };
nix.optimise.automatic = true;
users.users.appdaemon = { nix.optimise.dates = [ "Mon *-*-* 05:00:00" ];
isNormalUser = true;
home = "${adHome}";
extraGroups = [ "wheel" "docker" ];
openssh.authorizedKeys.keyFiles = [ "/root/.ssh/authorized_keys" ];
};
nix.settings.trusted-users = [ "root" "@wheel" ];
home-manager = {
useGlobalPkgs = true;
users.appdaemon = { pkgs, ... }: {
home.stateVersion = stateVersion;
imports = [ ./git.nix ];
programs = {
ssh.enable = true;
git.extraConfig.safe.directory = "${adNixPath}";
bash = {
enable = true;
profileExtra = "cd ${adNixPath}";
};
};
};
};
system.stateVersion = stateVersion;
} }

View File

@@ -14,11 +14,11 @@
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1728672398, "lastModified": 1744206633,
"narHash": "sha256-KxuGSoVUFnQLB2ZcYODW7AVPAh9JqRlD5BrfsC/Q4qs=", "narHash": "sha256-pb5aYkE8FOoa4n123slgHiOf1UbNSnKe5pEZC+xXD5g=",
"owner": "cachix", "owner": "cachix",
"repo": "cachix", "repo": "cachix",
"rev": "aac51f698309fd0f381149214b7eee213c66ef0a", "rev": "8a60090640b96f9df95d1ab99e5763a586be1404",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -34,14 +34,16 @@
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"git-hooks": "git-hooks", "git-hooks": "git-hooks",
"nix": "nix", "nix": "nix",
"nixpkgs": "nixpkgs_3" "nixpkgs": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1733323168, "lastModified": 1750097069,
"narHash": "sha256-d5DwB4MZvlaQpN6OQ4SLYxb5jA4UH5EtV5t5WOtjLPU=", "narHash": "sha256-MePLDJw4megMq47O3WXgmpnDOIaQrHYrgA3xS7Ps+c8=",
"owner": "cachix", "owner": "cachix",
"repo": "devenv", "repo": "devenv",
"rev": "efa9010b8b1cfd5dd3c7ed1e172a470c3b84a064", "rev": "ab8a1563714393d366b2db7d93f021afb45e7a6f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -53,11 +55,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1696426674, "lastModified": 1733328505,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -69,11 +71,11 @@
"flake-compat_2": { "flake-compat_2": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1696426674, "lastModified": 1733328505,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -104,6 +106,24 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"git-hooks": { "git-hooks": {
"inputs": { "inputs": {
"flake-compat": [ "flake-compat": [
@@ -113,17 +133,14 @@
"nixpkgs": [ "nixpkgs": [
"devenv", "devenv",
"nixpkgs" "nixpkgs"
],
"nixpkgs-stable": [
"devenv"
] ]
}, },
"locked": { "locked": {
"lastModified": 1730302582, "lastModified": 1746537231,
"narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=", "narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf", "rev": "fa466640195d38ec97cf0493d6d6882bc4d14969",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -154,6 +171,47 @@
"type": "github" "type": "github"
} }
}, },
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1750099781,
"narHash": "sha256-6EVPi3XzioPzwxLZ/2nD6jbKCLA2ZXRdOWFgHg2ozrA=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "1db3cb415da14c81d8e0fdd3a5edeba82ad13a1f",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"home-manager_2": {
"inputs": {
"nixpkgs": [
"nix-home",
"nixpkgs"
]
},
"locked": {
"lastModified": 1750033262,
"narHash": "sha256-TcFN78w6kPspxpbPsxW/8vQ1GAtY8Y3mjBaC+oB8jo4=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "66523b0efe93ce5b0ba96dcddcda15d36673c1f0",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"libgit2": { "libgit2": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -189,11 +247,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1727438425, "lastModified": 1745930071,
"narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", "narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=",
"owner": "domenkozar", "owner": "domenkozar",
"repo": "nix", "repo": "nix",
"rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", "rev": "b455edf3505f1bf0172b39a735caef94687d0d9c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -203,13 +261,34 @@
"type": "github" "type": "github"
} }
}, },
"nix-home": {
"inputs": {
"home-manager": "home-manager_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1750100488,
"narHash": "sha256-WFY6/1AtATVloT/takLMt6/0RNx2ivU1ZXG4Pn64/eA=",
"ref": "refs/heads/main",
"rev": "696f5a00078b39c9ca81802170924c4647ffd5a1",
"revCount": 16,
"type": "git",
"url": "https://gitea.john-stream.com/john/nix-home"
},
"original": {
"type": "git",
"url": "https://gitea.john-stream.com/john/nix-home"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1730531603, "lastModified": 1733212471,
"narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -227,11 +306,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1733319315, "lastModified": 1749760516,
"narHash": "sha256-cFQBdRmtIZFVjr2P6NkaCOp7dddF93BC0CXBwFZFaN0=", "narHash": "sha256-koLwnVjVrR4yS2ea1owMj6ps2sOhH67ObTIld9H27Yo=",
"owner": "cachix", "owner": "cachix",
"repo": "nixpkgs-python", "repo": "nixpkgs-python",
"rev": "01263eeb28c09f143d59cd6b0b7c4cc8478efd48", "rev": "908dbb466af5955ea479ac95953333fd64387216",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -258,27 +337,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1716977621, "lastModified": 1749794982,
"narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", "narHash": "sha256-Kh9K4taXbVuaLC0IL+9HcfvxsSUx8dPB5s5weJcc9pc=",
"owner": "cachix",
"repo": "devenv-nixpkgs",
"rev": "4267e705586473d3e5c8d50299e71503f16a6fb6",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "rolling",
"repo": "devenv-nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1733212471,
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", "rev": "ee930f9755f58096ac6e8ca94a1887e0534e2d81",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -288,11 +351,83 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_4": {
"locked": {
"lastModified": 1682134069,
"narHash": "sha256-TnI/ZXSmRxQDt2sjRYK/8j8iha4B4zP2cnQCZZ3vp7k=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fd901ef4bf93499374c5af385b2943f5801c0833",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": { "root": {
"inputs": { "inputs": {
"devenv": "devenv", "devenv": "devenv",
"nixpkgs": "nixpkgs_4", "home-manager": "home-manager",
"nixpkgs-python": "nixpkgs-python" "nix-home": "nix-home",
"nixpkgs": "nixpkgs_3",
"nixpkgs-python": "nixpkgs-python",
"sops-nix": "sops-nix",
"vscode-server": "vscode-server"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1749592509,
"narHash": "sha256-VunQzfZFA+Y6x3wYi2UE4DEQ8qKoAZZCnZPUlSoqC+A=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "50754dfaa0e24e313c626900d44ef431f3210138",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"vscode-server": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1729422940,
"narHash": "sha256-DlvJv33ml5UTKgu4b0HauOfFIoDx6QXtbqUF3vWeRCY=",
"owner": "nix-community",
"repo": "nixos-vscode-server",
"rev": "8b6db451de46ecf9b4ab3d01ef76e59957ff549f",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixos-vscode-server",
"type": "github"
} }
} }
}, },

143
flake.nix Normal file
View File

@@ -0,0 +1,143 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
vscode-server.url = "github:nix-community/nixos-vscode-server";
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
nixpkgs-python = {
url = "github:cachix/nixpkgs-python";
inputs.nixpkgs.follows = "nixpkgs";
};
devenv = {
url = "github:cachix/devenv";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-home = {
url = "git+https://gitea.john-stream.com/john/nix-home";
inputs.nixpkgs.follows = "nixpkgs";
};
};
nixConfig = {
extra-trusted-public-keys = "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=";
extra-substituters = "https://devenv.cachix.org";
};
outputs = { self, ... }@inputs:
let
inherit (self) outputs;
nixosSystem = inputs.nixpkgs.lib.nixosSystem;
userSettings = {
gitUserName = "John Lancaster";
gitUserEmail = "32917998+jsl12@users.noreply.github.com";
userName = "appdaemon";
adHome = "/home/appdaemon";
};
systemSettings = {
hostName = "ad-nix";
stateVersion = "24.05";
system = "x86_64-linux";
timeZone = "America/Chicago";
locale = "en_US.UTF-8";
# pythonVersion = "3.11.10"; # This is largely irrelevant because uv will handle it
};
pkgs = inputs.nixpkgs.legacyPackages.${systemSettings.system};
in
{
nixosConfigurations.${systemSettings.hostName} = nixosSystem {
system = systemSettings.system;
specialArgs = {
inherit inputs;
inherit systemSettings;
inherit userSettings;
};
modules = [
(inputs.nixpkgs + "/nixos/modules/virtualisation/proxmox-lxc.nix")
inputs.home-manager.nixosModules.default
inputs.nix-home.nixosModules.default { user = "appdaemon"; }
inputs.vscode-server.nixosModules.default
inputs.sops-nix.nixosModules.sops
./configuration.nix
];
};
# https://devenv.sh/guides/using-with-flakes/#the-flakenix-file
packages.${systemSettings.system} = {
devenv-up = self.devShells.${systemSettings.system}.default.config.procfileScript;
devenv-test = self.devShells.${systemSettings.system}.default.config.test;
};
devShells.${systemSettings.system}.default = inputs.devenv.lib.mkShell {
inherit inputs pkgs;
modules = [
({ pkgs, config, ... }: {
# This is your devenv configuration
# https://devenv.sh/reference/options/#pre-commithooks
git-hooks.hooks = {
end-of-file-fixer.enable = true;
trim-trailing-whitespace.enable = true;
};
# https://devenv.sh/supported-languages/python/
languages.python = {
enable = true;
# version = systemSettings.pythonVersion;
uv = {
enable = true;
package = pkgs.uv;
sync = {
enable = true;
allExtras = true;
arguments = [ "-U" ];
};
};
};
packages = with pkgs; [
git
gdbm
# (python312.withPackages (python-pkgs: with python-pkgs; [ gdbm ]))
(python312.withPackages (python-pkgs: with python-pkgs; [
gdbm
notebook # kinda hacky, but needed so that jupyter notebook has some shared library it needs?
]))
(writeShellScriptBin "docs" "${pkgs.uv}/bin/uv run sphinx-autobuild -E ./docs/ ./docs_build --port 9999")
(writeShellScriptBin "ab" "${pkgs.uv}/bin/uv build --wheel --refresh")
(writeShellScriptBin "adb" "ab && ${pkgs.docker}/bin/docker build -t acockburn/appdaemon:local-dev .")
# (writeShellScriptBin "ad-nb" "cd $(readlink -f /etc/nixos) && devenv up")
];
# processes = {
# my-jup.exec = "uv run jupyter notebook";
# };
enterShell = ''
alias fix="${pkgs.uv}/bin/uv run ruff check --fix"
alias appdaemon="${pkgs.uv}/bin/uv run --frozen appdaemon"
# alias ad="appdaemon"
export PS1="\[\e[0;34m\](AppDaemon)\[\e[0m\] \[\033[1;32m\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\$\[\033[0m\] "
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
echo -e "URL: \e[34m$(${pkgs.git}/bin/git config --get remote.origin.url)\e[0m"
echo -e "Branch/Tag: \e[32m$(${pkgs.git}/bin/git describe --tags --exact-match 2>/dev/null || ${pkgs.git}/bin/git rev-parse --abbrev-ref HEAD)\e[0m"
echo -e "Hash: \e[33m$(${pkgs.git}/bin/git rev-parse --short HEAD)\e[0m"
echo "AppDaemon v$(${pkgs.uv}/bin/uv pip show appdaemon | awk '/^Version:/ {print $2}') development shell started"
'';
})
];
};
};
}

24
home-manager/default.nix Normal file
View File

@@ -0,0 +1,24 @@
{ lib, pkgs, systemSettings, userSettings, ... }:
{
security.sudo-rs = {
enable = true;
execWheelOnly = false;
wheelNeedsPassword = false;
};
users.users.${userSettings.userName} = {
isNormalUser = true;
extraGroups = [ "wheel" "docker" ];
};
home-manager = {
useGlobalPkgs = true;
users.${userSettings.userName} = {
home.stateVersion = systemSettings.stateVersion;
home.homeDirectory = lib.mkForce "${userSettings.adHome}";
systemd.user.startServices = "sd-switch"; # helps with handling systemd services when switching
programs.ssh.enable = true;
programs.gh.enable = true;
};
};
}

12
home-manager/git.nix Normal file
View File

@@ -0,0 +1,12 @@
{ userSettings, ... }:
{
programs.git = {
enable = true;
extraConfig.credential.helper = "store --file ~/.git-credentials";
userName = "${userSettings.gitUserName}";
userEmail = "${userSettings.gitUserEmail}";
extraConfig = {
safe.directory = "/home/appdaemon/ad-nix";
};
};
}

23
home-manager/zsh.nix Normal file
View File

@@ -0,0 +1,23 @@
{ ... }:
{
programs.zsh = {
enable = true;
oh-my-zsh = {
enable = true;
# https://github.com/ohmyzsh/ohmyzsh/wiki/themes
# theme = "robbyrussell";
# theme = "simple";
theme = "risto";
plugins = [
"sudo"
"dotenv"
"git"
"ssh"
"ssh-agent"
];
};
shellAliases = {
ls = "eza -lgs type -o --no-time";
};
};
}

7
nixos/default.nix Normal file
View File

@@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./docker
./services
];
}

7
nixos/docker/default.nix Normal file
View File

@@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./portainer.nix
./watchtower.nix
];
}

View File

@@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./promtail.nix
./telegraf.nix
./restic.nix
];
}

View File

@@ -1,12 +1,17 @@
{ config, ... }: { config, pkgs, ... }:
let let
lokiHost = "192.168.1.174:3100"; lokiHost = "https://loki.john-stream.com";
in in
{ {
systemd.services.promtail.serviceConfig = { systemd.services.promtail.serviceConfig = {
SupplementaryGroups = [ "docker" ]; SupplementaryGroups = [ "docker" ];
}; };
environment.systemPackages = with pkgs; [
(pkgs.writeShellScriptBin "promtail-check" "systemctl status promtail.service")
(pkgs.writeShellScriptBin "promtail-watch" "journalctl -u promtail.service -b -n 25 -f")
];
services.promtail = { services.promtail = {
enable = true; enable = true;
configuration = { configuration = {
@@ -17,7 +22,7 @@ in
positions = { positions = {
filename = "/tmp/positions.yaml"; filename = "/tmp/positions.yaml";
}; };
clients = [{url = "http://${lokiHost}/loki/api/v1/push";}]; clients = [{url = "${lokiHost}/loki/api/v1/push";}];
scrape_configs = [ scrape_configs = [
{ {
job_name = "journal"; job_name = "journal";

49
nixos/services/restic.nix Normal file
View File

@@ -0,0 +1,49 @@
{ config, pkgs, userSettings, ... }:
{
sops.secrets.restic_password = {
owner = config.users.users.${userSettings.userName}.name;
mode = "0440";
};
environment.systemPackages = with pkgs; [
restic
(pkgs.writeShellScriptBin "restic-backup" "sudo systemctl start restic-backups-localBackup.service")
(pkgs.writeShellScriptBin "restic-backup-check" "sudo journalctl -b -u restic-backups-localBackup.service")
];
environment.variables = {
RESTIC_REPOSITORY = "/mnt/restic/appdaemon";
RESTIC_PASSWORD = "${builtins.readFile config.sops.secrets."restic_password".path}";
};
services.restic.backups = {
localBackup = {
repository = "/mnt/restic/appdaemon";
passwordFile = config.sops.secrets."restic_password".path;
initialize = true;
timerConfig = {
OnCalendar = "03:00";
RandomizedDelaySec = "2h";
Persistent = true;
};
paths = [
"/home"
"/conf"
"/etc/nixos"
"/etc/ssh" # necessary for SOPS nix to have the same keys
];
exclude = [
".cache"
".vscode*"
".devenv"
".venv"
"build"
"dist"
"__pycache__"
"*.egg-info"
"namespaces"
];
};
};
}

View File

@@ -1,18 +1,25 @@
{ ... }: { config, pkgs, ... }:
let let
influxURL = "http://panoptes.john-stream.com:8086"; influxURL = "http://panoptes.john-stream.com:8086";
organization = "homelab"; organization = "homelab";
bucket = "docker"; bucket = "docker";
envFile = ./telegraf.env; token = "${builtins.readFile config.sops.secrets."telegraf_influx_token".path}";
in in
{ {
systemd.services.telegraf.serviceConfig = { sops.secrets."telegraf_influx_token" = { };
SupplementaryGroups = [ "docker" ];
environment.systemPackages = with pkgs; [
(pkgs.writeShellScriptBin "telegraf-check" "systemctl status telegraf.service")
(pkgs.writeShellScriptBin "telegraf-watch" "journalctl -u telegraf.service -b -n 25 -f")
];
systemd.services.telegraf = {
environment.INFLUX_WRITE_TOKEN = token;
serviceConfig.SupplementaryGroups = [ "docker" ];
}; };
services.telegraf = { services.telegraf = {
enable = true; enable = true;
environmentFiles = [ "${envFile}" ];
extraConfig = { extraConfig = {
agent = { agent = {
interval = "10s"; interval = "10s";

9
scripts/default.nix Normal file
View File

@@ -0,0 +1,9 @@
{ pkgs, systemSettings, ... }:
{
environment.systemPackages = with pkgs; [
(pkgs.writeShellScriptBin "ads" "nix develop --no-pure-eval $(readlink -f /etc/nixos)")
(pkgs.writeShellScriptBin "link-nix" "${builtins.readFile ./link-nix.sh}")
(pkgs.writeShellScriptBin "sops-ad" "sops $(readlink -f /etc/nixos)/secrets/encrypted_secrets.yaml")
(pkgs.writeShellScriptBin "lola-up" "docker compose -f /conf/lola/docker-compose.yml up -d")
];
}

18
scripts/link-nix.sh Normal file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -e
if [ "$#" -eq 0 ]; then
echo "Error: No arguments provided."
echo "Usage: $0 <path>"
exit 1
fi
CURRENT=$(readlink -f /etc/nixos)
if [ -d "/etc/nixos" ]; then
sudo rm -r /etc/nixos
fi
echo "Unlinked $CURRENT"
sudo ln -s $1 /etc/nixos
echo "Linked $(readlink -f /etc/nixos)"

3
secrets/authorized_keys Normal file
View File

@@ -0,0 +1,3 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDIaHS9CLiDc6T1tja0fBwwv5qc6iwuckWN6w8MNo5yiR8LPWyrfueowNJkL4HMqu6OEuggtdybGw1Do4sW5o+toHCyWfZf3khI1l15opPXuVpD4CWED+SpJiZ0wBgRaCaWhfxLI+s4JOhjOO2OjiClPX3HfxIHyTpRiR78lOMcIieHSnzrAV2MatYKf6lL2ckOsIPwxo/OVM+1ljjX+HLq9IxGUCpWOnF4nF1rq3gKL2JUh2KsrgrzE3NB7EFuqKm8F0tF2rG3JjSvlwox0h06drKD02lpZWXPOBRlcyFDpNXymmc2bpG0S2Bbj5g+pqNBB0jO0h3kzWvYYqrtU/ElObg1cXhyi0PFOhhptlbhbK0Ao8B+pAbSZ661nMT3jpRWLVbnJrRFnXXdjX08r5eseQ3k4CFpv+g64n7yg3IMo9f8gA9P/hOexR+qu5AQ1Ad/tvkp6pPXnR/zsUnbe4p2A9MaNJm4E1zxbs5VGlXynNikXwDL+spkrnjwdfUULTk= john@JOHN-PC
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFn5ilhqaeDsOWSk7y29se2NvxGm8djlfL3RGLokj0q6 john@john-p14s
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHh9SBuxU2dOJHnpGZAE4cwe0fXcTBBAx+JmRsmIX+Tk8zooeM32vbNxxSXiZNpBGH5wzHNb534dWexGGG3sOaONmcL7SCoPIvaAdnIn5VsiznerLrzppSbx3Qn8eyF97WAGCcOcIUNmTIDDx1m6zG762WQnoaUEy0Ul5IR7ET5GQxP3p5Qwx8yqfixKDwarvV421sUIxYt9gee31jS9jcI3MFd6EL57hWle95Z8BGpR/Q7sXDBTZQWMZauh5NPwLMZS7k3bHgxXZ7WNOw/J/yts1ckBbvIFJSRNnMuWD0oGnDTL6aivGi+Eiswp0fpKzYGzquB3/wr3VU4G1JcMM5 JuiceSSH

View File

@@ -0,0 +1,31 @@
telegraf_influx_token: ENC[AES256_GCM,data:XHT7lvRrw9MeC0Jxe2EYTTa/iB5QLVTzp9TDJaljssRR+kGdK3va1u14NX5b6jFrHnAXLiMdMQ5UTdbsnYH43TnRkY29mcVHxwaQv+rbCgEIKOAYFeIw0g==,iv:uzBYXWYRDH6bHZ3pubWh5Qn/2dN2Rz+sjEmrqpKhA4o=,tag:wemgU05aTl9S1rwt+fVQug==,type:str]
restic_password: ENC[AES256_GCM,data:8ArxlyulTejzZ2eA9LqLptAZdBfBZJpeNmaw7r9H2ZPQsPAuT4uMcGRgvYF3tD1d9msyUC5yFy5trQfUxUMhXUrnPnFgZEYUrq+BVG/VraYjH74N1YTSKHksz7kqEGmTpMh6DpNLSq3JWfUT/T2GWDhIjRfQf1O++nlAWHDLT0+aEPT633+o63k8+GZuC38Khsv22dYHki1U57QQusk8x5Rj/0ZwuftJe7ItKs28nXZyLejFq+c+OTvJxjQb70FvHY0QfrGFA8RPteJgoLuTDrnKtkw2CuTpfnfhQXQw9oxUnT6x3L34RMY6Tla1PZt/xp07VZC1vnmmLB1prwJtUgvtQfzp8hLVNipoNAfg9ujg7eTq0Dwm7yHVe5hSkOxp1qh47mwA7Og9yb0t7FZE3ZiVT0P5dH/+Qvp76KhCCQUDA4ttKKw8TNjsiqrcEMyDBj+c1mXRpcXfgoAhJpgtEgHT28GEwVl927Zz3zpGG23Gu9pn5ow09GRWJOzvInwnEI/3Thz+DKySzKB2xDK/Nu8hXsmF37iYafLBSnDRGw8RPp6DQBBFNT84WlncCz71yNt7diiAmdxFVESIv3P0sXMVEXEJ3yx/8ke/2quGiCvYUfvxFsU8xsPIkA3gQodHJY+8q16kjafuMUZkuhZxhFZuScKEThlSkJcvlX+C19dlJYbQM/NoLN8KEeJ+ULoTd+CgGtlK7gXEE9GC5i+rTW/9pZrsg8MaPJAxw/jnZO9ikxJtxRPiJGJ7r2zkEwM9DdlPNlbPWw3BQO/ikOS6UhtcuQI2dj0KJC1b4jzrHCALa7h4tRZmT40isEC1KuGcj02CR0QFAVYWWCz9S6TE2RR8y+OiEJosRfTWFg1CbWyGjBAsZ8WbyAhufB6EhF2F5CA3bMnGc1D6JAgrQw0rowce1Znzs2hYQP4ysaDMLoUhRfDjdfUlb9byOeRwKnLFxg67mAHO1ON8DUT+ZnLeNH3rEmams5g9irtLcH3nxV45ESZfFDqVLr645gmfPNs92a8K1ZUwU3XpO6mOR7+iLiKpFIhlVavtsJPKE1XAxnhilH6Hekd78PAdKc+aZLeDGHUZcTZYEN76mxRfBe20GpkUlx9ekHN4ZP1qvQl301vefNpmfflcJheJ/fgsLjDW5US5hyG6PZ/+GG1xAEhBEmSKH9GvN7sk+FwaxdVSzZwcL7Dj2fyX89kSWoZdKMbE6RwsUHNo1Pdfc1w1M8RxSnOLZL7ijG/nJFLn0T6I5cjnKQ+qscsRQz+62aUczTRp80jFHnNo1VOrsO9Oz0YX1/t9Pnq1mR/X/UzZFwiRKrdLacTwRSEWUFi5zf4PX5rcd6EeZbp5DuvP7RZt39npAmzNz+TBKZP06RymG5CdDVzO41xNJWt7bQ/sd3tw3MUXJaz87Glbg7xq+5EdoUE9J/PaJfO5i+9CAaKCOiFBUfr/NjWv3zpfMCZ50HzqlsQCLnOMWS8S65V5xh2a1h77sOYsrWESvUcdg1ryfGd98znyNE5P7BEBo83P8DIKdYrRoPaWPWHRC6ldOOvFDEeaHy6GedV6k0qKcueGHNYRHG4aMOV9lnlc3qMOpXkNFWk45Mv5pmFgGlgrmutjXzi3ljxa0cGe5UUdPbr4lDZ+U2yPvCOu7Lg7FpVyCR77QMerF0xENKrhB4G57QBUhtx8TUdYH/B6+vka1LiKz/i09VEDiQ2K1q5831hUfrS6GyXN8p7JdhCQ3C66V8cMpb9/llO06LLV5Cc4ooB0svSigMuQ4UFDO5bTkrt7wGJLG/mHrb8DjDPI5nuWhyoxs6OqCvg2t2/HJwK9,iv:wiW/f7wLO7kfd3CKDfoYZnXj697qIFRokAut7VXALVM=,tag:VzKJ/BrCL6zNbglsDqJx9w==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age197d424aa7jpj2s735fl2h2s4c687y8vm44usx8wag0r2kh2v7ces4efdyn
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAralB5SnNwckUxMkRad0Jr
U2xMRVpnUU9GNHpZTEtLdnpwc2tmT08rQmpNCnFzdHpOdWFpZzBNR1lUSHR5U3lr
Vk1HTEQ3REFvdUg1T0hMM014N3BtcVEKLS0tIE5LUTF4Qk1XSXlNNkxNN2pnVi9P
TXd3eUJyYTZYaENSV3FEU2pGbFc1RDQKMj8dOska8lpMAFKV2w6bbO/r01K/9Dw5
Q/jp5XdYtyaGSZcxRnHHbJYldyKKYII9Rcm/uDNuMNA/gCFvbSLccA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1qf4c4asf7wcqqyd9aju8fq9dvum4ptcqr8dd6xqengsf6jx7daqqtgup30
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuWmtMR1Vuc0g2OCsxSjJ2
eCs1bWJyT3g3QktRRHlzVFB6bkZjVjIwRlRFCmVtam9HWWErdlVwYkFrSUprZHR4
bllDcWdCT2ZiRFpaQ1lVZVBSb05kb2MKLS0tIGgrRUx4TTljdDVGVCtxN0kyZGRL
Vm1ldGhPRmNyZHErekRlbFBZQy8wK0EKY2vsWzqtX5w4vM0aLGEN2ZO0Rm9slcKk
6Yx2KvJAT6dNg2lqjzXYYS/MvnpOrW6fA46bmWKaAl9IzKhyW+2avw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-02-17T06:15:17Z"
mac: ENC[AES256_GCM,data:zbnP62SqnI7UUb5lP4UlgzWPDkUegvVX2lAbRcDqWqZJsXTkRPefdUIFPO3aZn2EW0aKlFQGEwARTtOtQ9hLYhbqcvAvh5Ur5eFh3szp9ejgF59JBdYGH8PTR/6FkCaVnyuMA1t3940gVhs8eIRdfdjihTHsIe254/3xzBtVG4o=,iv:j7EImL80FgAt7bjlkgB5KIKduKniUaoyz8fnHr/v2rM=,tag:5vK0s6Qf6t2HRhDPaZkT6Q==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.4