Compare commits
117 Commits
staging/mo
...
staging/ni
Author | SHA1 | Date | |
---|---|---|---|
0db7f0857a | |||
38befe502c | |||
2de6f7d364 | |||
c66699b697 | |||
97044bf70e | |||
3122334a41 | |||
0b2faef989 | |||
8acd6ca4f1 | |||
8169f7c6b2 | |||
cd1aa0b376 | |||
72b627100c | |||
567c08460a | |||
9b66aecf1b | |||
16cb3b83a2 | |||
970438be8a | |||
51da29555e | |||
8a745a9b8a | |||
3505f3b9f3 | |||
444595e847 | |||
3e1407c30b | |||
0a744117a4 | |||
a2935cedaa | |||
22e46d52c2 | |||
1e0c213adf | |||
3e1340ed61 | |||
341dd3f2b2 | |||
1c9caa40bd | |||
3be15c6d05 | |||
8e8168ec28 | |||
28397807fc | |||
42ebb9a155 | |||
a8a4b8e739 | |||
2550601179 | |||
199a49755a | |||
8c7700688f | |||
8fe304d6c1 | |||
700fef7df3 | |||
01db7e1f23 | |||
df6e8f1562 | |||
1f0a40c81f | |||
995b41d1e8 | |||
7674735d42 | |||
329693c9ce | |||
5ae3bb2f6c | |||
e0b1aef127 | |||
9b8363dfb4 | |||
58ad87df8e | |||
5fc894cda9 | |||
07e6ec2533 | |||
005a79e680 | |||
0f5279bbca | |||
e9b3b7ebab | |||
7a83c1d6df | |||
46788fe565 | |||
a473ef6db3 | |||
3627d47f12 | |||
115f8d7054 | |||
ac44b04d99 | |||
afff0aff19 | |||
f0086dc5bd | |||
acabd34f28 | |||
d0e6b82739 | |||
dc09b7b9b2 | |||
38c5b82a08 | |||
89def1a073 | |||
ad2ed370d9 | |||
3e8f7a9ba2 | |||
028ecfe93f | |||
c5ac792c13 | |||
bd1624bef9 | |||
3ae53d7f32 | |||
e7f2d41b1f | |||
3394a79e2b | |||
b01501663d | |||
cbd5ccd1c8 | |||
cf857eaf9f | |||
3a7eb294c7 | |||
2ccb470adc | |||
0a2a929507 | |||
2014d5ce77 | |||
041adb7092 | |||
a979521a98 | |||
77881be955 | |||
0450b4d9a6 | |||
edea64a41c | |||
90e479592f | |||
62d83d94f2 | |||
52bbe4e9f4 | |||
ab176b8d4b | |||
62df4492a3 | |||
f4ed194abc | |||
6420c9fd16 | |||
86245b460b | |||
bf1ba786b3 | |||
35a896a3e2 | |||
b4314bd919 | |||
4696209822 | |||
c3957d81c2 | |||
8a5be00c93 | |||
c2db9fe28e | |||
ccaac901f7 | |||
7f285a8254 | |||
b0b82a3d88 | |||
b0664d81ab | |||
8ba52bb9cd | |||
20f0a19e25 | |||
9dc17a3874 | |||
2992644901 | |||
d5d89a10b9 | |||
f7d9fdfe04 | |||
c42aa2847b | |||
768c5c910f | |||
8790a7d9fd | |||
7c36a0d522 | |||
977a80d59e | |||
63c92a44ed | |||
bf838ea203 |
60
flake.lock
generated
60
flake.lock
generated
@@ -54,11 +54,11 @@
|
||||
"mobile-nixos": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1668897543,
|
||||
"narHash": "sha256-1bjvy5zi/6KDzhN3ihOUEA6y5FFEOf5xvIbf65RWIh0=",
|
||||
"lastModified": 1670131242,
|
||||
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
|
||||
"owner": "nixos",
|
||||
"repo": "mobile-nixos",
|
||||
"rev": "25eec596116553112681d72ee4880107fc3957fa",
|
||||
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -69,11 +69,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1669542132,
|
||||
"narHash": "sha256-DRlg++NJAwPh8io3ExBJdNW7Djs3plVI5jgYQ+iXAZQ=",
|
||||
"lastModified": 1671359686,
|
||||
"narHash": "sha256-3MpC6yZo+Xn9cPordGz2/ii6IJpP2n8LE8e/ebUXLrs=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a115bb9bd56831941be3776c8a94005867f316a7",
|
||||
"rev": "04f574a1c0fde90b51bf68198e2297ca4e7cccf4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -82,37 +82,37 @@
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-22_05": {
|
||||
"locked": {
|
||||
"lastModified": 1669513802,
|
||||
"narHash": "sha256-AmTRNi8bHgJlmaNe3r5k+IMFbbXERM/KarqveMAZmsY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6649e08812f579581bfb4cada3ba01e30485c891",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-22.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1669546925,
|
||||
"narHash": "sha256-Gvtk9agz88tBgqmCdHl5U7gYttTkiuEd8/Rq1Im0pTg=",
|
||||
"lastModified": 1671313200,
|
||||
"narHash": "sha256-itZTrtHeDJjV696+ur0/TzkTqb5y3Eb57WRLRPK3rwA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "fecf05d4861f3985e8dee73f08bc82668ef75125",
|
||||
"rev": "0938d73bb143f4ae037143572f11f4338c7b2d1c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-22.05",
|
||||
"ref": "nixos-22.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1671459584,
|
||||
"narHash": "sha256-6wRK7xmeHfClJ0ICOkax1avLZVGTDqBodQlkl/opccY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "87b58217c9a05edcf7630b9be32570f889217aef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-22.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"home-manager": "home-manager",
|
||||
@@ -129,14 +129,14 @@
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-22_05": "nixpkgs-22_05"
|
||||
"nixpkgs-stable": "nixpkgs-stable_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1669714206,
|
||||
"narHash": "sha256-9aiMbzRL8REsyi9U0eZ+lT4s7HaILA1gh9n2apKzLxU=",
|
||||
"lastModified": 1671472949,
|
||||
"narHash": "sha256-9iHSGpljCX+RypahQssBXPwkru9onfKfceCTeVrMpH4=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "8295b8139ef7baadeb90c5cad7a40c4c9297ebf7",
|
||||
"rev": "32840f16ffa0856cdf9503a8658f2dd42bf70342",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
14
flake.nix
14
flake.nix
@@ -4,7 +4,7 @@
|
||||
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs-stable.url = "nixpkgs/nixos-22.05";
|
||||
nixpkgs-stable.url = "nixpkgs/nixos-22.11";
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
mobile-nixos = {
|
||||
url = "github:nixos/mobile-nixos";
|
||||
@@ -38,7 +38,10 @@
|
||||
patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches {
|
||||
name = "nixpkgs-patched-uninsane";
|
||||
src = nixpkgs;
|
||||
patches = import ./nixpatches/list.nix nixpkgs.legacyPackages.${system}.fetchpatch;
|
||||
patches = import ./nixpatches/list.nix {
|
||||
inherit (nixpkgs.legacyPackages.${system}) fetchpatch;
|
||||
inherit (nixpkgs.lib) fakeHash;
|
||||
};
|
||||
};
|
||||
# return something which behaves like `pkgs`, for the provided system
|
||||
# `local` = architecture of builder. `target` = architecture of the system beying deployed to
|
||||
@@ -69,8 +72,15 @@
|
||||
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
|
||||
cross = (nixpkgsFor local target) // (customPackagesFor local target);
|
||||
stable = import nixpkgs-stable { system = target; };
|
||||
|
||||
# cross-compatible packages
|
||||
# gocryptfs = cross.gocryptfs;
|
||||
|
||||
# pinned packages:
|
||||
# 2022/12/13: grpc does not build on aarch64-linux. https://github.com/NixOS/nixpkgs/issues/205887
|
||||
grpc = stable.grpc;
|
||||
# depends on grpc, so pinned.
|
||||
duplicity = stable.duplicity;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
32
hosts/common/bluetooth.nix
Normal file
32
hosts/common/bluetooth.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# TODO: don't need to depend on binsh if we were to use a nix-style shebang
|
||||
system.activationScripts.linkBluetoothKeys = let
|
||||
unwrapped = ../../scripts/install-bluetooth;
|
||||
install-bluetooth = pkgs.writeShellApplication {
|
||||
name = "install-bluetooth";
|
||||
runtimeInputs = with pkgs; [ coreutils gnused ];
|
||||
text = ''${unwrapped} "$@"'';
|
||||
};
|
||||
in (lib.stringAfter
|
||||
[ "setupSecrets" "binsh" ]
|
||||
''
|
||||
${install-bluetooth}/bin/install-bluetooth /run/secrets/bt
|
||||
''
|
||||
);
|
||||
|
||||
# TODO: use a glob, or a list, or something?
|
||||
sops.secrets."bt/car" = {
|
||||
sopsFile = ../../secrets/universal/bt/car.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."bt/earbuds" = {
|
||||
sopsFile = ../../secrets/universal/bt/earbuds.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."bt/portable-speaker" = {
|
||||
sopsFile = ../../secrets/universal/bt/portable-speaker.bin;
|
||||
format = "binary";
|
||||
};
|
||||
}
|
@@ -1,8 +1,10 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./bluetooth.nix
|
||||
./fs.nix
|
||||
./hardware
|
||||
./i2p.nix
|
||||
./machine-id.nix
|
||||
./net.nix
|
||||
./secrets.nix
|
||||
|
4
hosts/common/i2p.nix
Normal file
4
hosts/common/i2p.nix
Normal file
@@ -0,0 +1,4 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.i2p.enable = true;
|
||||
}
|
@@ -76,4 +76,8 @@
|
||||
sopsFile = ../../secrets/universal/net/iphone.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
|
||||
sops.secrets."router_passwd" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
}
|
||||
|
@@ -11,7 +11,12 @@
|
||||
# since that also depends on `users`.
|
||||
system.activationScripts.persist-ssh-host-keys.text = ''
|
||||
mkdir -p /etc/ssh/host_keys
|
||||
mount --bind /nix/persist/etc/ssh/host_keys /etc/ssh/host_keys
|
||||
if ! (mountpoint /etc/ssh/host_keys)
|
||||
then
|
||||
# avoid mounting the keys more than once, otherwise we have a million _stacked_ entries.
|
||||
# TODO: should we just symlink? or find a way to make sure the existing mount is correct.
|
||||
mount --bind /nix/persist/etc/ssh/host_keys /etc/ssh/host_keys
|
||||
fi
|
||||
'';
|
||||
|
||||
services.openssh.hostKeys = [
|
||||
|
@@ -1,58 +1,69 @@
|
||||
{ config, ... }:
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
networking.wg-quick.interfaces.ovpnd-us = {
|
||||
# to add a new OVPN VPN:
|
||||
# - generate a privkey `wg genkey`
|
||||
# - add this key to `sops secrets/universal.yaml`
|
||||
# - upload pubkey to OVPN.com
|
||||
# - generate config @ OVPN.com
|
||||
# - copy the Address, PublicKey, Endpoint from OVPN's config
|
||||
# N.B.: maximum interface name in Linux is 15 characters.
|
||||
let
|
||||
def-ovpn = name: { endpoint, publicKey, address }: {
|
||||
networking.wg-quick.interfaces."ovpnd-${name}" = {
|
||||
inherit address;
|
||||
privateKeyFile = config.sops.secrets."wg_ovpnd_${name}_privkey".path;
|
||||
dns = [
|
||||
"46.227.67.134"
|
||||
"192.165.9.158"
|
||||
];
|
||||
peers = [
|
||||
{
|
||||
allowedIPs = [
|
||||
"0.0.0.0/0"
|
||||
"::/0"
|
||||
];
|
||||
inherit endpoint publicKey;
|
||||
}
|
||||
];
|
||||
# to start: `systemctl start wg-quick-ovpnd-${name}`
|
||||
autostart = false;
|
||||
};
|
||||
sops.secrets."wg_ovpnd_${name}_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
};
|
||||
in lib.mkMerge [
|
||||
(def-ovpn "us" {
|
||||
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
|
||||
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
|
||||
address = [
|
||||
"172.27.237.218/32"
|
||||
"fd00:0000:1337:cafe:1111:1111:ab00:4c8f/128"
|
||||
];
|
||||
dns = [
|
||||
"46.227.67.134"
|
||||
"192.165.9.158"
|
||||
})
|
||||
# NB: us-* share the same wg key and link-local addrs, but distinct public addresses
|
||||
(def-ovpn "us-atl" {
|
||||
endpoint = "vpn18.prd.atlanta.ovpn.com:9929";
|
||||
publicKey = "Dpg/4v5s9u0YbrXukfrMpkA+XQqKIFpf8ZFgyw0IkE0=";
|
||||
address = [
|
||||
"172.21.182.178/32"
|
||||
"fd00:0000:1337:cafe:1111:1111:cfcb:27e3/128"
|
||||
];
|
||||
peers = [
|
||||
{
|
||||
allowedIPs = [
|
||||
"0.0.0.0/0"
|
||||
"::/0"
|
||||
];
|
||||
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
|
||||
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
|
||||
}
|
||||
})
|
||||
(def-ovpn "us-mi" {
|
||||
endpoint = "vpn34.prd.miami.ovpn.com:9929";
|
||||
publicKey = "VtJz2irbu8mdkIQvzlsYhU+k9d55or9mx4A2a14t0V0=";
|
||||
address = [
|
||||
"172.21.182.178/32"
|
||||
"fd00:0000:1337:cafe:1111:1111:cfcb:27e3/128"
|
||||
];
|
||||
privateKeyFile = config.sops.secrets.wg_ovpnd_us_privkey.path;
|
||||
# to start: `systemctl start wg-quick-ovpnd-us`
|
||||
autostart = false;
|
||||
};
|
||||
|
||||
networking.wg-quick.interfaces.ovpnd-ukr = {
|
||||
})
|
||||
(def-ovpn "ukr" {
|
||||
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
|
||||
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
|
||||
address = [
|
||||
"172.18.180.159/32"
|
||||
"fd00:0000:1337:cafe:1111:1111:ec5c:add3/128"
|
||||
];
|
||||
dns = [
|
||||
"46.227.67.134"
|
||||
"192.165.9.158"
|
||||
];
|
||||
peers = [
|
||||
{
|
||||
allowedIPs = [
|
||||
"0.0.0.0/0"
|
||||
"::/0"
|
||||
];
|
||||
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
|
||||
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
|
||||
}
|
||||
];
|
||||
privateKeyFile = config.sops.secrets.wg_ovpnd_ukr_privkey.path;
|
||||
# to start: `systemctl start wg-quick-ovpnd-ukr`
|
||||
autostart = false;
|
||||
};
|
||||
|
||||
sops.secrets."wg_ovpnd_us_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
sops.secrets."wg_ovpnd_ukr_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
}
|
||||
})
|
||||
]
|
||||
|
@@ -25,6 +25,9 @@
|
||||
neededForUsers = true;
|
||||
};
|
||||
|
||||
# don't enable wifi by default: it messes with connectivity.
|
||||
systemd.services.iwd.enable = false;
|
||||
|
||||
# default config: https://man.archlinux.org/man/snapper-configs.5
|
||||
# defaults to something like:
|
||||
# - hourly snapshots
|
||||
|
@@ -40,7 +40,9 @@
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
# /boot space is at a premium. default was 20.
|
||||
boot.loader.generic-extlinux-compatible.configurationLimit = 10;
|
||||
# even 10 can be too much
|
||||
# TODO: compress moby kernels!
|
||||
boot.loader.generic-extlinux-compatible.configurationLimit = 8;
|
||||
# mobile.bootloader.enable = false;
|
||||
# mobile.boot.stage-1.enable = false;
|
||||
# boot.initrd.systemd.enable = false;
|
||||
|
@@ -14,9 +14,8 @@
|
||||
pkgs.freshrss
|
||||
];
|
||||
sane.impermanence.enable = true;
|
||||
sane.services.dyn-dns.enable = true;
|
||||
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||
sane.services.nixserve.enable = true;
|
||||
sane.services.nixserve.sopsFile = ../../secrets/servo.yaml;
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
@@ -13,83 +13,145 @@
|
||||
|
||||
# networking.firewall.enable = false;
|
||||
networking.firewall.enable = true;
|
||||
# TODO: split these into the submodules
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
25 # SMTP
|
||||
80 # HTTP
|
||||
143 # IMAP
|
||||
443 # HTTPS
|
||||
465 # SMTPS
|
||||
587 # SMTPS/submission
|
||||
993 # IMAPS
|
||||
4001 # IPFS
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
|
||||
4001 # IPFS
|
||||
|
||||
# this is needed to forward packets from the VPN to the host
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
|
||||
# unless we add interface-specific settings for each VPN, we have to define nameservers globally.
|
||||
# networking.nameservers = [
|
||||
# "1.1.1.1"
|
||||
# "9.9.9.9"
|
||||
# ];
|
||||
|
||||
# use systemd's stub resolver.
|
||||
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link).
|
||||
# instead, running the stub resolver on a known address in the root ns lets us rewrite packets
|
||||
# in the ovnps namespace to use the provider's DNS resolvers.
|
||||
# a weakness is we can only query 1 NS at a time (unless we were to clone the packets?)
|
||||
# there also seems to be some cache somewhere that's shared between the two namespaces.
|
||||
# i think this is a libc thing. might need to leverage proper cgroups to _really_ kill it.
|
||||
# - getent ahostsv4 www.google.com
|
||||
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
|
||||
services.resolved.enable = true;
|
||||
networking.nameservers = [
|
||||
# use systemd-resolved resolver
|
||||
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
|
||||
# stub resolver (just forwards upstream) lives on 127.0.0.54
|
||||
"127.0.0.53"
|
||||
];
|
||||
|
||||
# we need to use externally-visible nameservers in order for VPNs to be able to resolve hosts.
|
||||
networking.nameservers = [
|
||||
"1.1.1.1"
|
||||
"9.9.9.9"
|
||||
];
|
||||
# services.resolved.extraConfig = ''
|
||||
# # docs: `man resolved.conf`
|
||||
# # DNS servers to use via the `wg0` interface.
|
||||
# # i hope that from the root ns, these aren't visible.
|
||||
# DNS=46.227.67.134%wg0 192.165.9.158%wg0
|
||||
# FallbackDNS=1.1.1.1 9.9.9.9
|
||||
# '';
|
||||
|
||||
# OVPN CONFIG (https://www.ovpn.com):
|
||||
# DOCS: https://nixos.wiki/wiki/WireGuard
|
||||
# if you `systemctl restart wireguard-wg0`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
||||
# TODO: why not create the namespace as a seperate operation (nix config for that?)
|
||||
networking.wireguard.enable = true;
|
||||
networking.wireguard.interfaces.wg0 = {
|
||||
networking.wireguard.interfaces.wg0 = let
|
||||
ip = "${pkgs.iproute2}/bin/ip";
|
||||
in-ns = "${ip} netns exec ovpns";
|
||||
iptables = "${pkgs.iptables}/bin/iptables";
|
||||
veth-host-ip = "10.0.1.5";
|
||||
veth-local-ip = "10.0.1.6";
|
||||
vpn-ip = "185.157.162.178";
|
||||
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
|
||||
vpn-dns = "46.227.67.134";
|
||||
in {
|
||||
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
|
||||
# wg is active only in this namespace.
|
||||
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
|
||||
# sudo ip netns exec ovpns ping www.google.com
|
||||
# note: without the namespace, you'll need to add a specific route through eth0 for the peer (185.157.162.178/32)
|
||||
interfaceNamespace = "ovpns";
|
||||
preSetup = "${pkgs.iproute2}/bin/ip netns add ovpns || true";
|
||||
postShutdown = "${pkgs.iproute2}/bin/ip netns delete ovpns";
|
||||
ips = [
|
||||
"185.157.162.178/32"
|
||||
];
|
||||
peers = [
|
||||
{
|
||||
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
|
||||
endpoint = "vpn36.prd.amsterdam.ovpn.com:9930";
|
||||
endpoint = "185.157.162.10:9930";
|
||||
# alternatively: use hostname, but that presents bootstrapping issues (e.g. if host net flakes)
|
||||
# endpoint = "vpn36.prd.amsterdam.ovpn.com:9930";
|
||||
allowedIPs = [ "0.0.0.0/0" ];
|
||||
# nixOS says this is important for keeping NATs active
|
||||
persistentKeepalive = 25;
|
||||
# re-executes wg this often. docs hint that this might help wg notice DNS/hostname changes.
|
||||
# so, maybe that helps if we specify endpoint as a domain name
|
||||
# dynamicEndpointRefreshSeconds = 30;
|
||||
# when refresh fails, try it again after this period instead.
|
||||
# TODO: not avail until nixpkgs upgrade
|
||||
# dynamicEndpointRefreshRestartSeconds = 5;
|
||||
}
|
||||
];
|
||||
preSetup = "" + ''
|
||||
${ip} netns add ovpns || echo "ovpns already exists"
|
||||
'';
|
||||
postShutdown = "" + ''
|
||||
${in-ns} ip link del ovpns-veth-b || echo "couldn't delete ovpns-veth-b"
|
||||
${ip} link del ovpns-veth-a || echo "couldn't delete ovpns-veth-a"
|
||||
${ip} netns delete ovpns || echo "couldn't delete ovpns"
|
||||
# restore rules/routes
|
||||
${ip} rule del from ${veth-host-ip} lookup ovpns pref 50 || echo "couldn't delete init -> ovpns rule"
|
||||
${ip} route del default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns || echo "couldn't delete init -> ovpns route"
|
||||
${ip} rule add from all lookup local pref 0
|
||||
${ip} rule del from all lookup local pref 100
|
||||
'';
|
||||
postSetup = "" + ''
|
||||
# DOCS:
|
||||
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
|
||||
# - iptables primer: <https://danielmiessler.com/study/iptables/>
|
||||
# create veth pair
|
||||
${ip} link add ovpns-veth-a type veth peer name ovpns-veth-b
|
||||
${ip} addr add ${veth-host-ip}/24 dev ovpns-veth-a
|
||||
${ip} link set ovpns-veth-a up
|
||||
|
||||
# mv veth-b into the ovpns namespace
|
||||
${ip} link set ovpns-veth-b netns ovpns
|
||||
${in-ns} ip addr add ${veth-local-ip}/24 dev ovpns-veth-b
|
||||
${in-ns} ip link set ovpns-veth-b up
|
||||
|
||||
# make it so traffic originating from the host side of the veth
|
||||
# is sent over the veth no matter its destination.
|
||||
${ip} rule add from ${veth-host-ip} lookup ovpns pref 50
|
||||
# for traffic originating at the host veth to the WAN, use the veth as our gateway
|
||||
# not sure if the metric 1002 matters.
|
||||
${ip} route add default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns
|
||||
# give the default route lower priority
|
||||
${ip} rule add from all lookup local pref 100
|
||||
${ip} rule del from all lookup local pref 0
|
||||
|
||||
# bridge HTTP traffic:
|
||||
# any external port-80 request sent to the VPN addr will be forwarded to the rootns.
|
||||
# this exists so LetsEncrypt can procure a cert for the MX over http.
|
||||
# TODO: we could use _acme_challence.mx.uninsane.org CNAME to avoid this forwarding
|
||||
# - <https://community.letsencrypt.org/t/where-does-letsencrypt-resolve-dns-from/37607/8>
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 80 -m iprange --dst-range ${vpn-ip} \
|
||||
-j DNAT --to-destination ${veth-host-ip}:80
|
||||
|
||||
# we also bridge DNS traffic
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
||||
-j DNAT --to-destination ${veth-host-ip}:53
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
||||
-j DNAT --to-destination ${veth-host-ip}:53
|
||||
|
||||
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
|
||||
-j DNAT --to-destination ${vpn-dns}:53
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.wg0veth = {
|
||||
description = "veth pair to allow communication between host and wg0 netns";
|
||||
after = [ "wireguard-wg0.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
|
||||
ExecStart = with pkgs; writeScript "wg0veth-start" ''
|
||||
#!${bash}/bin/bash
|
||||
# create veth pair
|
||||
${iproute2}/bin/ip link add ovpns-veth-a type veth peer name ovpns-veth-b
|
||||
${iproute2}/bin/ip addr add 10.0.1.5/24 dev ovpns-veth-a
|
||||
${iproute2}/bin/ip link set ovpns-veth-a up
|
||||
# mv veth-b into the ovpns namespace
|
||||
${iproute2}/bin/ip link set ovpns-veth-b netns ovpns
|
||||
${iproute2}/bin/ip -n ovpns addr add 10.0.1.6/24 dev ovpns-veth-b
|
||||
${iproute2}/bin/ip -n ovpns link set ovpns-veth-b up
|
||||
# forward HTTP traffic, which we need for letsencrypt to work
|
||||
${iproute2}/bin/ip netns exec ovpns ${socat}/bin/socat TCP4-LISTEN:80,reuseaddr,fork,su=nobody TCP4:10.0.1.5:80 &
|
||||
'';
|
||||
|
||||
ExecStop = with pkgs; writeScript "wg0veth-stop" ''
|
||||
#!${bash}/bin/bash
|
||||
${iproute2}/bin/ip -n wg0 link del ovpns-veth-b
|
||||
${iproute2}/bin/ip link del ovpns-veth-a
|
||||
'';
|
||||
};
|
||||
};
|
||||
# create a new routing table that we can use to proxy traffic out of the root namespace
|
||||
# through the ovpns namespace, and to the WAN via VPN.
|
||||
networking.iproute2.rttablesExtraConfig = ''
|
||||
5 ovpns
|
||||
'';
|
||||
networking.iproute2.enable = true;
|
||||
|
||||
sops.secrets."wg_ovpns_privkey" = {
|
||||
sopsFile = ../../secrets/servo.yaml;
|
||||
|
31
hosts/servo/services/ddns-afraid.nix
Normal file
31
hosts/servo/services/ddns-afraid.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# using manual ddns now
|
||||
lib.mkIf false
|
||||
{
|
||||
systemd.services.ddns-afraid = {
|
||||
description = "update dynamic DNS entries for freedns.afraid.org";
|
||||
serviceConfig = {
|
||||
EnvironmentFile = config.sops.secrets.ddns_afraid.path;
|
||||
# TODO: ProtectSystem = "strict";
|
||||
# TODO: ProtectHome = "full";
|
||||
# TODO: PrivateTmp = true;
|
||||
};
|
||||
script = let
|
||||
curl = "${pkgs.curl}/bin/curl -4";
|
||||
in ''
|
||||
${curl} "https://freedns.afraid.org/dynamic/update.php?$AFRAID_KEY"
|
||||
'';
|
||||
};
|
||||
systemd.timers.ddns-afraid = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
timerConfig = {
|
||||
OnStartupSec = "2min";
|
||||
OnUnitActiveSec = "10min";
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets."ddns_afraid" = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
};
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# we use manual DDNS now
|
||||
lib.mkIf false
|
||||
{
|
||||
systemd.services.ddns-he = {
|
||||
description = "update dynamic DNS entries for HurricaneElectric";
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./ddns-afraid.nix
|
||||
./ddns-he.nix
|
||||
./ejabberd.nix
|
||||
./freshrss.nix
|
||||
@@ -9,13 +10,17 @@
|
||||
./ipfs.nix
|
||||
./jackett.nix
|
||||
./jellyfin.nix
|
||||
./kiwix-serve.nix
|
||||
./matrix
|
||||
./navidrome.nix
|
||||
./nixserve.nix
|
||||
./nginx.nix
|
||||
./pleroma.nix
|
||||
./postfix.nix
|
||||
./postgres.nix
|
||||
./prosody.nix
|
||||
./transmission.nix
|
||||
./trust-dns.nix
|
||||
./wikipedia.nix
|
||||
];
|
||||
}
|
||||
|
@@ -1,23 +1,76 @@
|
||||
# docs:
|
||||
# - <https://docs.ejabberd.im/admin/configuration/basic>
|
||||
# example configs:
|
||||
# - <https://github.com/vkleen/machines/blob/138a2586ce185d7cf201d4e1fe898c83c4af52eb/hosts/europium/ejabberd.nix>
|
||||
# - <https://github.com/Mic92/stockholm/blob/675ef0088624c9de1cb531f318446316884a9d3d/tv/3modules/ejabberd/default.nix>
|
||||
# - <https://github.com/buffet/tararice/blob/bc5b65509f4e622313af3f1f4be690628123f1f3/programs/ejabberd.nix>
|
||||
# - enables STUN and TURN
|
||||
# - uses stun_disco module (but with no options)
|
||||
# - <https://github.com/leo60228/dotfiles/blob/39b3abba3009bdc31413d4757ca2f882a33eec8b/files/ejabberd.yml>
|
||||
# - <https://github.com/Mic92/dotfiles/blob/ddf0f4821f554f7667fc803344657367c55fb9e6/nixos/eve/modules/ejabberd.nix>
|
||||
# - <nixpkgs:nixos/tests/xmpp/ejabberd.nix>
|
||||
# - 2013: <https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example>
|
||||
{ lib, ... }:
|
||||
|
||||
# XXX disabled: fails to start because of `mnesia_tm` dependency
|
||||
# XXX: avatar support works in MUCs but not DMs
|
||||
# lib.mkIf false
|
||||
{
|
||||
sane.impermanence.service-dirs = [
|
||||
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
3478 # STUN
|
||||
5222 # XMPP client -> server
|
||||
5269 # XMPP server -> server
|
||||
5280 # bosh
|
||||
5281 # bosh (https) ??
|
||||
5349 # STUN (TLS)
|
||||
5443 # web services (file uploads, websockets, admin)
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
3478 # STUN
|
||||
];
|
||||
|
||||
# provide access to certs
|
||||
users.users.ejabberd.extraGroups = [ "nginx" ];
|
||||
|
||||
security.acme.certs."uninsane.org".extraDomainNames = [
|
||||
"conference.xmpp.uninsane.org"
|
||||
"pubsub.xmpp.uninsane.org"
|
||||
"upload.xmpp.uninsane.org"
|
||||
"vjid.xmpp.uninsane.org"
|
||||
];
|
||||
|
||||
# exists so the XMPP server's cert can obtain altNames for all its resources
|
||||
services.nginx.virtualHosts."conference.xmpp.uninsane.org" = {
|
||||
useACMEHost = "uninsane.org";
|
||||
};
|
||||
services.nginx.virtualHosts."pubsub.xmpp.uninsane.org" = {
|
||||
useACMEHost = "uninsane.org";
|
||||
};
|
||||
services.nginx.virtualHosts."upload.xmpp.uninsane.org" = {
|
||||
useACMEHost = "uninsane.org";
|
||||
};
|
||||
services.nginx.virtualHosts."vjid.xmpp.uninsane.org" = {
|
||||
useACMEHost = "uninsane.org";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
# XXX: toplevel xmpp might not actually be used/needed.
|
||||
CNAME."xmpp" = [ "native" ];
|
||||
CNAME."conference.xmpp" = [ "native" ];
|
||||
CNAME."pubsub.xmpp" = [ "native" ];
|
||||
CNAME."upload.xmpp" = [ "native" ];
|
||||
CNAME."vjid.xmpp" = [ "native" ];
|
||||
|
||||
# _Service._Proto.Name TTL Class SRV Priority Weight Port Target
|
||||
SRV."_xmpp-client._tcp" = [ "0 0 5222 native" ];
|
||||
SRV."_xmpp-server._tcp" = [ "0 0 5269 native" ];
|
||||
SRV."_stun._udp" = [ "0 0 3478 native" ];
|
||||
SRV."_stun._tcp" = [ "0 0 3478 native" ];
|
||||
SRV."_stuns._tcp" = [ "0 0 5349 native" ];
|
||||
};
|
||||
|
||||
# TODO: allocate UIDs/GIDs ?
|
||||
services.ejabberd.enable = true;
|
||||
services.ejabberd.configFile = builtins.toFile "ejabberd.yaml" ''
|
||||
@@ -35,9 +88,39 @@
|
||||
|
||||
pam_userinfotype: jid
|
||||
|
||||
acl:
|
||||
admin:
|
||||
user:
|
||||
- "colin@uninsane.org"
|
||||
local:
|
||||
user_regexp: ""
|
||||
loopback:
|
||||
ip:
|
||||
- 127.0.0.0/8
|
||||
- ::1/128
|
||||
|
||||
access_rules:
|
||||
local:
|
||||
allow: local
|
||||
c2s_access:
|
||||
allow: all
|
||||
announce:
|
||||
allow: admin
|
||||
configure:
|
||||
allow: admin
|
||||
muc_create:
|
||||
allow: local
|
||||
pubsub_createnode_access:
|
||||
allow: local
|
||||
trusted_network:
|
||||
allow: loopback
|
||||
|
||||
# docs: <https://docs.ejabberd.im/admin/configuration/basic/#shaper-rules>
|
||||
shaper_rules:
|
||||
max_s2s_connections: 3
|
||||
# setting this to above 1 may break outgoing messages
|
||||
# - maybe some servers rate limit? or just don't understand simultaneous connections?
|
||||
max_s2s_connections: 1
|
||||
max_user_sessions: 10
|
||||
max_user_offline_messages: 5000
|
||||
c2s_shaper:
|
||||
fast: all
|
||||
@@ -59,26 +142,156 @@
|
||||
# - burst_size: 5000000
|
||||
|
||||
# see: <https://docs.ejabberd.im/admin/configuration/listen/>
|
||||
# TODO: host web admin panel
|
||||
s2s_use_starttls: true
|
||||
# s2s_use_starttls: true
|
||||
s2s_use_starttls: optional
|
||||
# lessens 504: remote-server-timeout errors
|
||||
# see: <https://github.com/processone/ejabberd/issues/3105#issuecomment-562182967>
|
||||
negotiation_timeout: 60
|
||||
|
||||
listen:
|
||||
-
|
||||
port: 5222
|
||||
module: ejabberd_c2s
|
||||
shaper: c2s_shaper
|
||||
starttls: true
|
||||
access: c2s_access
|
||||
-
|
||||
port: 5269
|
||||
module: ejabberd_s2s_in
|
||||
shaper: s2s_shaper
|
||||
-
|
||||
port: 5280
|
||||
port: 5443
|
||||
module: ejabberd_http
|
||||
tls: true
|
||||
request_handlers:
|
||||
/admin: ejabberd_web_admin
|
||||
/api: mod_http_api
|
||||
/admin: ejabberd_web_admin # TODO: ensure this actually works
|
||||
/api: mod_http_api # ejabberd API endpoint (to control server)
|
||||
/bosh: mod_bosh
|
||||
/upload: mod_http_upload
|
||||
/ws: ejabberd_http_ws
|
||||
# /.well-known/host-meta: mod_host_meta
|
||||
# /.well-known/host-meta.json: mod_host_meta
|
||||
-
|
||||
port: 3478
|
||||
module: ejabberd_stun
|
||||
transport: tcp
|
||||
-
|
||||
port: 3478
|
||||
module: ejabberd_stun
|
||||
transport: udp
|
||||
-
|
||||
port: 5349
|
||||
module: ejabberd_stun
|
||||
transport: tcp
|
||||
tls: true
|
||||
|
||||
# TODO: enable mod_client_state for net optimization
|
||||
# TODO: enable mod_fail2ban
|
||||
# TODO(low): look into mod_http_fileserver for serving macros?
|
||||
modules:
|
||||
# mod_adhoc: {}
|
||||
# mod_announce:
|
||||
# access: admin
|
||||
# allows users to set avatars in vCard
|
||||
# - <https://docs.ejabberd.im/admin/configuration/modules/#mod-avatar>
|
||||
mod_avatar: {}
|
||||
mod_caps: {} # for mod_pubsub
|
||||
mod_carboncopy: {} # allows multiple clients to receive a user's message
|
||||
# mod_conversejs: TODO: enable once on 21.12
|
||||
# allows clients like Dino to discover where to upload files
|
||||
mod_disco:
|
||||
server_info:
|
||||
-
|
||||
modules: all
|
||||
name: abuse-addresses
|
||||
urls:
|
||||
- "mailto:admin.xmpp@uninsane.org"
|
||||
- "xmpp:colin@uninsane.org"
|
||||
-
|
||||
modules: all
|
||||
name: admin-addresses
|
||||
urls:
|
||||
- "mailto:admin.xmpp@uninsane.org"
|
||||
- "xmpp:colin@uninsane.org"
|
||||
mod_http_upload:
|
||||
host: upload.xmpp.uninsane.org
|
||||
hosts:
|
||||
- upload.xmpp.uninsane.org
|
||||
put_url: "https://@HOST@:5443/upload"
|
||||
dir_mode: "0750"
|
||||
file_mode: "0750"
|
||||
rm_on_unregister: false
|
||||
# allow discoverability of BOSH and websocket endpoints
|
||||
# TODO: enable once on ejabberd 22.05 (presently 21.04)
|
||||
# mod_host_meta: {}
|
||||
mod_jidprep: {} # probably not needed: lets clients normalize jids
|
||||
mod_last: {} # allow other users to know when i was last online
|
||||
mod_mam:
|
||||
# Mnesia is limited to 2GB, better to use an SQL backend
|
||||
# For small servers SQLite is a good fit and is very easy
|
||||
# to configure. Uncomment this when you have SQL configured:
|
||||
# db_type: sql
|
||||
assume_mam_usage: true
|
||||
default: always
|
||||
mod_muc:
|
||||
access:
|
||||
- allow
|
||||
access_admin:
|
||||
- allow: admin
|
||||
access_create: muc_create
|
||||
access_persistent: muc_create
|
||||
access_mam:
|
||||
- allow
|
||||
history_size: 100 # messages to show new participants
|
||||
host: conference.xmpp.uninsane.org
|
||||
hosts:
|
||||
- conference.xmpp.uninsane.org
|
||||
default_room_options:
|
||||
anonymous: false
|
||||
lang: en
|
||||
persistent: true
|
||||
mam: true
|
||||
mod_muc_admin: {}
|
||||
mod_offline: # store messages for a user when they're offline (TODO: understand multi-client workflow?)
|
||||
access_max_user_messages: max_user_offline_messages
|
||||
store_groupchat: true
|
||||
mod_ping: {}
|
||||
mod_privacy: {} # deprecated, but required for `ejabberctl export_piefxis`
|
||||
mod_private: {} # allow local clients to persist arbitrary data on my server
|
||||
mod_roster:
|
||||
versioning: true
|
||||
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-s2s-dialback>
|
||||
# mod_s2s_dialback: {} # XXX: MIGHT need to enable this to federate with some servers
|
||||
mod_shared_roster: {} # creates groups for @all, @online, and anything manually administered?
|
||||
mod_stream_mgmt:
|
||||
resend_on_timeout: if_offline # resend undelivered messages if the origin client is offline
|
||||
# fallback for when DNS-based STUN discovery is unsupported.
|
||||
# - see: <https://xmpp.org/extensions/xep-0215.html>
|
||||
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-stun-disco>
|
||||
# people say to just keep this defaulted (i guess ejabberd knows to return its `host` option of uninsane.org?)
|
||||
mod_stun_disco: {}
|
||||
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-vcard>
|
||||
mod_vcard:
|
||||
allow_return_all: true # all users are discoverable (?)
|
||||
host: vjid.xmpp.uninsane.org
|
||||
hosts:
|
||||
- vjid.xmpp.uninsane.org
|
||||
search: true
|
||||
mod_vcard_xupdate: {} # needed for avatars
|
||||
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-pubsub>
|
||||
mod_pubsub: # needed for avatars
|
||||
access_createnode: pubsub_createnode_access
|
||||
host: pubsub.xmpp.uninsane.org
|
||||
hosts:
|
||||
- pubsub.xmpp.uninsane.org
|
||||
plugins:
|
||||
- pep
|
||||
# - flat
|
||||
force_node_config:
|
||||
# avoid buggy clients to make their bookmarks public
|
||||
# XXX: not sure if this is necessary: copying config from examples
|
||||
storage:bookmarks:
|
||||
access_model: whitelist
|
||||
mod_version: {}
|
||||
'';
|
||||
}
|
||||
|
@@ -49,4 +49,13 @@
|
||||
# the default ("*:0/5") is to run every 5 minutes.
|
||||
# `systemctl list-timers` to show
|
||||
systemd.services.freshrss-updater.startAt = lib.mkForce "*:3/30";
|
||||
|
||||
services.nginx.virtualHosts."rss.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
# the routing is handled by services.freshrss.virtualHost
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = [ "native" ];
|
||||
}
|
||||
|
@@ -72,4 +72,18 @@
|
||||
"/var/lib/gitea"
|
||||
];
|
||||
};
|
||||
|
||||
# hosted git (web view and for `git <cmd>` use
|
||||
# TODO: enable publog?
|
||||
services.nginx.virtualHosts."git.uninsane.org" = {
|
||||
forceSSL = true; # gitea complains if served over a different protocol than its config file says
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:3000";
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = [ "native" ];
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
|
||||
# hardening
|
||||
WorkingDirectory = "/tmp";
|
||||
@@ -42,4 +43,26 @@
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
# server statistics
|
||||
services.nginx.virtualHosts."sink.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
root = "/var/lib/uninsane/sink";
|
||||
|
||||
locations."/ws" = {
|
||||
proxyPass = "http://127.0.0.1:7890";
|
||||
# XXX not sure how much of this is necessary
|
||||
extraConfig = ''
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 7d;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = [ "native" ];
|
||||
}
|
||||
|
@@ -14,6 +14,28 @@ lib.mkIf false # i don't actively use ipfs anymore
|
||||
# TODO: mode? could be more granular
|
||||
{ user = "261"; group = "261"; directory = "/var/lib/ipfs"; }
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 4001 ];
|
||||
networking.firewall.allowedUDPPorts = [ 4001 ];
|
||||
|
||||
services.nginx.virtualHosts."ipfs.uninsane.org" = {
|
||||
# don't default to ssl upgrades, since this may be dnslink'd from a different domain.
|
||||
# ideally we'd disable ssl entirely, but some places assume it?
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8080";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Ipfs-Gateway-Prefix "";
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = [ "native" ];
|
||||
|
||||
# services.ipfs.enable = true;
|
||||
services.kubo.localDiscovery = true;
|
||||
services.kubo.settings = {
|
||||
|
@@ -7,12 +7,26 @@
|
||||
];
|
||||
services.jackett.enable = true;
|
||||
|
||||
systemd.services.jackett.after = ["wg0veth.service"];
|
||||
systemd.services.jackett.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.jackett.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.jackett.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
# patch jackett to listen on the public interfaces
|
||||
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
|
||||
};
|
||||
|
||||
# jackett torrent search
|
||||
services.nginx.virtualHosts."jackett.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/" = {
|
||||
# proxyPass = "http://ovpns.uninsane.org:9117";
|
||||
proxyPass = "http://10.0.1.6:9117";
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = [ "native" ];
|
||||
}
|
||||
|
||||
|
@@ -1,14 +1,69 @@
|
||||
{ config, ... }:
|
||||
{ config, lib, ... }:
|
||||
|
||||
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
|
||||
# else it's too spammy
|
||||
lib.mkIf false
|
||||
{
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
|
||||
];
|
||||
sane.impermanence.service-dirs = [
|
||||
# TODO: mode? could be more granular
|
||||
{ user = "jellyfin"; group = "jellyfin"; directory = "/var/lib/jellyfin"; }
|
||||
];
|
||||
|
||||
# Jellyfin multimedia server
|
||||
# this is mostly taken from the official jellfin.org docs
|
||||
services.nginx.virtualHosts."jelly.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8096";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
|
||||
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
# locations."/web/" = {
|
||||
# proxyPass = "http://127.0.0.1:8096/web/index.html";
|
||||
# extraConfig = ''
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
# proxy_set_header X-Forwarded-Host $http_host;
|
||||
# '';
|
||||
# };
|
||||
locations."/socket" = {
|
||||
proxyPass = "http://127.0.0.1:8096";
|
||||
extraConfig = ''
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = [ "native" ];
|
||||
|
||||
# users.users.jellyfin.uid = config.sane.allocations.jellyfin-uid;
|
||||
# users.groups.jellyfin.gid = config.sane.allocations.jellyfin-gid;
|
||||
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
|
||||
# else it's too spammy
|
||||
# services.jellyfin.enable = true;
|
||||
services.jellyfin.enable = true;
|
||||
}
|
||||
|
17
hosts/servo/services/kiwix-serve.nix
Normal file
17
hosts/servo/services/kiwix-serve.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{ ... }:
|
||||
{
|
||||
sane.services.kiwix-serve = {
|
||||
enable = true;
|
||||
port = 8013;
|
||||
zimPaths = [ "/var/lib/uninsane/www-archive/wikipedia_en_all_maxi_2022-05.zim" ];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."w.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/".proxyPass = "http://127.0.0.1:8013";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = [ "native" ];
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
# docs: https://nixos.wiki/wiki/Matrix
|
||||
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse
|
||||
{ config, lib, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
@@ -77,6 +77,55 @@
|
||||
# create a token with limited uses:
|
||||
# curl -d '{ "uses_allowed": 1 }' --header "Authorization: Bearer <my_token>" localhost:8008/_synapse/admin/v1/registration_tokens/new
|
||||
|
||||
# matrix chat server
|
||||
# TODO: was `publog`
|
||||
services.nginx.virtualHosts."matrix.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
|
||||
# TODO colin: replace this with something helpful to the viewer
|
||||
# locations."/".extraConfig = ''
|
||||
# return 404;
|
||||
# '';
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8008";
|
||||
};
|
||||
# redirect browsers to the web client.
|
||||
# i don't think native matrix clients ever fetch the root.
|
||||
# ideally this would be put behind some user-agent test though.
|
||||
locations."= /" = {
|
||||
return = "301 https://web.matrix.uninsane.org";
|
||||
};
|
||||
|
||||
# locations."/_matrix" = {
|
||||
# proxyPass = "http://127.0.0.1:8008";
|
||||
# };
|
||||
};
|
||||
|
||||
# matrix web client
|
||||
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-element-web
|
||||
services.nginx.virtualHosts."web.matrix.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
|
||||
root = pkgs.element-web.override {
|
||||
conf = {
|
||||
default_server_config."m.homeserver" = {
|
||||
"base_url" = "https://matrix.uninsane.org";
|
||||
"server_name" = "uninsane.org";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
CNAME."matrix" = [ "native" ];
|
||||
CNAME."web.matrix" = [ "native" ];
|
||||
};
|
||||
|
||||
|
||||
sops.secrets.matrix_synapse_secrets = {
|
||||
sopsFile = ../../../../secrets/servo.yaml;
|
||||
|
@@ -14,4 +14,13 @@
|
||||
AutoImportPlaylists = false;
|
||||
ScanSchedule = "@every 1h";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."music.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/".proxyPass = "http://127.0.0.1:4533";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = [ "native" ];
|
||||
}
|
||||
|
@@ -9,9 +9,12 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
kTLS = true; # in-kernel TLS for better perf
|
||||
# kTLS = true; # in-kernel TLS for better perf
|
||||
in
|
||||
{
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.appendConfig = ''
|
||||
# use 1 process per core.
|
||||
@@ -45,7 +48,7 @@ in
|
||||
# and things don't look right. so force SSL.
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
# inherit kTLS;
|
||||
# for OCSP stapling
|
||||
sslTrustedCertificate = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
@@ -93,246 +96,6 @@ in
|
||||
# };
|
||||
};
|
||||
|
||||
# server statistics
|
||||
services.nginx.virtualHosts."sink.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
root = "/var/lib/uninsane/sink";
|
||||
|
||||
locations."/ws" = {
|
||||
proxyPass = "http://127.0.0.1:7890";
|
||||
# XXX not sure how much of this is necessary
|
||||
extraConfig = ''
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_buffering off;
|
||||
proxy_read_timeout 7d;
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
# Pleroma server and web interface
|
||||
services.nginx.virtualHosts."fed.uninsane.org" = publog {
|
||||
forceSSL = true; # pleroma redirects to https anyway
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4000";
|
||||
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
|
||||
extraConfig = ''
|
||||
# XXX colin: this block is in the nixos examples: i don't understand all of it
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always;
|
||||
if ($request_method = OPTIONS) {
|
||||
return 204;
|
||||
}
|
||||
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Referrer-Policy same-origin;
|
||||
add_header X-Download-Options noopen;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
# proxy_set_header Host $http_host;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
# colin: added this due to Pleroma complaining in its logs
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
client_max_body_size 16m;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# transmission web client
|
||||
services.nginx.virtualHosts."bt.uninsane.org" = {
|
||||
# basicAuth is literally cleartext user/pw, so FORCE this to happen over SSL
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
locations."/" = {
|
||||
# proxyPass = "http://ovpns.uninsane.org:9091";
|
||||
proxyPass = "http://10.0.1.6:9091";
|
||||
};
|
||||
};
|
||||
|
||||
# jackett torrent search
|
||||
services.nginx.virtualHosts."jackett.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
locations."/" = {
|
||||
# proxyPass = "http://ovpns.uninsane.org:9117";
|
||||
proxyPass = "http://10.0.1.6:9117";
|
||||
};
|
||||
};
|
||||
|
||||
# matrix chat server
|
||||
services.nginx.virtualHosts."matrix.uninsane.org" = publog {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
|
||||
# TODO colin: replace this with something helpful to the viewer
|
||||
# locations."/".extraConfig = ''
|
||||
# return 404;
|
||||
# '';
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8008";
|
||||
};
|
||||
# redirect browsers to the web client.
|
||||
# i don't think native matrix clients ever fetch the root.
|
||||
# ideally this would be put behind some user-agent test though.
|
||||
locations."= /" = {
|
||||
return = "301 https://web.matrix.uninsane.org";
|
||||
};
|
||||
|
||||
# locations."/_matrix" = {
|
||||
# proxyPass = "http://127.0.0.1:8008";
|
||||
# };
|
||||
};
|
||||
|
||||
# matrix web client
|
||||
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-element-web
|
||||
services.nginx.virtualHosts."web.matrix.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
|
||||
root = pkgs.element-web.override {
|
||||
conf = {
|
||||
default_server_config."m.homeserver" = {
|
||||
"base_url" = "https://matrix.uninsane.org";
|
||||
"server_name" = "uninsane.org";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# hosted git (web view and for `git <cmd>` use
|
||||
services.nginx.virtualHosts."git.uninsane.org" = publog {
|
||||
forceSSL = true; # gitea complains if served over a different protocol than its config file says
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:3000";
|
||||
};
|
||||
};
|
||||
|
||||
# Jellyfin multimedia server
|
||||
# this is mostly taken from the official jellfin.org docs
|
||||
services.nginx.virtualHosts."jelly.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8096";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
|
||||
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
# locations."/web/" = {
|
||||
# proxyPass = "http://127.0.0.1:8096/web/index.html";
|
||||
# extraConfig = ''
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
# proxy_set_header X-Forwarded-Host $http_host;
|
||||
# '';
|
||||
# };
|
||||
locations."/socket" = {
|
||||
proxyPass = "http://127.0.0.1:8096";
|
||||
extraConfig = ''
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."music.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
locations."/".proxyPass = "http://127.0.0.1:4533";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."rss.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
# the routing is handled by freshrss.nix
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."ipfs.uninsane.org" = {
|
||||
# don't default to ssl upgrades, since this may be dnslink'd from a different domain.
|
||||
# ideally we'd disable ssl entirely, but some places assume it?
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8080";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Ipfs-Gateway-Prefix "";
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# exists only to manage certs for dovecot
|
||||
services.nginx.virtualHosts."imap.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
# exists only to manage certs for Postfix
|
||||
services.nginx.virtualHosts."mx.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
services.nginx.virtualHosts."nixcache.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
inherit kTLS;
|
||||
# serverAliases = [ "nixcache" ];
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://localhost:${toString config.services.nix-serve.port};
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
'';
|
||||
};
|
||||
|
||||
# serve any site not listed above, if it's static.
|
||||
# because we define it dynamically, SSL isn't trivial. support only http
|
||||
|
21
hosts/servo/services/nixserve.nix
Normal file
21
hosts/servo/services/nixserve.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
services.nginx.virtualHosts."nixcache.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
# serverAliases = [ "nixcache" ];
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://localhost:${toString config.services.nix-serve.port};
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
'';
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = [ "native" ];
|
||||
|
||||
sane.services.nixserve.enable = true;
|
||||
sane.services.nixserve.sopsFile = ../../../secrets/servo.yaml;
|
||||
}
|
@@ -127,6 +127,7 @@
|
||||
systemd.services.pleroma.serviceConfig = {
|
||||
# postgres can be slow to service early requests, preventing pleroma from starting on the first try
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
|
||||
# systemd.services.pleroma.serviceConfig = {
|
||||
@@ -136,6 +137,50 @@
|
||||
# CapabilityBoundingSet = lib.mkForce "~";
|
||||
# };
|
||||
|
||||
# Pleroma server and web interface
|
||||
# TODO: enable publog?
|
||||
services.nginx.virtualHosts."fed.uninsane.org" = {
|
||||
forceSSL = true; # pleroma redirects to https anyway
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:4000";
|
||||
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
|
||||
extraConfig = ''
|
||||
# XXX colin: this block is in the nixos examples: i don't understand all of it
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always;
|
||||
if ($request_method = OPTIONS) {
|
||||
return 204;
|
||||
}
|
||||
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Referrer-Policy same-origin;
|
||||
add_header X-Download-Options noopen;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
# proxy_set_header Host $http_host;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
# colin: added this due to Pleroma complaining in its logs
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
client_max_body_size 16m;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = [ "native" ];
|
||||
|
||||
sops.secrets.pleroma_secrets = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
owner = config.users.users.pleroma.name;
|
||||
|
@@ -25,6 +25,61 @@ in
|
||||
# "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
|
||||
# "/var/lib/dovecot"
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
25 # SMTP
|
||||
143 # IMAP
|
||||
465 # SMTPS
|
||||
587 # SMTPS/submission
|
||||
993 # IMAPS
|
||||
];
|
||||
|
||||
# exists only to manage certs for dovecot
|
||||
services.nginx.virtualHosts."imap.uninsane.org" = {
|
||||
enableACME = true;
|
||||
};
|
||||
# exists only to manage certs for Postfix
|
||||
services.nginx.virtualHosts."mx.uninsane.org" = {
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
MX."@" = [ "10 mx.uninsane.org." ];
|
||||
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
||||
A."mx" = [ "185.157.162.178" ];
|
||||
CNAME."imap" = [ "native" ];
|
||||
|
||||
# Sender Policy Framework:
|
||||
# +mx => mail passes if it originated from the MX
|
||||
# +a => mail passes if it originated from the A address of this domain
|
||||
# +ip4:.. => mail passes if it originated from this IP
|
||||
# -all => mail fails if none of these conditions were met
|
||||
TXT."@" = [ "v=spf1 a mx -all" ];
|
||||
|
||||
# DKIM public key:
|
||||
TXT."mx._domainkey" = [
|
||||
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
|
||||
];
|
||||
|
||||
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
|
||||
# p=none|quarantine|reject: what to do with failures
|
||||
# sp = p but for subdomains
|
||||
# rua = where to send aggregrate reports
|
||||
# ruf = where to send individual failure reports
|
||||
# fo=0|1|d|s controls WHEN to send failure reports
|
||||
# (1=on bad alignment; d=on DKIM failure; s=on SPF failure);
|
||||
# Additionally:
|
||||
# adkim=r|s (is DKIM relaxed [default] or strict)
|
||||
# aspf=r|s (is SPF relaxed [default] or strict)
|
||||
# pct = sampling ratio for punishing failures (default 100 for 100%)
|
||||
# rf = report format
|
||||
# ri = report interval
|
||||
TXT."_dmarc" = [
|
||||
"v=DMARC1;p=quarantine;sp=reject;rua=mailto:admin+mail@uninsane.org;ruf=mailto:admin+mail@uninsane.org;fo=1:d:s"
|
||||
];
|
||||
};
|
||||
|
||||
services.postfix.enable = true;
|
||||
services.postfix.hostname = "mx.uninsane.org";
|
||||
services.postfix.origin = "uninsane.org";
|
||||
@@ -55,7 +110,8 @@ in
|
||||
services.postfix.enableSubmissions = true;
|
||||
services.postfix.submissionsOptions = submissionOptions;
|
||||
|
||||
systemd.services.postfix.after = [ "wg0veth.service" ];
|
||||
systemd.services.postfix.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.postfix.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.postfix.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
@@ -76,7 +132,8 @@ in
|
||||
# keeping this the same as the hostname seems simplest
|
||||
services.opendkim.selector = "mx";
|
||||
|
||||
systemd.services.opendkim.after = [ "wg0veth.service" ];
|
||||
systemd.services.opendkim.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.opendkim.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.opendkim.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
|
@@ -1,3 +1,5 @@
|
||||
# example configs:
|
||||
# - <https://github.com/kittywitch/nixfiles/blob/main/services/prosody.nix>
|
||||
# create users with:
|
||||
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
|
||||
|
||||
@@ -13,7 +15,7 @@ lib.mkIf false
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
5222 # XMPP client -> server
|
||||
5269 # XMPP server -> server
|
||||
5280 # Prosody HTTP port (necessary?)
|
||||
5280 # bosh
|
||||
5281 # Prosody HTTPS port (necessary?)
|
||||
];
|
||||
|
||||
@@ -34,7 +36,7 @@ lib.mkIf false
|
||||
# c2s_require_encryption = true
|
||||
# '';
|
||||
|
||||
# extraModules = [ "private" "vcard" "privacy" "compression" "component" "muc" "pep" "adhoc" "lastactivity" "admin_adhoc" "blocklist"];
|
||||
extraModules = [ "private" "vcard" "privacy" "compression" "component" "muc" "pep" "adhoc" "lastactivity" "admin_adhoc" "blocklist"];
|
||||
|
||||
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
|
||||
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
|
||||
@@ -51,7 +53,7 @@ lib.mkIf false
|
||||
domain = "localhost";
|
||||
enabled = true;
|
||||
};
|
||||
"uninsane.org" = {
|
||||
"xmpp.uninsane.org" = {
|
||||
domain = "uninsane.org";
|
||||
enabled = true;
|
||||
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.service-dirs = [
|
||||
@@ -40,11 +40,41 @@
|
||||
# transmission will by default not allow the world to read its files.
|
||||
services.transmission.downloadDirPermissions = "775";
|
||||
|
||||
systemd.services.transmission.after = ["wg0veth.service"];
|
||||
systemd.services.transmission.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.transmission.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.transmission.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
LogLevelMax = "warning";
|
||||
};
|
||||
|
||||
# service to automatically backup torrents i add to transmission
|
||||
systemd.services.backup-torrents = {
|
||||
description = "archive torrents to storage not owned by transmission";
|
||||
script = ''
|
||||
${pkgs.rsync}/bin/rsync -arv /var/lib/transmission/.config/transmission-daemon/torrents/ /var/backup/torrents/
|
||||
'';
|
||||
};
|
||||
systemd.timers.backup-torrents = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
timerConfig = {
|
||||
OnStartupSec = "11min";
|
||||
OnUnitActiveSec = "240min";
|
||||
};
|
||||
};
|
||||
|
||||
# transmission web client
|
||||
services.nginx.virtualHosts."bt.uninsane.org" = {
|
||||
# basicAuth is literally cleartext user/pw, so FORCE this to happen over SSL
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
locations."/" = {
|
||||
# proxyPass = "http://ovpns.uninsane.org:9091";
|
||||
proxyPass = "http://10.0.1.6:9091";
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = ["native"];
|
||||
}
|
||||
|
||||
|
69
hosts/servo/services/trust-dns.nix
Normal file
69
hosts/servo/services/trust-dns.nix
Normal file
@@ -0,0 +1,69 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.services.trust-dns.enable = true;
|
||||
|
||||
sane.services.trust-dns.listenAddrsIPv4 = [
|
||||
# specify each address explicitly, instead of using "*".
|
||||
# this ensures responses are sent from the address at which the request was received.
|
||||
"192.168.0.5"
|
||||
"10.0.1.5"
|
||||
];
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
||||
|
||||
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
|
||||
# SOA MNAME RNAME (... rest)
|
||||
# MNAME = Master name server for this zone. this is where update requests should be sent.
|
||||
# RNAME = admin contact (encoded email address)
|
||||
# Serial = YYYYMMDDNN, where N is incremented every time this file changes, to trigger secondary NS to re-fetch it.
|
||||
# Refresh = how frequently secondary NS should query master
|
||||
# Retry = how long secondary NS should wait until re-querying master after a failure (must be < Refresh)
|
||||
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
SOA."@" = [''
|
||||
ns1.uninsane.org. admin-dns.uninsane.org. (
|
||||
2022121601 ; Serial
|
||||
4h ; Refresh
|
||||
30m ; Retry
|
||||
7d ; Expire
|
||||
5m) ; Negative response TTL
|
||||
''];
|
||||
TXT."rev" = [ "2022121801" ];
|
||||
|
||||
# XXX NS records must also not be CNAME
|
||||
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
||||
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
||||
# A."ns1" = [ "%NATIVE%" ];
|
||||
A."ns2" = [ "185.157.162.178" ];
|
||||
A."ns3" = [ "185.157.162.178" ];
|
||||
A."ovpns" = [ "185.157.162.178" ];
|
||||
NS."@" = [
|
||||
"ns1.uninsane.org."
|
||||
"ns2.uninsane.org."
|
||||
"ns3.uninsane.org."
|
||||
];
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".include = [
|
||||
"/var/lib/trust-dns/native.uninsane.org.zone"
|
||||
];
|
||||
|
||||
systemd.services.trust-dns.preStart = let
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
zone-dir = "/var/lib/trust-dns";
|
||||
zone-out = "${zone-dir}/native.uninsane.org.zone";
|
||||
zone-template = pkgs.writeText "native.uninsane.org.zone.in" ''
|
||||
@ A %NATIVE%
|
||||
ns1 A %NATIVE%
|
||||
native A %NATIVE%
|
||||
'';
|
||||
in ''
|
||||
# make WAN records available to trust-dns
|
||||
mkdir -p ${zone-dir}
|
||||
ip=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
||||
${sed} s/%NATIVE%/$ip/ ${zone-template} > ${zone-out}
|
||||
'';
|
||||
|
||||
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
||||
}
|
33
hosts/servo/services/wikipedia.nix
Normal file
33
hosts/servo/services/wikipedia.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
# docs: <https://nixos.wiki/wiki/MediaWiki>
|
||||
{ config, lib, ... }:
|
||||
|
||||
# XXX: working to host wikipedia with kiwix instead of mediawiki
|
||||
# mediawiki does more than i need and isn't obviously superior in any way
|
||||
# except that the dumps are more frequent/up-to-date.
|
||||
lib.mkIf false
|
||||
{
|
||||
sops.secrets."mediawiki_pw" = {
|
||||
owner = config.users.users.mediawiki.name;
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
};
|
||||
|
||||
users.users.mediawiki.uid = config.sane.allocations.mediawiki-uid;
|
||||
|
||||
services.mediawiki.enable = true;
|
||||
services.mediawiki.name = "Uninsane Wiki";
|
||||
services.mediawiki.passwordFile = config.sops.secrets.mediawiki_pw.path;
|
||||
services.mediawiki.extraConfig = ''
|
||||
# Disable anonymous editing
|
||||
$wgGroupPermissions['*']['edit'] = false;
|
||||
'';
|
||||
services.mediawiki.virtualHost.listen = [
|
||||
{
|
||||
ip = "127.0.0.1";
|
||||
port = 8013;
|
||||
ssl = false;
|
||||
}
|
||||
];
|
||||
services.mediawiki.virtualHost.hostName = "w.uninsane.org";
|
||||
services.mediawiki.virtualHost.adminAddr = "admin+mediawiki@uninsane.org";
|
||||
# services.mediawiki.extensions = TODO: wikipedia sync extension?
|
||||
}
|
@@ -23,8 +23,10 @@ in
|
||||
sane.allocations.greeter-uid = mkId 999;
|
||||
sane.allocations.greeter-gid = mkId 999;
|
||||
|
||||
# new servo users
|
||||
sane.allocations.freshrss-uid = mkId 2401;
|
||||
sane.allocations.freshrss-gid = mkId 2401;
|
||||
sane.allocations.mediawiki-uid = mkId 2402;
|
||||
|
||||
sane.allocations.colin-uid = mkId 1000;
|
||||
sane.allocations.guest-uid = mkId 1100;
|
||||
|
9
modules/gui/snippets.txt
Normal file
9
modules/gui/snippets.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
https://search.nixos.org/packages?channel=unstable&query=
|
||||
https://nixos.wiki/index.php?go=Go&search=
|
||||
https://github.com/nixos/nixpkgs/pulls?q=
|
||||
https://w.uninsane.org/viewer#search?books.name=wikipedia_en_all_maxi_2022-05&pattern=
|
||||
https://fed.uninsane.org
|
||||
https://jackett.uninsane.org
|
||||
https://bt.uninsane.org
|
||||
https://sci-hub.se
|
||||
https://news.ycombinator.com
|
@@ -81,8 +81,25 @@ in
|
||||
sane.home-manager.windowManager.sway = {
|
||||
enable = true;
|
||||
wrapperFeatures.gtk = true;
|
||||
config = rec {
|
||||
terminal = "${pkgs.kitty}/bin/kitty";
|
||||
config = let
|
||||
fuzzel = "${pkgs.fuzzel}/bin/fuzzel";
|
||||
wtype = "${pkgs.wtype}/bin/wtype";
|
||||
kitty = "${pkgs.kitty}/bin/kitty";
|
||||
lock-cmd = "${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
|
||||
vol-up-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5";
|
||||
vol-down-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5";
|
||||
mute-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --toggle-mute";
|
||||
brightness-up-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set +2%";
|
||||
brightness-down-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set 2%-";
|
||||
screenshot-cmd = "${pkgs.sway-contrib.grimshot}/bin/grimshot copy area";
|
||||
# "bookmarking"/snippets inspired by Luke Smith:
|
||||
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>
|
||||
snip-file = ./snippets.txt;
|
||||
snip-cmd = "${wtype} $(cat ${snip-file} | ${fuzzel} -d -i)";
|
||||
# TODO: next splatmoji release should allow `-s none` to disable skin tones
|
||||
emoji-cmd = "${pkgs.splatmoji}/bin/splatmoji -s medium-light type";
|
||||
in rec {
|
||||
terminal = kitty;
|
||||
window = {
|
||||
border = 3; # pixel boundary between windows
|
||||
hideEdgeBorders = "smart"; # don't show border if only window on workspace
|
||||
@@ -103,7 +120,7 @@ in
|
||||
modifier = "Mod1";
|
||||
# list of launchers: https://www.reddit.com/r/swaywm/comments/v39hxa/your_favorite_launcher/
|
||||
# menu = "${pkgs.dmenu}/bin/dmenu_path";
|
||||
menu = "${pkgs.fuzzel}/bin/fuzzel";
|
||||
menu = fuzzel;
|
||||
# menu = "${pkgs.albert}/bin/albert";
|
||||
left = "h";
|
||||
down = "j";
|
||||
@@ -114,7 +131,9 @@ in
|
||||
"${modifier}+Return" = "exec ${terminal}";
|
||||
"${modifier}+Shift+q" = "kill";
|
||||
"${modifier}+d" = "exec ${menu}";
|
||||
"${modifier}+l" = "exec ${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
|
||||
"${modifier}+s" = "exec ${snip-cmd}";
|
||||
"${modifier}+l" = "exec ${lock-cmd}";
|
||||
"${modifier}+slash" = "exec ${emoji-cmd}";
|
||||
|
||||
# "${modifier}+${left}" = "focus left";
|
||||
# "${modifier}+${down}" = "focus down";
|
||||
@@ -141,7 +160,7 @@ in
|
||||
"${modifier}+f" = "fullscreen toggle";
|
||||
"${modifier}+a" = "focus parent";
|
||||
|
||||
"${modifier}+s" = "layout stacking";
|
||||
# "${modifier}+s" = "layout stacking";
|
||||
"${modifier}+w" = "layout tabbed";
|
||||
"${modifier}+e" = "layout toggle split";
|
||||
|
||||
@@ -185,19 +204,20 @@ in
|
||||
"exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'";
|
||||
|
||||
"${modifier}+r" = "mode resize";
|
||||
} // {
|
||||
|
||||
# media keys
|
||||
XF86MonBrightnessDown = ''exec "${pkgs.brightnessctl}/bin/brightnessctl set 2%-"'';
|
||||
XF86MonBrightnessUp = ''exec "${pkgs.brightnessctl}/bin/brightnessctl set +2%"'';
|
||||
XF86MonBrightnessDown = "exec ${brightness-down-cmd}";
|
||||
XF86MonBrightnessUp = "exec ${brightness-up-cmd}";
|
||||
|
||||
XF86AudioRaiseVolume = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5'";
|
||||
XF86AudioLowerVolume = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5'";
|
||||
XF86AudioMute = "exec '${pkgs.pulsemixer}/bin/pulsemixer --toggle-mute'";
|
||||
# TODO: hook into a visual prompt to display volume?
|
||||
XF86AudioRaiseVolume = "exec ${vol-up-cmd}";
|
||||
XF86AudioLowerVolume = "exec ${vol-down-cmd}";
|
||||
XF86AudioMute = "exec ${mute-cmd}";
|
||||
|
||||
"${modifier}+Page_Up" = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5'";
|
||||
"${modifier}+Page_Down" = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5'";
|
||||
"${modifier}+Page_Up" = "exec ${vol-up-cmd}";
|
||||
"${modifier}+Page_Down" = "exec ${vol-down-cmd}";
|
||||
|
||||
"${modifier}+Print" = "exec '${pkgs.sway-contrib.grimshot}/bin/grimshot copy area'";
|
||||
"${modifier}+Print" = "exec ${screenshot-cmd}";
|
||||
};
|
||||
|
||||
# mostly defaults:
|
||||
|
@@ -26,6 +26,7 @@ in
|
||||
./mpv.nix
|
||||
./nb.nix
|
||||
./neovim.nix
|
||||
./splatmoji.nix
|
||||
./ssh.nix
|
||||
./sublime-music.nix
|
||||
./vlc.nix
|
||||
|
@@ -63,6 +63,10 @@ in rec {
|
||||
(mkPod "https://www.cbsnews.com/latest/rss/60-minutes" // pol // infrequent)
|
||||
## The Verge - Decoder
|
||||
(mkPod "https://feeds.megaphone.fm/recodedecode" // tech // weekly)
|
||||
## Matrix (chat) Live
|
||||
(mkPod "https://feed.podbean.com/matrixlive/feed.xml" // tech // weekly)
|
||||
## Michael Malice - Your Welcome
|
||||
(mkPod "https://www.podcastone.com/podcast?categoryID2=2232" // pol // weekly)
|
||||
];
|
||||
|
||||
texts = [
|
||||
|
@@ -43,6 +43,7 @@ let
|
||||
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
|
||||
inherit name hash;
|
||||
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
|
||||
# extid can be found by unar'ing the above xpi, and copying browser_specific_settings.gecko.id field
|
||||
fixedExtid = extid;
|
||||
};
|
||||
localAddon = pkg: pkgs.fetchFirefoxAddon {
|
||||
@@ -51,11 +52,16 @@ let
|
||||
fixedExtid = pkg.extid;
|
||||
};
|
||||
in [
|
||||
# get names from:
|
||||
# - ~/ref/nix-community/nur-combined/repos/rycee/pkgs/firefox-addons/generated-firefox-addons.nix
|
||||
# `wget ...xpi`; `unar ...xpi`; `cat */manifest.json | jq '.browser_specific_settings.gecko.id'`
|
||||
(addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-+xc4lcdsOwXxMsr4enFsdePbIb6GHq0bFLpqvH5xXos=")
|
||||
(addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-30F8oDIgshXVY7YKgnfoc1tUTHfgeFbzXISJuVJs0AM=")
|
||||
(addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-aDBRpcOeMyROnXjmveHKm9zsPC+LzXCG0uhAqI1EWf0=")
|
||||
(addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-7ZDkG8O1rEYdh/La0PLi9tp92JxYeQvaOFt/BmnDv3U=")
|
||||
(addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=")
|
||||
(addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=")
|
||||
(addon "ublacklist" "@ublacklist" "sha256-vHe/7EYOzcKeAbTElmt0Rb4E2rX0f3JgXThJaUmaz+M=")
|
||||
(addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=")
|
||||
# (addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=")
|
||||
(localAddon pkgs.browserpass-extension)
|
||||
];
|
||||
|
20
modules/home-manager/splatmoji.nix
Normal file
20
modules/home-manager/splatmoji.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
# borrows from:
|
||||
# - default config: <https://github.com/cspeterson/splatmoji/blob/master/splatmoji.config>
|
||||
# - wayland: <https://github.com/cspeterson/splatmoji/issues/32#issuecomment-830862566>
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
home-manager.users.colin = {
|
||||
xdg.configFile."splatmoji/splatmoji.config".text = ''
|
||||
history_file=/home/colin/.local/state/splatmoji/history
|
||||
history_length=5
|
||||
# TODO: wayland equiv
|
||||
paste_command=xdotool key ctrl+v
|
||||
# rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null
|
||||
rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 80
|
||||
xdotool_command=${pkgs.wtype}/bin/wtype
|
||||
# TODO: wayland equiv
|
||||
xsel_command=xsel -b -i
|
||||
'';
|
||||
};
|
||||
}
|
@@ -59,5 +59,12 @@ lib.mkIf config.sane.home-manager.enable
|
||||
# common typos
|
||||
"cd.." = "cd ..";
|
||||
"cd../" = "cd ../";
|
||||
# convenient `cd`-isms
|
||||
"knowledge" = "cd ~/knowledge";
|
||||
"nixos" = "cd ~/nixos";
|
||||
"nixpkgs" = "cd ~/dev/3rd/nixpkgs";
|
||||
"ref" = "cd ~/ref";
|
||||
"secrets" = "cd ~/knowledge/secrets";
|
||||
"uninsane" = "cd ~/dev/uninsane";
|
||||
};
|
||||
}
|
||||
|
@@ -50,6 +50,7 @@ in
|
||||
# "/var/lib/AccountsService" # not sure what this is, but it's empty
|
||||
"/var/lib/alsa" # preserve output levels, default devices
|
||||
# "/var/lib/blueman" # files aren't human readable
|
||||
# TODO: if we changed the bluetooth installer to auto-discover the host MAC address, we could de-persist this
|
||||
"/var/lib/bluetooth" # preserve bluetooth handshakes
|
||||
"/var/lib/colord" # preserve color calibrations (?)
|
||||
# "/var/lib/dhclient" # empty on lappy; dunno about desko
|
||||
|
@@ -4,6 +4,11 @@ with lib;
|
||||
with pkgs;
|
||||
let
|
||||
cfg = config.sane.packages;
|
||||
|
||||
imagemagick = pkgs.imagemagick.override {
|
||||
ghostscriptSupport = true;
|
||||
};
|
||||
|
||||
consolePkgs = [
|
||||
backblaze-b2
|
||||
cdrtools
|
||||
@@ -12,11 +17,13 @@ let
|
||||
efivar
|
||||
flashrom
|
||||
fwupd
|
||||
ghostscript # TODO: imagemagick wrapper should add gs to PATH
|
||||
gnupg
|
||||
gocryptfs
|
||||
gopass
|
||||
gopass-jsonapi
|
||||
ifuse
|
||||
imagemagick
|
||||
ipfs
|
||||
libimobiledevice
|
||||
libsecret # for managing user keyrings
|
||||
@@ -80,6 +87,7 @@ let
|
||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
||||
{ pkg = fractal-next; private = ".local/share/fractal"; }
|
||||
|
||||
gajim # XMPP client
|
||||
gimp # broken on phosh
|
||||
gnome.cheese
|
||||
gnome.dconf-editor
|
||||
@@ -153,7 +161,7 @@ let
|
||||
|
||||
# kaiteki # Pleroma client
|
||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
||||
gpt2tc
|
||||
# gpt2tc # XXX: unreliable mirror
|
||||
|
||||
logseq
|
||||
losslesscut-bin
|
||||
@@ -203,11 +211,14 @@ let
|
||||
parted
|
||||
pciutils
|
||||
powertop
|
||||
pstree
|
||||
ripgrep
|
||||
screen
|
||||
smartmontools
|
||||
socat
|
||||
strace
|
||||
tcpdump
|
||||
tree
|
||||
usbutils
|
||||
wget
|
||||
];
|
||||
|
@@ -2,6 +2,9 @@
|
||||
{
|
||||
imports = [
|
||||
./duplicity.nix
|
||||
./dyn-dns.nix
|
||||
./kiwix-serve.nix
|
||||
./nixserve.nix
|
||||
./trust-dns.nix
|
||||
];
|
||||
}
|
||||
|
91
modules/services/dyn-dns.nix
Normal file
91
modules/services/dyn-dns.nix
Normal file
@@ -0,0 +1,91 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.sane.services.dyn-dns;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.services.dyn-dns = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
ipPath = mkOption {
|
||||
default = "/var/lib/uninsane/wan.txt";
|
||||
type = types.str;
|
||||
description = "where to store the latest WAN IPv4 address";
|
||||
};
|
||||
|
||||
ipCmd = mkOption {
|
||||
default = "${pkgs.sane-scripts}/bin/sane-ip-check-router-wan";
|
||||
type = types.path;
|
||||
description = "command to run to query the current WAN IP";
|
||||
};
|
||||
|
||||
interval = mkOption {
|
||||
type = types.str;
|
||||
default = "10min";
|
||||
description = "systemd time string for how frequently to re-check the IP";
|
||||
};
|
||||
|
||||
restartOnChange = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "list of systemd unit files to restart when the IP changes";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.dyn-dns = {
|
||||
description = "update this host's record of its WAN IP";
|
||||
serviceConfig.Type = "oneshot";
|
||||
restartTriggers = [(builtins.toJSON cfg)];
|
||||
|
||||
after = [ "network.target" ];
|
||||
wantedBy = cfg.restartOnChange;
|
||||
before = cfg.restartOnChange;
|
||||
|
||||
script = ''
|
||||
mkdir -p "$(dirname '${cfg.ipPath}')"
|
||||
newIp=$(${cfg.ipCmd})
|
||||
oldIp=$(cat '${cfg.ipPath}' || true)
|
||||
# systemd path units are triggered on any file write action,
|
||||
# regardless of content change. so only update the file if our IP *actually* changed
|
||||
if [ "$newIp" != "$oldIp" ]
|
||||
then
|
||||
echo "$newIp" > '${cfg.ipPath}'
|
||||
echo "WAN ip changed $oldIp -> $newIp"
|
||||
fi
|
||||
exit $(test -f '${cfg.ipPath}')
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.timers.dyn-dns = {
|
||||
# if anything wants dyn-dns.service, they surely want the timer too.
|
||||
wantedBy = [ "dyn-dns.service" ];
|
||||
timerConfig = {
|
||||
OnUnitActiveSec = cfg.interval;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.paths.dyn-dns-watcher = {
|
||||
before = [ "dyn-dns.timer" ];
|
||||
wantedBy = [ "dyn-dns.timer" ];
|
||||
pathConfig = {
|
||||
Unit = "dyn-dns-reactor.service";
|
||||
PathChanged = [ cfg.ipPath ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.dyn-dns-reactor = {
|
||||
description = "react to the system's WAN IP changing";
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = if cfg.restartOnChange != [] then ''
|
||||
${pkgs.systemd}/bin/systemctl restart ${toString cfg.restartOnChange}
|
||||
'' else "${pkgs.coreutils}/bin/true";
|
||||
};
|
||||
};
|
||||
}
|
55
modules/services/kiwix-serve.nix
Normal file
55
modules/services/kiwix-serve.nix
Normal file
@@ -0,0 +1,55 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.sane.services.kiwix-serve;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.services.kiwix-serve = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.kiwix-tools;
|
||||
defaultText = literalExpression "pkgs.kiwix-tools";
|
||||
description = lib.mdDoc ''
|
||||
The package that provides `bin/kiwix-serve`.
|
||||
'';
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 80;
|
||||
description = lib.mdDoc "Port number to listen on.";
|
||||
};
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
IP address to listen on. Listens on all available addresses if unspecified.
|
||||
'';
|
||||
};
|
||||
zimPaths = mkOption {
|
||||
type = types.nonEmptyListOf (types.either types.str types.path);
|
||||
description = lib.mdDoc "ZIM file path(s)";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.kiwix-serve = {
|
||||
description = "Deliver ZIM file(s) articles via HTTP";
|
||||
serviceConfig = let
|
||||
maybeListenAddress = lib.optionals (cfg.listenAddress != null) ["-l" cfg.listenAddress];
|
||||
args = maybeListenAddress ++ ["-p" cfg.port] ++ cfg.zimPaths;
|
||||
in {
|
||||
ExecStart = "${cfg.package}/bin/kiwix-serve ${lib.escapeShellArgs args}";
|
||||
Type = "simple";
|
||||
};
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
}
|
144
modules/services/trust-dns.nix
Normal file
144
modules/services/trust-dns.nix
Normal file
@@ -0,0 +1,144 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.sane.services.trust-dns;
|
||||
toml = pkgs.formats.toml { };
|
||||
fmtRecord = proto: rrtype: name: value: "${name}\t${proto}\t${rrtype}\t${value}";
|
||||
fmtRecordList = proto: rrtype: name: values: concatStringsSep
|
||||
"\n"
|
||||
(map (fmtRecord proto rrtype name) values)
|
||||
;
|
||||
fmtRecordAttrs = proto: rrtype: rrAttrs:
|
||||
concatStringsSep
|
||||
"\n"
|
||||
(
|
||||
attrValues (
|
||||
mapAttrs
|
||||
(name: fmtRecordList proto rrtype name)
|
||||
rrAttrs
|
||||
)
|
||||
);
|
||||
fmtIncludes = paths: concatStringsSep
|
||||
"\n"
|
||||
(map (path: "$INCLUDE ${path}") paths);
|
||||
configFile = toml.generate "trust-dns.toml" {
|
||||
listen_addrs_ipv4 = cfg.listenAddrsIPv4;
|
||||
zones = attrValues (
|
||||
mapAttrs (zone: zcfg: {
|
||||
inherit zone;
|
||||
zone_type = "Primary";
|
||||
file = pkgs.writeText "${zone}.zone" ''
|
||||
$TTL ${toString zcfg.TTL}
|
||||
${fmtRecordAttrs "IN" "SOA" zcfg.inet.SOA}
|
||||
${fmtRecordAttrs "IN" "A" zcfg.inet.A}
|
||||
${fmtRecordAttrs "IN" "CNAME" zcfg.inet.CNAME}
|
||||
${fmtRecordAttrs "IN" "MX" zcfg.inet.MX}
|
||||
${fmtRecordAttrs "IN" "NS" zcfg.inet.NS}
|
||||
${fmtRecordAttrs "IN" "SRV" zcfg.inet.SRV}
|
||||
${fmtRecordAttrs "IN" "TXT" zcfg.inet.TXT}
|
||||
${fmtIncludes zcfg.include}
|
||||
${zcfg.extraConfig}
|
||||
'';
|
||||
}) cfg.zones
|
||||
);
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.services.trust-dns = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
listenAddrsIPv4 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "array of ipv4 addresses on which to listen for DNS queries";
|
||||
};
|
||||
# reference <nixpkgs:nixos/modules/services/web-servers/nginx/vhost-options.nix>
|
||||
zones = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
TTL = mkOption {
|
||||
type = types.int;
|
||||
description = "default TTL";
|
||||
default = 3600;
|
||||
};
|
||||
include = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "paths of other zone files to $INCLUDE into this one";
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
description = "extra lines to append to the zone file";
|
||||
default = "";
|
||||
};
|
||||
inet = {
|
||||
SOA = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "Start of Authority record(s)";
|
||||
default = {};
|
||||
};
|
||||
A = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "IPv4 address record(s)";
|
||||
default = {};
|
||||
};
|
||||
CNAME = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "canonical name record(s)";
|
||||
default = {};
|
||||
};
|
||||
MX = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "mail exchanger record(s)";
|
||||
default = {};
|
||||
};
|
||||
NS = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "name server record(s)";
|
||||
default = {};
|
||||
};
|
||||
SRV = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "service record(s)";
|
||||
default = {};
|
||||
};
|
||||
TXT = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
description = "text record(s)";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
description = "Declarative zone config";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = [ 53 ];
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
systemd.services.trust-dns = {
|
||||
description = "trust-dns DNS server";
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.trust-dns}/bin/named \
|
||||
--config ${configFile} \
|
||||
--zonedir /
|
||||
'';
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
# TODO: hardening (like, don't run as root!)
|
||||
};
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
}
|
26
nixpatches/2022-12-19-i2p-aarch64.patch
Normal file
26
nixpatches/2022-12-19-i2p-aarch64.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
diff --git a/pkgs/tools/networking/i2p/default.nix b/pkgs/tools/networking/i2p/default.nix
|
||||
index e835007fdc5..1406486c7d4 100644
|
||||
--- a/pkgs/tools/networking/i2p/default.nix
|
||||
+++ b/pkgs/tools/networking/i2p/default.nix
|
||||
@@ -50,7 +50,7 @@ stdenv.mkDerivation rec {
|
||||
binaryBytecode # source bundles dependencies as jars
|
||||
];
|
||||
license = licenses.gpl2;
|
||||
- platforms = [ "x86_64-linux" "i686-linux" ];
|
||||
+ platforms = [ "x86_64-linux" "i686-linux" "aarch64-linux" ];
|
||||
maintainers = with maintainers; [ joelmo ];
|
||||
};
|
||||
}
|
||||
diff --git a/pkgs/tools/system/java-service-wrapper/default.nix b/pkgs/tools/system/java-service-wrapper/default.nix
|
||||
index 93d86a75d18..ab563085f93 100644
|
||||
--- a/pkgs/tools/system/java-service-wrapper/default.nix
|
||||
+++ b/pkgs/tools/system/java-service-wrapper/default.nix
|
||||
@@ -44,7 +44,7 @@ stdenv.mkDerivation rec {
|
||||
homepage = "https://wrapper.tanukisoftware.com/";
|
||||
changelog = "https://wrapper.tanukisoftware.com/doc/english/release-notes.html#${version}";
|
||||
license = licenses.gpl2Only;
|
||||
- platforms = [ "x86_64-linux" "i686-linux" ];
|
||||
+ platforms = [ "x86_64-linux" "i686-linux" "aarch64-linux" ];
|
||||
maintainers = [ maintainers.suhr ];
|
||||
};
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
fetchpatch: [
|
||||
{ fakeHash, fetchpatch }: [
|
||||
# librewolf: build with `MOZ_REQUIRE_SIGNING=false`
|
||||
(fetchpatch {
|
||||
url = "https://github.com/NixOS/nixpkgs/pull/199134.diff";
|
||||
@@ -6,6 +6,21 @@ fetchpatch: [
|
||||
sha256 = "sha256-Ne4hyHQDwBHUlWo8Z3QyRdmEv1rYGOjFGxSfOAcLUvQ=";
|
||||
})
|
||||
|
||||
# trust-dns: init at 0.22.0
|
||||
(fetchpatch {
|
||||
# https://git.uninsane.org/colin/nixpkgs/compare/master...pr-trust-dns.diff
|
||||
url = "https://git.uninsane.org/colin/nixpkgs/commit/feee7e0357a74ab0510b2d113a3bdede1d509759.diff";
|
||||
sha256 = "sha256-t4sG+xLDaxbJ/mV5G18N4ag8EC3IXPgtN5FJGANh1Dc=";
|
||||
})
|
||||
|
||||
# kiwix-tools: init at 3.4.0
|
||||
(fetchpatch {
|
||||
url = "https://github.com/NixOS/nixpkgs/pull/206254.diff";
|
||||
sha256 = "sha256-Z4V9mOv4HYg3kDnWoYcxz3ch03I/1USrLjzlq4X9YqI=";
|
||||
})
|
||||
|
||||
./2022-12-19-i2p-aarch64.patch
|
||||
|
||||
# # kaiteki: init at 2022-09-03
|
||||
# vendorHash changes too frequently (might not be reproducible).
|
||||
# using local package defn until stabilized
|
||||
|
@@ -45,6 +45,8 @@
|
||||
browserpass-extension = prev.callPackage ./browserpass-extension { };
|
||||
gopass-native-messaging-host = prev.callPackage ./gopass-native-messaging-host { };
|
||||
tokodon = prev.libsForQt5.callPackage ./tokodon { };
|
||||
splatmoji = prev.callPackage ./splatmoji { };
|
||||
# trust-dns = prev.callPackage ./trust-dns { };
|
||||
# kaiteki = prev.kaiteki;
|
||||
})
|
||||
|
||||
|
@@ -18,16 +18,23 @@ resholve.mkDerivation {
|
||||
scripts = [ "bin/*" ];
|
||||
interpreter = "${pkgs.bash}/bin/bash";
|
||||
inputs = with pkgs; [
|
||||
coreutils
|
||||
# string is interpreted as relative path from @OUT@.
|
||||
# this lets our scripts reference eachother.
|
||||
# see: <https://github.com/abathur/resholve/issues/26>
|
||||
"bin"
|
||||
coreutils-full
|
||||
curl
|
||||
duplicity
|
||||
file
|
||||
findutils
|
||||
gnugrep
|
||||
gnused
|
||||
gocryptfs
|
||||
ifuse
|
||||
inetutils
|
||||
inotify-tools
|
||||
iwd
|
||||
jq
|
||||
ncurses
|
||||
oath-toolkit
|
||||
openssh
|
||||
@@ -36,6 +43,7 @@ resholve.mkDerivation {
|
||||
ssh-to-age
|
||||
sops
|
||||
sudo
|
||||
systemd
|
||||
util-linux
|
||||
which
|
||||
];
|
||||
@@ -49,33 +57,47 @@ resholve.mkDerivation {
|
||||
fake = {
|
||||
external = [
|
||||
# https://github.com/abathur/resholve/issues/29
|
||||
"umount"
|
||||
# "umount"
|
||||
# "/run/wrappers/bin/sudo"
|
||||
"sudo"
|
||||
|
||||
# these are used internally; probably a better fix
|
||||
"sane-mount-servo"
|
||||
"sane-private-unlock"
|
||||
];
|
||||
};
|
||||
fix = {
|
||||
# this replaces umount with the non-setuid-wrapper umount.
|
||||
# not sure if/where that lack of suid causes problems.
|
||||
umount = true;
|
||||
};
|
||||
# prologue is broken; see <https://github.com/abathur/resholve/issues/89>
|
||||
# prologue = "bin/prologue";
|
||||
|
||||
# list of programs which *can* or *cannot* exec their arguments
|
||||
execer = with pkgs; [
|
||||
"cannot:${duplicity}/bin/duplicity"
|
||||
"cannot:${gocryptfs}/bin/gocryptfs"
|
||||
"cannot:${ifuse}/bin/ifuse"
|
||||
"cannot:${iwd}/bin/iwctl"
|
||||
"cannot:${oath-toolkit}/bin/oathtool"
|
||||
"cannot:${openssh}/bin/ssh-keygen"
|
||||
"cannot:${rmlint}/bin/rmlint"
|
||||
"cannot:${rsync}/bin/rsync"
|
||||
"cannot:${sops}/bin/sops"
|
||||
"cannot:${ssh-to-age}/bin/ssh-to-age"
|
||||
"cannot:${systemd}/bin/systemctl"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
patchPhase = ''
|
||||
# remove python scripts
|
||||
# TODO: figure out how to make resholve process only shell scripts
|
||||
rm sane-reclaim-boot-space
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p "$out/bin"
|
||||
cp -R * "$out"/bin/
|
||||
mkdir -p $out/bin
|
||||
cp -R * $out/bin/
|
||||
# allow scripts to make use of sudo, umount wrappers
|
||||
sed -i '3iPATH=$PATH:/run/wrappers/bin' $out/bin/*;
|
||||
'';
|
||||
|
||||
meta = {
|
||||
|
3
pkgs/sane-scripts/src/sane-ip-check
Executable file
3
pkgs/sane-scripts/src/sane-ip-check
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
curl https://ipinfo.io/ip
|
||||
echo
|
15
pkgs/sane-scripts/src/sane-ip-check-router-wan
Executable file
15
pkgs/sane-scripts/src/sane-ip-check-router-wan
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# query the WAN IP address OF MY ROUTER
|
||||
# requires creds
|
||||
passwd=$(sudo cat /run/secrets/router_passwd)
|
||||
cookie=$(mktemp)
|
||||
|
||||
# authenticate
|
||||
curl -s --insecure --cookie-jar $cookie \
|
||||
--data "username=admin&password=$passwd" \
|
||||
https://192.168.0.1
|
||||
# query the WAN IP
|
||||
curl -s --insecure --cookie $cookie \
|
||||
-H "X-Requested-With: XMLHttpRequest" \
|
||||
"https://192.168.0.1/cgi/cgi_action?Action=GetConnectionStatus" \
|
||||
| jq -r .wan_status.ipaddr
|
20
pkgs/sane-scripts/src/sane-ip-reconnect
Executable file
20
pkgs/sane-scripts/src/sane-ip-reconnect
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# reconnect to best wifi network.
|
||||
# lappy frequently DCs from the ideal network
|
||||
|
||||
set -ex
|
||||
|
||||
sudo iwctl station wlan0 scan
|
||||
sleep 5
|
||||
|
||||
# get networks. remove control characters (colors), then leading info, then take the top-rated network
|
||||
networks=$(iwctl station wlan0 get-networks rssi-dbms | sed 's/\[[0-9;]*m//g' | sed 's/ [ >]*/ /g' | sed 's/^ //' | tail -n +5)
|
||||
|
||||
strengths=$(echo "$networks" | grep -o '\-[0-9][0-9]* *$')
|
||||
best_strength=$(echo "$strengths" | sort -h | tail -n 1)
|
||||
best_line=$(echo "$networks" | grep -- "$best_strength$")
|
||||
# network names could have spaces in them if someone's evil, so rather than `cut`, we trim the `psk` and `db` columnds
|
||||
best_network=$(echo "$best_line" | sed 's/ [a-z][a-z]* -[0-9][0-9]* *$//g')
|
||||
|
||||
sudo iwctl station wlan0 connect "$best_network"
|
11
pkgs/sane-scripts/src/sane-private-do
Executable file
11
pkgs/sane-scripts/src/sane-private-do
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# unlock the ~/private store, run some command, and then re-lock the store
|
||||
|
||||
set -x
|
||||
|
||||
external_cmd=$@
|
||||
|
||||
sane-private-unlock
|
||||
$external_cmd
|
||||
exec sane-private-lock
|
@@ -2,8 +2,7 @@
|
||||
|
||||
set -ex
|
||||
|
||||
# configure persistent, encrypted storage that is auto-mounted on login.
|
||||
# this is a one-time setup and user should log out/back in after running it.
|
||||
# mounts ~/private
|
||||
|
||||
mount=/home/colin/private
|
||||
cipher="/nix/persist$mount"
|
||||
|
@@ -1,3 +1,10 @@
|
||||
#!/usr/bin/env sh
|
||||
# copy some remote file(s) to the working directory, with sane defaults
|
||||
rsync -arv --progress --append-verify "$@" .
|
||||
# rsync, with sane defaults
|
||||
# + verbosity
|
||||
# + default to cwd as destination if none is provided
|
||||
dest=
|
||||
if (( $# <= 1 )); then
|
||||
# rsync to the current directory by default
|
||||
dest='.'
|
||||
fi
|
||||
rsync -arv --progress --append-verify "$@" $dest
|
||||
|
194
pkgs/sane-scripts/src/sane-reclaim-boot-space
Executable file
194
pkgs/sane-scripts/src/sane-reclaim-boot-space
Executable file
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
EXTLINUX_CONF = "/boot/extlinux/extlinux.conf"
|
||||
|
||||
class ConfItem:
|
||||
pass
|
||||
|
||||
class ConfLine:
|
||||
""" uninteresting line in the config """
|
||||
def __init__(self, line: str):
|
||||
self.line = line
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.line
|
||||
|
||||
class ConfEntry:
|
||||
""" boot entry, with label/linux/etc """
|
||||
menu = linux = initrd = append = fdtdir = None
|
||||
def __init__(self, label: str):
|
||||
self.label = label
|
||||
|
||||
def format_attr(self, attr_name: str) -> str:
|
||||
attr_val = getattr(self, attr_name)
|
||||
assert attr_val is not None, f"not set: {attr_name}"
|
||||
return f"{attr_name.upper()} {attr_val}"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"""
|
||||
{self.format_attr("label")}
|
||||
{self.format_attr("menu")}
|
||||
{self.format_attr("linux")}
|
||||
{self.format_attr("initrd")}
|
||||
{self.format_attr("append")}
|
||||
{self.format_attr("fdtdir")}
|
||||
""".strip()
|
||||
|
||||
def parse(self, line: str) -> None:
|
||||
split_at = line.index(" ")
|
||||
directive, contents = line[:split_at], line[1+split_at:]
|
||||
self.setattr(directive.lower(), contents)
|
||||
|
||||
def setattr(self, directive: str, contents: str) -> None:
|
||||
assert getattr(self, directive) is None, f"attr already set: {directive} = {contents!r}"
|
||||
setattr(self, directive, contents)
|
||||
|
||||
|
||||
class UseTracker:
|
||||
def __init__(self):
|
||||
self.linux = []
|
||||
self.initrd = []
|
||||
self.fdtdir = []
|
||||
self.sizes = {} # item: str -> [num_using, bytes]
|
||||
|
||||
@staticmethod
|
||||
def from_items(entries: list) -> 'UseTracker':
|
||||
me = UseTracker()
|
||||
me.populate_from_fs()
|
||||
for i in entries:
|
||||
me.track(i)
|
||||
return me
|
||||
|
||||
def populate_from_fs(self) -> None:
|
||||
for entry in os.listdir("/boot/nixos"):
|
||||
item = os.path.join("../nixos", entry)
|
||||
self.sizes[item] = [0, self._get_size(item)]
|
||||
|
||||
def append_unique(self, list_: list, item: str) -> None:
|
||||
if item not in list_:
|
||||
list_.append(item)
|
||||
self.sizes[item][0] += 1
|
||||
|
||||
def track(self, entry: ConfItem) -> None:
|
||||
if isinstance(entry, ConfEntry):
|
||||
self.append_unique(self.linux, entry.linux)
|
||||
self.append_unique(self.initrd, entry.initrd)
|
||||
self.append_unique(self.fdtdir, entry.fdtdir)
|
||||
|
||||
def get_use_count(self, item: str) -> int:
|
||||
return self.sizes[item][0]
|
||||
|
||||
def get_size(self, item: str) -> int:
|
||||
return self.sizes[item][1]
|
||||
|
||||
def used_size(self) -> int:
|
||||
return sum(i[1] for i in self.sizes.values() if i[0] != 0)
|
||||
|
||||
def get_unused(self) -> list:
|
||||
return [i for (i, v) in self.sizes.items() if v[0] == 0]
|
||||
|
||||
def unused_size(self) -> int:
|
||||
return sum(self.get_size(i) for i in self.get_unused())
|
||||
|
||||
def _get_size(self, item: str) -> int:
|
||||
path = os.path.join("/boot/extlinux", item)
|
||||
du_output = subprocess.check_output(["du", "-b", "-c", path], text=True).strip()
|
||||
last = du_output.split("\n")[-1]
|
||||
size, label = last.split("\t")
|
||||
assert label == "total", f"unexpected du output: {last}"
|
||||
return int(size)
|
||||
|
||||
def print_use_by_cat(tracker: UseTracker, label: str) -> None:
|
||||
items = getattr(tracker, label)
|
||||
formatted_items = []
|
||||
for item in items:
|
||||
count, size = tracker.get_use_count(item), tracker.get_size(item)
|
||||
formatted_items.append(f"\n {item}\n {count}x {size}")
|
||||
print(f" {label}:{''.join(formatted_items)}")
|
||||
|
||||
def print_tracker_use(tracker: UseTracker) -> None:
|
||||
print("in use:")
|
||||
print_use_by_cat(tracker, "linux")
|
||||
print_use_by_cat(tracker, "initrd")
|
||||
print_use_by_cat(tracker, "fdtdir")
|
||||
print("unused:")
|
||||
for i in tracker.get_unused():
|
||||
print(f" {i}\n {tracker.get_size(i)}")
|
||||
print(f"used space: {tracker.used_size()}")
|
||||
|
||||
def delete_unused_from_disk(tracker: UseTracker) -> None:
|
||||
for f in tracker.get_unused():
|
||||
path = os.path.join("/boot/extlinux", f)
|
||||
cmd = ["rm", "-r", "-f", path]
|
||||
print(" ".join(cmd))
|
||||
subprocess.check_output(cmd)
|
||||
|
||||
def parse_extlinux(contents: str) -> list:
|
||||
items = []
|
||||
active_entry = None
|
||||
for line in contents.split("\n"):
|
||||
if line.startswith("#") or line == "" or line.startswith("DEFAULT ") or line.startswith("MENU ") or line.startswith("TIMEOUT "):
|
||||
items.append(ConfLine(line))
|
||||
elif line.startswith("LABEL "):
|
||||
items.append(ConfEntry(line[len("LABEL "):]))
|
||||
elif line.startswith(" "):
|
||||
items[-1].parse(line[2:])
|
||||
else:
|
||||
assert False, f"unknown directive {line!r}"
|
||||
|
||||
return items
|
||||
|
||||
def write_extlinux(contents: str) -> None:
|
||||
with open(EXTLINUX_CONF, "r+") as new:
|
||||
# backup file
|
||||
with open("./extlinux.conf.back", "w") as back:
|
||||
back.write(new.read())
|
||||
|
||||
new.seek(0)
|
||||
new.write(new_extlinux)
|
||||
new.truncate()
|
||||
|
||||
def dump_items(items: list) -> str:
|
||||
return "\n".join(str(i) for i in items)
|
||||
|
||||
def prompt_continue() -> None:
|
||||
if input("continue? [y/N] ").lower() != "y":
|
||||
print("aborting")
|
||||
sys.exit(0)
|
||||
|
||||
orig_extlinux = open(EXTLINUX_CONF, "r").read()
|
||||
items = parse_extlinux(orig_extlinux)
|
||||
tracker = UseTracker.from_items(items)
|
||||
print_tracker_use(tracker)
|
||||
print()
|
||||
|
||||
if tracker.get_unused():
|
||||
print(f"recommended to delete unused items from disk to save {tracker.unused_size()}b")
|
||||
prompt_continue()
|
||||
else:
|
||||
orig_tracker = tracker
|
||||
rmcount = 0
|
||||
while tracker.used_size() == orig_tracker.used_size():
|
||||
item = items.pop()
|
||||
rmcount += isinstance(item, ConfEntry)
|
||||
tracker = UseTracker.from_items(items)
|
||||
|
||||
orig_size = orig_tracker.used_size()
|
||||
new_size = tracker.used_size()
|
||||
print(f"recommended to delete {rmcount} oldest entries to save {orig_size - new_size}b")
|
||||
print_tracker_use(tracker)
|
||||
prompt_continue()
|
||||
print()
|
||||
|
||||
new_extlinux = dump_items(items)
|
||||
print(f"new contents:\n{new_extlinux}")
|
||||
prompt_continue()
|
||||
|
||||
write_extlinux(new_extlinux)
|
||||
|
||||
delete_unused_from_disk(tracker)
|
@@ -8,4 +8,4 @@ sudo systemctl stop nginx
|
||||
sudo systemctl stop postgresql
|
||||
sudo systemctl stop duplicity.timer
|
||||
sudo systemctl stop duplicity
|
||||
sudo systemctl stop wg0veth wireguard-wg0
|
||||
sudo systemctl stop wireguard-wg0
|
||||
|
@@ -2,15 +2,18 @@
|
||||
|
||||
# first arg should be the region, e.g. `us` or `ukr`
|
||||
|
||||
case $1 in
|
||||
ukr)
|
||||
iface=wg-quick-ovpnd-ukr;;
|
||||
us)
|
||||
iface=wg-quick-ovpnd-us;;
|
||||
*)
|
||||
echo "invalid vpn name '$1'"; exit 1;;
|
||||
esac
|
||||
vpns=$(systemctl list-unit-files | grep wg-quick-ovpnd- | cut -f 1 -d ' ' | sed s'/^wg-quick-ovpnd-\([a-zA-Z-]*\)\.service$/\1/g')
|
||||
|
||||
echo vpn: $(curl https://ipinfo.io/ip)
|
||||
if ! [ $(echo "$vpns" | grep "^$1$") ]
|
||||
then
|
||||
echo "invalid vpn name '$1'"
|
||||
echo "choices:"
|
||||
echo "$vpns"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
iface=wg-quick-ovpnd-$1.service
|
||||
|
||||
echo vpn: $(sane-ip-check)
|
||||
sudo systemctl stop $iface
|
||||
echo plain: $(curl https://ipinfo.io/ip)
|
||||
echo plain: $(sane-ip-check)
|
||||
|
@@ -2,15 +2,18 @@
|
||||
|
||||
# first arg should be the region, e.g. `us` or `ukr`
|
||||
|
||||
case $1 in
|
||||
ukr)
|
||||
iface=wg-quick-ovpnd-ukr;;
|
||||
us)
|
||||
iface=wg-quick-ovpnd-us;;
|
||||
*)
|
||||
echo "invalid vpn name '$1'"; exit 1;;
|
||||
esac
|
||||
vpns=$(systemctl list-unit-files | grep wg-quick-ovpnd- | cut -f 1 -d ' ' | sed s'/^wg-quick-ovpnd-\([a-zA-Z-]*\)\.service$/\1/g')
|
||||
|
||||
echo plain: $(curl https://ipinfo.io/ip)
|
||||
if ! [ $(echo "$vpns" | grep "^$1$") ]
|
||||
then
|
||||
echo "invalid vpn name '$1'"
|
||||
echo "choices:"
|
||||
echo "$vpns"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
iface=wg-quick-ovpnd-$1.service
|
||||
|
||||
echo plain: $(sane-ip-check)
|
||||
sudo systemctl start $iface
|
||||
echo vpn: $(curl https://ipinfo.io/ip)
|
||||
echo vpn: $(sane-ip-check)
|
||||
|
37
pkgs/splatmoji/default.nix
Normal file
37
pkgs/splatmoji/default.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, fetchFromGitHub
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "splatmoji";
|
||||
version = "1.2.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "cspeterson";
|
||||
repo = "splatmoji";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-fsZ8FhLP3vAalRJWUEi/0fe0DlwAz5zZeRZqAuwgv/U=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
# TODO: generate a wrapper so that bin/lib, bin/data aren't linked into the environment?
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp splatmoji $out/bin
|
||||
cp -R lib $out/bin/lib
|
||||
cp -R data $out/bin/data
|
||||
cp splatmoji.config $out/bin
|
||||
|
||||
patchShebangs $out/bin/splatmoji
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Quickly look up and input emoji and/or emoticons/kaomoji on your GNU/Linux desktop via pop-up menu";
|
||||
homepage = "https://github.com/cspeterson/splatmoji";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ colinsane ];
|
||||
platforms = with platforms; linux;
|
||||
};
|
||||
}
|
33
pkgs/trust-dns/default.nix
Normal file
33
pkgs/trust-dns/default.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{ lib
|
||||
, fetchFromGitHub
|
||||
, openssl
|
||||
, pkg-config
|
||||
, rustPlatform
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "trust-dns";
|
||||
version = "0.22.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "bluejekyll";
|
||||
repo = "trust-dns";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-b9tK1JbTwB3ZuRPh0wb3cOFj9dMW7URXIaFzUq0Yipw=";
|
||||
};
|
||||
cargoHash = "sha256-mpobdeTRWJzIEmhwtcM6UE66qRD5ot/0yLeQM6Tec+0=";
|
||||
|
||||
buildInputs = [ openssl ];
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
|
||||
# tests expect internet connectivity to query real nameservers like 8.8.8.8
|
||||
doCheck = false;
|
||||
|
||||
meta = with lib; {
|
||||
description = "A Rust based DNS client, server, and resolver";
|
||||
homepage = "https://trust-dns.org/";
|
||||
maintainers = with maintainers; [ colinsane ];
|
||||
platforms = platforms.linux;
|
||||
license = with licenses; [ asl20 mit ];
|
||||
};
|
||||
}
|
25
scripts/install-bluetooth
Executable file
25
scripts/install-bluetooth
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
# usage: install-bluetooth <source_dir> <dest_dir>
|
||||
# source_dir contains plain-text files of any filename.
|
||||
# for each file, this extracts the MAC and creates a symlink in dest_dir which
|
||||
# points to the original file, using the MAC name as file path
|
||||
#
|
||||
# bluetooth connection structure is /var/lib/bluetooth/<HOST_MAC>/<DEVICE_MAX>/{attributes,info}
|
||||
#
|
||||
set -ex
|
||||
|
||||
src_dir="$1"
|
||||
dest_dir="$2"
|
||||
|
||||
if [ "x$dest_dir" = "x" ]
|
||||
then
|
||||
# default to the first MAC address on the host
|
||||
dest_dir="/var/lib/bluetooth/$(ls /var/lib/bluetooth)"
|
||||
fi
|
||||
|
||||
for f in $(ls "$src_dir")
|
||||
do
|
||||
mac=$(sed -rn 's/# MAC=(.*)/\1/p' "$src_dir/$f")
|
||||
mkdir -p "$dest_dir/$mac"
|
||||
ln -sf "$src_dir/$f" "$dest_dir/$mac/info"
|
||||
done
|
@@ -1,5 +1,9 @@
|
||||
mediawiki_pw: ENC[AES256_GCM,data:g7qM+CMU12apnGQ=,iv:q5K8sBAaUi47Hr0DAWiU1o5CVIO6zkdVVGJ5Zk4P9HA=,tag:CFpSmsflkNFG4kIBzrr5yQ==,type:str]
|
||||
duplicity_passphrase: ENC[AES256_GCM,data:LgPORB0HhIAfpJdQrwjS+/TWdOeddQ2YNYqfRbWhhuNlImuOlniPzrPaaFv+Mfght7OHs7rnuVr3tOHfeIEBo9S2z05ABOulttHEyeuyJZPE1/0t8IBz2gcNNWs4nhCYbVX3y/rSAG8bhz1Vdb2B/MiCicfJEZAqpXkRilQELXTR5cF5NnmEcR7zOso=,iv:NvwZhBbkYnTDt3izwwQPj4U4XAmiOD5Dv3sF50JA97o=,tag:HSJ5xr/WXn6MQdyV8QYWYw==,type:str]
|
||||
#ENC[AES256_GCM,data:5uf2kYCg8ZqoOLv50QNI73MYV0HDl4ML2xEKHPOEvCf/Z3aeM6ED,iv:ljqw6IBTPDodejMO2dcjLYyv+LlS/7r9nQ7RyiKC2Dg=,tag:Jko9tIhER4ByDbv5qhsfaQ==,type:comment]
|
||||
ddns_he: ENC[AES256_GCM,data:zAKbEAIMIsENUctG9bNAAjAty6g+w3QW5VM=,iv:ncIjblXnTiU3TQcHJutz9lCl0wBdWs+FybY0sZcnaH0=,tag:7O6EIob2/if1fcVDVEkVzQ==,type:str]
|
||||
#ENC[AES256_GCM,data:s9NlxWPP5H3OV0PNEWz81XuPX3EXCz7GWcoJcicXpMatLM8d7MvvUJzTWCX29KIcpfXnN/ASjhML+SnAN4l+JLm2ltTJbcIVnpcWvcQ=,iv:9q73OtDm2o0YwpOYB5x5NH1Wr+QQN4lmbgJkCY/UW2c=,tag:qO6UvqGQCCl04pr2nNFauw==,type:comment]
|
||||
ddns_afraid: ENC[AES256_GCM,data:fTjwU7DoPDXulmjUNXSe5FVLGv4DvPvIHYCLwagVmKXlWOc39Rsco2YGf/kcoAk5oXqUdtdwuA==,iv:x0QwZb2xne8w7BaOXq4Srh5YbFldwLFsgdfK7WE2LGI=,tag:s8QyDBma/ljcSzAY4V1vkA==,type:str]
|
||||
#ENC[AES256_GCM,data:LMfqz2Rih6CR7RcCbA==,iv:MQ7z93Mhus2Z2q7HZMk4BzkkY/apBIR+9hIiZlknolc=,tag:HU5McecdYk12I3AcvVHEBw==,type:comment]
|
||||
#ENC[AES256_GCM,data:zhL2iNWZ8xPbBneffWcc93ZCW/SDv5FH,iv:P3a8+oucJRM8o7hnHUxAvefHdZEAbKJKhK2Y1+r75GA=,tag:VFvFucE5c780RmspW7p8Qg==,type:comment]
|
||||
#ENC[AES256_GCM,data:N0wn6NUjQKXFbSULhrKzqDc4bHVbM3JLWJwOu5Zoi00gCKSiMA==,iv:9NhoT+OM+bjz4DwRRm2c4rTBZ3Jr6eMOY7F1l4WeE1k=,tag:inkd6kw8HvT5Tz3UAbIklw==,type:comment]
|
||||
@@ -56,8 +60,8 @@ sops:
|
||||
cWplOHBNWjlJdGI3ZWtJc0t4Mk9URG8KE+9IPGYZsIs2PaDJ2AUE4gB4QEj5zo6P
|
||||
aZVbubu6Tbg+tD/98RkfWAkNvoVeDYuLNPDNgqOL0UgCQiTrPPaTjw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-11-16T03:02:50Z"
|
||||
mac: ENC[AES256_GCM,data:0/lDp6jWueeF4TPfB5rSoEzEF8QVw815DYEHRRea+SrYXGHJT80eK5sqUz00m6adG8aaSlNMAD8d2/nClar6VJKKOHdY+oN8hLztxNGQraMo107d8XOMMycj9vA4IGkCbnlng0cZTB2jsPV6Mfkmf5v+PN4N9F0bQ9W50V1Pf40=,iv:slFJjjlyCyk8aAwfRbiZ/2SKLmUGZE4OvpfrrvSJw3g=,tag:X+057fZLJnDW7CAka8+pCw==,type:str]
|
||||
lastmodified: "2022-12-15T09:12:44Z"
|
||||
mac: ENC[AES256_GCM,data:QQiTsQogs6MP9X0lrpf2FeSia6SeQP5/9dtUrWQOd2Vh/s0fBJfIGUdLeLgt5itvaD5QywY6lN9Rsx++BUN0rrwUu/uF42KOMC7wjHdSv07CYuDfvlFZItuIo5eWlfcEq9+p6/VwUXY0TU3M6Ex+mABT5XK67tnLuh/SoHUl+DA=,iv:12sa+wFdO5T7pZrLM3mnEwoJ0WmXZZLKpucEgMYQHMI=,tag:zZEz6+vTma6KDMwXi/fNZA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.3
|
||||
|
@@ -1,5 +1,16 @@
|
||||
#ENC[AES256_GCM,data:3Swm4ixzL+sg9UVl0VWUq5HmXoLFFY2tkfCLeACB,iv:brZxrQmInGekhv+sX72Ne2ow1katiT4upDBuTPStLuA=,tag:ORcRds8Fo86S5DkAHeeGKw==,type:comment]
|
||||
#ENC[AES256_GCM,data:LA3vDETFSVN8HZ9dieFHAvV3oP4lmG2Hpiz50MF6NHpSf7mCLbgikTv7UFohKM3vLpU=,iv:rby8r8+ELAV5ZSxALxbRTeXn0u+gv8b5wlxLwbwHt2o=,tag:50csomwWpHmSvLEGiPBAdA==,type:comment]
|
||||
#ENC[AES256_GCM,data:03yoGnxvrxifgY2sPWVo4AoqJzOfmDw4dGG+/gfbdhnymsYK7MC8Dr9g6sAdXk2r22rtPh97Wz+lkKekAxB8EX6/XIQMvUSFoAOFOKjOyC43hl0=,iv:9QKJNnZT9joQJ0klbluaVc3V3KcgqfJgrX+yn0/VgkM=,tag:TKNubbb0yGFyAbXenUvtbg==,type:comment]
|
||||
#ENC[AES256_GCM,data:UfEMJoxSCGajodTRERNT9UWHIw==,iv:dG/UI4AW8ZwmI0fr8dAOWRkSyrNwX1GOI1MCYcIVBy8=,tag:rONazGrpRolwttbTEX3Y1A==,type:comment]
|
||||
#ENC[AES256_GCM,data:NQA7bJoU,iv:nufPTe+1v70yQhznqJ/rf9C4p8oFYZDTDMsR0yrLp7U=,tag:MAG3g70Rxu9QEQilC/Ij1w==,type:comment]
|
||||
#ENC[AES256_GCM,data:IK/8v+Y=,iv:hhqaIkH13dFmTUPjkS5OEvR93ymDj9zKsOBlMNOgiq4=,tag:sCR4a5pJBhQIFTZnI8awzw==,type:comment]
|
||||
#ENC[AES256_GCM,data:O1Unbl8lDfY8,iv:u7V1SQQ7Z0D6D077yJdVjg7mMqAc1RLnj3YjLTD62b0=,tag:VNQDVP3YTur674N0tQzFRw==,type:comment]
|
||||
wg_ovpnd_us_privkey: ENC[AES256_GCM,data:5YkQ4r7HNWiRr/5pa1XfexxtJAz6kDjX+hNiZcheUWCXVIuK0/AuyzcdQ/0=,iv:vr1UHSlsWFnTwEfZj3pBLxvaibQxhSum3SL0Uaqtceo=,tag:dN2U+TkQAgJejgDDYIWdOA==,type:str]
|
||||
wg_ovpnd_us-atl_privkey: ENC[AES256_GCM,data:NMguzx35VvOAo37U9pGD5bYa/ghWeSK5tVh2XRNsfKjMPhMa44lm3pTscdU=,iv:f9hBhMksL0VGT8k2RsztU9AjR2AIIL+Z2Ls24UOPeNA=,tag:C46xDGb2d32mmHWl7WQb2g==,type:str]
|
||||
wg_ovpnd_us-mi_privkey: ENC[AES256_GCM,data:uEC3UOOqn1l7KwGmOxKvXccPR9Gu8/BNTlpXxXlNWf19/pIX1CLPORUWme0=,iv:cnPGghGBAsIsR86F1hPZawLWlY/pLCNF/1cg6gjrIKE=,tag:LqMbpGklQH0GX7dNNV3/8Q==,type:str]
|
||||
wg_ovpnd_ukr_privkey: ENC[AES256_GCM,data:5zfhsZnBk0Kb9Nb/3igsV/fN0ZDjwTAGTKyMLMly/l7MlJe6MEmd5Lv+JT8=,iv:Mov9eUP8WfvzfZ6NljgLolJ49GSqR7eSV+k0dgE1+1I=,tag:O9UtGX2qt+qEvabcsA0vIA==,type:str]
|
||||
#ENC[AES256_GCM,data:qlF8rpSMUv6Z/YrOTp7WYs0lcpmSIi/r+gCuiw==,iv:cneNp/0av/ttQvnW4JVX9mj3261QFAzkLIzEMwiKwE8=,tag:FFsPUQBsSeImtymawY4eSg==,type:comment]
|
||||
router_passwd: ENC[AES256_GCM,data:Tya3Pd75Yu4=,iv:lqi7SavFnymL+uOQXDEzGxgikB6/ckNOBifjhyjXn1Q=,tag:HG3kf6e2g53uNUGI9FXyqQ==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
@@ -78,8 +89,8 @@ sops:
|
||||
YmhsY0FaSW5oWVNJMlhUSDRCeWQ4KzAKaQp321XYtAZ98f4QMl5PxivAYm6VMF43
|
||||
wCThiQgvYAP59jvVDTZngvfWAD5PyWVVvMNbjHGvAzK5WnsTPmxlsg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2022-07-09T07:48:24Z"
|
||||
mac: ENC[AES256_GCM,data:j5Rvh2EcWyi42lWhiKF5/t6isowgPZPqwHQIW+H6T7eb1YCRUusqnK69KSIBUvk/19ZXQXxcYqFSxilAEiuinKglXqmK5Tq2hSF+vJjqW9cunuPgeQl58GeA9PyjxrRo+HNjsXqGND9/fcZf+cqvZEQnhQdPE7mCzZaJ3kAXMKY=,iv:BsDIVtzO8nSStlKYYoFktZs2sRwVk5EgQ3GBkCk+1UE=,tag:pxQyFn6Y8bbDF9hQMJqTvA==,type:str]
|
||||
lastmodified: "2022-12-19T05:49:20Z"
|
||||
mac: ENC[AES256_GCM,data:sFi/oip78pnd7hKK3L8ExBPt0/QYh1Vl68uLIOKiKBoKpk/mPGBgHAP5jGCWiSG+X6GCe5DpztremmkJhuCyMVcurS/ynZKpXpMuomy2QxLHQnvXXwF4MrqPBGheITczY07J6mJJ3tGI65+NdzCyjb9kE+YfWWMkUHv4PDUT9Mk=,iv:qjxFrkLYcbtox0maq4MyA+VLeTyQxcno5lc6fXnyPiU=,tag:6nqEZPfnllQ4N+Q6Gs6lFA==,type:str]
|
||||
pgp: []
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.3
|
||||
|
48
secrets/universal/bt/car.bin
Normal file
48
secrets/universal/bt/car.bin
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:+AGpYL+H20r13Ynl0r1w2wmk9t1vI8gxuedfXeWSrt/aa6isCiWC23+NpqZxfzHk8BihTdQ2MAi75tUSaE0QHlaMI15igtEOTjKo6KU1XkdUn1Lz79Z4jE11Ug6+IgwOXIdXEaoqot9KPUBy+/jBsZ4GaFJSHtAvnRiJZFTvVZDOHeJFknkhaFOl6fAPvf4QSX4Fg9FLSGONsShjPXX34HHiXoeyQmLUXnmc/eFhDX2BQDe+fs3AmLR0UT7H4zRmOzToChiSuXSHZIpc24c20orEpqANRRe6ghPW+26VJvVxSbAmd7aMZfTGgEUZ1hchEJkaHHyeU22Ao5MKuMniHFay4u3liYCHZAufym0VB8tpeCpLT8CxS9/rhsJaH4AcvERCjCSR1uoWq/8lbzdmcg0X9yTIbcVOMLkvn2CjqvuOHkKZqw9WKm+jh5DdmvVHGyfq8PQpOjox4vMTm6p4Dzi36sburCMW3eZNkVf+A0oXL+R1bRWERJTnEQ==,iv:bbYhaZibN8YjcrLHKk/p67p9dsAH2NPDMvNrMxp6EXs=,tag:Srcq9V+niuMC04bdGIxT1g==,type:str]",
|
||||
"sops": {
|
||||
"kms": null,
|
||||
"gcp_kms": null,
|
||||
"azure_kv": null,
|
||||
"hc_vault": null,
|
||||
"age": [
|
||||
{
|
||||
"recipient": "age1tnl4jfgacwkargzeqnhzernw29xx8mkv73xh6ufdyde6q7859slsnzf24x",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhRW1DZmVTVCs0Ym9vLytG\nUm1DWGZHaUhsZkNSTW9RWURDWmxhRFY4QkRZCkMvbExwWGplTFFnQUdDdG5RdFhY\nYWNEM1cxR0hIQS90dS9nVE1rMmhSdDAKLS0tIDFjcEVTZ3pQc2pwVU5yeEJDQjFl\nUmFLZGlQN29saTlramcxejFaWDcyamsKX3GnzkjF3Yqc3T2g0sw+8d0MHUCUDaGg\nG/HBpGBS2ESTH+jAVxv5PFbnS5VFpf4nlPxhUzdE3j7KTikvmAJoAA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1j2pqnl8j0krdzk6npe93s4nnqrzwx978qrc0u570gzlamqpnje9sc8le2g",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6eWhOc0xNTDY4YUdyYmcv\nQWQ4WEFFcVpmZEhNbGthRVlVcVM1RzQraFZvCmN5L00zTTV2MXFTcWxaWC8ydytu\nQ0NTbDVsRXBaWTVMSzI2VTFCWGFxZFUKLS0tIFoxSTUvREVreEo5dmdmYmExSDB1\nckp5ZnUrOGZxSjB0SHFMaTB2VFFEUVEKqn/1aXfZ/WHtDDVOmGjOT/PUas+5eZ/S\n+QY0qc6mjeJ8yn8ULOmm9M1E4zk5dJGiOIHzJ/rSFZDO0ayR0tcbwg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1z8fauff34cdecr6sjkre260luzxcca05kpcwvhx988d306tpcejsp63znu",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiay9zZ3lCYk9oOVk1bzVi\naEhCeU9WOHFMdE5xb0RxeEhoTEpPT3B4em5RClhrWjN3YXRsd1E4WTVVc2RPMzJ1\nai94Y0RsUUxOSTlCTSs0SXdTL3ROVGMKLS0tIHBIcXFGc2h4WmtPZGxNM1hQamFt\nM1I3U1cySWtGK29BS0lXZ3paRXhVVFUKf/blwoKGYVgb1YbvDU8/gZbcQJaArKTw\n6oFb7R4bVAkmTtTuSEjRylGomu4tde562zuT3IiZ/ReNnNdcQOSi2g==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1zsrsvd7j6l62fjxpfd2qnhqlk8wk4p8r0dtxpe4sdgnh2474095qdu7xj9",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSaVpFTHVlTjJYdEJVVVp0\ndTZobFc2dlorTUx5STd4c3k3K2VzTTVSMlVjCnBtaDdaMjAzOUQ1ejlUMGFmQjJO\nM1hPSXJMa0NmYmgza0lYeWRkaHc1VWMKLS0tIFZJTTM1TFRSZU5GejlRSTQxMlVW\nMXJ3VTNzUjJET1dpaEg5emk0T0xrbEUKBBYPgzSCKXU9jMD9Sc5YRNqBxoxN340R\njf4sBD2LWTofriB1E+ltrd82o0Gz3+JH21/+0cEI0MTD8H5o1r6Sqg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1vnw7lnfpdpjn62l3u5nyv5xt2c965k96p98kc43mcnyzpetrts9q54mc9v",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMOVR3S1pDZzlmZVJibENs\nU0k0M1NEQWRacW1oOXY3eVREWE5LVkNaN0NVCk9DNE5CVnpvcGFGSWxZOUFCQ1hn\nS1BQdXBVWm9ta1pMWFZlMm43Zm44WGMKLS0tIDViYmdYWENhc3Y1eDdXYXFDWUR1\na1dBQWtHRTJRTjFySytzSHliaGJ0MlEKKN+Nrqi2NHhV9debUfIIbgYo0eClSUkY\nb24VJc1vj9WBHu6xP0fOfhDaue5oOk0g+7w1RQE7yI5lYBR7DQyxJA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1w7mectcjku6x3sd8plm8wkn2qfrhv9n6zhzlf329e2r2uycgke8qkf9dyn",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6U1B4aHRyem9INTIzU3py\nby9OS1AxYkRlbVlHSTFCVVdRU21INGdVclY4CllvQVZWTVVPajUrSDBFaFdPaGFR\naVhRU0xpNExreVFQZUNzVUlyTzdTbU0KLS0tICtCVVBCWndGNTQvSm1naGY2OVZ4\nY3BDMzZuek5XeXIySEI3MEF2eHhNOUkKPVFHVOVyatt141Nb4EMXR7KdrVIIoDNI\njb86cX3Nq4CyrajmnXKJmBbNoSMHdiehUEaFoimMccnTmQhhxtXKVw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtbFNpQy9XWTlJTThOUmFD\nMWYyNEs5ZkVESkp3TFVPOXpIRUJrYTkzRXlvCndzZ1JsOXphZkRSY1BPd3NWdjFB\nY1dzQ3FZVi9rM21QNE9wRnVKdzB0a1EKLS0tIEsycmRiYTJGRFVUNTVoU1N5c0RZ\nTDlKclFZQVkrYXVaWEJtenRXcW5hOEEKFhbLhR2HH5j8iId1PEt2Qr4uLIcSSoiP\nmka7YtK2fe1W9012xKUqKtqZvjtbuFrHb/L7p+UfvCxBXy2c+bXG8w==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDQW52MVVRell4eWVnMzZt\nenFqbnVtVGpGRlpVR0NnNkVvUk9Ed25qTXpZCjhlaTFzZXlUZHRsS3dHWDNUMUVI\nOVlmbkdiZnN2RnhVY3F2OWRqQUJBQzgKLS0tIHRJMHJ2d3RJV0JUVUdJTmMxYk1U\nTjQrUkZuQ0xVbWQxZm8xMm5RYzB1WGsKovG+0ueoZS0CQbTsC44upsX1tAXBtxn/\nxgdkUe7EiDX5QLq+AldVc0UzvEY5/ROBBf4d2LzSqp3jJPtEJbYc9Q==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2022-12-04T10:55:44Z",
|
||||
"mac": "ENC[AES256_GCM,data:AIFVCniHkBJex0u6LTKj6CmxH92qc7JlRIGFWDGIFqG0LhvHbHdtRq3asT6N557ZiCbZCt+tCe+bcEDTsZrYqzE2BIdTa3qtW5ofmfaB9UXt1qcNAKRAy4LWYAwAGLRjXtgbnRINgaD/NCmOVf/+g7/VkigYXkWHLBLVRAmS1Io=,iv:eVQYqQrDPPyvsOYDRzcZUWqh11KuAcR4+ZPaNGup0LU=,tag:Cje0SL8sxlTbu3BaBc0ogg==,type:str]",
|
||||
"pgp": null,
|
||||
"unencrypted_suffix": "_unencrypted",
|
||||
"version": "3.7.3"
|
||||
}
|
||||
}
|
48
secrets/universal/bt/earbuds.bin
Normal file
48
secrets/universal/bt/earbuds.bin
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:IGm1odrTgOg5GAJFpyWgVbQMC5FEDukW1k8kgWgIEnBPvCsamDyFC07EZD2uMuP0KEs7VLxhE2c+mJN9BdnFd8TJocy2JtHoizzvv6leTxO4YRx8rHBXutGI9FdUeeI/Sv+1V9hiLfVCxQPnvyBpvThfddKSfg7vjdgkEHMixnipCrUQZaRyCW2lByEoAe0WzzpmLtdJ0HBiyZQ6PKzQ+05gA7dwqOaK4ZYLh39cEzAqGVYxzPastxAqxXOIt+4pL5THwnwdfhqfb/buntj4VpA+avePRexMVbY/JmJx+hQpdvZKx17PFVzhlqCZJefsgglObDRrSyTsGkmkkdTch6SPtnymLlI97FYat+V3wFUGo2uwkZVSfSEuXjpwnM0y3hx9C2OlkR1sYCM8cLVQkAqR13x87Uvdq3O4qo48IOM6Zu1lBwL9AblxgCHHfK7DzomcF41VF/pI0yZltEwATOiqvr2ir41uFKLxZ+fw/O3oOjv/jEap/7UFTgx4ShFAAP6vCs54iAGmgh/7b+YnA3ec59bzpXzFC9lZZt1RJyoXnAl+ADev53Q=,iv:ZfxmfvSqWj0IbNJeRGayapUYEznXMD7hhmBhzNPwMuA=,tag:YsjgEJ5p2GXqnzQeGaRX1Q==,type:str]",
|
||||
"sops": {
|
||||
"kms": null,
|
||||
"gcp_kms": null,
|
||||
"azure_kv": null,
|
||||
"hc_vault": null,
|
||||
"age": [
|
||||
{
|
||||
"recipient": "age1tnl4jfgacwkargzeqnhzernw29xx8mkv73xh6ufdyde6q7859slsnzf24x",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrVGl5WEhVWEtGMjNZSUMx\nMStIUGpaQ2ttdmxjNUtyS1J0bVViY1k3Snk0CkhZMmhMQVQrM0lQL05hcFlTOTdv\ncFU2N01VNmlwWS9Tczd1aVlkUUpRem8KLS0tIDNXQ0xLVmUwYW5Edy8rSW9CaWhW\ndUVYRFdGMjVwV2w0My9PT0NHS1JtakEK/KjEcC0Ubci8hInUqc2G6uFs2hd9TN76\nPgMDTi8Mt1dM1cGNj7uiPeTo8/ft26yuAtikybpLGMdayuEXp6aTPA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1j2pqnl8j0krdzk6npe93s4nnqrzwx978qrc0u570gzlamqpnje9sc8le2g",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCTkNzYVowcGxwek4rdUow\nc3VYbndpSWVscVdmaXB2VFdVS3JpYWdPbGprCmtiQUJzSStjeTVpdGRodDRjcVlQ\nb2NFczZjUzNxSVd3Y0puYUV5WnM1V28KLS0tIC9HdlgxUVBFZ2hPdlBVcVRha05v\nb05hbmRqV29scGE5bjltVVNHZ2V5UU0KfKu9wvY0EfTxUB8Qiy7jc4eI5zoUBtIT\nDUdb6MO7OUHJxtq5YzVJcPui5krR4ehJI7vB5IRWXxT/Yx+BjUd2qw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1z8fauff34cdecr6sjkre260luzxcca05kpcwvhx988d306tpcejsp63znu",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzUEZmNHBmTlUrSVNON0Vx\nU0kwRTNyQTY0UTdjaDVwUjZFSzdPaWgyL2trCkJCZU1MdFlhSndHNjZZb3VBdE9V\na3Iza3FyTUhEcTB3azBURXJKS3dkakkKLS0tIFNMNkZtWXNralFRM1FKVlZuL09p\ncHJGeUJxSXFSMDA4MU1lNU9jWWl4OXcKK71tw9/Xg9uCANFgDQ+kC9sgVP5UEa9S\nqaWPn+VGCMMiGb3TAb9BoRonfmj9eI+NxA/er5jpyT5g2GxKymTN9w==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1zsrsvd7j6l62fjxpfd2qnhqlk8wk4p8r0dtxpe4sdgnh2474095qdu7xj9",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwUThqL2k0ZW9maHMzSVhm\nbFBBUEl1Vzh0ZW52S1ZxM1BBTG1ZdUxFQ0ZzClV6aE4zTzlkbW4vMjczMHBJNjRS\nUEs2a21xMndxK1FDMDZqN2xUTHFka0EKLS0tIG5paTZCUmJnN2Z2Y3JncWxPWTli\nSmd3dHZzT3l4MDBIeS9FMC9Bc1F2c0EK4jplLargqOCN5eSpsAqU7zmdEvZzN6Bd\nTLgiuOPwFeQwCJ28lPFXNtPYFQzXhoASatd4Sn/MOKWCQJeVJOhDog==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1vnw7lnfpdpjn62l3u5nyv5xt2c965k96p98kc43mcnyzpetrts9q54mc9v",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSb1hNd1k2ZUM3U1REVTlo\ndkhLUG81WGFxQlRVd2cvUU9WVmNSb09Ub1RFCmhINEdhT1I2WS9rUE9CNlppbDRa\nVlgwNzB6RmIra2NRUjU0Ni9abVNSd1kKLS0tIG5pbityUFc2RVJGQTlTend1YTV0\nbStYSWIxSjdGYU0rMHQrTHFkSGNjd2sKBymQa50r5Uo727VI+nM+qc3YAGzM+ZDI\nU6T+MA8L5noCb/ZzKYZFAEN8z8a/xHT7nRiqp8NWQ8OJ0KJDzQvE3w==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1w7mectcjku6x3sd8plm8wkn2qfrhv9n6zhzlf329e2r2uycgke8qkf9dyn",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxSHJtWVpWVE5mVmZ4RVV0\nS3J6MGhQY3NsYTk2S2FFbGJTQTBjaUlaNWc4CmZRamZmZ2l2OENKZWpOWU1IQXdo\nN29TSVM4dUJXbmZISkVyL0RCTFBrZ1UKLS0tIHY2SDBndG1PRVZqcGxJSjNXUWU5\nL3RyZ0JIblJPS0lmc1pDc2pGK2dTeHMKB1T/43hZDb4lP+seHsKt+aB1TdNyP6FZ\nOt8rezQZqeJ+GnHwV6qsdEtX1DE30niqe3upUS+igkHJ65RGd5TAuQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFOU9TWXlCRFh3Sk9aZkF3\nTDVUMWhzQkQ2OW1YbVlQSHUvdHBIWGx1R2tnCi9ubVJyV0lnUHYreDQwNFYxNTM0\nMEk0M1ZRQmliL0ZUVlZlYTM3aG01eXcKLS0tIDZxR3V1ZVpEWHRJajdCcU16NUZS\nNFpGanJxNlpKcm1VS1cxWHNieHVmbTgK0ggrvlCvK+j8F77b4gl1RsWGDfGiFmg/\ns0cMGtIflPT/0D43R/jczrJ/Xp1aBL0TeHyf9YxZu254QeZ5ZPa5kQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXTVg0YTFFL1owd1RNUEEx\nMWJOeGttbTI1elhZMTU1VXcwcWt4ZzdJSW5VCnlQRk5OakJJU0grczlHRnhJTWxI\nd21pTDdVTk1vc0dsdVpuWGNrVUpEVDAKLS0tIGNYQVNjellNajR3czlKc0ZYbWpL\nbkt6QnZ1MGRGL0hSS2F6aktXMzB3aVEKb/XnuAMiB6Zn2Hr+LUlPdCii5G7TKYgp\njE7Loh9mPY/WPK2KvCAPYFcjNCmu0JYzCYgpU/i+4Wm7ObsrXh+lGw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2022-12-04T11:32:25Z",
|
||||
"mac": "ENC[AES256_GCM,data:UIyF5JSi+GZqch1cPgmgrdZ1ImicdrzVTwYudwKhHDvfXXHzFG+I+1MGRRim872XbImc2EJRBSe27vhyum8pDc7y8cQVepecfqkeEdD66IxEbwx9Wt5ZW9X4nPlj+vobSHjjyV+0Wpmy9pgsfLiQzT+9S8jE4H0FgZv89MNNmCA=,iv:s9V7SDMhttZ1iFk3xNTrnNgMGnn+5LW3G/ORI66QHqY=,tag:+O3YRbsMuz+M+pzrk8zhiQ==,type:str]",
|
||||
"pgp": null,
|
||||
"unencrypted_suffix": "_unencrypted",
|
||||
"version": "3.7.3"
|
||||
}
|
||||
}
|
48
secrets/universal/bt/portable-speaker.bin
Normal file
48
secrets/universal/bt/portable-speaker.bin
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:639/SycbUOC4kwBAJvk2sQCBfnXZrYDzucXFXysOW8DOPU7nZwsdWKmB+41zvLg3vS5GyPTzMco/EaytPbGj+HvRqyKEYCJvBY/ZOoPpAZKltqMkkIS449OFy3vuOS46TPLQ1c5AgsBnHuSFrGGcVXRs+yP1A4rRcn5Au3Z7hPujZA/W3lUR+/Cp4UYc2tk1w2kpWD/SXLqkSX2XTRNPXb1rOva6xxllUiFuG7Yt1a7KfjrkaF4GJK5TNWgGVrY1N7IKzC75Sh1x5wvumF7A1mwLE1I+sa55Sn9qtGsmWwfsDBN+9SRg7uCUipTCrAEAgJK07QdN5P0ZFrQlxqNGn0i5BvKSxn+GK+f7xJIHjb+sexQgNMFQ56V83Zej8U5HQ9vyrx7EHpE44UneUQQ8FkckQVWyhSGs3MVSkfbznb3L2WnOCEogb0xft56pXPOG/K4q7uLkOwUtgcq0Jlf+gZZmuXRoVnNQc//o0u296CF8AFnxA/MJJc67bkONITjlekB7f23NFoywhzyX4RYjjbflRkMF8BRu0RDuynGu0xLZLLlK8QM4uJfpPyH8L2ThiKRbYO7OGaKCYJy6fYx+ViUVsRf3hpHMiDn8yGHxrqABOTv6HSIZvIKo3G4Kn5iF/GPxWQISTZxE7YdYhgUf61UpZEfkgw==,iv:jqWb8k8f8jKscWPwcZy9o9QmOJKG38m9ukbeBDX3IN8=,tag:vZh6J2mtUhaoiwpn17l80g==,type:str]",
|
||||
"sops": {
|
||||
"kms": null,
|
||||
"gcp_kms": null,
|
||||
"azure_kv": null,
|
||||
"hc_vault": null,
|
||||
"age": [
|
||||
{
|
||||
"recipient": "age1tnl4jfgacwkargzeqnhzernw29xx8mkv73xh6ufdyde6q7859slsnzf24x",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqTXp0RHN2bW9wUDdvWlJa\nNFhyMEJ0OUhSS2RvLyswejc3ZUx2SW1rdDFVCmtZVG9wZitidEZMaE1rdjZSZito\nclB1N2s2bU93S0IwK1UrYlk4NjU1UFUKLS0tIEdvcytSOElhRHlKY1FyRTlTYUlR\najdHeGh6d2FROUJab3d1cExkYlJLQUEKJQUv1/2YuAOEQGaaJ5itEtXrfwB18RcI\nC3V0MXuLqpQpVzsMz6tBU66+343gPTVMZXi/cLLKjpzARKUCPJ3ghA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1j2pqnl8j0krdzk6npe93s4nnqrzwx978qrc0u570gzlamqpnje9sc8le2g",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNdmtuT0NaUEplbzQ0WWV2\nQUsrOFRYN0ZET2lwNkhMeTE3bTV6OUUzWW5jCmtsT3dNbXdlSFQyTmlNdndqT0V6\nSGFDM3BaY1plUVYrRkZRSXQ3eno4dWsKLS0tIGRBSzQzVVdCQ3Q2WGpwdTlsSHJO\nZGR5NjRrbW1lWW80NCtVUWtIUEhGcTAKSRPJHEUFWCCe4v2nLnaDY3FIeWvc75jd\nMb8+grC61jBRO3kpMLrHb5dn3/okLX33nZtJNnkCA8jDlR1tyCXUuA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1z8fauff34cdecr6sjkre260luzxcca05kpcwvhx988d306tpcejsp63znu",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvRWZFWkVWVWlpWjBWenE3\naHp2d1RVcmNrQVVYNkVuWHRUcGRBNTBFbmdNCk4zUGFFSm5lWXhzR05RelNvbnBX\neHhoZDZjZTJPWndQT0dJajh0K2xhWGsKLS0tIHIyeUVoQ0szZHpBQkdBc0hVbFVF\nU29JWFNPT2VtaEFTSTc0OEpsYVVRbWMKLq33uUYhelMgkz/zuI3wmYTPbn+fv4uB\nkwUX2KDOzunPkfznFJ0/uGDHBRgTj5kYKid53IPPAByCGrWemXbbBA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1zsrsvd7j6l62fjxpfd2qnhqlk8wk4p8r0dtxpe4sdgnh2474095qdu7xj9",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVNlFGNGZyZWdLQnRkSE1z\nTUgwOWFvL2ZQSWVOVTBBOHJOM0RSaHNFOWlBCmljOTdKQzB1UTU3ZFFENDJFRnps\nYi8xa0czTTNvTFFGc2QydWVmTmN2bEUKLS0tIFJQMkNQOUhDazlsRTlrRDR3TFJP\nLzl3UGRSakhITXdnYzEvMXdsZ3M2RjgKbXJw6e5aFsrL52zknH5vva3y7sLvqVTd\nsyOnStwaTwBWEMRAvG+vtEhgLIJDVCJGEYqKIBzzoOOujJ9ojuzOqw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1vnw7lnfpdpjn62l3u5nyv5xt2c965k96p98kc43mcnyzpetrts9q54mc9v",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRRmh3R05RNXhjclRHYnB6\ndmxIV1dPQTNud0htRFFHN3ZveUd3NSt1RENRCkRmQzJvNUxZQzc3enlvZjRGTE9x\nWmFxaGRrYzNTUm5WNUtkaHJzbmo1Q3cKLS0tIFVJdXliL0xnZHRnYVBwYkcrTnhx\nc1M2bzQvNmxHcEsyZmZNVUYycDh5QTQKyOSJlIwrwUaglkvdAw24NxxdZnmy88J5\nNWo04oEImdlMCEZQBQ3/o1xyftU8BNY+ovNy7Nym0darKM9f8ka1PA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1w7mectcjku6x3sd8plm8wkn2qfrhv9n6zhzlf329e2r2uycgke8qkf9dyn",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiR3VhRUZybjJuVVFrNXVo\nMkJwNDgweFFmb3BIeEhSZ01RNWk0dEQ1bHlVCkI5Wm42d3haTms3bjlJdldpSGtW\nSGN5cnlkZmlpSm11VjBFeHI4blI0aUkKLS0tIHhESkdjbGFPZis4V0tQcUpXaVJ1\nTEpadHlVL3NUeUZudU15WldZWlpKNXMKVxsLBUb7BwJJ0lJRQk1ZppMID8bt/cbC\namvKeagoT6QDR42FyA6W2Rp8+tBrrkBD3CGRAcXMfUSPIzN9p6kcQg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPSXRPbW9OeGFpYng5RXR4\nT3BUMDZmOTRoNlVsVlp3endKOEJCWno2TjFZClpYWklWbDU3OGoySFFJUkRjS2tw\nUFhtZ0puTkV2ckRPMUhLY01MVW1kR2MKLS0tIGJkdHhaNzQ3WG9JRXF6OTNMNnF5\nQ3FVU2FVVDJyYUNqaVlhSkEyZmd6RGcKMRxyVMpxCYxoWXK6zlAPyo3YcPJtTWIO\no2RUlS8oSTB05G7sGkjq3VSFRSgNnekvXOBE513Qmym/cDDbusxpAQ==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzYnMxbDNUR2xyV3B5VzFQ\nM1IxQzV5OXM5L1VYdFRYWUt0cWl4ZUdsQVNJCmRjUjdPMmhoaEFmUUxrVmJCRlFl\nNzZqY3p0YUF3T2lYdysvakx4WVg0bFUKLS0tIFFlazJzb3hmVXNyUU5leUFKL3p0\nNlN0TGxVbGtoUHFtK3hBS2RiYUViVFEKii4w04zeDD6HWURzmAhJdxNdNmQgsPw/\nawI6HSVbbmEGXyL23Pe0oultY8k/ZVE4oHRKBkHh00XoCZM/Ye6neA==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2022-12-03T10:23:14Z",
|
||||
"mac": "ENC[AES256_GCM,data:KBm0rXwAGPa0ZkqGI9K3rW5B4vJ1FLmITa8xV5WR1SG2MlSqvCqSj4Qe5kxcIc3AqqHF2W+LDaJ0f1fXOCVqWRe1mi/LJyYgPERL5Hn3iOHty9g984Q/QSGvH13O7eY/Fuk2h0mpIX4pOhdpW74qlp1zYDXqUswsKW7ERTTRf6E=,iv:maE+9/OgdgYNX4F/MrzIpJr+/XXyFSayC1YX382oc2Y=,tag:NmrKXA9AjnoTXrQThnvxvg==,type:str]",
|
||||
"pgp": null,
|
||||
"unencrypted_suffix": "_unencrypted",
|
||||
"version": "3.7.3"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user