piped-proxy on raspberry
This commit is contained in:
parent
ed7e0c4db5
commit
d69991819a
|
@ -23,6 +23,7 @@
|
||||||
raspberry = {
|
raspberry = {
|
||||||
ip = "10.69.42.5";
|
ip = "10.69.42.5";
|
||||||
public = "IGq+WanFM/bKNUkwjO/0AAtDhJLvtvU+mVxH27QyHTc=";
|
public = "IGq+WanFM/bKNUkwjO/0AAtDhJLvtvU+mVxH27QyHTc=";
|
||||||
|
endpoint = "raspberry.servers.genderfucked.monster:51820";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,11 +202,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694550850,
|
"lastModified": 1694714112,
|
||||||
"narHash": "sha256-lN3W5WhbxLrsp2lgGh4fk2th5RkhQIMFd4WCNAlYvs8=",
|
"narHash": "sha256-x2CgsEvWIf4ETx4puLqmHrPthesNXW30OMYg4pVJARg=",
|
||||||
"owner": "ChaotiCryptidz",
|
"owner": "ChaotiCryptidz",
|
||||||
"repo": "piped-flake",
|
"repo": "piped-flake",
|
||||||
"rev": "6ef001f2a840fe3fefbcda619126659ba9cc1981",
|
"rev": "c5ad01eac79809686d9685671e77a6dac4e17ddf",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -4,7 +4,7 @@ in {
|
||||||
programs.ssh.enable = true;
|
programs.ssh.enable = true;
|
||||||
programs.ssh.matchBlocks =
|
programs.ssh.matchBlocks =
|
||||||
lib.mkMerge
|
lib.mkMerge
|
||||||
((lib.forEach ["hetzner-vm" "vault" "vault-decrypt"] (hostname: {
|
((lib.forEach ["hetzner-vm" "vault" "raspberry" "vault-decrypt"] (hostname: {
|
||||||
"${hostname}" = {
|
"${hostname}" = {
|
||||||
user = "root";
|
user = "root";
|
||||||
hostname = "${hostname}.servers.genderfucked.monster";
|
hostname = "${hostname}.servers.genderfucked.monster";
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
|
internal_wireguard = import ../../../../data/chaos_wireguard_internal.nix {};
|
||||||
|
|
||||||
container-addresses = import ../../data/container-addresses.nix {};
|
container-addresses = import ../../data/container-addresses.nix {};
|
||||||
hostIP = container-addresses.host;
|
hostIP = container-addresses.host;
|
||||||
containerIP = container-addresses.containers.piped;
|
containerIP = container-addresses.containers.piped;
|
||||||
|
@ -104,8 +106,12 @@ in {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://unix:${pipedSocketForComponent "proxy"}";
|
proxyPass = "http://${internal_wireguard.hosts.raspberry.ip}";
|
||||||
extraConfig = config.services.piped.proxyNginxExtraConfig;
|
extraConfig = ''
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
'';
|
||||||
|
#proxyPass = "http://unix:${pipedSocketForComponent "proxy"}";
|
||||||
|
#extraConfig = config.services.piped.proxyNginxExtraConfig;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ in {
|
||||||
backendDomain = "backend.piped.owo.monster";
|
backendDomain = "backend.piped.owo.monster";
|
||||||
proxyDomain = "proxy.piped.owo.monster";
|
proxyDomain = "proxy.piped.owo.monster";
|
||||||
|
|
||||||
|
disableProxy = true; # Currently using proxy via raspberry in UK
|
||||||
|
|
||||||
nginxForceSSL = false;
|
nginxForceSSL = false;
|
||||||
nginxEnableACME = false;
|
nginxEnableACME = false;
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ in {
|
||||||
config.services.nginx.virtualHosts."${piped_config.backendDomain}" = {
|
config.services.nginx.virtualHosts."${piped_config.backendDomain}" = {
|
||||||
extraConfig = "listen unix:/var/sockets/piped-backend.sock;";
|
extraConfig = "listen unix:/var/sockets/piped-backend.sock;";
|
||||||
};
|
};
|
||||||
config.services.nginx.virtualHosts."${piped_config.proxyDomain}" = {
|
#config.services.nginx.virtualHosts."${piped_config.proxyDomain}" = {
|
||||||
extraConfig = "listen unix:/var/sockets/piped-proxy.sock;";
|
# extraConfig = "listen unix:/var/sockets/piped-proxy.sock;";
|
||||||
};
|
#};
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,10 +41,11 @@ in {
|
||||||
modules.nixos.rclone-sync
|
modules.nixos.rclone-sync
|
||||||
modules.nixos.secrets
|
modules.nixos.secrets
|
||||||
|
|
||||||
|
./secrets.nix
|
||||||
|
|
||||||
users.root
|
users.root
|
||||||
]
|
]
|
||||||
++ (with hosts.hetzner-vm.containers.storage; [
|
++ (with hosts.hetzner-vm.containers.storage; [
|
||||||
profiles.secrets
|
|
||||||
profiles.auto-secrets
|
profiles.auto-secrets
|
||||||
profiles.rclone-configs
|
profiles.rclone-configs
|
||||||
profiles.rclone-serve
|
profiles.rclone-serve
|
||||||
|
|
|
@ -12,8 +12,10 @@
|
||||||
profiles.base
|
profiles.base
|
||||||
profiles.sshd
|
profiles.sshd
|
||||||
profiles.nginx
|
profiles.nginx
|
||||||
|
profiles.nginx-firewall
|
||||||
profiles.nix-gc
|
profiles.nix-gc
|
||||||
profiles.kernels.latest
|
profiles.kernels.latest
|
||||||
|
profiles.cross.arm64
|
||||||
|
|
||||||
./networking.nix
|
./networking.nix
|
||||||
./hardware.nix
|
./hardware.nix
|
||||||
|
|
|
@ -33,6 +33,8 @@ in {
|
||||||
publicKey = "${data.hosts.raspberry.public}";
|
publicKey = "${data.hosts.raspberry.public}";
|
||||||
presharedKeyFile = "${secrets.wg_preshared_raspberry.path}";
|
presharedKeyFile = "${secrets.wg_preshared_raspberry.path}";
|
||||||
allowedIPs = ["${data.hosts.raspberry.ip}/32"];
|
allowedIPs = ["${data.hosts.raspberry.ip}/32"];
|
||||||
|
endpoint = "${data.hosts.raspberry.endpoint}";
|
||||||
|
persistentKeepalive = 25;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
presets.nixos.encrypted-usb
|
presets.nixos.encrypted-usb
|
||||||
|
|
||||||
profiles.cross.arm64
|
profiles.cross.arm64
|
||||||
|
profiles.remote-builders
|
||||||
|
|
||||||
hosts.lappy-t495.profiles.wireguard
|
hosts.lappy-t495.profiles.wireguard
|
||||||
|
|
||||||
|
|
2
hosts/raspberry/profiles/auto-storage-backups.nix
Normal file
2
hosts/raspberry/profiles/auto-storage-backups.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{...}: {
|
||||||
|
}
|
|
@ -37,8 +37,8 @@ in {
|
||||||
|
|
||||||
systemd.tmpfiles.rules = ["d ${external_drive_data.mountpoint} - root root"];
|
systemd.tmpfiles.rules = ["d ${external_drive_data.mountpoint} - root root"];
|
||||||
|
|
||||||
# services.udev.extraRules = ''
|
#services.udev.extraRules = ''
|
||||||
# ACTION=="add", ENV{PARTNAME}=="${external_drive_data.encrypted_partlabel}", ENV{SYSTEMD_WANTS}="mount-external-drive.service"
|
# ACTION=="add", ENV{PARTLABEL}=="${external_drive_data.encrypted_label}", ENV{SYSTEMD_WANTS}="mount-external-drive.service"
|
||||||
# ACTION=="remove", ENV{PARTNAME}=="${external_drive_data.encrypted_partlabel}", ENV{SYSTEMD_WANTS}="unmount-external-drive.service"
|
# ACTION=="remove", ENV{PARTLABEL}=="${external_drive_data.encrypted_label}", ENV{SYSTEMD_WANTS}="unmount-external-drive.service"
|
||||||
# '';
|
#'';
|
||||||
}
|
}
|
||||||
|
|
25
hosts/raspberry/profiles/piped-proxy.nix
Normal file
25
hosts/raspberry/profiles/piped-proxy.nix
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
config.services.piped = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Takes too much time to compile otherwise, idm extra bandwidth
|
||||||
|
proxyPackage =
|
||||||
|
(pkgs.piped-proxy.override {
|
||||||
|
withAVIF = false;
|
||||||
|
withWebP = false;
|
||||||
|
})
|
||||||
|
.overrideAttrs {
|
||||||
|
pname = "piped-proxy-debug";
|
||||||
|
doCheck = false;
|
||||||
|
buildType = "debug";
|
||||||
|
};
|
||||||
|
proxyDomain = "proxy.piped.owo.monster";
|
||||||
|
|
||||||
|
disableBackend = true;
|
||||||
|
disableFrontend = true;
|
||||||
|
};
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
persistentKeepalive = 15;
|
persistentKeepalive = 15;
|
||||||
in {
|
in {
|
||||||
networking.firewall.trustedInterfaces = ["wg0"];
|
networking.firewall.trustedInterfaces = ["wg0"];
|
||||||
|
networking.firewall.allowedUDPPorts = [51820];
|
||||||
networking.wg-quick.interfaces = {
|
networking.wg-quick.interfaces = {
|
||||||
wg0 = {
|
wg0 = {
|
||||||
address = ["${data.hosts.raspberry.ip}/32"];
|
address = ["${data.hosts.raspberry.ip}/32"];
|
||||||
|
|
|
@ -15,6 +15,8 @@ in {
|
||||||
|
|
||||||
profiles.base
|
profiles.base
|
||||||
profiles.sshd
|
profiles.sshd
|
||||||
|
profiles.nginx
|
||||||
|
profiles.nginx-firewall
|
||||||
|
|
||||||
profiles.connectivity.network_manager
|
profiles.connectivity.network_manager
|
||||||
profiles.connectivity.bluetooth
|
profiles.connectivity.bluetooth
|
||||||
|
@ -27,6 +29,9 @@ in {
|
||||||
]
|
]
|
||||||
++ (with hosts.raspberry.profiles; [
|
++ (with hosts.raspberry.profiles; [
|
||||||
external-drive
|
external-drive
|
||||||
|
wireguard
|
||||||
|
piped-proxy
|
||||||
|
auto-storage-backups
|
||||||
]);
|
]);
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
|
|
17
hosts/raspberry/rclone_config.template
Normal file
17
hosts/raspberry/rclone_config.template
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[StorageBox-Remote]
|
||||||
|
type = webdav
|
||||||
|
vendor = other
|
||||||
|
host = u323231.your-storagebox.de
|
||||||
|
url = https://u323231.your-storagebox.de
|
||||||
|
user = u323231
|
||||||
|
pass = STORAGEBOX_PASSWORD
|
||||||
|
|
||||||
|
[StorageBox-Hasher]
|
||||||
|
type = hasher
|
||||||
|
remote = StorageBox-Remote:
|
||||||
|
hashes = sha1,md5
|
||||||
|
max_age = off
|
||||||
|
|
||||||
|
[StorageBox]
|
||||||
|
type = alias
|
||||||
|
remote = StorageBox-Hasher:
|
|
@ -1,6 +1,22 @@
|
||||||
{...}: {
|
{pkgs, ...}: {
|
||||||
services.secrets = {
|
services.secrets = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
|
packages = with pkgs; [rclone];
|
||||||
|
|
||||||
|
extraFunctions = ''
|
||||||
|
simple_get_obscure() {
|
||||||
|
rclone obscure "$(simple_get "$@")"
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
requiredVaultPaths = [
|
||||||
|
"private-public-keys/data/cryptsetup/raspberry-ext-drive" # used dynamically
|
||||||
|
"private-public-keys/data/wireguard/chaos-internal/raspberry"
|
||||||
|
"passwords/data/wifi/parentals-home"
|
||||||
|
"api-keys/data/hetzner/storagebox"
|
||||||
|
];
|
||||||
|
|
||||||
secrets = {
|
secrets = {
|
||||||
# Used for fetching the encryption drive's key at runtime
|
# Used for fetching the encryption drive's key at runtime
|
||||||
# can be revoked in case of hardware theft
|
# can be revoked in case of hardware theft
|
||||||
|
@ -31,6 +47,25 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rclone_config = {
|
||||||
|
fetchScript = ''
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
|
||||||
|
cp ${./rclone_config.template} "$TMP_DIR/template"
|
||||||
|
|
||||||
|
pushd "$TMP_DIR" >/dev/null
|
||||||
|
|
||||||
|
STORAGEBOX_PASSWORD=$(simple_get_obscure /api-keys/hetzner/storagebox .password)
|
||||||
|
sed -i "s/STORAGEBOX_PASSWORD/$STORAGEBOX_PASSWORD/" ./template
|
||||||
|
|
||||||
|
cp ./template "$secretFile"
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# for internal wireguard VPN
|
# for internal wireguard VPN
|
||||||
wg_priv = {
|
wg_priv = {
|
||||||
fetchScript = ''
|
fetchScript = ''
|
||||||
|
|
|
@ -34,6 +34,8 @@ in {
|
||||||
publicKey = "${data.hosts.raspberry.public}";
|
publicKey = "${data.hosts.raspberry.public}";
|
||||||
presharedKeyFile = "${secrets.wg_preshared_raspberry.path}";
|
presharedKeyFile = "${secrets.wg_preshared_raspberry.path}";
|
||||||
allowedIPs = ["${data.hosts.raspberry.ip}/32"];
|
allowedIPs = ["${data.hosts.raspberry.ip}/32"];
|
||||||
|
endpoint = "${data.hosts.raspberry.endpoint}";
|
||||||
|
persistentKeepalive = 25;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
profiles.sshd
|
profiles.sshd
|
||||||
profiles.nix-gc
|
profiles.nix-gc
|
||||||
profiles.nginx
|
profiles.nginx
|
||||||
|
profiles.nginx-firewall
|
||||||
profiles.kernels.latest
|
profiles.kernels.latest
|
||||||
|
|
||||||
hosts.vault.profiles.wireguard
|
hosts.vault.profiles.wireguard
|
||||||
|
|
|
@ -19,6 +19,7 @@ in
|
||||||
system: let
|
system: let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
config.allowUnfree = true;
|
||||||
overlays = [
|
overlays = [
|
||||||
(import ./overlay)
|
(import ./overlay)
|
||||||
];
|
];
|
||||||
|
@ -26,6 +27,10 @@ in
|
||||||
in
|
in
|
||||||
lib.foldl' lib.recursiveUpdate {} [
|
lib.foldl' lib.recursiveUpdate {} [
|
||||||
{
|
{
|
||||||
|
# we expose nixpkgs.${system} so that we can nix run/build stuff
|
||||||
|
# from nixpkgs from flake's input versions
|
||||||
|
nixpkgs = pkgs;
|
||||||
|
|
||||||
formatter = pkgs.alejandra;
|
formatter = pkgs.alejandra;
|
||||||
|
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
|
|
4
profiles/nginx-firewall.nix
Normal file
4
profiles/nginx-firewall.nix
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{...}: {
|
||||||
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
networking.firewall.allowedUDPPorts = [80 443];
|
||||||
|
}
|
48
profiles/remote-builders.nix
Normal file
48
profiles/remote-builders.nix
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib.modules) mkIf;
|
||||||
|
|
||||||
|
current_machine_hostname = config.networking.hostName;
|
||||||
|
|
||||||
|
usb_ssh_key_file = "/usb/ssh-keys/chaos.priv";
|
||||||
|
|
||||||
|
ssh_key_file =
|
||||||
|
if
|
||||||
|
builtins.elem current_machine_hostname [
|
||||||
|
"lappy-t495"
|
||||||
|
"tablet"
|
||||||
|
]
|
||||||
|
then usb_ssh_key_file
|
||||||
|
else throw "host isn't configured for remote-builders";
|
||||||
|
|
||||||
|
builderDefaults = {
|
||||||
|
sshUser = "root";
|
||||||
|
sshKey = ssh_key_file;
|
||||||
|
supportedFeatures = ["nixos-test" "benchmark" "big-parallel" "kvm"];
|
||||||
|
mandatoryFeatures = [];
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
nix.buildMachines = [
|
||||||
|
(mkIf (current_machine_hostname != "hetzner-vm") (builderDefaults
|
||||||
|
// {
|
||||||
|
hostName = "hetzner-vm.servers.genderfucked.monster";
|
||||||
|
systems = ["x86_64-linux" "aarch64-linux"];
|
||||||
|
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU1JdDJBQnF3SGhNano5cjZhdHY0WHVYNTh4RVdlU3RrbVhVd3ZNVkd2NHcgcm9vdEBuaXhvcwo=";
|
||||||
|
maxJobs = 3;
|
||||||
|
speedFactor = 2;
|
||||||
|
}))
|
||||||
|
(mkIf (current_machine_hostname != "vault") (builderDefaults
|
||||||
|
// {
|
||||||
|
hostName = "vault.servers.genderfucked.monster";
|
||||||
|
systems = ["x86_64-linux"];
|
||||||
|
publicHostKey = "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSU16L1dyaG81MTFGdzhXN3FsU0NUY1V4cWh4TGlBQkJXbFNNNFRNNzJ5RWQgcm9vdEBuaXhvcwo=";
|
||||||
|
maxJobs = 2;
|
||||||
|
speedFactor = 1;
|
||||||
|
}))
|
||||||
|
];
|
||||||
|
nix.distributedBuilds = true;
|
||||||
|
nix.extraOptions = "builders-use-substitutes = true";
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -ex
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
REPO_ROOT="${SCRIPT_DIR}/.."
|
cd $SCRIPT_DIR
|
||||||
cd $REPO_ROOT
|
cd $(git rev-parse --show-toplevel)
|
||||||
|
|
||||||
HOSTNAME=$(hostname)
|
HOSTNAME=$(hostname)
|
||||||
|
|
||||||
[ "${NO_REBUILD}" == "" ] && ./scripts/rebuild.sh $@
|
[ "${NO_REBUILD}" == "" ] && ./scripts/rebuild.sh $@
|
||||||
[ "${HOSTNAME}" != "hetzner-vm" ] && deploy -s ".#hetzner-vm" -- $@
|
[ "${HOSTNAME}" != "hetzner-vm" ] && ./scripts/deploy/hetzner-vm.sh $@
|
||||||
[ "${HOSTNAME}" != "vault" ] && deploy -s ".#vault" -- $@
|
[ "${HOSTNAME}" != "vault" ] && ./scripts/deploy/vault.sh $@
|
||||||
[ "${HOSTNAME}" != "raspberry" ] && nixos-rebuild --flake .#raspberry --target-host root@192.168.0.203 $@
|
[ "${HOSTNAME}" != "raspberry" ] && ./scripts/deploy/raspberry.sh $@
|
9
scripts/deploy/hetzner-vm.sh
Executable file
9
scripts/deploy/hetzner-vm.sh
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
cd $SCRIPT_DIR
|
||||||
|
cd $(git rev-parse --show-toplevel)
|
||||||
|
|
||||||
|
nixos-rebuild switch --flake .#hetzner-vm --target-host hetzner-vm -s $@
|
9
scripts/deploy/raspberry.sh
Normal file
9
scripts/deploy/raspberry.sh
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
cd $SCRIPT_DIR
|
||||||
|
cd $(git rev-parse --show-toplevel)
|
||||||
|
|
||||||
|
nixos-rebuild switch --flake .#raspberry --target-host raspberry -s $@
|
9
scripts/deploy/vault.sh
Normal file
9
scripts/deploy/vault.sh
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
cd $SCRIPT_DIR
|
||||||
|
cd $(git rev-parse --show-toplevel)
|
||||||
|
|
||||||
|
nixos-rebuild switch --flake .#vault --target-host vault -s $@
|
Loading…
Reference in a new issue