mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 04:19:19 -08:00
refactor: systems/ folder
This commit is contained in:
parent
a06248ba9a
commit
41b772c6d1
22 changed files with 10 additions and 10 deletions
12
systems/ct/nixos.nix
Normal file
12
systems/ct/nixos.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
meta,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = with meta;
|
||||
[
|
||||
nixos.reisen-ct
|
||||
];
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
}
|
||||
16
systems/tei/nixos.nix
Normal file
16
systems/tei/nixos.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
meta,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = with meta;
|
||||
[
|
||||
nixos.reisen-ct
|
||||
nixos.sops
|
||||
nixos.tailscale
|
||||
];
|
||||
|
||||
sops.defaultSopsFile = ./secrets.yaml;
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
}
|
||||
57
systems/tei/secrets.yaml
Normal file
57
systems/tei/secrets.yaml
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
tailscale-key: ENC[AES256_GCM,data:0ify9ntv5wgr8S8wUdV72mbjt3h/jjceFnocMEIndeEJ1VYTINKlyoPL8VxVJpsi0QxtH7T7pvw=,iv:iapyEmjAT2gGBj+fTfSRtGX1/cvBmqbyI9h1flPprPM=,tag:UZDyojQcVwkquDPiRtfGKQ==,type:str]
|
||||
sops:
|
||||
shamir_threshold: 1
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age16vcudjuaf3j28vlc44n78ly9eztrwekjss2kstzx9yhhutl9vpdsq58wtv
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3UDkvWFdVOHFxSkl2T1dx
|
||||
TE1qRjIrQ2VsaTB1Ym16MkJBTkJQNmFLQlJFCnptS1Q2bzJoV3NCNWZjaHNEc3hH
|
||||
ODlHUjIxY1hTdXdKVUE3UGUvQlRpRlkKLS0tIHJCOEYyMnRCMEVoRUJ3QjhXbE1a
|
||||
Y0xxeFpUeC9iUm9uS0h6anN2UDdHNGcKAUmeJWwD6McZyOQKO8DXygpKlj6QwnLw
|
||||
5w+qGwcOH9WclZf/ENQZHD8b4QxBTkguHz8rWc2Ruy9gkjZG3afuKQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-01-06T21:27:28Z"
|
||||
mac: ENC[AES256_GCM,data:QVnNJ37mJDOSG0khDHEpez8/sPsh9TqLhXCBXJ9HDZoPiG17LTLp6p0+2NlTuuxF8rHYakDSKnAVamhsuTAdbgKmdG2m1Hm4zRFPLc/GlTr9618fo8/Ob+cIoV9yoTyVFFykQWBS0oNR+dorp9yKpcB8IlyxbtW9WmU1CWEAd2E=,iv:ODW2e+93MKEZ5fsxne2SpLLDyLc6z8X1VCqamoLAPwM=,tag:2uDKu5UEn72z6vL5Y/RT9Q==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-01-06T22:38:31Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA82M54yws73UAQ//fULmaMuT7Bckde6ljCNBi8P3EFATvZ58ZY1Yt0lkerma
|
||||
Paa00POnyEWyQGSHXiJ+jeYELKG9JoFbsipN18B3JHokvMLQhkb78pPSDf6kaTqR
|
||||
7IKDP8DEHqGhfmwg+HrLtSceXccCAvsridyvx5Kq6ljuEy5anPZjL6Sld+EvB35L
|
||||
wrReuTXYVv+23qi75nlA6hFPNoja0HvrK2mRro/jgirVE4h5u3bgtkdHZ11WXDww
|
||||
449AweYlxOnbrGBTJnfxgI9SK57dP6zq13BKG3ECeEXgztWp7y98RrjI8HnDqg+u
|
||||
2dPWr7Hy6yv7ZvcXC9kPHYTCO1YJEMzE3jL5Klo9FfV3+ZrbA5/linfhFUKgbROb
|
||||
eCRp2UaCRdnJQEeMIy4FCEkqtLJK7JQX0F4ZOfVKyh3neBlPHKHPnygA3C0X+uHg
|
||||
SXy3wDhI2Ib78ehEfyp4Dk1TDEA6cXZOxkIiWUVreSB3y00H6J9gdNTOUYbn8hLB
|
||||
0MDD6Tl5ZqgsxiDRiH1Qn/WI+uJpotw0L4bqAhIkI7dCuYOzU6oZVCOLQ8D1TQyo
|
||||
8LWG3TQapcT7kvq0CyGGVX8aRxsvJfXWoSOYq9etclda/eT52Em/gHFUVv61fOlQ
|
||||
KDpMbl5VyCcau4ZvbU6nNMivu+j0zccyIAj2MbWjfKUftXGcQaEtbJK00KzaufvS
|
||||
XgHtPNsevoJLdK521ypL5I6I0QnMPSidcFLq3V8fMIFn6b4OuIUc8O7/96qnacA3
|
||||
2uVuH6yqwPCaQb3WvutvXYp25sF8DbuYNX7PhdDAlm2rZNlYXtcYGnc5xWwTYVQ=
|
||||
=lsdN
|
||||
-----END PGP MESSAGE-----
|
||||
fp: CD8CE78CB0B3BDD4
|
||||
- created_at: "2024-01-06T22:38:31Z"
|
||||
enc: |-
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQEMA2W9MER3HLb7AQgAwzTjn7nYMXWQo1oh11vfogqtPttPrQCgiD1HR+rtC8WZ
|
||||
jNy8yk3aFIaG0H03YAj8GjnLFajZ/SPvMA8BzmXDfoNuLtKbcC8B+qCwC4rcOPL9
|
||||
INeUmF2s7VXhnqMfameT4VFS46nIz+KxNOtp91VKqYY5C1vmTO44zniqchHDmZl/
|
||||
sLn3cAoxzHQVlWWzSLdk7/hxLMA/AUWLwK/aXOXyBIJF5INgB0XiKr54Rae3LjEm
|
||||
Fy91s7RglXSn9Mbu/zO4xTd4AlcySgdR/jPx9yVBha414USIq4/nYsKNWppQbDuR
|
||||
GffaUxMgerMspk7rW9mXT8l+erlDtQBmm50q5uvjpdJeAauvOKRwDFA3KMCCWddx
|
||||
Bzjm+rVXGGiSX4owL/y7UOepowGuublGDJ/vnUWZWXvkpQbDiZBCrAdUVlAB/m7a
|
||||
G+M+9mRFi9ASxt+CKp8XFSR/DBjamQhtZHLgirKu8Q==
|
||||
=+YRG
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 65BD3044771CB6FB
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
||||
99
systems/tewi/access.nix
Normal file
99
systems/tewi/access.nix
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
meta,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; {
|
||||
services.nginx.virtualHosts = mkMerge [
|
||||
(mkIf (config.networking.hostName == "tewi") {
|
||||
"gensokyo.zone" = {
|
||||
locations."/" = {
|
||||
root = pkgs.gensokyoZone;
|
||||
};
|
||||
};
|
||||
"z2m.gensokyo.zone" = {
|
||||
extraConfig = ''
|
||||
auth_request /validate;
|
||||
error_page 401 = @error401;
|
||||
'';
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://127.0.0.1:8072";
|
||||
extraConfig = ''
|
||||
add_header Access-Control-Allow-Origin https://login.gensokyo.zone;
|
||||
add_header Access-Control-Allow-Origin https://id.gensokyo.zone;
|
||||
proxy_set_header X-Vouch-User $auth_resp_x_vouch_user;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
'';
|
||||
};
|
||||
"@error401" = {
|
||||
extraConfig = ''
|
||||
return 302 https://login.gensokyo.zone/login?url=$scheme://$http_host$request_uri&vouch-failcount=$auth_resp_failcount&X-Vouch-Token=$auth_resp_jwt&error=$auth_resp_err;
|
||||
'';
|
||||
};
|
||||
"/validate" = {
|
||||
recommendedProxySettings = false;
|
||||
proxyPass = "http://127.0.0.1:30746/validate";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
auth_request_set $auth_resp_x_vouch_user $upstream_http_x_vouch_user;
|
||||
auth_request_set $auth_resp_jwt $upstream_http_x_vouch_jwt;
|
||||
auth_request_set $auth_resp_err $upstream_http_x_vouch_err;
|
||||
auth_request_set $auth_resp_failcount $upstream_http_x_vouch_failcount;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
(mkIf (config.networking.hostName != "tewi") {
|
||||
"home.${config.networking.domain}" = {
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = meta.tailnet.yukari.pp 4 8123;
|
||||
extraConfig = ''
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
"cloud.kittywit.ch" = {
|
||||
locations = {
|
||||
"/".proxyPass = meta.tailnet.yukari.ppp 4 80 "nextcloud/";
|
||||
};
|
||||
};
|
||||
"plex.kittywit.ch" = {
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = meta.tailnet.yukari.pp 4 32400;
|
||||
extraConfig = ''
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_redirect off;
|
||||
proxy_buffering off;
|
||||
proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier;
|
||||
proxy_set_header X-Plex-Device $http_x_plex_device;
|
||||
proxy_set_header X-Plex-Device-Name $http_x_plex_device_name;
|
||||
proxy_set_header X-Plex-Platform $http_x_plex_platform;
|
||||
proxy_set_header X-Plex-Platform-Version $http_x_plex_platform_version;
|
||||
proxy_set_header X-Plex-Product $http_x_plex_product;
|
||||
proxy_set_header X-Plex-Token $http_x_plex_token;
|
||||
proxy_set_header X-Plex-Version $http_x_plex_version;
|
||||
proxy_set_header X-Plex-Nocache $http_x_plex_nocache;
|
||||
proxy_set_header X-Plex-Provides $http_x_plex_provides;
|
||||
proxy_set_header X-Plex-Device-Vendor $http_x_plex_device_vendor;
|
||||
proxy_set_header X-Plex-Model $http_x_plex_model;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
40
systems/tewi/androidtvremote2.nix
Normal file
40
systems/tewi/androidtvremote2.nix
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{ lib
|
||||
, buildPythonPackage
|
||||
, fetchFromGitHub
|
||||
, aiofiles
|
||||
, cryptography
|
||||
, protobuf
|
||||
, setuptools
|
||||
, pytestCheckHook
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "androidtvremote2";
|
||||
version = "0.0.13";
|
||||
format = "pyproject";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "tronikos";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
hash = "sha256-+9VVUIvM//Fxv1a/+PAKWSQE8/TgBZzeTisgMqj6KPU=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
setuptools
|
||||
];
|
||||
|
||||
propagatedBuildInputs = [
|
||||
aiofiles
|
||||
cryptography
|
||||
protobuf
|
||||
];
|
||||
|
||||
checkInputs = [
|
||||
pytestCheckHook
|
||||
];
|
||||
|
||||
pythonImportsCheck = [
|
||||
"androidtvremote2"
|
||||
];
|
||||
}
|
||||
75
systems/tewi/cloudflared.nix
Normal file
75
systems/tewi/cloudflared.nix
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
{ pkgs, config, utils, lib, ... }: let
|
||||
inherit (lib) mapAttrsToList mapAttrs' nameValuePair splitString last singleton
|
||||
mkIf mkMerge mkForce;
|
||||
inherit (config) services;
|
||||
inherit (services.kanidm.serverSettings) domain;
|
||||
cfg = services.cloudflared;
|
||||
apartment = "131222b0-9db0-4168-96f5-7d45ec51c3be";
|
||||
shadowTunnel = {
|
||||
${apartment}.ingress.deluge = {
|
||||
hostname._secret = config.sops.secrets.cloudflared-tunnel-apartment-deluge.path;
|
||||
service = "http://localhost:${toString services.deluge.web.port}";
|
||||
};
|
||||
};
|
||||
in {
|
||||
sops.secrets.cloudflared-tunnel-apartment.owner = services.cloudflared.user;
|
||||
sops.secrets.cloudflared-tunnel-apartment-deluge.owner = services.cloudflared.user;
|
||||
services.cloudflared = {
|
||||
enable = true;
|
||||
tunnels = {
|
||||
${apartment} = {
|
||||
credentialsFile = config.sops.secrets.cloudflared-tunnel-apartment.path;
|
||||
default = "http_status:404";
|
||||
ingress = mapAttrs' (prefix: nameValuePair "${prefix}${domain}") {
|
||||
"".service = "http://localhost:80";
|
||||
"home.".service = "http://localhost:${toString services.home-assistant.config.http.server_port}";
|
||||
"z2m.".service = "http://localhost:80";
|
||||
"login.".service = "http://localhost:${toString services.vouch-proxy.settings.vouch.port}";
|
||||
"id." = let
|
||||
inherit (services.kanidm.serverSettings) bindaddress;
|
||||
port = last (splitString ":" bindaddress);
|
||||
in {
|
||||
service = "https://127.0.0.1:${port}";
|
||||
originRequest.noTLSVerify = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.services = let
|
||||
filterConfig = lib.filterAttrsRecursive (_: v: ! builtins.elem v [ null [ ] { } ]);
|
||||
mapIngress = hostname: ingress: {
|
||||
inherit hostname;
|
||||
} // filterConfig (filterConfig ingress);
|
||||
in mkIf cfg.enable (mapAttrs' (uuid: tunnel: let
|
||||
RuntimeDirectory = "cloudflared-tunnel-${uuid}";
|
||||
configPath = "/run/${RuntimeDirectory}/config.yml";
|
||||
settings = {
|
||||
tunnel = uuid;
|
||||
credentials-file = tunnel.credentialsFile;
|
||||
ingress = mapAttrsToList mapIngress tunnel.ingress
|
||||
++ mapAttrsToList mapIngress shadowTunnel.${uuid}.ingress or { }
|
||||
++ singleton { service = tunnel.default; };
|
||||
};
|
||||
in nameValuePair "cloudflared-tunnel-${uuid}" (mkMerge [
|
||||
{
|
||||
after = [ "tailscale-autoconnect.service" ];
|
||||
serviceConfig = {
|
||||
RestartSec = 10;
|
||||
};
|
||||
}
|
||||
(mkIf (shadowTunnel.${uuid} or { } != { }) {
|
||||
serviceConfig = {
|
||||
inherit RuntimeDirectory;
|
||||
ExecStart = mkForce [
|
||||
"${cfg.package}/bin/cloudflared tunnel --config=${configPath} --no-autoupdate run"
|
||||
];
|
||||
ExecStartPre = [
|
||||
(pkgs.writeShellScript "cloudflared-tunnel-${uuid}-prepare" ''
|
||||
${utils.genJqSecretsReplacementSnippet settings configPath}
|
||||
'')
|
||||
];
|
||||
};
|
||||
})
|
||||
])) cfg.tunnels);
|
||||
}
|
||||
55
systems/tewi/deluge.nix
Normal file
55
systems/tewi/deluge.nix
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{ config, utils, lib, ... }: let
|
||||
inherit (lib) mkAfter;
|
||||
cfg = config.services.deluge;
|
||||
shadowDir = "/mnt/shadow";
|
||||
mediaDir = "${shadowDir}/deluge";
|
||||
in {
|
||||
sops.secrets.deluge-auth = {
|
||||
inherit (cfg) group;
|
||||
owner = cfg.user;
|
||||
};
|
||||
services.deluge = {
|
||||
enable = true;
|
||||
declarative = true;
|
||||
openFirewall = true;
|
||||
web = {
|
||||
enable = true;
|
||||
};
|
||||
config = {
|
||||
download_location = "${mediaDir}/download";
|
||||
move_completed_path = "${mediaDir}/complete";
|
||||
move_completed = true;
|
||||
max_upload_speed = 10.0;
|
||||
#share_ratio_limit = 2.0;
|
||||
max_connections_global = 1024;
|
||||
max_connections_per_second = 50;
|
||||
max_active_limit = 100;
|
||||
max_active_downloading = 75;
|
||||
max_upload_slots_global = 25;
|
||||
max_active_seeding = 1;
|
||||
allow_remote = true;
|
||||
daemon_port = 58846;
|
||||
listen_ports = [ 6881 6889 ];
|
||||
random_port = false;
|
||||
};
|
||||
authFile = config.sops.secrets.deluge-auth.path;
|
||||
};
|
||||
systemd.services = {
|
||||
deluged = {
|
||||
bindsTo = [
|
||||
"${utils.escapeSystemdPath shadowDir}.mount"
|
||||
];
|
||||
unitConfig = {
|
||||
RequiresMountsFor = [
|
||||
shadowDir
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
systemd.tmpfiles.rules = mkAfter [
|
||||
# work around https://github.com/NixOS/nixpkgs/blob/8f40f2f90b9c9032d1b824442cfbbe0dbabd0dbd/nixos/modules/services/torrent/deluge.nix#L205-L210
|
||||
# (this is dumb, there's no guarantee the disk is even mounted)
|
||||
"z '${cfg.config.move_completed_path}' 0775 ${cfg.user} ${cfg.group}"
|
||||
"x '${mediaDir}/*'"
|
||||
];
|
||||
}
|
||||
260
systems/tewi/home-assistant.nix
Normal file
260
systems/tewi/home-assistant.nix
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.home-assistant;
|
||||
inherit (lib.attrsets) attrNames filterAttrs mapAttrs' nameValuePair;
|
||||
inherit (lib.strings) hasPrefix;
|
||||
in {
|
||||
# MDNS
|
||||
services.avahi.enable = true;
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# Home Assistant
|
||||
cfg.config.http.server_port
|
||||
] ++ map ({ port, ... }: port) cfg.config.homekit;
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
# MDNS
|
||||
5353
|
||||
];
|
||||
|
||||
networking.firewall.allowedUDPPortRanges = [
|
||||
# Chromecast
|
||||
{
|
||||
from = 32768;
|
||||
to = 60999;
|
||||
}
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
ha-integration = {
|
||||
owner = "hass";
|
||||
path = "${cfg.configDir}/integration.yaml";
|
||||
};
|
||||
ha-secrets = {
|
||||
owner = "hass";
|
||||
path = "${cfg.configDir}/secrets.yaml";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.home-assistant = {
|
||||
# UI-editable config files
|
||||
preStart = lib.mkBefore ''
|
||||
touch ${cfg.configDir}/{automations,scenes,scripts,manual,homekit_entity_config,homekit_include_entities}.yaml
|
||||
'';
|
||||
};
|
||||
|
||||
services.home-assistant = {
|
||||
enable = true;
|
||||
config = {
|
||||
homeassistant = {
|
||||
name = "Gensokyo";
|
||||
unit_system = "metric";
|
||||
latitude = "!secret home_lat";
|
||||
longitude = "!secret home_long";
|
||||
elevation = "!secret home_asl";
|
||||
currency = "CAD";
|
||||
country = "CA";
|
||||
time_zone = "America/Vancouver";
|
||||
external_url = "https://home.gensokyo.zone";
|
||||
packages = {
|
||||
manual = "!include manual.yaml";
|
||||
};
|
||||
};
|
||||
frontend = {
|
||||
themes = "!include_dir_merge_named themes";
|
||||
};
|
||||
powercalc = {
|
||||
};
|
||||
utility_meter = {
|
||||
};
|
||||
withings = {
|
||||
use_webhook = true;
|
||||
};
|
||||
logger = {
|
||||
default = "info";
|
||||
};
|
||||
http = {
|
||||
cors_allowed_origins = [
|
||||
"https://google.com"
|
||||
"https://www.home-assistant.io"
|
||||
];
|
||||
use_x_forwarded_for = "true";
|
||||
trusted_proxies = [
|
||||
"127.0.0.0/24"
|
||||
"200::/7"
|
||||
"100.64.0.0/10"
|
||||
"fd7a:115c:a1e0:ab12::/64"
|
||||
"::1"
|
||||
];
|
||||
};
|
||||
recorder = {
|
||||
db_url = "postgresql://@/hass";
|
||||
auto_purge = true;
|
||||
purge_keep_days = 14;
|
||||
commit_interval = 1;
|
||||
exclude = {
|
||||
domains = [
|
||||
"automation"
|
||||
"updater"
|
||||
];
|
||||
entity_globs = [
|
||||
"sensor.weather_*"
|
||||
"sensor.date_*"
|
||||
];
|
||||
entities = [
|
||||
"sun.sun"
|
||||
"sensor.last_boot"
|
||||
"sensor.date"
|
||||
"sensor.time"
|
||||
];
|
||||
event_types = [
|
||||
"call_service"
|
||||
];
|
||||
};
|
||||
};
|
||||
google_assistant = {
|
||||
project_id = "gensokyo-5cfaf";
|
||||
service_account = "!include integration.yaml";
|
||||
report_state = true;
|
||||
exposed_domains = [
|
||||
"scene"
|
||||
"script"
|
||||
"climate"
|
||||
#"sensor"
|
||||
];
|
||||
entity_config = {};
|
||||
};
|
||||
homekit = [ {
|
||||
name = "Tewi";
|
||||
port = 21063;
|
||||
ip_address = "10.1.1.38";
|
||||
filter = let
|
||||
inherit (cfg.config) google_assistant;
|
||||
in {
|
||||
include_domains = google_assistant.exposed_domains;
|
||||
include_entities = "!include homekit_include_entities.yaml";
|
||||
};
|
||||
entity_config = "!include homekit_entity_config.yaml";
|
||||
} ];
|
||||
tts = [
|
||||
{
|
||||
platform = "google_translate";
|
||||
service_name = "google_say";
|
||||
}
|
||||
];
|
||||
# https://nixos.wiki/wiki/Home_Assistant#Combine_declarative_and_UI_defined_automations
|
||||
"automation manual" = [];
|
||||
"automation ui" = "!include automations.yaml";
|
||||
# https://nixos.wiki/wiki/Home_Assistant#Combine_declarative_and_UI_defined_scenes
|
||||
"scene manual" = [];
|
||||
"scene ui" = "!include scenes.yaml";
|
||||
"script manual" = [];
|
||||
"script ui" = "!include scripts.yaml";
|
||||
counter = {};
|
||||
device_tracker = {};
|
||||
energy = {};
|
||||
group = {};
|
||||
history = {};
|
||||
input_boolean = {};
|
||||
input_button = {};
|
||||
input_datetime = {};
|
||||
input_number = {};
|
||||
input_select = {};
|
||||
input_text = {};
|
||||
logbook = {};
|
||||
schedule = {};
|
||||
map = {};
|
||||
media_source = {};
|
||||
media_player = [
|
||||
{
|
||||
platform = "mpd";
|
||||
name = "Shanghai MPD";
|
||||
host = "10.1.1.32";
|
||||
password = "!secret mpd-shanghai-password";
|
||||
}
|
||||
];
|
||||
mobile_app = {};
|
||||
my = {};
|
||||
person = {};
|
||||
prometheus = {};
|
||||
ssdp = {};
|
||||
switch = {};
|
||||
stream = {};
|
||||
sun = {};
|
||||
system_health = {};
|
||||
tag = {};
|
||||
template = {};
|
||||
timer = {};
|
||||
webhook = {};
|
||||
wake_on_lan = {};
|
||||
zeroconf = {};
|
||||
zone = {};
|
||||
sensor = {};
|
||||
};
|
||||
package = let
|
||||
inherit (lib) warn versionOlder elem;
|
||||
inherit (cfg.package) python;
|
||||
hasBrother = elem "brother" cfg.extraComponents;
|
||||
# https://github.com/pysnmp/pysnmp/issues/51
|
||||
needsPyasn1pin = if versionOlder python.pkgs.pysnmplib.version "6.0"
|
||||
then true
|
||||
else warn "pyasn1 pin likely no longer needed" false;
|
||||
pyasn1prefix = "${python.pkgs.pysnmp-pyasn1}/${python.sitePackages}";
|
||||
home-assistant = pkgs.home-assistant.override {
|
||||
packageOverrides = self: super: {
|
||||
};
|
||||
};
|
||||
in home-assistant.overrideAttrs (old: {
|
||||
makeWrapperArgs = old.makeWrapperArgs ++ lib.optional (hasBrother && needsPyasn1pin) "--prefix PYTHONPATH : ${pyasn1prefix}";
|
||||
disabledTests = old.disabledTests or [ ] ++ [
|
||||
"test_check_config"
|
||||
];
|
||||
});
|
||||
extraPackages = python3Packages:
|
||||
with python3Packages; [
|
||||
psycopg2
|
||||
aiohomekit
|
||||
securetar
|
||||
getmac # for upnp integration
|
||||
python-otbr-api
|
||||
protobuf3
|
||||
adb-shell
|
||||
(callPackage ./androidtvremote2.nix { })
|
||||
(aiogithubapi.overrideAttrs (_: {doInstallCheck = false;}))
|
||||
];
|
||||
extraComponents = [
|
||||
"automation"
|
||||
"scene"
|
||||
"script"
|
||||
"zha"
|
||||
"esphome"
|
||||
"apple_tv"
|
||||
"spotify"
|
||||
"default_config"
|
||||
"brother"
|
||||
"ipp"
|
||||
"androidtv"
|
||||
"cast"
|
||||
"plex"
|
||||
"environment_canada"
|
||||
"met"
|
||||
"generic_thermostat"
|
||||
"google"
|
||||
"google_assistant"
|
||||
"google_cloud"
|
||||
"google_translate"
|
||||
"homekit"
|
||||
"mpd"
|
||||
"mqtt"
|
||||
"shopping_list"
|
||||
"tile"
|
||||
"wake_on_lan"
|
||||
"withings"
|
||||
"wled"
|
||||
"zeroconf"
|
||||
];
|
||||
};
|
||||
}
|
||||
48
systems/tewi/kanidm.nix
Normal file
48
systems/tewi/kanidm.nix
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
conf = import ./snakeoil-certs.nix;
|
||||
domain = conf.domain;
|
||||
unencryptedCert = with pkgs;
|
||||
runCommand "kanidm-cert" {
|
||||
domain = "id.gensokyo.zone";
|
||||
nativeBuildInputs = [minica];
|
||||
} ''
|
||||
install -d $out
|
||||
cd $out
|
||||
minica \
|
||||
--ca-key ca.key.pem \
|
||||
--ca-cert ca.cert.pem \
|
||||
--domains $domain
|
||||
cat $domain/cert.pem ca.cert.pem > $domain.pem
|
||||
'';
|
||||
in {
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
8081
|
||||
636
|
||||
];
|
||||
|
||||
services.kanidm = {
|
||||
enableServer = true;
|
||||
enablePam = false;
|
||||
enableClient = true;
|
||||
clientSettings = {
|
||||
uri = "https://id.gensokyo.zone";
|
||||
verify_ca = true;
|
||||
verify_hostnames = true;
|
||||
};
|
||||
serverSettings = {
|
||||
domain = "gensokyo.zone";
|
||||
origin = "https://id.gensokyo.zone";
|
||||
role = "WriteReplica";
|
||||
log_level = "info";
|
||||
db_fs_type = "zfs";
|
||||
bindaddress = "0.0.0.0:8081";
|
||||
ldapbindaddress = "0.0.0.0:636";
|
||||
tls_chain = "${unencryptedCert}/${unencryptedCert.domain}.pem";
|
||||
tls_key = "${unencryptedCert}/${unencryptedCert.domain}/key.pem";
|
||||
};
|
||||
};
|
||||
}
|
||||
47
systems/tewi/mediatomb.nix
Normal file
47
systems/tewi/mediatomb.nix
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
{ config, utils, lib, ... }: with lib; let
|
||||
cfg = config.services.mediatomb;
|
||||
shadowDir = "/mnt/shadow";
|
||||
inherit (config.services) deluge;
|
||||
in {
|
||||
services.mediatomb = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
port = 4152;
|
||||
serverName = config.networking.hostName;
|
||||
uuid = "082fd344-bf69-5b72-a68f-a5a4d88e76b2";
|
||||
mediaDirectories = [
|
||||
{
|
||||
path = "${shadowDir}/media";
|
||||
recursive = true;
|
||||
hidden-files = false;
|
||||
}
|
||||
(mkIf deluge.enable {
|
||||
path = builtins.dirOf deluge.config.download_location;
|
||||
recursive = true;
|
||||
hidden-files = false;
|
||||
})
|
||||
];
|
||||
};
|
||||
systemd.services.mediatomb = {
|
||||
confinement.enable = true;
|
||||
bindsTo = [
|
||||
"${utils.escapeSystemdPath shadowDir}.mount"
|
||||
];
|
||||
unitConfig = {
|
||||
RequiresMountsFor = [
|
||||
shadowDir
|
||||
];
|
||||
};
|
||||
serviceConfig = {
|
||||
RestartSec = 15;
|
||||
StateDirectory = cfg.package.pname;
|
||||
BindReadOnlyPaths = mkMerge [
|
||||
(map (path: "${shadowDir}/media/${path}") [
|
||||
"anime" "movies" "tv" "unsorted"
|
||||
"music" "music-to-import" "music-raw"
|
||||
])
|
||||
(mkIf deluge.enable [ deluge.config.move_completed_path ])
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
57
systems/tewi/mosquitto.nix
Normal file
57
systems/tewi/mosquitto.nix
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
1883
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
z2m-pass.owner = "mosquitto";
|
||||
systemd-pass.owner = "mosquitto";
|
||||
hass-pass.owner = "mosquitto";
|
||||
espresense-pass.owner = "mosquitto";
|
||||
};
|
||||
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
persistence = true;
|
||||
listeners = [
|
||||
{
|
||||
acl = [
|
||||
"pattern readwrite #"
|
||||
];
|
||||
users = {
|
||||
z2m = {
|
||||
passwordFile = config.sops.secrets.z2m-pass.path;
|
||||
acl = [
|
||||
"readwrite #"
|
||||
];
|
||||
};
|
||||
espresense = {
|
||||
passwordFile = config.sops.secrets.espresense-pass.path;
|
||||
acl = [
|
||||
"readwrite #"
|
||||
];
|
||||
};
|
||||
systemd = {
|
||||
passwordFile = config.sops.secrets.systemd-pass.path;
|
||||
acl = [
|
||||
"readwrite #"
|
||||
];
|
||||
};
|
||||
hass = {
|
||||
passwordFile = config.sops.secrets.hass-pass.path;
|
||||
acl = [
|
||||
"readwrite #"
|
||||
];
|
||||
};
|
||||
};
|
||||
settings = {
|
||||
allow_anonymous = false;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
35
systems/tewi/nginx.nix
Normal file
35
systems/tewi/nginx.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; {
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
443
|
||||
80
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = false;
|
||||
commonHttpConfig = ''
|
||||
map $scheme $hsts_header {
|
||||
https "max-age=31536000; includeSubdomains; preload";
|
||||
}
|
||||
#add_header Strict-Transport-Security $hsts_header;
|
||||
#add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always;
|
||||
add_header 'Referrer-Policy' 'origin-when-cross-origin';
|
||||
#add_header X-Frame-Options DENY;
|
||||
#add_header X-Content-Type-Options nosniff;
|
||||
#add_header X-XSS-Protection "1; mode=block";
|
||||
#proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
|
||||
'';
|
||||
clientMaxBodySize = "512m";
|
||||
virtualHosts = {
|
||||
};
|
||||
};
|
||||
}
|
||||
253
systems/tewi/nixos.nix
Normal file
253
systems/tewi/nixos.nix
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
{
|
||||
meta,
|
||||
config,
|
||||
lib,
|
||||
utils,
|
||||
pkgs,
|
||||
modulesPath,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
hddopts = ["luks" "discard" "noauto" "nofail"];
|
||||
md = {
|
||||
shadow = rec {
|
||||
name = "shadowlegend";
|
||||
device = "/dev/md/${name}";
|
||||
unit = utils.escapeSystemdPath device + ".device";
|
||||
where = "/mnt/shadow";
|
||||
mount = utils.escapeSystemdPath where + ".mount";
|
||||
service = "md-shadow.service";
|
||||
disk = "/dev/disk/by-uuid/84aafe0e-132a-4ee5-8c5c-c4a396b999bf";
|
||||
cryptDisks =
|
||||
lib.flip lib.mapAttrs {
|
||||
seagate0 = {
|
||||
device = "/dev/disk/by-uuid/78880135-6455-4603-ae07-4e044a77b740";
|
||||
keyFile = "/root/ST4000DM000-1F21.key";
|
||||
options = hddopts;
|
||||
};
|
||||
hgst = {
|
||||
device = "/dev/disk/by-uuid/4033c877-fa1f-4f75-b9de-07be84f83afa";
|
||||
keyFile = "/root/HGST-HDN724040AL.key";
|
||||
options = hddopts;
|
||||
};
|
||||
} (disk: attrs:
|
||||
attrs
|
||||
// {
|
||||
service = "systemd-cryptsetup@${disk}.service";
|
||||
});
|
||||
};
|
||||
};
|
||||
in {
|
||||
imports = with meta;
|
||||
[
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
nixos.sops
|
||||
nixos.tailscale
|
||||
inputs.systemd2mqtt.nixosModules.default
|
||||
./access.nix
|
||||
./syncplay.nix
|
||||
./kanidm.nix
|
||||
./vouch.nix
|
||||
./home-assistant.nix
|
||||
./zigbee2mqtt.nix
|
||||
./mosquitto.nix
|
||||
./postgres.nix
|
||||
./nginx.nix
|
||||
./mediatomb.nix
|
||||
./deluge.nix
|
||||
./cloudflared.nix
|
||||
];
|
||||
|
||||
boot.supportedFilesystems = ["nfs"];
|
||||
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="tty", GROUP="input", MODE="0660"
|
||||
'';
|
||||
|
||||
services.cockroachdb.locality = "provider=local,network=gensokyo,host=${config.networking.hostName}";
|
||||
|
||||
sops.defaultSopsFile = ./secrets.yaml;
|
||||
|
||||
networking = {
|
||||
useNetworkd = true;
|
||||
useDHCP = false;
|
||||
};
|
||||
services.resolved.enable = true;
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.cryptsetup
|
||||
];
|
||||
|
||||
boot = {
|
||||
loader = {
|
||||
systemd-boot = {
|
||||
enable = true;
|
||||
};
|
||||
efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
initrd = {
|
||||
availableKernelModules = ["xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"];
|
||||
};
|
||||
kernelModules = ["kvm-intel"];
|
||||
};
|
||||
|
||||
services.openiscsi = {
|
||||
enable = true;
|
||||
enableAutoLoginOut = true;
|
||||
name = "";
|
||||
};
|
||||
|
||||
services.systemd2mqtt = {
|
||||
enable = true;
|
||||
user = "root";
|
||||
mqtt = {
|
||||
url = "tcp://localhost:1883";
|
||||
username = "systemd";
|
||||
};
|
||||
units = {
|
||||
${md.shadow.mount} = {};
|
||||
"mediatomb.service" = mkIf config.services.mediatomb.enable {};
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
"iscsi/initiatorname.iscsi" = lib.mkForce {
|
||||
source = config.sops.secrets.openiscsi-config.path;
|
||||
};
|
||||
crypttab.text = let
|
||||
inherit (lib) concatStringsSep mapAttrsToList;
|
||||
cryptOpts = lib.concatStringsSep ",";
|
||||
in
|
||||
concatStringsSep "\n" (mapAttrsToList (
|
||||
disk: {
|
||||
device,
|
||||
keyFile,
|
||||
options,
|
||||
...
|
||||
}: "${disk} ${device} ${keyFile} ${cryptOpts options}"
|
||||
)
|
||||
md.shadow.cryptDisks);
|
||||
};
|
||||
|
||||
sops.secrets = {
|
||||
openiscsi-config = {};
|
||||
openiscsi-env = mkIf config.services.openiscsi.enableAutoLoginOut { };
|
||||
systemd2mqtt-env = {};
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/6c5d82b1-5d11-4c72-96c6-5f90e6ce57f5";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/85DC-72FA";
|
||||
fsType = "vfat";
|
||||
};
|
||||
${md.shadow.where} = {
|
||||
device = md.shadow.disk;
|
||||
fsType = "xfs";
|
||||
options = [
|
||||
"x-systemd.automount"
|
||||
"noauto" "nofail"
|
||||
"x-systemd.requires=${md.shadow.service}"
|
||||
"x-systemd.after=${md.shadow.service}"
|
||||
"x-systemd.after=${md.shadow.unit}"
|
||||
];
|
||||
};
|
||||
};
|
||||
systemd = let
|
||||
inherit (lib) getExe;
|
||||
serviceName = lib.removeSuffix ".service";
|
||||
toSystemdIni = pkgs.lib.generators.toINI {
|
||||
listsAsDuplicateKeys = true;
|
||||
};
|
||||
cryptServices = lib.mapAttrsToList (_: {service, ...}: service) md.shadow.cryptDisks;
|
||||
in {
|
||||
services = {
|
||||
nfs-mountd = {
|
||||
wants = ["network-online.target"];
|
||||
};
|
||||
mdmonitor.enable = false;
|
||||
${serviceName md.shadow.service} = rec {
|
||||
restartIfChanged = false;
|
||||
wants = cryptServices ++ [ "iscsi.service" ];
|
||||
bindsTo = cryptServices;
|
||||
after = wants;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = "true";
|
||||
ExecStartPre = [
|
||||
"-${getExe pkgs.mdadm} --assemble --scan"
|
||||
];
|
||||
ExecStart = [
|
||||
"${getExe pkgs.mdadm} --detail ${md.shadow.device}"
|
||||
];
|
||||
ExecStop = [
|
||||
"${getExe pkgs.mdadm} --stop ${md.shadow.device}"
|
||||
];
|
||||
};
|
||||
};
|
||||
iscsid = rec {
|
||||
wantedBy = cryptServices;
|
||||
before = wantedBy;
|
||||
};
|
||||
iscsi = let
|
||||
cfg = config.services.openiscsi;
|
||||
in mkIf cfg.enableAutoLoginOut rec {
|
||||
wantedBy = cryptServices;
|
||||
before = wantedBy;
|
||||
serviceConfig = {
|
||||
EnvironmentFile = [ config.sops.secrets.openiscsi-env.path ];
|
||||
ExecStartPre = [
|
||||
"${cfg.package}/bin/iscsiadm --mode discoverydb --type sendtargets --portal $DISCOVER_PORTAL --discover"
|
||||
];
|
||||
};
|
||||
};
|
||||
systemd2mqtt = mkIf config.services.systemd2mqtt.enable rec {
|
||||
requires = mkIf config.services.mosquitto.enable ["mosquitto.service"];
|
||||
after = requires;
|
||||
serviceConfig.EnvironmentFile = [
|
||||
config.sops.secrets.systemd2mqtt-env.path
|
||||
];
|
||||
};
|
||||
};
|
||||
units = {
|
||||
${md.shadow.mount} = {
|
||||
overrideStrategy = "asDropin";
|
||||
text = toSystemdIni {
|
||||
Unit.BindsTo = [
|
||||
md.shadow.service
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
network = {
|
||||
networks.eno1 = {
|
||||
inherit (config.systemd.network.links.eno1) matchConfig;
|
||||
networkConfig = {
|
||||
DHCP = "yes";
|
||||
DNSDefaultRoute = true;
|
||||
MulticastDNS = true;
|
||||
};
|
||||
};
|
||||
links.eno1 = {
|
||||
matchConfig = {
|
||||
Type = "ether";
|
||||
Driver = "e1000e";
|
||||
};
|
||||
linkConfig = {
|
||||
WakeOnLan = "magic";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
swapDevices = lib.singleton {
|
||||
device = "/dev/disk/by-uuid/137605d3-5e3f-47c8-8070-6783ce651932";
|
||||
};
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
}
|
||||
11
systems/tewi/postgres.nix
Normal file
11
systems/tewi/postgres.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ config, pkgs, ... }: {
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_14;
|
||||
ensureDatabases = [ "hass" ];
|
||||
ensureUsers = [{
|
||||
name = "hass";
|
||||
ensureDBOwnership = true;
|
||||
}];
|
||||
};
|
||||
}
|
||||
82
systems/tewi/secrets.yaml
Normal file
82
systems/tewi/secrets.yaml
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
espresense-pass: ENC[AES256_GCM,data:wGwUiDHkm5xpVTYxuTy2hQ==,iv:U5Ys+AFEkT7ThbR/qgh5VLNTBRsG72zYqOIO09HFTTc=,tag:h3wNg8nUKOYekpkdJelbOw==,type:str]
|
||||
hass-pass: ENC[AES256_GCM,data:LvoI4sQ77HpYdmNoPLQ=,iv:oAQGTqBh1sf4fbuWGs9AqCE1yS8IApyhEQDUG+yQk7k=,tag:sBPdLuLTJ8OMoZYzUdmnAQ==,type:str]
|
||||
systemd-pass: ENC[AES256_GCM,data:3bEqqWsnBHOgzD95YqwDvg==,iv:ack6EGhE2GzxwRi3gwj1A19Tzi2PJ9iiisMrKozPV/M=,tag:uCR51yn9dAG2x9DCfo1mGQ==,type:str]
|
||||
z2m-pass: ENC[AES256_GCM,data:1bqOab8EQbniAMeL9XRmDg==,iv:uUU3kbuCRIGaueTPE54EHwm4IGwUu+67O4gPYZmd1h4=,tag:iceTSLsRuADiOgZ5cnlnjw==,type:str]
|
||||
tailscale-key: ENC[AES256_GCM,data:dGqnKoCFSF6ZmeptOP7bGy4HYDdUCC1oTdXpiUURDgXl/FltOKExby0=,iv:c8yN1XLk3ZAAzkBozzHJ9BWerWdiNQG/p8e46j8cZyo=,tag:E5Ey5R+t372yLE6XegoOrA==,type:str]
|
||||
vouch-client-secret: ENC[AES256_GCM,data:4MZL99JM4AeUcUfZ8a335utxgqvdH5PCc1R3KAvuOGpaWFGmU7CaD3vV5eLJ62gJ,iv:n1xbPBHi2TcZ12lm7LqItv2aOo7dkgzRh10uxFsy3yM=,tag:+fmJzYMhbiUae/kSyWbT5Q==,type:str]
|
||||
vouch-jwt: ENC[AES256_GCM,data:XDalZtedsBNnDYApmWpdYR9yHBvNXA2DlMmKyCPmcMlqTlbAIVL702/HzTaWLvwpgVXpn3pgG8hNXm9rUE764Q==,iv:qyvGCsildhYgzQiYQ4M0H6eFYrKp8aTkwEeZywpQqHM=,tag:ogtAgvpYE43VPhLhD4NuNA==,type:str]
|
||||
openiscsi-config: ENC[AES256_GCM,data:xyZVJRzR4vK+UAtq3+/QcszLIlcHXYifHnFKm5tVbFUj3c7PjxYGLkvXZfFvERStewdNIQ==,iv:BcbEupXiLECXwfETaVOqfHQ+vkBbrGxkQn54WBYug54=,tag:e0cddYTQAfzSk2AhvzJFvA==,type:str]
|
||||
openiscsi-env: ENC[AES256_GCM,data:uAlnrtk64UQukKBWHYrH5J4Ys+GIpu5zDg==,iv:7ahUk9nocs4cSgtr/A4G0Xhlp7pZj/bUlUDLMMYEAMk=,tag:rE2mdBGT3kZqyoDIaKUY3w==,type:str]
|
||||
systemd2mqtt-env: ENC[AES256_GCM,data:Zo3+acCcMWgai2ERKbmOlI0hvdkOlNviBqeLb1ALuA==,iv:NxXBDCEevBRqMDY9/3z/Uq2+vENswkYTgTa82wKc32U=,tag:01WUphYRJrwmHv9HE4ac8w==,type:str]
|
||||
z2m-secret: ENC[AES256_GCM,data:SCxz8nbB/QhfPcAzSEDHMpiQnjv+j0xLtg/20qf5ZEe3P5YRaiKXMSqdw6MX7uQtGh8T44raEgS8PFuGKXY423GV/MNPSzMl16DLBwU5P7TL6lYT97uVYRIqWMKqtPy/1f155743wH8HsJvslmg=,iv:Yw9dvH1dBq+vxHvKm0eeHlqVHRdUuzL71mDTbIF7DDg=,tag:bCiDNSwq7P21TwblvVGq6A==,type:str]
|
||||
deluge-auth: ENC[AES256_GCM,data:qJP/CztnN7RV4Z3pP+jbH1B0zzBm8oa3n3X0pecEVe7UI3+NOSwFaQCBD7Q7JDxzh+qTNdQ/wWi7w0XJDG+aRIikgDG28S9RjdPL/w==,iv:GUEwmuk3JWMgsXsDgDrObW657WcN6wcYAsgXhK4Dvx0=,tag:vZMQ67j5kWBWOa6ZqCaQHw==,type:str]
|
||||
syncplay-env: ENC[AES256_GCM,data:MzL/Q4ihwVX+QgdWl20PfpCP8hiPd3uc00FuTJ+gsVN7EJOoDlTyA2pgfw75eklQgWa0r9T+3u3gigo7jxrBqmgD2oYDFrZNKrHyrXlxALQ=,iv:AO7hcXucPqJkCa3u3Y7nrgfIsw9f8fbWBc5g7Kb77cM=,tag:G+URgzoVrwiS6TjEgRy9rg==,type:str]
|
||||
ha-secrets: ENC[AES256_GCM,data:sw+sxrDyNIOAkHSA2fPLqtHR32iKIaZDdgJ1ZcQTeOqlgdZDhK5XzXiBkpZBTwKswUc2UPDOANsn+YRusX2tUvLYjdxZz4jIBKJuaW3aEtOcxjmG55KYxHmTzSbR4IhpuZ+1wDhvp4UiUqyD273Lt6LTFDmohZAVqwxJc2k4YTZJXiofVf8ywcXPMcS+zIMxb5nBX9EJqgJ80pnBI8vZeCg4pFv/Ux2OoS+PTnkYHnsywf57NA23YcKqnsbJoZwi3e4ooM2erygv0DuoP7QBnBdEf5RKSziECDTDPUFQVNYIOEAgJIYOD/GtZmWMx4SadsmrgTB1RqtAdPnvuuD3jLYW20zci8CxmI4F/h/+8lxUH/TGiG2bUmPYvwTE1eW1cLK91XhxXp6ORyWMGYcR98ryGL00ctD/BaZLdk7FYbQMTF2y2vx5vWAABTnYLsv6H9csmD4O7OeNkd9k+YQB/atENAXRgIiGDvkkbNoRkRU5SzIIHGcjjU7GC6hT+LDportPuhUW+g6KJj0ENOCI0yXNkIfa6LXAJcCmdovJCIbdw1HCGHuu+dc5rSWueiOWo+2rr8loytZTTMwevTaldfrNyu42K+bZI2BkPdXzkPQDeV8y5PmfnXfdXthmmnZbYRyVYUd1OH9L,iv:zxpazCPJTWmuw7/BNj90G89aGyk3fCqBB+RCyKW6QwY=,tag:5zSnrZOxo8G2Wg4LNtEsaQ==,type:str]
|
||||
cloudflared-tunnel-apartment: ENC[AES256_GCM,data:ccqV0jqrnbSz/r+C8v5FTWCtWVDHNdMwhiYHmjyrSLRt0xlcfSzqLhlTPMOfcEcded/NgiM9x3KrLm3hjW8GJpnaPGmQhP4GwBFEJ81R7dzXwpzbj0jbkj/sxxE7MEyofxfF+H2g5Kk55Yu148thxOB5Q4w2c6ZT16bHEXD20Cr88+T8chKQycfCWec0tE1WGmJYM3yrnaNvaey4oh4YWl+RApzxuA==,iv:KNjWDOF6PV8SVmXwzgom3wI+mjfnUSAzyuVIkDMgWHI=,tag:q9wOCGsXF5BOKEnt8jEAog==,type:str]
|
||||
cloudflared-tunnel-apartment-deluge: ENC[AES256_GCM,data:BG4ak9wQQjDanJ+RqI33PrAx8g==,iv:s1c/6pWQZim73VjLiJmvR2ly7ktAQf7rJ6Yx34EFddo=,tag:nNu/Re0U5HJSb8JLFu2NMA==,type:str]
|
||||
ha-integration: ENC[AES256_GCM,data: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,iv:tRzbBW/YFMp2vw26M9ediGY49GuxvyV2ijZ1W7mjURQ=,tag:L4ACYnVzdarztrjlsX3cAQ==,type:str]
|
||||
sops:
|
||||
shamir_threshold: 1
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age17haatqc7gpk9t690affyqcvwmhmz0us95en2r7qpqzw29tpq3ffspld0cf
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2a0xYL1ZUemk0NzExb0N0
|
||||
Z1lGcEpTL3Q5U1BHUnJjVktrQUFrNjZKRnhrCm41MW9tbUFzbCtrem5JMXBuMGRv
|
||||
Tk1kaWdaYU8yT3F0NmdHWVA1SlNmQU0KLS0tIGlmM2ZlSFBpc1RCRHhKb21iVVNZ
|
||||
OS9BSForMEJPaUtaNi8rYXJRV3dJZXMKfz+v2KzomXM+OZL43AGyYt05oIuh0OTM
|
||||
jZ4CbkL93bVw+IWY7iZumAskBJycBR2BwOnBlza/1e/jjLeRxkziew==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age172nhlv3py990k2rgw64hy27hffmnpv6ssxyu9fepww7zxfgg347qna4gzt
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkeWhlWEI5N2w5S2gyMjhi
|
||||
MjBMRDRIdktSYmxEQ1k4ZDh3dmg0TTdzdVFBCnRtMTFjVDdaNEpFckpyeUc5cFRH
|
||||
Q2xsV04zODVTV0t1bURDK0ptejE1VTgKLS0tIFluUTVmQnpvUUVPZzdKWkZxdnB0
|
||||
VndVTG0zQWhsUHcwTkFjK2ZPdzRPUUEKJ3flgZ6/s+TjlFgzsANYaOFiEPQuE4zR
|
||||
7npNUDFLe26Q32G3j/lLSBzZZfKoOC5SOSp9TB8eWMYSxfNnXEIu0g==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-01-06T20:31:10Z"
|
||||
mac: ENC[AES256_GCM,data:A9llofFkb5PfjS3KzcINuBuU9TbIFpDswmhBNJ3VpXJSvkrWLVhc3T4TcLotqffXtvidptngjiP0qcK4wM6oXcpfhRs9Td1MDtQQ8B9ICQknmt7ukIDU3FneJuVkxvSpJiNsAIH1x5ZCFzp9Dt550gloYSLklzzl3eozLOwcQ1U=,iv:wV4rjaC9+x+ALxRhlUys2Ao4Fv8E+9QyF7Rf3Kzs15g=,tag:xJzJkgNks3LdkoZEqpJQNg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2023-03-10T17:06:53Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA82M54yws73UARAAnk1rE3kQa0KYvvdn335ekY7m9pp3CraVVckOTi7Jkbhr
|
||||
Fud8P7EmF4pp1O/ibQXRChK3xUVPrO8v3tIMFSVeRPyeE/8Seo/cINSKpBZbC3LA
|
||||
eKekxl1GzNVzrhEZjZ/Huu9o8qtih5lFwqKbNrB3HGh7NnkFycf0gLMNod++I5Eh
|
||||
ib+LdMJA/R5oudPKp46P0NFY+/TjB6lfV/AQC3GtxcKJ9tAECH5CHhN67pthkhQ4
|
||||
F2nJEPl0XD64U7FVpPBXUl1t03X1W33Z6EK6RWsQkb+JS3IegyutKnrWZbyz243f
|
||||
MKmhbZEQ4gJjz6FZBH2rMD0E0YuH+OZsC+YMgMw2gRgd7RIzoO1ipOu4EKYHoB9s
|
||||
oVoC8J/qvtP1UJgfXUnRA7rk9X9qaxk/1kKUiwiyx2NQo/tX3shcemXKjoYQMHW7
|
||||
6opIe2PFEoOktbdewR3gZbkKPNHw+s6ajgCgoAWije9flouS39hhr0c9z/2FOjDk
|
||||
nK29r3A7xsthZebRzs37075b/ZlynUhiWBKjZzJ5WW70XSve9om9T5vasjxk7/uA
|
||||
Hi4bKltNrlbzqoqiDB0JgOTnns98azerCa7SwEgmO475Se344XY5KoxJS1WApsqB
|
||||
Pe41SjVbhrinpVEy9we4ZBr1BHu9WEF844+yPBpLgARrF0R6GIqD6RDgfo71cDHS
|
||||
XAGaHnj5eMdjEASeJ+KHR5zbwWeUssyeJWdzpK0MJcr9ItLt6LMD3brbvlacCGMY
|
||||
P+DuHm5No7rWNWATykRQ3bBF3v1IEPh1wa7MLLjtQfvEEwfQD0l8Bgou1Sft
|
||||
=eZUS
|
||||
-----END PGP MESSAGE-----
|
||||
fp: CD8CE78CB0B3BDD4
|
||||
- created_at: "2023-03-10T17:06:53Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQEMA2W9MER3HLb7AQgAt7a6OVIgJo8NHx7atPm68MckNqvYCs61jZUyEEZcrktc
|
||||
ZkgGhR9IK5jSRZYYCVkZgfj1fikdAv6fF7GotEIJmdgcrQml3VzpAjpIyYuu1ilt
|
||||
bybLp+ryoiE0pK9YF5Bl9vnZ4R+5m8SeAy6Z9WS7O7phxLCkAQ+dCQByyGD1Q4Zn
|
||||
RRF+jIG6o2DnVu3wvkIs6s7dVWEDWJKh8sui97aOAzL5sLevT07WaeDC6LIikkhi
|
||||
KMmvm3HgWghklDvMUTjw0MG3/k9qvg1kW5pQ2ZWivuCeMXA+NFAX1Epx61uZmgxf
|
||||
8313IEfv4gXDXC2xCwmdOn0G6swktqdkY02t8ldFeNJcAXQ8PpieQ3aadGTvK6R9
|
||||
0SgQ4MifOqnNMUDn1FvrfvrXRYHkc7qoyU+8PTzlQ1WCWYJvkrHS1ufFubeA57oJ
|
||||
Kbf3xIXqe/8xP6uOw1/MEh4c3HeGbY7+ieW8miI=
|
||||
=3NVV
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 65BD3044771CB6FB
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
||||
42
systems/tewi/syncplay.nix
Normal file
42
systems/tewi/syncplay.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.services.syncplay;
|
||||
args =
|
||||
[
|
||||
"--disable-ready"
|
||||
"--port"
|
||||
cfg.port
|
||||
]
|
||||
++ optionals (cfg.certDir != null) ["--tls" cfg.certDir];
|
||||
in {
|
||||
sops.secrets.syncplay-env.owner = cfg.user;
|
||||
|
||||
users.users.${cfg.user} = {
|
||||
inherit (cfg) group;
|
||||
isSystemUser = true;
|
||||
home = "/var/lib/syncplay";
|
||||
};
|
||||
users.groups.${cfg.group} = {};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [cfg.port];
|
||||
|
||||
services.syncplay = {
|
||||
enable = true;
|
||||
user = "syncplay";
|
||||
};
|
||||
systemd.services.syncplay = mkIf cfg.enable {
|
||||
serviceConfig = {
|
||||
StateDirectory = "syncplay";
|
||||
EnvironmentFile = singleton config.sops.secrets.syncplay-env.path;
|
||||
ExecStart = mkForce [
|
||||
"${pkgs.syncplay-nogui}/bin/syncplay-server ${utils.escapeSystemdExecArgs args}"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
121
systems/tewi/vouch.nix
Normal file
121
systems/tewi/vouch.nix
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
{
|
||||
config,
|
||||
utils,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
options = with lib; let
|
||||
origin = "https://id.gensokyo.zone";
|
||||
in {
|
||||
services.vouch-proxy = {
|
||||
settings = {
|
||||
vouch = {
|
||||
cookie = {
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "gensokyo.zone";
|
||||
};
|
||||
secure = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
port = mkOption {
|
||||
type = lib.types.port;
|
||||
default = 30746;
|
||||
};
|
||||
listen = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
allowAllUsers = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
oauth = {
|
||||
auth_url = mkOption {
|
||||
type = types.str;
|
||||
default = "${origin}/ui/oauth2";
|
||||
};
|
||||
token_url = mkOption {
|
||||
type = types.str;
|
||||
default = "${origin}/oauth2/token";
|
||||
};
|
||||
user_info_url = mkOption {
|
||||
type = types.str;
|
||||
default = "${origin}/oauth2/openid/vouch/userinfo";
|
||||
};
|
||||
scopes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = ["openid" "email" "profile"];
|
||||
};
|
||||
callback_url = mkOption {
|
||||
type = types.str;
|
||||
default = "https://login.gensokyo.zone/auth";
|
||||
};
|
||||
provider = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "oidc";
|
||||
};
|
||||
code_challenge_method = mkOption {
|
||||
type = types.str;
|
||||
default = "S256";
|
||||
};
|
||||
client_id = mkOption {
|
||||
type = types.str;
|
||||
default = "vouch";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
services.vouch-proxy.settings = {
|
||||
vouch.cookie.secure = false;
|
||||
};
|
||||
|
||||
sops.secrets = {
|
||||
vouch-jwt.owner = "vouch-proxy";
|
||||
vouch-client-secret.owner = "vouch-proxy";
|
||||
};
|
||||
|
||||
systemd.services.vouch-proxy = {
|
||||
description = "Vouch-proxy";
|
||||
after = ["network.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
serviceConfig = {
|
||||
ExecStart = let
|
||||
recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets;
|
||||
settings = recursiveMergeAttrs [
|
||||
config.services.vouch-proxy.settings
|
||||
{
|
||||
oauth.client_secret._secret = config.sops.secrets.vouch-client-secret.path;
|
||||
vouch.jwt.secret._secret = config.sops.secrets.vouch-jwt.path;
|
||||
}
|
||||
];
|
||||
in
|
||||
pkgs.writeShellScript "vouch-proxy-start" ''
|
||||
${utils.genJqSecretsReplacementSnippet settings "/run/vouch-proxy/vouch-config.json"}
|
||||
${pkgs.vouch-proxy}/bin/vouch-proxy -config /run/vouch-proxy/vouch-config.json
|
||||
'';
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
WorkingDirectory = "/var/lib/vouch-proxy";
|
||||
StateDirectory = "vouch-proxy";
|
||||
RuntimeDirectory = "vouch-proxy";
|
||||
User = "vouch-proxy";
|
||||
Group = "vouch-proxy";
|
||||
StartLimitBurst = 3;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.vouch-proxy = {
|
||||
isSystemUser = true;
|
||||
group = "vouch-proxy";
|
||||
};
|
||||
|
||||
users.groups.vouch-proxy = {};
|
||||
};
|
||||
}
|
||||
45
systems/tewi/zigbee2mqtt.nix
Normal file
45
systems/tewi/zigbee2mqtt.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# Zigbee2MQTT Frontend
|
||||
8072
|
||||
];
|
||||
|
||||
sops.secrets.z2m-secret = {
|
||||
owner = "zigbee2mqtt";
|
||||
path = "${config.services.zigbee2mqtt.dataDir}/secret.yaml";
|
||||
};
|
||||
|
||||
users.groups.input.members = ["zigbee2mqtt"];
|
||||
|
||||
services.zigbee2mqtt = {
|
||||
enable = true;
|
||||
settings = {
|
||||
advanced = {
|
||||
log_level = "info";
|
||||
network_key = "!secret network_key";
|
||||
};
|
||||
mqtt = {
|
||||
server = "mqtt://127.0.0.1:1883";
|
||||
user = "z2m";
|
||||
password = "!secret z2m_pass";
|
||||
};
|
||||
homeassistant = true;
|
||||
permit_join = false;
|
||||
frontend = {
|
||||
port = 8072;
|
||||
};
|
||||
serial = {
|
||||
port = "/dev/ttyUSB0";
|
||||
};
|
||||
availability = {
|
||||
# minutes
|
||||
active.timeout = 10;
|
||||
passive.timeout = 60 * 50;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue