major tidy
This commit is contained in:
parent
907785359f
commit
599122d3af
29
data/chaosInternalWireGuard.nix
Normal file
29
data/chaosInternalWireGuard.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
let
|
||||
pubkeys = builtins.fromJSON (builtins.readFile ./chaosInternalWireGuardPubKeys.json);
|
||||
in rec {
|
||||
hosts = {
|
||||
"hetzner-vm" = {
|
||||
ip = "10.69.42.1";
|
||||
public = pubkeys."hetzner-vm";
|
||||
endpoint = "hetzner-vm.servers.genderfucked.monster:51820";
|
||||
};
|
||||
"vault" = {
|
||||
ip = "10.69.42.2";
|
||||
public = pubkeys."vault";
|
||||
endpoint = "vault.servers.genderfucked.monster:51820";
|
||||
};
|
||||
#"iphone8" = {
|
||||
# ip = "10.69.42.3";
|
||||
# public = "PEBw7EI5uogB433cp8eSfJ5DCEiYj+YG2dZd0XkIV1c=";
|
||||
#};
|
||||
#"lappy-t495" = {
|
||||
# ip = "10.69.42.4";
|
||||
# public = "BR23xeK/nTgw8Ad001wz9wrfS6gTknTpCKZBLG9bnHM=";
|
||||
#};
|
||||
"raspberry" = {
|
||||
ip = "10.69.42.5";
|
||||
public = pubkeys."raspberry";
|
||||
endpoint = "raspberry.servers.genderfucked.monster:51820";
|
||||
};
|
||||
};
|
||||
}
|
5
data/chaosInternalWireGuardPubKeys.json
Normal file
5
data/chaosInternalWireGuardPubKeys.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"hetzner-vm": "xgOQQcZQXftPC25+A7Iyf/XK6/iSo3Osyx6kTrZKdzw=",
|
||||
"vault": "u8hSeht8xR48O9AN+0cSsXPK0ZZFNcnPhOxdc+rsrlI=",
|
||||
"raspberry": "Ghrs0ps2RCsg0My9seLq+8ZFZCM4NLZWE8RiY3g9/RU="
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{}: rec {
|
||||
all = "10.69.42.1/24";
|
||||
|
||||
hosts = {
|
||||
hetzner-vm = {
|
||||
ip = "10.69.42.1";
|
||||
public = "liO33kMSEwuaaH4i6qDuorWssd9s/EfTBKBHQEbaDXE=";
|
||||
endpoint = "hetzner-vm.servers.genderfucked.monster:51820";
|
||||
};
|
||||
vault = {
|
||||
ip = "10.69.42.2";
|
||||
public = "GJ/IQ5W2Ch2vSiqcciKkrBA+pVycY2cibhvF1SFzi0I=";
|
||||
#endpoint = "vault.servers.genderfucked.monster:51820";
|
||||
};
|
||||
iphone8 = {
|
||||
ip = "10.69.42.3";
|
||||
public = "PEBw7EI5uogB433cp8eSfJ5DCEiYj+YG2dZd0XkIV1c=";
|
||||
};
|
||||
lappy-t495 = {
|
||||
ip = "10.69.42.4";
|
||||
public = "BR23xeK/nTgw8Ad001wz9wrfS6gTknTpCKZBLG9bnHM=";
|
||||
};
|
||||
raspberry = {
|
||||
ip = "10.69.42.5";
|
||||
public = "ld5XI4l/Gmr5JWg8r5midy7MTIgZkWVhMPsJqzIonng=";
|
||||
endpoint = "raspberry.servers.genderfucked.monster:51820";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
{}: (import ./normal_drive_data.nix {})
|
30
data/encryptedUSB.nix
Normal file
30
data/encryptedUSB.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
rec {
|
||||
# Mountpoints
|
||||
mountpoint = "/usb";
|
||||
|
||||
# Partition Labels
|
||||
encryptedPartLabel = "usb";
|
||||
unencryptedLabel = "usb_unencrypted";
|
||||
|
||||
# Partition Filesystems
|
||||
unencryptedFSType = "ext4";
|
||||
|
||||
# Mapper Information
|
||||
mapperName = "usb_unencrypted";
|
||||
preBootMapperName = "usb_unencrypted_preboot";
|
||||
|
||||
# FS Paths
|
||||
encryptedPath = "/dev/disk/by-partlabel/${encryptedPartLabel}";
|
||||
unencryptedPath = "/dev/disk/by-label/${unencryptedLabel}";
|
||||
mapperPath = "/dev/mapper/${mapperName}";
|
||||
preBootMapperPath = "/dev/mapper/${preBootMapperName}";
|
||||
|
||||
# Paths to some important files
|
||||
encryptionKeysPath = "${mountpoint}/encryption-keys";
|
||||
|
||||
chaosAgePrivateKeyPath = "${mountpoint}/age-keys/chaoskey.priv";
|
||||
chaosAgePublicKeyPath = "${mountpoint}/age-keys/chaoskey.pub";
|
||||
|
||||
sshPrivateKeyPath = "${mountpoint}/ssh-keys/chaos.priv";
|
||||
sshPublicKeyPath = "${mountpoint}/ssh-keys/chaos.pub";
|
||||
}
|
23
data/normalEncryptedDrive.nix
Normal file
23
data/normalEncryptedDrive.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
rec {
|
||||
# Mountpoints
|
||||
mountpoint = "/";
|
||||
bootMountpoint = "/boot";
|
||||
|
||||
# Partition Labels
|
||||
bootLabel = "nixboot";
|
||||
unencryptedLabel = "nixos";
|
||||
encryptedPartLabel = "nixos_encrypted";
|
||||
|
||||
# Partition Filesystems
|
||||
unencryptedFSType = "ext4";
|
||||
bootFSType = "vfat";
|
||||
|
||||
# Mapper Name
|
||||
mapperName = "cryptroot";
|
||||
|
||||
# FS Paths
|
||||
encryptedPath = "/dev/disk/by-partlabel/${encryptedPartLabel}";
|
||||
decryptedPath = "/dev/mapper/${mapperName}";
|
||||
|
||||
bootPath = "/dev/disk/by-label/${bootLabel}";
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{}: rec {
|
||||
# Mountpoints
|
||||
root_mountpoint = "/";
|
||||
boot_mountpoint = "/boot";
|
||||
|
||||
# Partition Labels
|
||||
boot_label = "nixboot";
|
||||
unencrypted_root_label = "nixos";
|
||||
encrypted_root_partlabel = "nixos_encrypted";
|
||||
|
||||
# Partition Filesystems
|
||||
unencrypted_root_fs_type = "ext4";
|
||||
boot_fs_type = "vfat";
|
||||
|
||||
# Mapper Name
|
||||
root_mapper_name = "cryptroot";
|
||||
|
||||
# FS Paths
|
||||
encrypted_root_path = "/dev/disk/by-partlabel/${encrypted_root_partlabel}";
|
||||
decrypted_root_path = "/dev/mapper/${root_mapper_name}";
|
||||
|
||||
boot_path = "/dev/disk/by-label/${boot_label}";
|
||||
}
|
16
data/raspberryExternalDrive.nix
Normal file
16
data/raspberryExternalDrive.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
rec {
|
||||
encryptedLabel = "raspberry_encrypted";
|
||||
unencryptedLabel = "raspberry_drive";
|
||||
|
||||
mapperName = "raspberry_external_drive";
|
||||
|
||||
mountpoint = "/external_drive";
|
||||
|
||||
encryptedPath = "/dev/disk/by-label/${encryptedLabel}";
|
||||
unencryptedPath = "/dev/disk/by-label/${unencryptedLabel}";
|
||||
mapperPath = "/dev/mapper/${mapperName}";
|
||||
|
||||
backupsPath = "${mountpoint}/backups";
|
||||
storagePath = "${mountpoint}/storage";
|
||||
extrasPath = "${mountpoint}/extras";
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{}: rec {
|
||||
encrypted_label = "raspberry_encrypted";
|
||||
unencrypted_label = "raspberry_drive";
|
||||
|
||||
mapper_name = "raspberry_external_drive";
|
||||
|
||||
mountpoint = "/external_drive";
|
||||
|
||||
backups_path = "${mountpoint}/backups";
|
||||
storage_path = "${mountpoint}/storage";
|
||||
extras_path = "${mountpoint}/extras";
|
||||
|
||||
encrypted_path = "/dev/disk/by-label/${encrypted_label}";
|
||||
unencrypted_path = "/dev/disk/by-label/${unencrypted_label}";
|
||||
mapper_path = "/dev/mapper/${mapper_name}";
|
||||
}
|
10
data/serverIPs.nix
Normal file
10
data/serverIPs.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
rec {
|
||||
"hetzner-vm" = {
|
||||
ipv4 = "65.21.182.73";
|
||||
ipv6 = "2a01:4f9:c010:8beb::1";
|
||||
};
|
||||
"vault" = {
|
||||
ipv4 = "65.21.145.62";
|
||||
ipv6 = "2a01:4f9:c010:6a89::1";
|
||||
};
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{}: rec {
|
||||
# Mountpoints
|
||||
mountpoint = "/usb";
|
||||
|
||||
# Partition Labels
|
||||
encrypted_partlabel = "usb";
|
||||
unencrypted_label = "usb_unencrypted";
|
||||
|
||||
# Partition Filesystems
|
||||
unencrypted_fs_type = "ext4";
|
||||
|
||||
# Mapper Information
|
||||
mapper_name = "usb_unencrypted";
|
||||
|
||||
# FS Paths
|
||||
encrypted_path = "/dev/disk/by-partlabel/${encrypted_partlabel}";
|
||||
unencrypted_path = "/dev/disk/by-label/${unencrypted_label}";
|
||||
mapper_path = "/dev/mapper/${mapper_name}";
|
||||
|
||||
# Paths to some important files
|
||||
encryption_keys_path = "${mountpoint}/encryption-keys";
|
||||
|
||||
chaos_age_privkey_path = "${mountpoint}/age-keys/chaoskey.priv";
|
||||
chaos_age_pubkey_path = "${mountpoint}/age-keys/chaoskey.pub";
|
||||
|
||||
ssh_priv_path = "${mountpoint}/ssh-keys/chaos.priv";
|
||||
ssh_pub_path = "${mountpoint}/ssh-keys/chaos.pub";
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
{
|
||||
nixosConfigurations,
|
||||
deploy-rs,
|
||||
...
|
||||
}: let
|
||||
activateNixOS_x64_64-linux = deploy-rs.lib.x86_64-linux.activate.nixos;
|
||||
in {
|
||||
tablet = {
|
||||
hostname = "tablet.internal.genderfucked.monster";
|
||||
profiles.system = {
|
||||
user = "root";
|
||||
sshUser = "root";
|
||||
path = activateNixOS_x64_64-linux nixosConfigurations.tablet;
|
||||
};
|
||||
};
|
||||
hetzner-vm = {
|
||||
hostname = "hetzner-vm.servers.genderfucked.monster";
|
||||
username = "root";
|
||||
profiles.system = {
|
||||
user = "root";
|
||||
sshUser = "root";
|
||||
path = activateNixOS_x64_64-linux nixosConfigurations.hetzner-vm;
|
||||
};
|
||||
};
|
||||
storage = {
|
||||
hostname = "storage.servers.genderfucked.monster";
|
||||
username = "root";
|
||||
profiles.system = {
|
||||
user = "root";
|
||||
sshUser = "root";
|
||||
path = activateNixOS_x64_64-linux nixosConfigurations.storage;
|
||||
};
|
||||
};
|
||||
vault = {
|
||||
hostname = "vault.servers.genderfucked.monster";
|
||||
username = "root";
|
||||
profiles.system = {
|
||||
user = "root";
|
||||
sshUser = "root";
|
||||
path = activateNixOS_x64_64-linux nixosConfigurations.vault;
|
||||
};
|
||||
};
|
||||
buildbox = {
|
||||
hostname = "buildbox.servers.genderfucked.monster";
|
||||
username = "root";
|
||||
profiles.system = {
|
||||
user = "root";
|
||||
sshUser = "root";
|
||||
path = activateNixOS_x64_64-linux nixosConfigurations.buildbox;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
wireguard_data = import ../data/chaos_wireguard_internal.nix {};
|
||||
wireguard_hosts = wireguard_data.hosts;
|
||||
|
||||
inherit (pkgs) writeShellScriptBin;
|
||||
inherit (lib.lists) forEach filter;
|
||||
inherit (builtins) hasAttr attrNames;
|
||||
|
||||
kvPathForHost = host: "/private-public-keys/wireguard/chaos-internal/${host}";
|
||||
in rec {
|
||||
initAllScript = writeShellScriptBin "wg-keys-init-all" (let
|
||||
vault = "${pkgs.vault-bin}/bin/vault";
|
||||
jq = "${pkgs.jq}/bin/jq";
|
||||
in ''
|
||||
|
||||
${lib.concatStringsSep "\n" (lib.forEach (attrNames wireguard_hosts) (hostName: ''
|
||||
if [ -z "$PRESHARED_ONLY" ]; then
|
||||
echo "{}" | vault kv put "${kvPathForHost hostName}" - 2>/dev/null
|
||||
fi
|
||||
''))}
|
||||
|
||||
${lib.concatStringsSep "\n" (lib.forEach (attrNames wireguard_hosts) (hostName: ''
|
||||
echo "Deploying keys for ${hostName}"
|
||||
|
||||
"${genInitScript hostName}/bin/wg-keys-init-${hostName}"
|
||||
''))}
|
||||
|
||||
${lib.concatStringsSep "\n" (lib.forEach (attrNames wireguard_hosts) (hostName: ''
|
||||
echo
|
||||
|
||||
PUBLIC=$(${vault} kv get -format=json "${kvPathForHost hostName}" | ${jq} .data.data.public)
|
||||
echo "Public Key for ${hostName}: $PUBLIC"
|
||||
''))}
|
||||
'');
|
||||
|
||||
genInitScript = systemHostName: (writeShellScriptBin "wg-keys-init-${systemHostName}" (let
|
||||
vault = "${pkgs.vault-bin}/bin/vault";
|
||||
jq = "${pkgs.jq}/bin/jq";
|
||||
wg = "${pkgs.wireguard-tools}/bin/wg";
|
||||
sponge = "${pkgs.moreutils}/bin/sponge";
|
||||
|
||||
hostsWithEndpoints = filter (hostName: (hostName != systemHostName && hasAttr "endpoint" wireguard_hosts.${hostName})) (attrNames wireguard_hosts);
|
||||
in ''
|
||||
PRIVATE=$(${wg} genkey)
|
||||
PUBLIC=$(echo "$PRIVATE" | ${wg} pubkey)
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
pushd "$TMP_DIR"
|
||||
|
||||
echo "{}" > currentHost.json
|
||||
if [ -z "$PRESHARED_ONLY" ]; then
|
||||
${jq} ".public = \"$PUBLIC\"" currentHost.json | ${sponge} currentHost.json
|
||||
${jq} ".private = \"$PRIVATE\"" currentHost.json | ${sponge} currentHost.json
|
||||
fi
|
||||
|
||||
${jq} '.preshared_keys = {}' currentHost.json | ${sponge} currentHost.json
|
||||
|
||||
${lib.concatStringsSep "\n" (lib.forEach hostsWithEndpoints (hostName: ''
|
||||
echo "Generating preshared key for ${hostName}"
|
||||
|
||||
PSK=$(${wg} genpsk)
|
||||
${jq} ".preshared_keys.\"${hostName}\" = \"$PSK\"" currentHost.json | ${sponge} currentHost.json
|
||||
''))}
|
||||
|
||||
|
||||
${lib.concatStringsSep "\n" (lib.forEach hostsWithEndpoints (hostName: ''
|
||||
echo "Deploying preshared key for ${hostName}"
|
||||
|
||||
PSK=$(jq -r '.preshared_keys."${hostName}"' currentHost.json)
|
||||
|
||||
${vault} kv get -format=json "${kvPathForHost hostName}" 2>/dev/null | jq -r .data.data > otherHost.json
|
||||
${jq} ".preshared_keys.\"${systemHostName}\" = \"$PSK\"" otherHost.json | ${sponge} otherHost.json
|
||||
cat otherHost.json | vault kv put "${kvPathForHost hostName}" - 2>/dev/null
|
||||
|
||||
rm otherHost.json
|
||||
''))}
|
||||
|
||||
if [ -z "$PRESHARED_ONLY" ]; then
|
||||
cat currentHost.json | ${vault} kv put "${kvPathForHost systemHostName}" - 2>/dev/null
|
||||
cat currentHost.json | jq
|
||||
fi
|
||||
rm currentHost.json
|
||||
|
||||
|
||||
popd
|
||||
|
||||
rm -rf "$TMP_DIR"
|
||||
|
||||
echo "Public Key for ${systemHostName}: $PUBLIC"
|
||||
''));
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
stdenv,
|
||||
bash,
|
||||
parted,
|
||||
cryptsetup,
|
||||
e2fsprogs,
|
||||
dosfstools,
|
||||
}: let
|
||||
ssd_data = import ../data/dual_drive_data.nix {};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "mk-dual-enc-ssd";
|
||||
src = ./mk-dual-enc-ssd.sh;
|
||||
unpackPhase = ''
|
||||
for srcFile in $src; do
|
||||
cp $srcFile $(stripHash $srcFile)
|
||||
done
|
||||
'';
|
||||
|
||||
inherit bash parted cryptsetup e2fsprogs dosfstools;
|
||||
|
||||
patchPhase = ''
|
||||
substituteAllInPlace mk-dual-enc-ssd.sh
|
||||
substituteInPlace mk-dual-enc-ssd.sh \
|
||||
--replace "@SSD_ENCRYPTED_PARTLABEL@" "${ssd_data.encrypted_root_partlabel}" \
|
||||
--replace "@SSD_UNENCRYPTED_LABEL@" "${ssd_data.unencrypted_root_label}" \
|
||||
--replace "@SSD_BOOT_LABEL@" "${ssd_data.boot_label}"
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp mk-dual-enc-ssd.sh $out/bin/mk-dual-enc-ssd
|
||||
chmod +x $out/bin/mk-dual-enc-ssd
|
||||
'';
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
#! @bash@/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# e.g /dev/nvme0n1
|
||||
SSD_PATH=$1
|
||||
KEY_FILE=$2
|
||||
NIXOS_SIZE=$3
|
||||
|
||||
if echo "$SSD_PATH" | grep -q "[0-9]$"; then
|
||||
PARTITION_SEPARATOR="p"
|
||||
else
|
||||
PARTITION_SEPARATOR=""
|
||||
fi
|
||||
|
||||
if [ -z "$SSD_PATH" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$KEY_FILE" ]; then
|
||||
echo "Please specify a key file to use"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$NIXOS_SIZE" ]; then
|
||||
echo "Please specify how big to make the NixOS partition"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# encrypted partition label
|
||||
SSD_ENCRYPTED_PARTLABEL=@SSD_ENCRYPTED_PARTLABEL@
|
||||
# unencrypted filesystem label
|
||||
SSD_UNENCRYPTED_LABEL=@SSD_UNENCRYPTED_LABEL@
|
||||
# ssd boot label
|
||||
SSD_BOOT_LABEL=@SSD_BOOT_LABEL@
|
||||
|
||||
echo "Creating Partitions..."
|
||||
@parted@/bin/parted ${SSD_PATH} -- mklabel gpt
|
||||
@parted@/bin/parted ${SSD_PATH} -- mkpart ESP fat32 1MiB 1024MiB
|
||||
@parted@/bin/parted ${SSD_PATH} -- mkpart primary 1072MiB "${NIXOS_SIZE}"
|
||||
@parted@/bin/parted ${SSD_PATH} -- set 1 esp on
|
||||
@parted@/bin/parted ${SSD_PATH} -- name 1 "${SSD_BOOT_LABEL}"
|
||||
@parted@/bin/parted ${SSD_PATH} -- name 2 "${SSD_ENCRYPTED_PARTLABEL}"
|
||||
|
||||
echo "Formatting boot partition"
|
||||
@dosfstools@/bin/mkfs.fat -n "${SSD_BOOT_LABEL}" "${SSD_PATH}${PARTITION_SEPARATOR}1"
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup luksFormat "${SSD_PATH}${PARTITION_SEPARATOR}2" --key-file "${KEY_FILE}"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup open "${SSD_PATH}${PARTITION_SEPARATOR}2" "mk_dual_enc_ssd" --key-file "${KEY_FILE}"
|
||||
|
||||
echo "Formatting Encrypted Root Filesystem"
|
||||
@e2fsprogs@/bin/mkfs.ext4 -L "${SSD_UNENCRYPTED_LABEL}" /dev/mapper/mk_dual_enc_ssd
|
||||
|
||||
echo "mount /dev/mapper/mk_dual_enc_ssd to install"
|
|
@ -1,33 +1,57 @@
|
|||
{
|
||||
stdenv,
|
||||
bash,
|
||||
parted,
|
||||
cryptsetup,
|
||||
e2fsprogs,
|
||||
writeShellApplication,
|
||||
}: let
|
||||
usb_data = import ../data/usb_data.nix {};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "mk-enc-usb";
|
||||
src = ./mk-enc-usb.sh;
|
||||
unpackPhase = ''
|
||||
for srcFile in $src; do
|
||||
cp $srcFile $(stripHash $srcFile)
|
||||
done
|
||||
'';
|
||||
encryptedUSBData = import ../data/encryptedUSB.nix;
|
||||
in (writeShellApplication {
|
||||
name = "mk-enc-usb";
|
||||
runtimeInputs = [
|
||||
parted
|
||||
cryptsetup
|
||||
e2fsprogs
|
||||
];
|
||||
text = ''
|
||||
if [ -z "''${1-}" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
inherit bash parted cryptsetup e2fsprogs;
|
||||
# e.g /dev/sdb
|
||||
USB_DEVICE=$1
|
||||
|
||||
patchPhase = ''
|
||||
substituteAllInPlace mk-enc-usb.sh
|
||||
substituteInPlace mk-enc-usb.sh \
|
||||
--replace "@USB_ENCRYPTED_PARTLABEL@" "${usb_data.encrypted_partlabel}" \
|
||||
--replace "@USB_UNENCRYPTED_LABEL@" "${usb_data.unencrypted_label}"
|
||||
'';
|
||||
if echo "$USB_DEVICE" | grep -q "[0-9]$"; then
|
||||
PARTITION_SEPARATOR="p"
|
||||
else
|
||||
PARTITION_SEPARATOR=""
|
||||
fi
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp mk-enc-usb.sh $out/bin/mk-enc-usb
|
||||
chmod +x $out/bin/mk-enc-usb
|
||||
'';
|
||||
}
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "Creating Encrypted USB."
|
||||
|
||||
echo "Creating Partitions..."
|
||||
parted "$USB_DEVICE" -- mklabel gpt
|
||||
parted "$USB_DEVICE" -- mkpart primary 0% 100%
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
cryptsetup luksFormat "''${USB_DEVICE}''${PARTITION_SEPARATOR}1"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
cryptsetup open "''${USB_DEVICE}''${PARTITION_SEPARATOR}1" "mk_enc_usb"
|
||||
|
||||
echo "Making Encrypted Filesystem"
|
||||
mkfs.ext4 -L "${encryptedUSBData.unencryptedLabel}" /dev/mapper/mk_enc_usb
|
||||
|
||||
echo "Closing Encrypted Partition"
|
||||
cryptsetup close "mk_enc_usb"
|
||||
|
||||
# Do this now so that i can run the damn script with usb-automount and stop it trying to mount
|
||||
echo "Naming Partitions"
|
||||
parted "$USB_DEVICE" -- name 1 ${encryptedUSBData.encryptedPartLabel}
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
#! @bash@/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# e.g /dev/sdb
|
||||
USB_DEVICE=$1
|
||||
|
||||
if echo "$USB_DEVICE" | grep -q "[0-9]$"; then
|
||||
PARTITION_SEPARATOR="p"
|
||||
else
|
||||
PARTITION_SEPARATOR=""
|
||||
fi
|
||||
|
||||
if [ -z "$USB_DEVICE" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# encrypted partition label
|
||||
USB_ENCRYPTED_PARTLABEL=@USB_ENCRYPTED_PARTLABEL@
|
||||
# unencrypted filesystem label
|
||||
USB_UNENCRYPTED_LABEL=@USB_UNENCRYPTED_LABEL@
|
||||
|
||||
echo "Creating Encrypted USB."
|
||||
|
||||
echo "Creating Partitions..."
|
||||
@parted@/bin/parted ${USB_DEVICE} -- mklabel gpt
|
||||
@parted@/bin/parted ${USB_DEVICE} -- mkpart primary 0% 100%
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup luksFormat "${USB_DEVICE}${PARTITION_SEPARATOR}1"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup open "${USB_DEVICE}${PARTITION_SEPARATOR}1" "mk_enc_usb"
|
||||
|
||||
echo "Making Encrypted Filesystem"
|
||||
@e2fsprogs@/bin/mkfs.ext4 -L "${USB_UNENCRYPTED_LABEL}" /dev/mapper/mk_enc_usb
|
||||
|
||||
echo "Closing Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup close "mk_enc_usb"
|
||||
|
||||
# Do this now so that i can run the damn script with usb-automount and stop it trying to mount
|
||||
echo "Naming Partitions"
|
||||
@parted@/bin/parted ${USB_DEVICE} -- name 1 "${USB_ENCRYPTED_PARTLABEL}"
|
|
@ -1,35 +1,64 @@
|
|||
{
|
||||
stdenv,
|
||||
bash,
|
||||
parted,
|
||||
cryptsetup,
|
||||
e2fsprogs,
|
||||
dosfstools,
|
||||
writeShellApplication,
|
||||
}: let
|
||||
ssd_data = import ../data/normal_drive_data.nix {};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "mk-normal-enc-ssd";
|
||||
src = ./mk-normal-enc-ssd.sh;
|
||||
unpackPhase = ''
|
||||
for srcFile in $src; do
|
||||
cp $srcFile $(stripHash $srcFile)
|
||||
done
|
||||
'';
|
||||
ssdData = import ../data/normalEncryptedDrive.nix;
|
||||
in (writeShellApplication {
|
||||
name = "mk-normal-enc-ssd";
|
||||
runtimeInputs = [
|
||||
parted
|
||||
cryptsetup
|
||||
e2fsprogs
|
||||
dosfstools
|
||||
];
|
||||
text = ''
|
||||
if [ -z "''${1-}" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
inherit bash parted cryptsetup e2fsprogs dosfstools;
|
||||
if [ -z "''${2-}" ]; then
|
||||
echo "Please specify a path to key file as second argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patchPhase = ''
|
||||
substituteAllInPlace mk-normal-enc-ssd.sh
|
||||
substituteInPlace mk-normal-enc-ssd.sh \
|
||||
--replace "@SSD_ENCRYPTED_PARTLABEL@" "${ssd_data.encrypted_root_partlabel}" \
|
||||
--replace "@SSD_UNENCRYPTED_LABEL@" "${ssd_data.unencrypted_root_label}" \
|
||||
--replace "@SSD_BOOT_LABEL@" "${ssd_data.boot_label}"
|
||||
'';
|
||||
SSD_PATH=$1
|
||||
KEY_FILE=$2
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp mk-normal-enc-ssd.sh $out/bin/mk-normal-enc-ssd
|
||||
chmod +x $out/bin/mk-normal-enc-ssd
|
||||
'';
|
||||
}
|
||||
if echo "$SSD_PATH" | grep -q "[0-9]$"; then
|
||||
PARTITION_SEPARATOR="p"
|
||||
else
|
||||
PARTITION_SEPARATOR=""
|
||||
fi
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "Creating Partitions..."
|
||||
parted "$SSD_PATH" -- mklabel gpt
|
||||
parted "$SSD_PATH" -- mkpart ESP fat32 1MiB 512MiB
|
||||
parted "$SSD_PATH" -- mkpart primary 620MiB -1MiB
|
||||
parted "$SSD_PATH" -- set 1 esp on
|
||||
parted "$SSD_PATH" -- name 1 "${ssdData.bootLabel}"
|
||||
parted "$SSD_PATH" -- name 2 "${ssdData.encryptedPartLabel}"
|
||||
|
||||
echo "Formatting boot partition"
|
||||
mkfs.fat -n "${ssdData.bootLabel}" "''${SSD_PATH}''${PARTITION_SEPARATOR}1"
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
cryptsetup luksFormat "''${SSD_PATH}''${PARTITION_SEPARATOR}2" --key-file "$KEY_FILE"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
cryptsetup open "''${SSD_PATH}''${PARTITION_SEPARATOR}2" "mk_normal_enc_ssd" --key-file "$KEY_FILE"
|
||||
|
||||
echo "Formatting Encrypted Root Filesystem"
|
||||
mkfs.ext4 -L "${ssdData.unencryptedLabel}" /dev/mapper/mk_normal_enc_ssd
|
||||
|
||||
echo "mount /dev/mapper/mk_normal_enc_ssd to install"
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
#! @bash@/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# e.g /dev/nvme0n1
|
||||
SSD_PATH=$1
|
||||
KEY_FILE=$2
|
||||
|
||||
if echo "$SSD_PATH" | grep -q "[0-9]$"; then
|
||||
PARTITION_SEPARATOR="p"
|
||||
else
|
||||
PARTITION_SEPARATOR=""
|
||||
fi
|
||||
|
||||
if [ -z "$SSD_PATH" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$KEY_FILE" ]; then
|
||||
echo "Please specify a key file to use"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# encrypted partition label
|
||||
SSD_ENCRYPTED_PARTLABEL=@SSD_ENCRYPTED_PARTLABEL@
|
||||
# unencrypted filesystem label
|
||||
SSD_UNENCRYPTED_LABEL=@SSD_UNENCRYPTED_LABEL@
|
||||
# ssd boot label
|
||||
SSD_BOOT_LABEL=@SSD_BOOT_LABEL@
|
||||
|
||||
echo "Creating Partitions..."
|
||||
@parted@/bin/parted ${SSD_PATH} -- mklabel gpt
|
||||
@parted@/bin/parted ${SSD_PATH} -- mkpart ESP fat32 1MiB 512MiB
|
||||
@parted@/bin/parted ${SSD_PATH} -- mkpart primary 620MiB -1MiB
|
||||
@parted@/bin/parted ${SSD_PATH} -- set 1 esp on
|
||||
@parted@/bin/parted ${SSD_PATH} -- name 1 "${SSD_BOOT_LABEL}"
|
||||
@parted@/bin/parted ${SSD_PATH} -- name 2 "${SSD_ENCRYPTED_PARTLABEL}"
|
||||
|
||||
echo "Formatting boot partition"
|
||||
@dosfstools@/bin/mkfs.fat -n "${SSD_BOOT_LABEL}" "${SSD_PATH}${PARTITION_SEPARATOR}1"
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup luksFormat "${SSD_PATH}${PARTITION_SEPARATOR}2" --key-file "${KEY_FILE}"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup open "${SSD_PATH}${PARTITION_SEPARATOR}2" "mk_normal_enc_ssd" --key-file "${KEY_FILE}"
|
||||
|
||||
echo "Formatting Encrypted Root Filesystem"
|
||||
@e2fsprogs@/bin/mkfs.ext4 -L "${SSD_UNENCRYPTED_LABEL}" /dev/mapper/mk_normal_enc_ssd
|
||||
|
||||
echo "mount /dev/mapper/mk_normal_enc_ssd to install"
|
|
@ -1,35 +1,67 @@
|
|||
{
|
||||
stdenv,
|
||||
bash,
|
||||
util-linux,
|
||||
cryptsetup,
|
||||
btrfs-progs,
|
||||
writeShellApplication,
|
||||
}: let
|
||||
external_drive_data = import ../data/raspberry_ext_drive.nix {};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "mk-raspberry-ext-drive";
|
||||
src = ./mk-raspberry-ext-drive.sh;
|
||||
unpackPhase = ''
|
||||
for srcFile in $src; do
|
||||
cp $srcFile $(stripHash $srcFile)
|
||||
done
|
||||
'';
|
||||
externalDriveData = import ../data/raspberryExternalDrive.nix;
|
||||
in (writeShellApplication {
|
||||
name = "mk-raspberry-ext-drive";
|
||||
runtimeInputs = [
|
||||
util-linux
|
||||
cryptsetup
|
||||
btrfs-progs
|
||||
];
|
||||
text = ''
|
||||
if [ -z "''${1-}" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
patchPhase = ''
|
||||
substituteAllInPlace mk-raspberry-ext-drive.sh
|
||||
substituteInPlace mk-raspberry-ext-drive.sh \
|
||||
--replace "@util-linux@" "${util-linux}" \
|
||||
--replace "@btrfs-progs@" "${btrfs-progs}" \
|
||||
--replace "@cryptsetup@" "${cryptsetup}" \
|
||||
--replace "@bash@" "${bash}" \
|
||||
--replace "@ENCRYPTED_LABEL@" "${external_drive_data.encrypted_label}" \
|
||||
--replace "@UNENCRYPTED_LABEL@" "${external_drive_data.unencrypted_label}"
|
||||
'';
|
||||
DRIVE_PATH=$1
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp mk-raspberry-ext-drive.sh $out/bin/mk-raspberry-ext-drive
|
||||
chmod +x $out/bin/mk-raspberry-ext-drive
|
||||
'';
|
||||
}
|
||||
if [ -z "''${2-}" ]; then
|
||||
echo "Please specify a key file to use"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KEY_FILE=$2
|
||||
|
||||
if [ -z "''${3-}" ]; then
|
||||
echo "Please specify a temp mountpoint to use"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP_MOUNTPOINT=$3
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
echo "Wiping Partitions..."
|
||||
wipefs --all "$DRIVE_PATH"
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
cryptsetup luksFormat "$DRIVE_PATH" --key-file "$KEY_FILE" --label "${externalDriveData.encryptedLabel}"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
cryptsetup open "$DRIVE_PATH" "mk-raspberry-ext-drive" --key-file "$KEY_FILE"
|
||||
|
||||
echo "Formatting Encrypted Filesystem"
|
||||
mkfs.btrfs -L "${externalDriveData.unencryptedLabel}" /dev/mapper/mk-raspberry-ext-drive
|
||||
|
||||
echo "Mounting Partition"
|
||||
mount -t btrfs /dev/mapper/mk-raspberry-ext-drive "$TEMP_MOUNTPOINT"
|
||||
|
||||
echo "Creating Folders"
|
||||
mkdir "$TEMP_MOUNTPOINT/backups"
|
||||
mkdir "$TEMP_MOUNTPOINT/storage"
|
||||
mkdir "$TEMP_MOUNTPOINT/extras"
|
||||
|
||||
echo "Unmounting"
|
||||
umount "$TEMP_MOUNTPOINT"
|
||||
|
||||
echo "Closing mapper device"
|
||||
cryptsetup close "mk-raspberry-ext-drive"
|
||||
'';
|
||||
})
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
#! @bash@/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# e.g /dev/nvme0n1
|
||||
DRIVE_PATH=$1
|
||||
KEY_FILE=$2
|
||||
TEMP_MOUNTPOINT=$3
|
||||
|
||||
if echo "$DRIVE_PATH" | grep -q "[0-9]$"; then
|
||||
PARTITION_SEPARATOR="p"
|
||||
else
|
||||
PARTITION_SEPARATOR=""
|
||||
fi
|
||||
|
||||
if [ -z "$DRIVE_PATH" ]; then
|
||||
echo "Please specify a path to device as first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$KEY_FILE" ]; then
|
||||
echo "Please specify a key file to use"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$TEMP_MOUNTPOINT" ]; then
|
||||
echo "Please specify a temp mountpoint to use"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# encrypted partition label
|
||||
ENCRYPTED_LABEL=@ENCRYPTED_LABEL@
|
||||
# unencrypted filesystem label
|
||||
UNENCRYPTED_LABEL=@UNENCRYPTED_LABEL@
|
||||
|
||||
echo "Wiping Partitions..."
|
||||
@util-linux@/bin/wipefs --all ${DRIVE_PATH}
|
||||
|
||||
echo "Creating Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup luksFormat "${DRIVE_PATH}" --key-file "${KEY_FILE}" --label "${ENCRYPTED_LABEL}"
|
||||
|
||||
echo "Opening Encrypted Partition"
|
||||
@cryptsetup@/bin/cryptsetup open "${DRIVE_PATH}" "mk-raspberry-ext-drive" --key-file "${KEY_FILE}"
|
||||
|
||||
echo "Formatting Encrypted Filesystem"
|
||||
@btrfs-progs@/bin/mkfs.btrfs -L "${UNENCRYPTED_LABEL}" /dev/mapper/mk-raspberry-ext-drive
|
||||
|
||||
echo "Mounting Partition"
|
||||
mount -t btrfs /dev/mapper/mk-raspberry-ext-drive "$TEMP_MOUNTPOINT"
|
||||
|
||||
echo "Creating Folders"
|
||||
mkdir "$TEMP_MOUNTPOINT/backups"
|
||||
mkdir "$TEMP_MOUNTPOINT/storage"
|
||||
mkdir "$TEMP_MOUNTPOINT/extras"
|
||||
|
||||
echo "Unmounting"
|
||||
umount "$TEMP_MOUNTPOINT"
|
||||
|
||||
echo "Closing mapper device"
|
||||
@cryptsetup@/bin/cryptsetup close "mk-raspberry-ext-drive"
|
|
@ -1,96 +0,0 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
nixpkgs,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
wifiInterface = "shenanigans0";
|
||||
wifiMac = "00:0F:55:A8:2B:8E";
|
||||
|
||||
usbethInterface = "shenanigans1";
|
||||
usbethMac = "d0:37:45:88:9a:49";
|
||||
|
||||
ssid = "Shenanigans";
|
||||
password = "password123";
|
||||
in {
|
||||
boot.extraModulePackages = with config.boot.kernelPackages; [rtl8812au];
|
||||
nixpkgs.config.allowBroken = true;
|
||||
|
||||
services.udev.extraRules = ''
|
||||
KERNEL=="wlan*", ATTR{address}=="${
|
||||
lib.toLower wifiMac
|
||||
}", NAME="${wifiInterface}"
|
||||
KERNEL=="eth*", ACTION=="add", ATTR{address}=="${
|
||||
lib.toLower usbethMac
|
||||
}", NAME="${usbethInterface}"
|
||||
'';
|
||||
|
||||
networking.interfaces."${wifiInterface}".ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
networking.interfaces."${usbethInterface}".ipv4.addresses = [
|
||||
{
|
||||
address = "192.168.2.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
networking.networkmanager.unmanaged = [
|
||||
# Wifi
|
||||
"interface-name:${wifiInterface}"
|
||||
"mac:${wifiMac}"
|
||||
"interface-name:${usbethInterface}"
|
||||
"mac:${usbethMac}"
|
||||
];
|
||||
|
||||
systemd.services.wifi-relay = let
|
||||
inherit (pkgs) iptables;
|
||||
in {
|
||||
description = "iptables rules for wifi-relay";
|
||||
after = ["dhcpd4.service"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
script = ''
|
||||
${iptables}/bin/iptables -w -t nat -I POSTROUTING -s 192.168.2.0/24 ! -o ${wifiInterface} -j MASQUERADE
|
||||
${iptables}/bin/iptables -w -I FORWARD -i ${wifiInterface} -s 192.168.2.0/24 -j ACCEPT
|
||||
${iptables}/bin/iptables -w -t nat -I POSTROUTING -s 192.168.2.0/24 ! -o ${usbethInterface} -j MASQUERADE
|
||||
${iptables}/bin/iptables -w -I FORWARD -i ${usbethInterface} -s 192.168.2.0/24 -j ACCEPT
|
||||
#${iptables}/bin/iptables -t nat -A PREROUTING -i ${wifiInterface} -p tcp --dport 80 -j REDIRECT --to-port 8080
|
||||
#${iptables}/bin/iptables -t nat -A PREROUTING -i ${wifiInterface} -p tcp --dport 443 -j REDIRECT --to-port 8080
|
||||
'';
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
trustedInterfaces = [wifiInterface usbethInterface];
|
||||
checkReversePath = lib.mkForce false;
|
||||
allowedTCPPorts = [53 80 443];
|
||||
};
|
||||
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
networking.firewall.allowedUDPPorts = [53 67];
|
||||
|
||||
services.hostapd = {
|
||||
enable = true;
|
||||
interface = wifiInterface;
|
||||
inherit ssid;
|
||||
wpaPassphrase = password;
|
||||
};
|
||||
|
||||
services.dhcpd4 = {
|
||||
enable = true;
|
||||
interfaces = ["${usbethInterface}"];
|
||||
extraConfig = ''
|
||||
subnet 192.168.2.0 netmask 255.255.255.0 {
|
||||
range 192.168.2.100 192.168.2.200;
|
||||
option subnet-mask 255.255.255.0;
|
||||
option broadcast-address 192.168.2.255;
|
||||
option routers 192.168.2.1;
|
||||
option domain-name-servers 192.168.2.1;
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
27
flake.lock
27
flake.lock
|
@ -1,31 +1,5 @@
|
|||
{
|
||||
"nodes": {
|
||||
"deploy-rs": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs-unstable"
|
||||
],
|
||||
"utils": [
|
||||
"flake-utils"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694513707,
|
||||
"narHash": "sha256-wE5kHco3+FQjc+MwTPwLVqYz4hM7uno2CgXDXUFMCpc=",
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"rev": "31c32fb2959103a796e07bbe47e0a5e287c343a8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "serokell",
|
||||
"repo": "deploy-rs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
|
@ -217,7 +191,6 @@
|
|||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"deploy-rs": "deploy-rs",
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"gitlab_archiver": "gitlab_archiver",
|
||||
|
|
|
@ -16,19 +16,11 @@
|
|||
home-manager-unstable.url = "github:nix-community/home-manager";
|
||||
home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
#nix-darwin-unstable.url = "github:lnl7/nix-darwin/master";
|
||||
#nix-darwin-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
tree-input.url = "github:kittywitch/tree";
|
||||
tree-input.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
nur.url = "github:nix-community/NUR";
|
||||
|
||||
deploy-rs.url = "github:serokell/deploy-rs";
|
||||
deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
deploy-rs.inputs.utils.follows = "flake-utils";
|
||||
deploy-rs.inputs.flake-compat.follows = "flake-compat";
|
||||
|
||||
vaultui.url = "gitlab:ChaotiCryptidz/VaultUI";
|
||||
vaultui.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
vaultui.inputs.utils.follows = "flake-utils";
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
{
|
||||
inputs,
|
||||
nixosConfig,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
nur = import inputs.nur {
|
||||
nurpkgs = pkgs;
|
||||
inherit pkgs;
|
||||
};
|
||||
|
||||
isGnome = nixosConfig.services.xserver.desktopManager.gnome.enable;
|
||||
extensions = with nixosConfig.nur; [
|
||||
repos.rycee.firefox-addons.ublock-origin
|
||||
repos.rycee.firefox-addons.stylus
|
||||
repos.rycee.firefox-addons.tampermonkey
|
||||
repos.rycee.firefox-addons.search-engines-helper
|
||||
#repos.rycee.firefox-addons.search-by-image
|
||||
repos.rycee.firefox-addons.offline-qr-code-generator
|
||||
repos.rycee.firefox-addons.i-dont-care-about-cookies
|
||||
repos.rycee.firefox-addons.don-t-fuck-with-paste
|
||||
repos.rycee.firefox-addons.amp2html
|
||||
repos.rycee.firefox-addons.a11ycss
|
||||
|
||||
extensions = with nur.repos.rycee.firefox-addons; [
|
||||
ublock-origin
|
||||
stylus
|
||||
tampermonkey
|
||||
search-engines-helper
|
||||
search-by-image
|
||||
offline-qr-code-generator
|
||||
i-dont-care-about-cookies
|
||||
don-t-fuck-with-paste
|
||||
amp2html
|
||||
a11ycss
|
||||
];
|
||||
in {
|
||||
programs.firefox = {
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
{lib, ...}: let
|
||||
container-addresses = import ../../hosts/hetzner-vm/data/container-addresses.nix {};
|
||||
{
|
||||
self,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkMerge;
|
||||
inherit (lib.lists) forEach;
|
||||
inherit (builtins) attrNames;
|
||||
|
||||
containerAddresses = import "${self}/hosts/hetzner-vm/data/containerAddresses.nix";
|
||||
in {
|
||||
programs.ssh.enable = true;
|
||||
programs.ssh.matchBlocks =
|
||||
lib.mkMerge
|
||||
((lib.forEach ["hetzner-vm" "vault" "raspberry" "vault-decrypt"] (hostname: {
|
||||
mkMerge
|
||||
((forEach ["hetzner-vm" "vault" "raspberry" "vault-decrypt"] (hostname: {
|
||||
"${hostname}" = {
|
||||
user = "root";
|
||||
hostname = "${hostname}.servers.genderfucked.monster";
|
||||
};
|
||||
}))
|
||||
++ (lib.forEach (lib.attrNames container-addresses.containers) (name: {
|
||||
"container-${name}" = {
|
||||
++ (forEach (attrNames containerAddresses.containers) (name: {
|
||||
"hetzner-vm-container-${name}" = {
|
||||
user = "root";
|
||||
hostname = "${container-addresses.containers.${name}}";
|
||||
hostname = "${containerAddresses.containers.${name}}";
|
||||
proxyJump = "hetzner-vm";
|
||||
};
|
||||
}))
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{pkgs, ...}: let
|
||||
usb_data = import ../../data/usb_data.nix {};
|
||||
{
|
||||
self,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
encryptedUSBData = import "${self}/data/encryptedUSB.nix";
|
||||
in {
|
||||
home.packages = with pkgs; [eza bat ripgrep vault-bin libarchive age];
|
||||
programs.zsh = {
|
||||
|
@ -27,9 +31,9 @@ in {
|
|||
log = "journalctl";
|
||||
dmesg = "dmesg -HP";
|
||||
hg = "history 0 | rg";
|
||||
chaos_age = "age -i ${usb_data.chaos_age_privkey_path}";
|
||||
chaos_age_encrypt = "age -a -e -i ${usb_data.chaos_age_privkey_path}";
|
||||
chaos_pub = "cat ${usb_data.chaos_age_pubkey_path}";
|
||||
chaos_age = "age -i ${encryptedUSBData.chaosAgePrivateKeyPath}";
|
||||
chaos_age_encrypt = "age -a -e -i ${encryptedUSBData.chaosAgePrivateKeyPath}";
|
||||
chaos_pub = "cat ${encryptedUSBData.chaosAgePublicKeyPath}";
|
||||
};
|
||||
envExtra = ''
|
||||
export VAULT_ADDR="https://vault.owo.monster"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
{pkgs, ...}: {home.packages = with pkgs.deploy-rs; [deploy-rs];}
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
mk-enc-usb
|
||||
mk-normal-enc-ssd
|
||||
mk-dual-enc-ssd
|
||||
mk-raspberry-ext-drive
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{tree, ...}: {
|
||||
# basically everything apart from home.all.dev.debugging and home.all.dev.deploy-rs and extra archives
|
||||
# basically everything apart from home.all.dev.debugging and extra archives
|
||||
imports = with tree; [
|
||||
home.dev.all.archives.common
|
||||
home.dev.all.compression
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
{
|
||||
nixosConfig,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
{pkgs, ...}: {
|
||||
gtk = {
|
||||
enable = true;
|
||||
iconTheme = {
|
||||
|
@ -15,10 +11,7 @@
|
|||
};
|
||||
font = {
|
||||
name = "Comic Code";
|
||||
size =
|
||||
if nixosConfig.networking.hostName == "tablet"
|
||||
then 10
|
||||
else 16;
|
||||
size = 16;
|
||||
package = pkgs.comic-code;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,23 +5,19 @@
|
|||
inputs,
|
||||
...
|
||||
}: let
|
||||
hm-lib = inputs.home-manager.lib.hm;
|
||||
homeManagerLib = inputs.home-manager.lib.hm;
|
||||
|
||||
font-sizes-all = {
|
||||
fontSizesAll = {
|
||||
default = {
|
||||
small = "14";
|
||||
medium = "16";
|
||||
};
|
||||
tablet = {
|
||||
small = "8";
|
||||
medium = "10";
|
||||
};
|
||||
};
|
||||
|
||||
font-sizes =
|
||||
if nixosConfig.networking.hostName == "tablet"
|
||||
then font-sizes-all.tablet
|
||||
else font-sizes-all.default;
|
||||
fontSizes =
|
||||
if fontSizesAll ? nixosConfig.networking.hostName
|
||||
then fontSizesAll.${nixosConfig.networking.hostName}
|
||||
else fontSizesAll.default;
|
||||
in {
|
||||
imports = with tree; [home.apps.kitty home.apps.rofi];
|
||||
|
||||
|
@ -54,13 +50,13 @@ in {
|
|||
# TODO: Maybe do this with fontconfig too?
|
||||
font-antialiasing = "rgba";
|
||||
font-hinting = "full";
|
||||
font-name = "Comic Code ${font-sizes.medium}";
|
||||
monospace-font-name = "Comic Code ${font-sizes.small}";
|
||||
font-name = "Comic Code ${fontSizes.medium}";
|
||||
monospace-font-name = "Comic Code ${fontSizes.small}";
|
||||
color-scheme = "prefer-dark";
|
||||
};
|
||||
"org/gnome/desktop/input-sources" = {
|
||||
# TODO: see if this changes when using gnome wayland?
|
||||
sources = [(hm-lib.gvariant.mkTuple ["xkb" "gb"])];
|
||||
sources = [(homeManagerLib.gvariant.mkTuple ["xkb" "gb"])];
|
||||
per-window = false;
|
||||
};
|
||||
"org/gnome/desktop/media-handling" = {
|
||||
|
@ -122,7 +118,7 @@ in {
|
|||
};
|
||||
"org/gnome/desktop/wm/preferences" = {
|
||||
num-workspaces = 9;
|
||||
titlebar-font = "Comic Code Medium ${font-sizes.small}";
|
||||
titlebar-font = "Comic Code Medium ${fontSizes.small}";
|
||||
titlebar-uses-system-font = true;
|
||||
};
|
||||
"org/gnome/settings-daemon/plugins/media-keys" = {
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
lib,
|
||||
tree,
|
||||
...
|
||||
}: {
|
||||
}: let
|
||||
inherit (lib.modules) mkMerge;
|
||||
inherit (lib.strings) escapeShellArgs;
|
||||
in {
|
||||
# import default terminal
|
||||
imports = with tree; [home.apps.kitty home.apps.rofi];
|
||||
|
||||
|
@ -64,11 +67,11 @@
|
|||
names = ["Comic Code"];
|
||||
size = 14.0;
|
||||
};
|
||||
statusCommand = lib.escapeShellArgs [
|
||||
"/home/chaos/Projects/rustbar/target/debug/rustbar"
|
||||
#"${pkgs.gobar}/bin/gobar"
|
||||
#"-config"
|
||||
#"cpu\\|mem\\|weather\\(Leighton\\ Buzzard\\)\\|bat\\(BAT0\\)\\|time"
|
||||
statusCommand = escapeShellArgs [
|
||||
#"/home/chaos/Projects/rustbar/target/debug/rustbar"
|
||||
"${pkgs.gobar}/bin/gobar"
|
||||
"-config"
|
||||
"cpu\\|mem\\|weather\\(Leighton\\ Buzzard\\)\\|bat\\(BAT0\\)\\|time"
|
||||
];
|
||||
}
|
||||
{command = "${pkgs.waybar}/bin/waybar";}
|
||||
|
@ -149,7 +152,7 @@
|
|||
|
||||
"${cfg.modifier}+r" = "mode resize";
|
||||
}
|
||||
// (lib.foldl lib.recursiveUpdate {} (map (workspace: {
|
||||
// (mkMerge (map (workspace: {
|
||||
"${cfg.modifier}+${workspace}" = "workspace ${workspace}";
|
||||
"${cfg.modifier}+Shift+${workspace}" = "move container to workspace ${workspace}";
|
||||
}) ["1" "2" "3" "4" "5" "6" "7" "8" "9"]));
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
# expected to be in default locations
|
||||
# Incase home.apps.manual-backup-apps is running in container which passes secrets in from host
|
||||
secrets =
|
||||
if builtins.elem "host_secrets" (builtins.attrNames file_inputs)
|
||||
then file_inputs.host_secrets
|
||||
if file_inputs ? "hostSecrets"
|
||||
then file_inputs.hostSecrets
|
||||
else nixosConfig.services.secrets.secrets;
|
||||
in {
|
||||
home.packages = with pkgs; [
|
||||
|
|
|
@ -1,27 +1,18 @@
|
|||
{nixosConfig, ...}: let
|
||||
font-size =
|
||||
if nixosConfig.networking.hostName == "tablet"
|
||||
then 18
|
||||
else 24;
|
||||
zoom-level =
|
||||
if nixosConfig.networking.hostName == "tablet"
|
||||
then -2
|
||||
else 0;
|
||||
in {
|
||||
{...}: {
|
||||
programs.vscode-mod = {
|
||||
enable = true;
|
||||
userSettings = {
|
||||
"terminal.integrated.shellIntegration.enabled" = false;
|
||||
"github.gitAuthentication" = false;
|
||||
"editor.fontSize" = font-size;
|
||||
"editor.fontSize" = 24;
|
||||
"editor.fontFamily" = "'Comic Code'";
|
||||
"terminal.integrated.fontSize" = font-size;
|
||||
"terminal.integrated.fontSize" = 18;
|
||||
"editor.codeLensFontFamily" = "'Comic Code'";
|
||||
"editor.inlayHints.fontFamily" = "'Comic Code'";
|
||||
"markdown.preview.fontFamily" = "'Comic Code'";
|
||||
"terminal.integrated.fontFamily" = "'Comic Code'";
|
||||
"files.autoSave" = "afterDelay";
|
||||
"window.zoomLevel" = zoom-level;
|
||||
"window.zoomLevel" = 0;
|
||||
"editor.tabSize" = 2;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{...}: let
|
||||
usb_data = import ../data/usb_data.nix {};
|
||||
in {
|
||||
programs.ssh.matchBlocks."*".identityFile = "${usb_data.ssh_priv_path}";
|
||||
programs.git.extraConfig = {
|
||||
gpg.format = "ssh";
|
||||
commit.gpgsign = "true";
|
||||
tag.gpgsign = "true";
|
||||
user = {signingKey = "${usb_data.ssh_priv_path}";};
|
||||
};
|
||||
}
|
11
home/sshUSB.nix
Normal file
11
home/sshUSB.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{...}: let
|
||||
encryptedUSBData = import ../data/encryptedUSB.nix;
|
||||
in {
|
||||
programs.ssh.matchBlocks."*".identityFile = "${encryptedUSBData.sshPrivateKeyPath}";
|
||||
programs.git.extraConfig = {
|
||||
gpg.format = "ssh";
|
||||
commit.gpgsign = "true";
|
||||
tag.gpgsign = "true";
|
||||
user.signingKey = "${encryptedUSBData.sshPrivateKeyPath}";
|
||||
};
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
{
|
||||
tree,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
secrets = config.services.secrets.secrets;
|
||||
in {
|
||||
imports = with tree; [
|
||||
users.root
|
||||
|
||||
profiles.base
|
||||
profiles.sshd
|
||||
profiles.nix-gc
|
||||
|
||||
./hardware.nix
|
||||
./networking.nix
|
||||
./secrets.nix
|
||||
];
|
||||
|
||||
environment.etc."mdadm.conf".text = ''
|
||||
HOMEHOST <ignore>
|
||||
PROGRAM /run/current-system/sw/bin/mdadm-notify
|
||||
'';
|
||||
|
||||
# some taken from https://github.com/hunleyd/mdadm_notify/blob/master/mdadm_notify
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellScriptBin "mdadm-notify" ''
|
||||
event=$1
|
||||
md_device=$2
|
||||
device=$3
|
||||
|
||||
case $event in
|
||||
DegradedArray)
|
||||
msg="$md_device is running in DEGRADED MODE"
|
||||
;;
|
||||
DeviceDisappeared)
|
||||
msg="$md_device has DISAPPEARED"
|
||||
;;
|
||||
Fail)
|
||||
msg="$md_device had an ACTIVE component FAIL ($device)"
|
||||
;;
|
||||
FailSpare)
|
||||
msg="$md_device had a SPARE component FAIL during rebuild ($device)"
|
||||
;;
|
||||
MoveSpare)
|
||||
msg="SPARE device $device has been MOVED to a new array ($md_device)"
|
||||
;;
|
||||
NewArray)
|
||||
# silence NewArray
|
||||
exit 0
|
||||
msg="$md_device has APPEARED"
|
||||
;;
|
||||
Rebuild??)
|
||||
msg="$md_device REBUILD is now `echo $event|sed 's/Rebuild//'`% complete"
|
||||
;;
|
||||
RebuildFinished)
|
||||
msg="REBUILD of $md_device is COMPLETE or ABORTED"
|
||||
;;
|
||||
RebuildStarted)
|
||||
msg="RECONSTRUCTION of $md_device has STARTED"
|
||||
;;
|
||||
SpareActive)
|
||||
msg="$device has become an ACTIVE COMPONENT of $md_device"
|
||||
;;
|
||||
SparesMissing)
|
||||
msg="$md_device is MISSING one or more SPARE devices"
|
||||
;;
|
||||
TestMessage)
|
||||
msg="TEST MESSAGE generated for $md_device"
|
||||
;;
|
||||
esac
|
||||
|
||||
printf "Subject: BuildBox mdadm: $event\n\n$msg" | msmtp "all@owo.monster"
|
||||
'')
|
||||
];
|
||||
|
||||
programs.msmtp = {
|
||||
enable = true;
|
||||
accounts = {
|
||||
default = {
|
||||
auth = true;
|
||||
tls = true;
|
||||
protocol = "smtp";
|
||||
host = "mail.owo.monster";
|
||||
port = 587;
|
||||
from = "system@owo.monster";
|
||||
user = "system@owo.monster";
|
||||
passwordeval = "cat ${secrets.system_mail_password.path}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.mdmonitor = {
|
||||
requires = ["network.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
path = with pkgs; [mdadm msmtp];
|
||||
script = ''
|
||||
exec mdadm --monitor --scan
|
||||
'';
|
||||
serviceConfig = {
|
||||
Restart = "always";
|
||||
StartLimitAction = "none";
|
||||
};
|
||||
};
|
||||
|
||||
home-manager.users.root = {
|
||||
imports = with tree; [home.base home.dev.small];
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
networking.hostName = "buildbox";
|
||||
time.timeZone = "Europe/London";
|
||||
|
||||
system.stateVersion = "23.05";
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
{config, ...}: {
|
||||
boot.initrd.kernelModules = ["dm-snapshot"];
|
||||
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod"];
|
||||
boot.kernelModules = ["kvm-amd"];
|
||||
|
||||
boot.initrd.services.swraid.mdadmConf =
|
||||
config.environment.etc."mdadm.conf".text;
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/root";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-label/boot";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
efiSupport = false;
|
||||
device = "nodev";
|
||||
devices = ["/dev/sda" "/dev/sdb"];
|
||||
};
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
{lib, ...}: {
|
||||
systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;
|
||||
|
||||
networking = {
|
||||
resolvconf.useLocalResolver = false;
|
||||
networkmanager.dns = "none";
|
||||
};
|
||||
networking.nameservers = ["1.1.1.1"];
|
||||
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = true;
|
||||
networking.firewall.allowedTCPPorts = [22];
|
||||
|
||||
networking.enableIPv6 = true;
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
networking.dhcpcd.enable = false;
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks.eth0 = {
|
||||
name = "eth0";
|
||||
address = ["144.76.97.18"];
|
||||
gateway = ["144.76.97.1"];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{...}: {
|
||||
services.secrets = {
|
||||
enable = true;
|
||||
|
||||
secrets = {
|
||||
system_mail_password = {
|
||||
user = "root";
|
||||
group = "root";
|
||||
fetchScript = ''
|
||||
simple_get "/api-keys/chaos_mail/system" .password > "$secretFile"
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
nixpkgs-unstable,
|
||||
nix-darwin-unstable,
|
||||
tree,
|
||||
...
|
||||
} @ inputs: let
|
||||
defaultSpecialArgs =
|
||||
defaults.defaultSpecialArgs
|
||||
// {
|
||||
inputs =
|
||||
inputs
|
||||
// {
|
||||
# set these to the correct versions from inputs
|
||||
nixpkgs = inputs.nixpkgs-unstable;
|
||||
home-manager = inputs.home-manager-unstable;
|
||||
darwin = inputs.nix-darwin-unstable;
|
||||
};
|
||||
};
|
||||
|
||||
defaultModules =
|
||||
defaults.defaultModules
|
||||
++ [
|
||||
# NO_INLINE
|
||||
tree.impure.profiles.base-darwin
|
||||
inputs.home-manager-unstable.darwinModules.home-manager
|
||||
];
|
||||
|
||||
darwinSystem = nix-darwin-unstable.lib.darwinSystem;
|
||||
in {
|
||||
"MacMini" = darwinSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "aarch64-darwin";
|
||||
modules = defaultModules ++ [./macmini/default.nix];
|
||||
};
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
{...} @ inputs: {
|
||||
nixosConfigurations = import ./nixos.nix inputs;
|
||||
#darwinConfigurations = import ./darwin.nix inputs;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
{
|
||||
self,
|
||||
tree,
|
||||
lib,
|
||||
inputs,
|
||||
config,
|
||||
pkgs,
|
||||
hostPath,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkMerge;
|
||||
inherit (lib.lists) forEach;
|
||||
|
||||
ports = [
|
||||
# SMTP
|
||||
25
|
||||
|
@ -21,9 +26,13 @@
|
|||
4190
|
||||
];
|
||||
|
||||
containerLib = import "${self}/lib/containerLib.nix" {
|
||||
inherit lib;
|
||||
};
|
||||
|
||||
# Using secrets from Host
|
||||
secrets = config.services.secrets.secrets;
|
||||
secrets_list = [
|
||||
secretsList = [
|
||||
"mail_restic_password"
|
||||
"mail_restic_env"
|
||||
"private_mail_aliases"
|
||||
|
@ -31,7 +40,7 @@
|
|||
"system_mail_passwd"
|
||||
"gotosocial_mail_passwd"
|
||||
];
|
||||
shared_files = [
|
||||
sharedFiles = [
|
||||
"/var/lib/acme/mail.owo.monster/fullchain.pem"
|
||||
"/var/lib/acme/mail.owo.monster/key.pem"
|
||||
];
|
||||
|
@ -39,15 +48,10 @@ in {
|
|||
containers.mail = {
|
||||
autoStart = true;
|
||||
|
||||
bindMounts = lib.mkMerge [
|
||||
(lib.mkMerge (lib.forEach secrets_list (secret_name: let
|
||||
path = "${secrets.${secret_name}.path}";
|
||||
in {
|
||||
"${path}" = {
|
||||
hostPath = "${path}";
|
||||
};
|
||||
})))
|
||||
(lib.mkMerge (lib.forEach shared_files (file: {
|
||||
bindMounts = mkMerge [
|
||||
(containerLib.genBindHostsForSecrets secrets secretsList)
|
||||
|
||||
(mkMerge (forEach sharedFiles (file: {
|
||||
"${file}" = {
|
||||
hostPath = "${file}";
|
||||
};
|
||||
|
@ -57,7 +61,9 @@ in {
|
|||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
host_secrets = secrets;
|
||||
inherit self;
|
||||
inherit hostPath;
|
||||
hostSecrets = secrets;
|
||||
};
|
||||
|
||||
config = {config, ...}: {
|
||||
|
|
|
@ -1,134 +1,173 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
}: let
|
||||
inherit (lib) types;
|
||||
inherit (lib.options) mkEnableOption mkOption mkPackageOption;
|
||||
|
||||
cfg = config.services.mailserver;
|
||||
in {
|
||||
options.services.mailserver = {
|
||||
enable = mkEnableOption "mailserver";
|
||||
|
||||
fqdn = mkOption {type = types.str;};
|
||||
|
||||
domains = mkOption {type = types.listOf types.str;};
|
||||
|
||||
ssl_config = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
useACME = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
cert = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/acme/${cfg.fqdn}/fullchain.pem";
|
||||
};
|
||||
key = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/acme/${cfg.fqdn}/key.pem";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
fqdn = mkOption {
|
||||
type = types.str;
|
||||
description = "domain used for mx records";
|
||||
};
|
||||
|
||||
debug_mode = mkOption {
|
||||
domains = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "all domains for receiving mail on";
|
||||
};
|
||||
|
||||
debugMode = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "enable debug logging on everything";
|
||||
};
|
||||
|
||||
enable_roundcube = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
sslConfig = {
|
||||
useACME = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
cert = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/acme/${cfg.fqdn}/fullchain.pem";
|
||||
};
|
||||
key = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/acme/${cfg.fqdn}/key.pem";
|
||||
};
|
||||
};
|
||||
|
||||
roundcube_url = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.fqdn}";
|
||||
roundcube = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
package = mkPackageOption pkgs "roundcube" {};
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.fqdn}";
|
||||
};
|
||||
plugins = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
forceSSL = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
enableACME = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
force_roundcube_ssl = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
spf = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
policydConfig = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
force_roundcube_acme = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
rspamd = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
redisPort = mkOption {
|
||||
type = types.number;
|
||||
default = 6380;
|
||||
};
|
||||
};
|
||||
|
||||
accounts = mkOption {
|
||||
# where name = email for login
|
||||
type = types.attrsOf (types.submodule ({name, ...}: {
|
||||
# where attrName = email for login
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
passwordHashFile = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = ''
|
||||
a file containing the hashed password for user, loaded at runtime
|
||||
|
||||
'';
|
||||
};
|
||||
aliases = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "a list of aliases for receiving/sending mail";
|
||||
};
|
||||
sieveScript = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
default = null;
|
||||
description = "a default sieve script for filtering mail";
|
||||
};
|
||||
passwordFile = mkOption {type = types.str;};
|
||||
aliases = mkOption {type = types.listOf types.str;};
|
||||
sieveScript = mkOption {type = types.nullOr types.lines;};
|
||||
};
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
extra_aliases_file = mkOption {
|
||||
extraAliasesFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "file containing postfix aliases for receiving, loaded at runtime";
|
||||
};
|
||||
|
||||
sieve_directory = mkOption {
|
||||
sieveDirectory = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/sieve";
|
||||
description = "path used for storing sieve scripts";
|
||||
};
|
||||
|
||||
dkim_directory = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/dkim";
|
||||
};
|
||||
|
||||
policyd_config = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
|
||||
extra_roundcube_config = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
|
||||
rspamd_redis_port = mkOption {
|
||||
type = types.number;
|
||||
default = 6380;
|
||||
};
|
||||
|
||||
vmail_config = mkOption {
|
||||
type = types.submodule {
|
||||
options = {
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "vmail";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.vmail_config.user}";
|
||||
};
|
||||
user_id = mkOption {
|
||||
type = types.number;
|
||||
default = 5000;
|
||||
};
|
||||
group_id = mkOption {
|
||||
type = types.number;
|
||||
default = cfg.vmail_config.user_id;
|
||||
};
|
||||
directory = mkOption {
|
||||
type = types.str;
|
||||
default = "/home/${cfg.vmail_config.user}";
|
||||
};
|
||||
};
|
||||
dkim = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
directory = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/dkim";
|
||||
description = "path used for storing dkim signing keys, make sure to keep this backed up";
|
||||
};
|
||||
};
|
||||
|
||||
vmail = {
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "vmail";
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "${cfg.vmail.user}";
|
||||
};
|
||||
userID = mkOption {
|
||||
type = types.number;
|
||||
default = 5000;
|
||||
};
|
||||
groupID = mkOption {
|
||||
type = types.number;
|
||||
default = cfg.vmail.userID;
|
||||
};
|
||||
directory = mkOption {
|
||||
type = types.str;
|
||||
default = "/home/${cfg.vmail.user}";
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,64 +4,39 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (lib.strings) concatStringsSep optionalString;
|
||||
|
||||
vmail_config = mail_config.vmail_config;
|
||||
|
||||
passwdDir = "/run/dovecot2";
|
||||
passwdFile = "${passwdDir}/passwd";
|
||||
mailConfig = config.services.mailserver;
|
||||
vmailConfig = mailConfig.vmail;
|
||||
|
||||
postfixCfg = config.services.postfix;
|
||||
|
||||
dovecotRuntimeDir = "/run/dovecot2";
|
||||
passwdFile = "${dovecotRuntimeDir}/passwd";
|
||||
|
||||
genPasswdScript = pkgs.writeScript "generate-password-file" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if (! test -d "${passwdDir}"); then
|
||||
mkdir "${passwdDir}"
|
||||
chmod 755 "${passwdDir}"
|
||||
fi
|
||||
|
||||
for f in ${
|
||||
builtins.toString
|
||||
(lib.mapAttrsToList (_: value: value.passwordFile)
|
||||
mail_config.accounts)
|
||||
}; do
|
||||
if [ ! -f "$f" ]; then
|
||||
echo "Expected password hash file $f does not exist!"
|
||||
${concatStringsSep "\n" (map (userPasswdFile: ''
|
||||
if [ ! -f "${userPasswdFile}" ]; then
|
||||
echo "Expected password hash file ${userPasswdFile} does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
'') (mapAttrsToList (_email: config: config.passwordHashFile) mailConfig.accounts))}
|
||||
|
||||
cat <<EOF > ${passwdFile}
|
||||
${
|
||||
lib.concatStringsSep "\n"
|
||||
(lib.mapAttrsToList (name: value: "${name}:$(head -n 1 ${value.passwordFile})") mail_config.accounts)
|
||||
}
|
||||
${concatStringsSep "\n" (mapAttrsToList (
|
||||
email: config: "${email}:$(head -n 1 ${config.passwordHashFile})"
|
||||
)
|
||||
mailConfig.accounts)}
|
||||
EOF
|
||||
|
||||
chmod 600 ${passwdFile}
|
||||
'';
|
||||
|
||||
pipeBin = pkgs.stdenv.mkDerivation {
|
||||
name = "pipe_bin";
|
||||
src = ./pipe_bin;
|
||||
buildInputs = with pkgs; [makeWrapper coreutils bash rspamd];
|
||||
buildCommand = ''
|
||||
mkdir -p $out/pipe/bin
|
||||
cp $src/* $out/pipe/bin/
|
||||
chmod a+x $out/pipe/bin/*
|
||||
patchShebangs $out/pipe/bin
|
||||
|
||||
for file in $out/pipe/bin/*; do
|
||||
wrapProgram $file \
|
||||
--set PATH "${pkgs.coreutils}/bin:${pkgs.rspamd}/bin"
|
||||
done
|
||||
'';
|
||||
};
|
||||
in {
|
||||
config = lib.mkIf (mail_config.enable) {
|
||||
config = mkIf (mailConfig.enable) {
|
||||
services.dovecot2 = {
|
||||
enable = true;
|
||||
enableImap = true;
|
||||
|
@ -70,12 +45,12 @@ in {
|
|||
enablePop3 = false;
|
||||
enablePAM = false; # Not using PAM for Auth
|
||||
|
||||
mailUser = vmail_config.user;
|
||||
mailGroup = vmail_config.group;
|
||||
mailLocation = "maildir:${vmail_config.directory}/%d/%n";
|
||||
mailUser = vmailConfig.user;
|
||||
mailGroup = vmailConfig.group;
|
||||
mailLocation = "maildir:${vmailConfig.directory}/%d/%n";
|
||||
|
||||
sslServerCert = mail_config.ssl_config.cert;
|
||||
sslServerKey = mail_config.ssl_config.key;
|
||||
sslServerCert = mailConfig.sslConfig.cert;
|
||||
sslServerKey = mailConfig.sslConfig.key;
|
||||
|
||||
# For Sieve
|
||||
modules = with pkgs; [dovecot_pigeonhole];
|
||||
|
@ -112,7 +87,7 @@ in {
|
|||
};
|
||||
|
||||
extraConfig = ''
|
||||
${lib.optionalString mail_config.debug_mode ''
|
||||
${optionalString mailConfig.debugMode ''
|
||||
mail_debug = yes
|
||||
auth_debug = yes
|
||||
verbose_ssl = yes
|
||||
|
@ -152,11 +127,11 @@ in {
|
|||
mail_plugins = $mail_plugins sieve
|
||||
}
|
||||
|
||||
mail_access_groups = "${vmail_config.group}"
|
||||
mail_access_groups = "${vmailConfig.group}"
|
||||
|
||||
userdb {
|
||||
driver = static
|
||||
args = uid=${toString vmail_config.user_id} gid=${toString vmail_config.group_id}
|
||||
args = uid=${toString vmailConfig.userID} gid=${toString vmailConfig.groupID}
|
||||
}
|
||||
|
||||
passdb {
|
||||
|
@ -181,8 +156,8 @@ in {
|
|||
|
||||
plugin {
|
||||
sieve_plugins = sieve_imapsieve sieve_extprograms
|
||||
sieve = file:${mail_config.sieve_directory}/%u/scripts;active=${mail_config.sieve_directory}/%u/active.sieve
|
||||
sieve_default = file:${mail_config.sieve_directory}/%u/default.sieve
|
||||
sieve = file:${mailConfig.sieveDirectory}/%u/scripts;active=${mailConfig.sieveDirectory}/%u/active.sieve
|
||||
sieve_default = file:${mailConfig.sieveDirectory}/%u/default.sieve
|
||||
sieve_default_name = default
|
||||
|
||||
# From elsewhere to Spam folder
|
||||
|
@ -196,20 +171,44 @@ in {
|
|||
imapsieve_mailbox2_causes = COPY
|
||||
imapsieve_mailbox2_before = file:${./spam_sieve/report-ham.sieve}
|
||||
|
||||
sieve_pipe_bin_dir = ${pipeBin}/pipe/bin
|
||||
sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
|
||||
${optionalString mailConfig.rspamd.enable (let
|
||||
pipeBin = pkgs.stdenv.mkDerivation {
|
||||
name = "pipe_bin";
|
||||
src = ./pipe_bin;
|
||||
buildInputs = with pkgs; [makeWrapper coreutils bash rspamd];
|
||||
buildCommand = ''
|
||||
mkdir -p $out/pipe/bin
|
||||
cp $src/* $out/pipe/bin/
|
||||
chmod a+x $out/pipe/bin/*
|
||||
patchShebangs $out/pipe/bin
|
||||
|
||||
for file in $out/pipe/bin/*; do
|
||||
wrapProgram $file \
|
||||
--set PATH "${pkgs.coreutils}/bin:${pkgs.rspamd}/bin"
|
||||
done
|
||||
'';
|
||||
};
|
||||
in ''
|
||||
sieve_pipe_bin_dir = ${pipeBin}/pipe/bin
|
||||
'')}
|
||||
|
||||
sieve_global_extensions = ${optionalString mailConfig.rspamd.enable "+vnd.dovecot.pipe"} +vnd.dovecot.environment
|
||||
}
|
||||
lda_mailbox_autosubscribe = yes
|
||||
lda_mailbox_autocreate = yes
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.dovecot2 = {
|
||||
preStart = ''
|
||||
${genPasswdScript}
|
||||
'';
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
"f ${passwdFile} 600 dovecot2 dovecot2"
|
||||
];
|
||||
services = {
|
||||
dovecot2.preStart = ''
|
||||
${genPasswdScript}
|
||||
'';
|
||||
postfix.restartTriggers = [genPasswdScript];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.postfix.restartTriggers = [genPasswdScript];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
config,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
inherit (lib.modules) mkIf;
|
||||
|
||||
mailConfig = config.services.mailserver;
|
||||
in {
|
||||
config = lib.mkIf mail_config.enable {
|
||||
config = mkIf mailConfig.enable {
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [
|
||||
# SMTP
|
||||
|
|
|
@ -3,82 +3,83 @@
|
|||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
mail_config = config.services.mailserver;
|
||||
dkimUser = config.services.opendkim.user;
|
||||
dkimGroup = config.services.opendkim.group;
|
||||
}: let
|
||||
inherit (lib.modules) mkIf mkForce;
|
||||
inherit (lib.trivial) flip;
|
||||
inherit (lib.strings) optionalString escapeShellArgs;
|
||||
inherit (builtins) toFile concatStringsSep;
|
||||
|
||||
keyDir = mail_config.dkim_directory;
|
||||
mailConfig = config.services.mailserver;
|
||||
|
||||
opendkimConfig = config.services.opendkim;
|
||||
opendkimArgs = ["-f" "-l" "-x" opendkimConfig.configFile];
|
||||
dkimUser = opendkimConfig.user;
|
||||
dkimGroup = opendkimConfig.group;
|
||||
|
||||
keyDir = mailConfig.dkim.directory;
|
||||
selector = "mail";
|
||||
|
||||
domains = mail_config.domains;
|
||||
domains = mailConfig.domains;
|
||||
|
||||
createDomainDkimCert = dom: let
|
||||
dkim_key = "${keyDir}/${dom}.${selector}.key";
|
||||
dkim_txt = "${keyDir}/${dom}.${selector}.txt";
|
||||
dkimKey = "${keyDir}/${dom}.${selector}.key";
|
||||
dkimDNSFile = "${keyDir}/${dom}.${selector}.txt";
|
||||
in ''
|
||||
if [ ! -f "${dkim_key}" ]
|
||||
if [ ! -f "${dkimKey}" ]
|
||||
then
|
||||
${pkgs.opendkim}/bin/opendkim-genkey -s "${selector}" \
|
||||
-d "${dom}" \
|
||||
--bits="1024" \
|
||||
--directory="${keyDir}"
|
||||
mv "${keyDir}/${selector}.private" "${dkim_key}"
|
||||
mv "${keyDir}/${selector}.txt" "${dkim_txt}"
|
||||
mv "${keyDir}/${selector}.private" "${dkimKey}"
|
||||
mv "${keyDir}/${selector}.txt" "${dkimDNSFile}"
|
||||
echo "Generated key for domain ${dom} selector ${selector}"
|
||||
fi
|
||||
'';
|
||||
|
||||
createAllCerts =
|
||||
concatStringsSep "\n" (map createDomainDkimCert mail_config.domains);
|
||||
concatStringsSep "\n" (map createDomainDkimCert mailConfig.domains);
|
||||
|
||||
keyTable = pkgs.writeText "opendkim-KeyTable" (concatStringsSep "\n"
|
||||
keyTable = toFile "opendkim-KeyTable" (concatStringsSep "\n"
|
||||
(flip map domains
|
||||
(dom: "${dom} ${dom}:${selector}:${keyDir}/${dom}.${selector}.key")));
|
||||
|
||||
signingTable =
|
||||
pkgs.writeText "opendkim-SigningTable"
|
||||
toFile "opendkim-SigningTable"
|
||||
(concatStringsSep "\n" (flip map domains (dom: "${dom} ${dom}")));
|
||||
|
||||
dkim = config.services.opendkim;
|
||||
args =
|
||||
["-f" "-l"]
|
||||
++ optionals (dkim.configFile != null) ["-x" dkim.configFile];
|
||||
in {
|
||||
config = mkIf (mail_config.enable) {
|
||||
config = mkIf (mailConfig.enable && mailConfig.dkim.enable) {
|
||||
services.opendkim = {
|
||||
enable = true;
|
||||
selector = selector;
|
||||
keyPath = keyDir;
|
||||
domains = "csl:${builtins.concatStringsSep "," domains}";
|
||||
configFile = pkgs.writeText "opendkim.conf" (''
|
||||
domains = "csl:${concatStringsSep "," domains}";
|
||||
configFile = toFile "opendkim.conf" (''
|
||||
Canonicalization relaxed/relaxed
|
||||
UMask 0002
|
||||
Socket ${dkim.socket}
|
||||
Socket ${opendkimConfig.socket}
|
||||
KeyTable file:${keyTable}
|
||||
SigningTable file:${signingTable}
|
||||
''
|
||||
+ (optionalString mail_config.debug_mode ''
|
||||
+ (optionalString mailConfig.debugMode ''
|
||||
Syslog yes
|
||||
SyslogSuccess yes
|
||||
LogWhy yes
|
||||
''));
|
||||
};
|
||||
|
||||
users.users = optionalAttrs (config.services.postfix.user == "postfix") {
|
||||
postfix.extraGroups = ["${dkimGroup}"];
|
||||
};
|
||||
systemd.tmpfiles.rules = ["d '${keyDir}' - ${dkimUser} ${dkimGroup} - -"];
|
||||
|
||||
users.users.postfix.extraGroups = ["${dkimGroup}"];
|
||||
|
||||
systemd.services.opendkim = {
|
||||
preStart = mkForce createAllCerts;
|
||||
serviceConfig = {
|
||||
ExecStart =
|
||||
mkForce
|
||||
"${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}";
|
||||
"${pkgs.opendkim}/bin/opendkim ${escapeShellArgs opendkimArgs}";
|
||||
PermissionsStartOnly = mkForce false;
|
||||
};
|
||||
};
|
||||
systemd.tmpfiles.rules = ["d '${keyDir}' - ${dkimUser} ${dkimGroup} - -"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,114 +4,101 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
submissionHeaderCleanupRules = pkgs.writeText "submission_header_cleanup_rules" ''
|
||||
/^Received:/ IGNORE
|
||||
/^X-Originating-IP:/ IGNORE
|
||||
/^X-Mailer:/ IGNORE
|
||||
/^User-Agent:/ IGNORE
|
||||
/^X-Enigmail:/ IGNORE
|
||||
/^Message-ID:\s+<(.*?)@.*?>/ REPLACE Message-ID: <$1@${mail_config.fqdn}>
|
||||
'';
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
inherit (lib.lists) flatten optional;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
inherit (builtins) toFile;
|
||||
|
||||
# Merge several lookup tables. A lookup table is a attribute set where
|
||||
# - the key is an address (user@example.com) or a domain (@example.com)
|
||||
# - the value is a list of addresses
|
||||
mergeLookupTables = tables: lib.zipAttrsWith (_: v: lib.flatten v) tables;
|
||||
|
||||
# valiases_postfix :: Map String [String]
|
||||
valiases_postfix = mergeLookupTables (lib.flatten (lib.mapAttrsToList
|
||||
(name: value: let
|
||||
to = name;
|
||||
in
|
||||
map (from: {"${from}" = to;}) (value.aliases ++ lib.singleton name))
|
||||
mail_config.accounts));
|
||||
|
||||
# all_valiases_postfix :: Map String [String]
|
||||
all_valiases_postfix = mergeLookupTables [valiases_postfix];
|
||||
|
||||
# lookupTableToString :: Map String [String] -> String
|
||||
lookupTableToString = attrs: let
|
||||
valueToString = value: lib.concatStringsSep ", " value;
|
||||
in
|
||||
lib.concatStringsSep "\n"
|
||||
(lib.mapAttrsToList (name: value: "${name} ${valueToString value}") attrs);
|
||||
|
||||
vhosts_file =
|
||||
builtins.toFile "vhosts" (lib.concatStringsSep "\n" mail_config.domains);
|
||||
|
||||
aliases_accounts_file = let
|
||||
content = lookupTableToString (mergeLookupTables [all_valiases_postfix]);
|
||||
in
|
||||
builtins.toFile "aliases_accounts" content;
|
||||
|
||||
mappedFile = name: "hash:/var/lib/postfix/conf/${name}";
|
||||
|
||||
policyd-spf = pkgs.writeText "policyd-spf.conf" mail_config.policyd_config;
|
||||
|
||||
submissionOptions = {
|
||||
smtpd_tls_security_level = "encrypt";
|
||||
smtpd_sasl_auth_enable = "yes";
|
||||
smtpd_sasl_type = "dovecot";
|
||||
smtpd_sasl_path = "/run/dovecot2/auth";
|
||||
smtpd_sasl_security_options = "noanonymous";
|
||||
smtpd_sasl_local_domain = "$myhostname";
|
||||
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
|
||||
smtpd_sender_login_maps = mappedFile "aliases_accounts";
|
||||
smtpd_sender_restrictions = "reject_sender_login_mismatch";
|
||||
smtpd_recipient_restrictions = "reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject";
|
||||
cleanup_service_name = "submission-header-cleanup";
|
||||
};
|
||||
mailConfig = config.services.mailserver;
|
||||
|
||||
tls_allowed = "TLSv1.3, TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3";
|
||||
tls_disallow = "MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL";
|
||||
|
||||
sendingReceivingAliases = concatStringsSep "\n" (flatten [
|
||||
(mapAttrsToList (email: config:
|
||||
map (
|
||||
alias: "${alias} ${email} "
|
||||
)
|
||||
config.aliases)
|
||||
mailConfig.accounts)
|
||||
(mapAttrsToList (email: _config: [
|
||||
# i dont know if this is actually needed
|
||||
"${email} ${email}"
|
||||
])
|
||||
mailConfig.accounts)
|
||||
]);
|
||||
|
||||
sendingReceivingAliasesMappedName = "sending_receiving_aliases";
|
||||
sendingReceivingAliasesFile = toFile "${sendingReceivingAliasesMappedName}" sendingReceivingAliases;
|
||||
|
||||
extraAliasesCombinedFilePath = "/run/postfix_sending_receiving_aliases";
|
||||
in {
|
||||
config = lib.mkIf (mail_config.enable) {
|
||||
systemd.tmpfiles.rules = lib.mkIf (mail_config.extra_aliases_file != null) [
|
||||
# folder to store the extra aliases file
|
||||
"f /run/postfix_extra_aliases 660 root root"
|
||||
config = mkIf (mailConfig.enable) {
|
||||
systemd.tmpfiles.rules = mkIf (mailConfig.extraAliasesFile != null) [
|
||||
"f ${extraAliasesCombinedFilePath} 660 root root"
|
||||
];
|
||||
|
||||
systemd.services.postfix-extra-aliases-setup = lib.mkIf (mail_config.extra_aliases_file != null) {
|
||||
systemd.services.postfix-extra-aliases-setup = mkIf (mailConfig.extraAliasesFile != null) {
|
||||
wantedBy = ["multi-user.target"];
|
||||
partOf = ["postfix.service"];
|
||||
before = ["postfix-setup.service"];
|
||||
script = ''
|
||||
cat ${aliases_accounts_file} > /run/postfix_extra_aliases
|
||||
echo >> /run/postfix_extra_aliases
|
||||
cat ${mail_config.extra_aliases_file} >> /run/postfix_extra_aliases
|
||||
cat "${sendingReceivingAliasesFile}" > ${extraAliasesCombinedFilePath}
|
||||
echo >> ${extraAliasesCombinedFilePath}
|
||||
cat "${mailConfig.extraAliasesFile}" >> ${extraAliasesCombinedFilePath}
|
||||
'';
|
||||
};
|
||||
|
||||
services.postfix = {
|
||||
services.postfix = let
|
||||
mappedFile = name: "hash:/var/lib/postfix/conf/${name}";
|
||||
|
||||
sendingReceivingAliasesMappedFile = mappedFile sendingReceivingAliasesMappedName;
|
||||
|
||||
submissionOptions = {
|
||||
smtpd_tls_security_level = "encrypt";
|
||||
smtpd_sasl_auth_enable = "yes";
|
||||
smtpd_sasl_type = "dovecot";
|
||||
smtpd_sasl_path = "/run/dovecot2/auth";
|
||||
smtpd_sasl_security_options = "noanonymous";
|
||||
smtpd_sasl_local_domain = "$myhostname";
|
||||
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
|
||||
smtpd_sender_login_maps = sendingReceivingAliasesMappedFile;
|
||||
smtpd_sender_restrictions = "reject_sender_login_mismatch";
|
||||
smtpd_recipient_restrictions = "reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject";
|
||||
cleanup_service_name = "submission-header-cleanup";
|
||||
};
|
||||
in {
|
||||
enable = true;
|
||||
hostname = "${mail_config.fqdn}";
|
||||
hostname = "${mailConfig.fqdn}";
|
||||
networksStyle = "host";
|
||||
|
||||
mapFiles."aliases_accounts" =
|
||||
if (mail_config.extra_aliases_file == null)
|
||||
then aliases_accounts_file
|
||||
else "/run/postfix_extra_aliases";
|
||||
mapFiles = {
|
||||
"sending_receiving_aliases" =
|
||||
if (mailConfig.extraAliasesFile == null)
|
||||
then sendingReceivingAliasesFile
|
||||
else "${extraAliasesCombinedFilePath}";
|
||||
};
|
||||
|
||||
sslCert = mail_config.ssl_config.cert;
|
||||
sslKey = mail_config.ssl_config.key;
|
||||
enableSubmission = true;
|
||||
enableSubmissions = true;
|
||||
sslCert = mailConfig.sslConfig.cert;
|
||||
sslKey = mailConfig.sslConfig.key;
|
||||
|
||||
config = {
|
||||
# Extra Config
|
||||
mydestination = "";
|
||||
recipient_delimiter = "+";
|
||||
smtpd_banner = "${mail_config.fqdn} ESMTP NO UCE";
|
||||
smtpd_banner = "${mailConfig.fqdn} ESMTP NO UCE";
|
||||
disable_vrfy_command = true;
|
||||
message_size_limit = "20971520";
|
||||
|
||||
virtual_uid_maps = "static:${toString mail_config.vmail_config.user_id}";
|
||||
virtual_gid_maps = "static:${toString mail_config.vmail_config.group_id}";
|
||||
virtual_mailbox_base = "${mail_config.vmail_config.directory}";
|
||||
virtual_mailbox_domains = vhosts_file;
|
||||
virtual_mailbox_maps = mappedFile "aliases_accounts";
|
||||
virtual_alias_maps = mappedFile "aliases_accounts";
|
||||
virtual_uid_maps = "static:${toString mailConfig.vmail.userID}";
|
||||
virtual_gid_maps = "static:${toString mailConfig.vmail.groupID}";
|
||||
virtual_mailbox_base = "${mailConfig.vmail.directory}";
|
||||
virtual_mailbox_domains = toFile "vhosts" (concatStringsSep "\n" mailConfig.domains);
|
||||
virtual_mailbox_maps = sendingReceivingAliasesMappedFile;
|
||||
virtual_alias_maps = sendingReceivingAliasesMappedFile;
|
||||
virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
||||
lmtp_destination_recipient_limit = "1";
|
||||
|
||||
|
@ -124,12 +111,10 @@ in {
|
|||
"reject_unauth_destination"
|
||||
];
|
||||
|
||||
policy-spf_time_limit = "3600s";
|
||||
policy-spf_time_limit = mkIf (mailConfig.spf.enable) "3600s";
|
||||
|
||||
smtpd_recipient_restrictions = [
|
||||
#"check_recipient_access ${mappedFile "denied_recipients"}"
|
||||
#"check_recipient_access ${mappedFile "reject_recipients"}"
|
||||
"check_policy_service unix:private/policy-spf"
|
||||
smtpd_recipient_restrictions = flatten [
|
||||
(optional mailConfig.spf.enable "check_policy_service unix:private/policy-spf")
|
||||
];
|
||||
|
||||
smtpd_tls_security_level = "may";
|
||||
|
@ -161,11 +146,14 @@ in {
|
|||
|
||||
milter_default_action = "quarantine";
|
||||
|
||||
smtpd_milters = [
|
||||
"unix:/run/opendkim/opendkim.sock"
|
||||
"unix:/run/rspamd/rspamd-milter.sock"
|
||||
smtpd_milters = flatten [
|
||||
(optional mailConfig.dkim.enable "unix:/run/opendkim/opendkim.sock")
|
||||
(optional mailConfig.rspamd.enable "unix:/run/rspamd/rspamd-milter.sock")
|
||||
];
|
||||
|
||||
non_smtpd_milters = flatten [
|
||||
(optional mailConfig.dkim.enable "unix:/run/opendkim/opendkim.sock")
|
||||
];
|
||||
non_smtpd_milters = ["unix:/run/opendkim/opendkim.sock"];
|
||||
|
||||
milter_protocol = "6";
|
||||
milter_mail_macros = "i {mail_addr} {client_addr} {client_name} {auth_type} {auth_authen} {auth_author} {mail_addr} {mail_host} {mail_mailer}";
|
||||
|
@ -180,15 +168,17 @@ in {
|
|||
# D => Delivered-To, O => X-Original-To, R => Return-Path
|
||||
args = ["flags=O"];
|
||||
};
|
||||
"policy-spf" = {
|
||||
"policy-spf" = mkIf (mailConfig.spf.enable) {
|
||||
type = "unix";
|
||||
privileged = true;
|
||||
chroot = false;
|
||||
command = "spawn";
|
||||
args = [
|
||||
args = let
|
||||
policydConfig = toFile "policyd-spf.conf" mailConfig.spf.policydConfig;
|
||||
in [
|
||||
"user=nobody"
|
||||
"argv=${pkgs.pypolicyd-spf}/bin/policyd-spf"
|
||||
"${policyd-spf}"
|
||||
"${policydConfig}"
|
||||
];
|
||||
};
|
||||
"submission-header-cleanup" = {
|
||||
|
@ -197,7 +187,16 @@ in {
|
|||
chroot = false;
|
||||
maxproc = 0;
|
||||
command = "cleanup";
|
||||
args = ["-o" "header_checks=pcre:${submissionHeaderCleanupRules}"];
|
||||
args = let
|
||||
submissionHeaderCleanupRules = toFile "submission_header_cleanup_rules" ''
|
||||
/^Received:/ IGNORE
|
||||
/^X-Originating-IP:/ IGNORE
|
||||
/^X-Mailer:/ IGNORE
|
||||
/^User-Agent:/ IGNORE
|
||||
/^X-Enigmail:/ IGNORE
|
||||
/^Message-ID:\s+<(.*?)@.*?>/ REPLACE Message-ID: <$1@${mailConfig.fqdn}>
|
||||
'';
|
||||
in ["-o" "header_checks=pcre:${submissionHeaderCleanupRules}"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,16 +3,17 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
inherit (lib.modules) mkIf;
|
||||
|
||||
mailConfig = config.services.mailserver;
|
||||
|
||||
postfixCfg = config.services.postfix;
|
||||
rspamdCfg = config.services.rspamd;
|
||||
rspamdSocket = "rspamd.service";
|
||||
in {
|
||||
config = lib.mkIf (mail_config.enable) {
|
||||
config = mkIf (mailConfig.enable && mailConfig.rspamd.enable) {
|
||||
services.rspamd = {
|
||||
enable = true;
|
||||
debug = mail_config.debug_mode;
|
||||
debug = mailConfig.debugMode;
|
||||
locals = {
|
||||
"milter_headers.conf" = {
|
||||
text = ''
|
||||
|
@ -21,7 +22,7 @@ in {
|
|||
};
|
||||
"redis.conf" = {
|
||||
text = ''
|
||||
servers = "127.0.0.1:${toString mail_config.rspamd_redis_port}";
|
||||
servers = "127.0.0.1:${toString mailConfig.rspamd.redisPort}";
|
||||
'';
|
||||
};
|
||||
"classifier-bayes.conf" = {
|
||||
|
@ -82,7 +83,7 @@ in {
|
|||
|
||||
services.redis.servers.rspamd = {
|
||||
enable = true;
|
||||
port = mail_config.rspamd_redis_port;
|
||||
port = mailConfig.rspamd.redisPort;
|
||||
};
|
||||
|
||||
systemd.services.rspamd = {
|
||||
|
@ -95,6 +96,6 @@ in {
|
|||
requires = [rspamdSocket];
|
||||
};
|
||||
|
||||
users.extraUsers.${postfixCfg.user}.extraGroups = [rspamdCfg.group];
|
||||
users.extraUsers.postfix.extraGroups = [rspamdCfg.group];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,22 +3,24 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
inherit (lib.modules) mkIf;
|
||||
|
||||
mailConfig = config.services.mailserver;
|
||||
acmeRoot = "/var/lib/acme/acme-challenge";
|
||||
in {
|
||||
config = lib.mkIf (mail_config.enable && mail_config.ssl_config.useACME) {
|
||||
config = mkIf (mailConfig.enable && mailConfig.sslConfig.useACME) {
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts."${mail_config.fqdn}" = {
|
||||
serverName = mail_config.fqdn;
|
||||
serverAliases = mail_config.domains;
|
||||
virtualHosts."${mailConfig.fqdn}" = {
|
||||
serverName = mailConfig.fqdn;
|
||||
serverAliases = mailConfig.domains;
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
acmeRoot = acmeRoot;
|
||||
};
|
||||
};
|
||||
|
||||
security.acme.certs."${mail_config.fqdn}" = {
|
||||
security.acme.certs."${mailConfig.fqdn}" = {
|
||||
reloadServices = ["postfix.service" "dovecot2.service"];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,70 +4,68 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
inherit (lib.attrsets) mapAttrsToList;
|
||||
|
||||
vmail_config = mail_config.vmail_config;
|
||||
vmail_user = vmail_config.user;
|
||||
vmail_group = vmail_config.group;
|
||||
mailConfig = config.services.mailserver;
|
||||
|
||||
sieve_directory = mail_config.sieve_directory;
|
||||
vmail = mailConfig.vmail;
|
||||
vmailUser = vmail.user;
|
||||
vmailGroup = vmail.group;
|
||||
|
||||
sieveDirectory = mailConfig.sieveDirectory;
|
||||
|
||||
scriptForUser = name: config:
|
||||
if builtins.isString config.sieveScript
|
||||
then ''
|
||||
cat ${builtins.toFile "default.sieve" config.sieveScript} > "${sieveDirectory}/${name}/default.sieve"
|
||||
chown "${vmailUser}:${vmailGroup}" "${sieveDirectory}/${name}/default.sieve"
|
||||
''
|
||||
else ''
|
||||
if [ -f "${sieveDirectory}/${name}/default.sieve" ]; then
|
||||
rm "${sieveDirectory}/${name}/default.sieve"
|
||||
fi
|
||||
if [ -f "${sieveDirectory}/${name}.svbin" ]; then
|
||||
rm "${sieveDirectory}/${name}/default.svbin"
|
||||
fi
|
||||
'';
|
||||
|
||||
virtualMailUsersActivationScript = pkgs.writeScript "activate-virtual-mail-users" ''
|
||||
#!${pkgs.stdenv.shell}
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Create directory to store user sieve scripts if it doesn't exist
|
||||
if (! test -d "${sieve_directory}"); then
|
||||
mkdir "${sieve_directory}"
|
||||
chown "${vmail_user}:${vmail_group}" "${sieve_directory}"
|
||||
chmod 770 "${sieve_directory}"
|
||||
fi
|
||||
|
||||
# Copy user's sieve script to the correct location (if it exists). If it
|
||||
# is null, remove the file.
|
||||
${lib.concatMapStringsSep "\n" ({
|
||||
name,
|
||||
sieveScript,
|
||||
}:
|
||||
if lib.isString sieveScript
|
||||
then ''
|
||||
if (! test -d "${sieve_directory}/${name}"); then
|
||||
mkdir -p "${sieve_directory}/${name}"
|
||||
chown "${vmail_user}:${vmail_group}" "${sieve_directory}/${name}"
|
||||
chmod 770 "${sieve_directory}/${name}"
|
||||
fi
|
||||
cat << 'EOF' > "${sieve_directory}/${name}/default.sieve"
|
||||
${sieveScript}
|
||||
EOF
|
||||
chown "${vmail_user}:${vmail_group}" "${sieve_directory}/${name}/default.sieve"
|
||||
''
|
||||
else ''
|
||||
if (test -f "${sieve_directory}/${name}/default.sieve"); then
|
||||
rm "${sieve_directory}/${name}/default.sieve"
|
||||
fi
|
||||
if (test -f "${sieve_directory}/${name}.svbin"); then
|
||||
rm "${sieve_directory}/${name}/default.svbin"
|
||||
fi
|
||||
'') (map (user: {inherit (user) name sieveScript;})
|
||||
(lib.attrValues mail_config.accounts))}
|
||||
${concatStringsSep "\n" (mapAttrsToList (name: config: scriptForUser name config) mailConfig.accounts)}
|
||||
'';
|
||||
in {
|
||||
config = lib.mkIf (mail_config.enable) {
|
||||
users.users."${vmail_user}" = {
|
||||
config = mkIf (mailConfig.enable) {
|
||||
users.users."${vmailUser}" = {
|
||||
isSystemUser = true;
|
||||
|
||||
home = vmail_config.directory;
|
||||
home = vmail.directory;
|
||||
createHome = true;
|
||||
|
||||
uid = vmail_config.user_id;
|
||||
group = "${vmail_group}";
|
||||
uid = vmail.userID;
|
||||
group = "${vmailGroup}";
|
||||
};
|
||||
users.groups."${vmail_group}" = {gid = vmail_config.group_id;};
|
||||
|
||||
users.groups."${vmailGroup}" = {
|
||||
gid = vmail.groupID;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules =
|
||||
[
|
||||
"d '${sieveDirectory}' - ${vmailUser} ${vmailGroup} - -"
|
||||
]
|
||||
++ (map (
|
||||
email: "d '${sieveDirectory}/${email}' 770 ${vmailUser} ${vmailGroup} - -"
|
||||
) (builtins.attrNames mailConfig.accounts));
|
||||
|
||||
systemd.services.activate-virtual-mail-users = {
|
||||
wantedBy = ["multi-user.target"];
|
||||
before = ["dovecot2.service"];
|
||||
serviceConfig = {ExecStart = virtualMailUsersActivationScript;};
|
||||
serviceConfig.ExecStart = virtualMailUsersActivationScript;
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,25 +3,32 @@
|
|||
lib,
|
||||
...
|
||||
}: let
|
||||
mail_config = config.services.mailserver;
|
||||
inherit (lib.modules) mkIf mkForce;
|
||||
|
||||
mailConfig = config.services.mailserver;
|
||||
in {
|
||||
config = lib.mkIf (mail_config.enable && mail_config.enable_roundcube) {
|
||||
config = mkIf (mailConfig.enable && mailConfig.roundcube.enable) {
|
||||
services.roundcube = {
|
||||
enable = true;
|
||||
hostName = "${mail_config.roundcube_url}";
|
||||
package = mailConfig.roundcube.package;
|
||||
plugins =
|
||||
mailConfig.roundcube.plugins
|
||||
++ [
|
||||
"managesieve"
|
||||
];
|
||||
hostName = "${mailConfig.roundcube.domain}";
|
||||
extraConfig = ''
|
||||
$config['smtp_server'] = "tls://${mail_config.fqdn}";
|
||||
$config['smtp_server'] = "tls://${mailConfig.fqdn}";
|
||||
$config['smtp_user'] = "%u";
|
||||
$config['smtp_pass'] = "%p";
|
||||
$config['plugins'] = ["managesieve"];
|
||||
$config['managesieve_host'] = 'tls://${mail_config.fqdn}';
|
||||
${mail_config.extra_roundcube_config}
|
||||
$config['managesieve_host'] = 'tls://${mailConfig.fqdn}';
|
||||
${mailConfig.roundcube.extraConfig}
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."${mail_config.roundcube_url}" = {
|
||||
forceSSL = mail_config.force_roundcube_ssl;
|
||||
enableACME = mail_config.force_roundcube_acme;
|
||||
services.nginx.virtualHosts."${mailConfig.roundcube.domain}" = {
|
||||
forceSSL = mkForce mailConfig.roundcube.forceSSL;
|
||||
enableACME = mkForce mailConfig.roundcube.enableACME;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,63 +1,67 @@
|
|||
{
|
||||
pkgs,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
secrets = host_secrets;
|
||||
secrets = hostSecrets;
|
||||
in {
|
||||
services.mailserver = {
|
||||
enable = true;
|
||||
fqdn = "mail.owo.monster";
|
||||
domains = ["owo.monster"];
|
||||
debugMode = true;
|
||||
|
||||
ssl_config = {
|
||||
sslConfig = {
|
||||
useACME = false;
|
||||
cert = "/var/lib/acme/mail.owo.monster/fullchain.pem";
|
||||
key = "/var/lib/acme/mail.owo.monster/key.pem";
|
||||
};
|
||||
|
||||
enable_roundcube = true;
|
||||
force_roundcube_ssl = false;
|
||||
force_roundcube_acme = false;
|
||||
|
||||
debug_mode = true;
|
||||
|
||||
extra_roundcube_config = ''
|
||||
$config['session_lifetime'] = (60 * 24 * 7 * 2); # 2 Weeks
|
||||
$config['product_name'] = 'Chaos Mail';
|
||||
$config['username_domain'] = "owo.monster";
|
||||
$config['username_domain_forced'] = true;
|
||||
$config['log_driver'] = 'syslog';
|
||||
$config['smtp_debug'] = true;
|
||||
'';
|
||||
|
||||
extra_aliases_file = "${secrets.private_mail_aliases.path}";
|
||||
rspamd.enable = true;
|
||||
spf.enable = false;
|
||||
|
||||
accounts = {
|
||||
"chaos@owo.monster" = {
|
||||
name = "chaos@owo.monster";
|
||||
passwordFile = "${secrets.chaos_mail_passwd.path}";
|
||||
passwordHashFile = "${secrets.chaos_mail_passwd.path}";
|
||||
aliases = [
|
||||
"all@owo.monster"
|
||||
"chaoticryptidz@owo.monster"
|
||||
];
|
||||
sieveScript = null;
|
||||
};
|
||||
|
||||
"system@owo.monster" = {
|
||||
name = "system@owo.monster";
|
||||
passwordFile = "${secrets.system_mail_passwd.path}";
|
||||
aliases = [];
|
||||
sieveScript = null;
|
||||
passwordHashFile = "${secrets.system_mail_passwd.path}";
|
||||
};
|
||||
|
||||
"gotosocial@owo.monster" = {
|
||||
name = "gotosocial@owo.monster";
|
||||
passwordFile = "${secrets.gotosocial_mail_passwd.path}";
|
||||
aliases = [];
|
||||
sieveScript = null;
|
||||
passwordHashFile = "${secrets.gotosocial_mail_passwd.path}";
|
||||
};
|
||||
};
|
||||
|
||||
extraAliasesFile = "${secrets.private_mail_aliases.path}";
|
||||
|
||||
roundcube = {
|
||||
enable = true;
|
||||
|
||||
package = pkgs.roundcube.withPlugins (_plugins:
|
||||
with pkgs.roundcubePlugins; [
|
||||
persistent_login
|
||||
]);
|
||||
plugins = ["persistent_login"];
|
||||
|
||||
# running in container, passing socket to host
|
||||
forceSSL = false;
|
||||
enableACME = false;
|
||||
|
||||
extraConfig = ''
|
||||
$config['session_lifetime'] = (60 * 24 * 7 * 2); # 2 Weeks
|
||||
$config['product_name'] = 'Chaos Mail';
|
||||
$config['username_domain'] = "owo.monster";
|
||||
$config['username_domain_forced'] = true;
|
||||
$config['log_driver'] = 'syslog';
|
||||
$config['smtp_debug'] = true;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
|
@ -68,15 +72,9 @@ in {
|
|||
"/var/sockets"
|
||||
];
|
||||
|
||||
services.roundcube = {
|
||||
package = pkgs.roundcube.withPlugins (_plugins:
|
||||
with pkgs.roundcubePlugins; [
|
||||
persistent_login
|
||||
]);
|
||||
plugins = ["persistent_login"];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."mail.owo.monster" = {
|
||||
# running in privateNetwork
|
||||
# required so nginx doesn't try listening on port 80
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
secrets = host_secrets;
|
||||
mail_config = config.services.mailserver;
|
||||
secrets = hostSecrets;
|
||||
mailConfig = config.services.mailserver;
|
||||
backupPrepareCommand = "${
|
||||
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
|
||||
systemctl start postgresqlBackup-roundcube --wait
|
||||
|
@ -27,9 +27,9 @@ in {
|
|||
paths = [
|
||||
"/var/backup/postgresql"
|
||||
|
||||
mail_config.vmail_config.directory
|
||||
mail_config.sieve_directory
|
||||
mail_config.dkim_directory
|
||||
mailConfig.vmail.directory
|
||||
mailConfig.sieveDirectory
|
||||
mailConfig.dkim.directory
|
||||
"/var/lib/redis-rspamd"
|
||||
];
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{}: {
|
||||
{
|
||||
mpd = 6600;
|
||||
mpd-opus-low = 4242;
|
||||
mpd-opus-medium = 4243;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
self,
|
||||
hostPath,
|
||||
tree,
|
||||
lib,
|
||||
inputs,
|
||||
|
@ -6,46 +8,43 @@
|
|||
pkgs,
|
||||
...
|
||||
}: let
|
||||
container-addresses = import ../../data/container-addresses.nix {};
|
||||
hostIP = container-addresses.host;
|
||||
containerIP = container-addresses.containers.music;
|
||||
inherit (lib.modules) mkMerge;
|
||||
inherit (lib.lists) forEach;
|
||||
|
||||
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
|
||||
|
||||
hostIP = containerAddresses.host;
|
||||
containerIP = containerAddresses.containers.${containerName};
|
||||
|
||||
containerName = "music";
|
||||
containerConfig = config.containers.${containerName}.config;
|
||||
|
||||
containerLib = import "${self}/lib/containerLib.nix" {
|
||||
inherit lib;
|
||||
};
|
||||
|
||||
# Using secrets from Host
|
||||
secrets = config.services.secrets.secrets;
|
||||
|
||||
ports = import ./data/ports.nix {};
|
||||
in {
|
||||
networking.nat.forwardPorts = [
|
||||
{
|
||||
sourcePort = ports.mpd;
|
||||
destination = "${containerIP}\:${toString ports.mpd}";
|
||||
}
|
||||
{
|
||||
sourcePort = ports.slskd;
|
||||
destination = "${containerIP}\:${toString ports.slskd}";
|
||||
}
|
||||
secretsList = [
|
||||
"mpd_control_password"
|
||||
"slskd_env"
|
||||
];
|
||||
|
||||
ports = import ./data/ports.nix;
|
||||
in {
|
||||
containers.music = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = hostIP;
|
||||
localAddress = containerIP;
|
||||
bindMounts = lib.mkMerge (lib.forEach [
|
||||
"mpd_control_password"
|
||||
"slskd_env"
|
||||
] (secret_name: let
|
||||
path = "${secrets.${secret_name}.path}";
|
||||
in {
|
||||
"${path}" = {
|
||||
hostPath = "${path}";
|
||||
};
|
||||
}));
|
||||
bindMounts = containerLib.genBindHostsForSecrets secrets secretsList;
|
||||
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
host_secrets = secrets;
|
||||
inherit self;
|
||||
inherit hostPath;
|
||||
hostSecrets = secrets;
|
||||
};
|
||||
|
||||
config = {config, ...}: {
|
||||
|
@ -53,40 +52,35 @@ in {
|
|||
|
||||
imports = with tree;
|
||||
[
|
||||
profiles.base
|
||||
inputs.home-manager-unstable.nixosModules.home-manager
|
||||
|
||||
presets.nixos.containerBase
|
||||
profiles.sshd
|
||||
profiles.firewallAllow.ssh
|
||||
|
||||
profiles.nginx
|
||||
|
||||
modules.nixos.secrets
|
||||
|
||||
users.root
|
||||
profiles.firewallAllow.httpCommon
|
||||
]
|
||||
++ (with hosts.hetzner-vm.containers.music; [
|
||||
profiles.music-sync
|
||||
profiles.mpd
|
||||
profiles.musicSync
|
||||
profiles.soulseek
|
||||
]);
|
||||
|
||||
networking.firewall.allowedTCPPorts = with ports; [
|
||||
mpd
|
||||
mpd-opus-low
|
||||
mpd-opus-medium
|
||||
mpd-opus-high
|
||||
mpd-flac
|
||||
slskd
|
||||
slskd-web
|
||||
];
|
||||
|
||||
# For Shared Secrets
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${config.services.secrets.secretsDir} - root root"
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [22] ++ lib.mapAttrsToList (_name: value: value) ports;
|
||||
};
|
||||
|
||||
home-manager.users.root = {
|
||||
imports = with tree; [home.base home.dev.small];
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
# Manually configure nameserver. Using resolved inside the container seems to fail
|
||||
# currently
|
||||
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
|
||||
home-manager.users.root.home.stateVersion = "23.05";
|
||||
system.stateVersion = "23.05";
|
||||
};
|
||||
};
|
||||
|
@ -108,7 +102,7 @@ in {
|
|||
in {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations = lib.mkMerge ([
|
||||
locations = mkMerge ([
|
||||
{
|
||||
"/mpd/flac" = {
|
||||
proxyPass = "http://${containerIP}:${toString ports.mpd-flac}";
|
||||
|
@ -116,7 +110,7 @@ in {
|
|||
};
|
||||
}
|
||||
]
|
||||
++ (lib.forEach ["low" "medium" "high"] (quality: {
|
||||
++ (forEach ["low" "medium" "high"] (quality: {
|
||||
"/mpd/opus-${quality}" = {
|
||||
proxyPass = "http://${containerIP}:${toString ports."mpd-opus-${quality}"}";
|
||||
inherit extraConfig;
|
||||
|
@ -126,15 +120,28 @@ in {
|
|||
|
||||
# For permissions of secrets
|
||||
users.users."mpd" = {
|
||||
uid = config.ids.uids.mpd;
|
||||
uid = containerConfig.ids.uids.mpd;
|
||||
group = "mpd";
|
||||
};
|
||||
users.groups."mpd" = {
|
||||
gid = config.ids.gids.mpd;
|
||||
gid = containerConfig.ids.gids.mpd;
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = with ports; [
|
||||
mpd
|
||||
slskd
|
||||
];
|
||||
networking = {
|
||||
nat.forwardPorts = [
|
||||
{
|
||||
sourcePort = ports.mpd;
|
||||
destination = "${containerIP}\:${toString ports.mpd}";
|
||||
}
|
||||
{
|
||||
sourcePort = ports.slskd;
|
||||
destination = "${containerIP}\:${toString ports.slskd}";
|
||||
}
|
||||
];
|
||||
|
||||
firewall.allowedTCPPorts = with ports; [
|
||||
mpd
|
||||
slskd
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
ports = import ../data/ports.nix {};
|
||||
secrets = host_secrets;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
inherit (lib.lists) forEach;
|
||||
|
||||
ports = import ../data/ports.nix;
|
||||
secrets = hostSecrets;
|
||||
in {
|
||||
environment.systemPackages = with pkgs; [mpc_cli];
|
||||
environment.systemPackages = with pkgs; [
|
||||
mpc_cli
|
||||
];
|
||||
|
||||
services.mpd = {
|
||||
enable = true;
|
||||
|
@ -29,7 +34,7 @@ in {
|
|||
replaygain "track"
|
||||
audio_output_format "44100:16:2"
|
||||
''
|
||||
+ lib.concatStringsSep "\n" (lib.forEach ["low" "medium" "high"] (quality: let
|
||||
+ concatStringsSep "\n" (forEach ["low" "medium" "high"] (quality: let
|
||||
bitrates = {
|
||||
"low" = "64";
|
||||
"medium" = "96";
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
{pkgs, ...}: {
|
||||
{pkgs, ...}: let
|
||||
inherit (pkgs) writeShellScriptBin;
|
||||
inherit (builtins) toFile;
|
||||
|
||||
rcloneConfig = toFile "rclone.conf" ''
|
||||
[Music]
|
||||
type = webdav
|
||||
url = https://storage-webdav.owo.monster/MusicRO/
|
||||
vendor = other
|
||||
'';
|
||||
in {
|
||||
environment.systemPackages = [
|
||||
(writeShellScriptBin "rclone-music" ''
|
||||
rclone --config ${rcloneConfig} "$@"
|
||||
'')
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /Music - mpd mpd"
|
||||
];
|
||||
|
@ -8,17 +24,11 @@
|
|||
after = ["network.target"];
|
||||
partOf = ["mpd.service"];
|
||||
|
||||
path = with pkgs; [bash rclone mount umount];
|
||||
script = let
|
||||
rclone_config = pkgs.writeText "rclone.conf" ''
|
||||
[Music]
|
||||
type = webdav
|
||||
url = https://storage-webdav.owo.monster/MusicRO/
|
||||
vendor = other
|
||||
'';
|
||||
in ''
|
||||
path = with pkgs; [bash rclone];
|
||||
|
||||
script = ''
|
||||
set -e
|
||||
rclone --config ${rclone_config} sync Music: /Music
|
||||
rclone --config ${rcloneConfig} sync Music: /Music
|
||||
chown -R mpd:mpd /Music
|
||||
'';
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
lib,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
ports = import ../data/ports.nix {};
|
||||
secrets = host_secrets;
|
||||
ports = import ../data/ports.nix;
|
||||
secrets = hostSecrets;
|
||||
|
||||
inherit (lib.modules) mkForce;
|
||||
in {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{}: {
|
||||
piped-backend = 3012;
|
||||
piped-proxy = 3013;
|
||||
{
|
||||
internal-piped-backend = 3012;
|
||||
internal-piped-proxy = 3013;
|
||||
|
||||
cockroachdb = 26257;
|
||||
cockroachdb-http = 3014;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
self,
|
||||
hostPath,
|
||||
tree,
|
||||
lib,
|
||||
inputs,
|
||||
|
@ -6,18 +8,23 @@
|
|||
pkgs,
|
||||
...
|
||||
}: let
|
||||
#container-addresses = import ../../data/container-addresses.nix {};
|
||||
#hostIP = container-addresses.host;
|
||||
#containerIP = container-addresses.containers.piped;
|
||||
containerConfig = config.containers.piped.config;
|
||||
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
|
||||
|
||||
ports = import ./data/ports.nix {};
|
||||
hostIP = containerAddresses.host;
|
||||
containerIP = containerAddresses.containers.${containerName};
|
||||
|
||||
containerName = "piped";
|
||||
containerConfig = config.containers.${containerName}.config;
|
||||
|
||||
containerLib = import "${self}/lib/containerLib.nix" {
|
||||
inherit lib;
|
||||
};
|
||||
|
||||
# Using secrets from Host
|
||||
secrets = config.services.secrets.secrets;
|
||||
secrets_list = [
|
||||
"piped_restic_env"
|
||||
"piped_restic_password"
|
||||
secretsList = [
|
||||
"piped_finland_restic_env"
|
||||
"piped_finland_restic_password"
|
||||
{
|
||||
name = "piped_cockroachdb_ca_certificate";
|
||||
path = "/var/lib/cockroachdb-certs/ca.crt";
|
||||
|
@ -32,11 +39,51 @@
|
|||
}
|
||||
];
|
||||
|
||||
containerName = "piped";
|
||||
pipedSocketForComponent = (
|
||||
component: "/var/lib/nixos-containers/${containerName}/var/sockets/piped-${component}.sock"
|
||||
);
|
||||
in {
|
||||
containers.piped = {
|
||||
autoStart = true;
|
||||
privateNetwork = false;
|
||||
hostAddress = hostIP;
|
||||
localAddress = containerIP;
|
||||
bindMounts = containerLib.genBindHostsForSecrets secrets secretsList;
|
||||
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
inherit self;
|
||||
inherit hostPath;
|
||||
hostSecrets = secrets;
|
||||
};
|
||||
|
||||
config = {config, ...}: {
|
||||
nixpkgs.pkgs = pkgs;
|
||||
|
||||
imports = with tree;
|
||||
[
|
||||
presets.nixos.containerBase
|
||||
|
||||
profiles.nginx
|
||||
profiles.firewallAllow.httpCommon
|
||||
]
|
||||
++ (with hosts.hetzner-vm.containers.piped.profiles; [
|
||||
piped
|
||||
restic
|
||||
cockroachDB
|
||||
]);
|
||||
|
||||
# For Shared Secrets
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${config.services.secrets.secretsDir} - root root"
|
||||
];
|
||||
|
||||
home-manager.users.root.home.stateVersion = "23.05";
|
||||
system.stateVersion = "23.05";
|
||||
};
|
||||
};
|
||||
|
||||
# Create this directory outside the container so the bind mounts work
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/nixos-containers/${containerName}/var/lib/cockroachdb-certs - root root"
|
||||
|
@ -50,81 +97,6 @@ in {
|
|||
gid = containerConfig.users.groups.cockroachdb.gid;
|
||||
};
|
||||
|
||||
containers.piped = {
|
||||
autoStart = true;
|
||||
#privateNetwork = false;
|
||||
#hostAddress = hostIP;
|
||||
#localAddress = containerIP;
|
||||
|
||||
bindMounts = lib.mkMerge (lib.forEach secrets_list (secret_item: let
|
||||
secret =
|
||||
if builtins.isString secret_item
|
||||
then secrets.${secret_item}
|
||||
else secrets.${secret_item.name};
|
||||
|
||||
hostPath = secret.path;
|
||||
containerPath =
|
||||
if builtins.isString secret_item
|
||||
then hostPath
|
||||
else secret_item.path;
|
||||
in {
|
||||
"${containerPath}" = {
|
||||
inherit hostPath;
|
||||
};
|
||||
}));
|
||||
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
host_secrets = secrets;
|
||||
};
|
||||
|
||||
config = {config, ...}: {
|
||||
nixpkgs.pkgs = pkgs;
|
||||
|
||||
imports = with tree;
|
||||
[
|
||||
profiles.base
|
||||
inputs.home-manager-unstable.nixosModules.home-manager
|
||||
|
||||
#profiles.sshd
|
||||
profiles.nginx
|
||||
profiles.cockroachdb-bin-fix
|
||||
|
||||
modules.nixos.secrets
|
||||
inputs.piped-flake.nixosModules.default
|
||||
|
||||
users.root
|
||||
]
|
||||
++ (with hosts.hetzner-vm.containers.piped.profiles; [
|
||||
piped
|
||||
restic
|
||||
cockroachdb
|
||||
]);
|
||||
|
||||
# For Shared Secrets
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${config.services.secrets.secretsDir} - root root"
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [22] ++ (lib.attrValues ports);
|
||||
};
|
||||
|
||||
home-manager.users.root = {
|
||||
imports = with tree; [home.base home.dev.small];
|
||||
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
# Manually configure nameserver. Using resolved inside the container seems to fail
|
||||
# currently
|
||||
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
|
||||
system.stateVersion = "23.05";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."piped-fi.owo.monster" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
|
20
hosts/hetzner-vm/containers/piped/profiles/cockroachDB.nix
Normal file
20
hosts/hetzner-vm/containers/piped/profiles/cockroachDB.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{self, ...}: let
|
||||
internalWireGuard = import "${self}/data/chaosInternalWireGuard.nix";
|
||||
ports = import ../data/ports.nix;
|
||||
in {
|
||||
services.cockroachdb-bin = {
|
||||
enable = true;
|
||||
certsDir = "/var/lib/cockroachdb-certs";
|
||||
join = "localhost:${toString ports.cockroachdb},${internalWireGuard.hosts.raspberry.ip}:26257";
|
||||
# ssh -L 3014:127.0.0.1:3014 -L 26257:127.0.0.1:26257 raspberry
|
||||
extraArgs = ["--advertise-addr=${internalWireGuard.hosts.hetzner-vm.ip}:26257"];
|
||||
listen = {
|
||||
port = ports.cockroachdb;
|
||||
address = "0.0.0.0";
|
||||
};
|
||||
http = {
|
||||
address = "0.0.0.0";
|
||||
port = ports.cockroachdb-http;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{...}: let
|
||||
ports = import ../data/ports.nix {};
|
||||
internal_wireguard = import ../../../../../data/chaos_wireguard_internal.nix {};
|
||||
in {
|
||||
services.cockroachdb = {
|
||||
enable = true;
|
||||
certsDir = "/var/lib/cockroachdb-certs";
|
||||
join = "localhost:${toString ports.cockroachdb},${internal_wireguard.hosts.raspberry.ip}:26257";
|
||||
# ssh -L 3014:127.0.0.1:3014 -L 26257:127.0.0.1:26257 hetzner-vm
|
||||
listen.port = ports.cockroachdb;
|
||||
http = {
|
||||
address = "0.0.0.0";
|
||||
port = ports.cockroachdb-http;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
{config, ...}: let
|
||||
ports = import ../data/ports.nix {};
|
||||
piped_config = config.services.piped;
|
||||
ports = import ../data/ports.nix;
|
||||
pipedConfig = config.services.piped;
|
||||
in {
|
||||
config.services.piped = {
|
||||
services.piped = {
|
||||
enable = true;
|
||||
frontendDomain = "piped-fi.owo.monster";
|
||||
backendDomain = "backend.piped-fi.owo.monster";
|
||||
proxyDomain = "proxy.piped-fi.owo.monster";
|
||||
|
||||
disableRegistrations = false;
|
||||
disableRegistrations = true;
|
||||
|
||||
# TODO: change these creds to be read from file before opening DB to firewall
|
||||
postgresDBName = "piped";
|
||||
postgresDBUsername = "piped";
|
||||
postgresDBPassword = "piped";
|
||||
|
@ -23,43 +24,54 @@ in {
|
|||
|
||||
# Do not set proxyNginxExtraConfig here as needs be set in outside of container
|
||||
|
||||
internalBackendPort = ports.piped-backend;
|
||||
internalProxyPort = ports.piped-proxy;
|
||||
internalBackendPort = ports.internal-piped-backend;
|
||||
internalProxyPort = ports.internal-piped-proxy;
|
||||
};
|
||||
|
||||
config.systemd.tmpfiles.rules = [
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/sockets - nginx nginx"
|
||||
];
|
||||
|
||||
config.systemd.services.nginx.serviceConfig.ReadWritePaths = [
|
||||
"/var/sockets"
|
||||
];
|
||||
systemd.services.nginx = {
|
||||
serviceConfig.ReadWritePaths = [
|
||||
"/var/sockets"
|
||||
];
|
||||
};
|
||||
|
||||
config.services.nginx.virtualHosts."${piped_config.frontendDomain}" = {
|
||||
extraConfig = "listen unix:/var/sockets/piped-frontend.sock;";
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 9080;
|
||||
}
|
||||
];
|
||||
systemd.services.piped-backend = {
|
||||
after = ["cockroachdb.service"];
|
||||
wants = ["cockroachdb.service"];
|
||||
};
|
||||
config.services.nginx.virtualHosts."${piped_config.backendDomain}" = {
|
||||
extraConfig = "listen unix:/var/sockets/piped-backend.sock;";
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 9080;
|
||||
}
|
||||
];
|
||||
};
|
||||
config.services.nginx.virtualHosts."${piped_config.proxyDomain}" = {
|
||||
extraConfig = "listen unix:/var/sockets/piped-proxy.sock;";
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 9080;
|
||||
}
|
||||
];
|
||||
|
||||
services.nginx.virtualHosts = let
|
||||
componentPath = component: "/var/sockets/piped-${component}.sock";
|
||||
in {
|
||||
"${pipedConfig.frontendDomain}" = {
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8091;
|
||||
}
|
||||
];
|
||||
extraConfig = "listen unix:${componentPath "frontend"};";
|
||||
};
|
||||
"${pipedConfig.backendDomain}" = {
|
||||
extraConfig = "listen unix:${componentPath "backend"};";
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8092;
|
||||
}
|
||||
];
|
||||
};
|
||||
"${pipedConfig.proxyDomain}" = {
|
||||
extraConfig = "listen unix:${componentPath "proxy"};";
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = 8093;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,36 +1,32 @@
|
|||
{
|
||||
pkgs,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
secrets = host_secrets;
|
||||
#backupPrepareCommand = "${
|
||||
# (pkgs.writeShellScriptBin "backupPrepareCommand" ''
|
||||
# systemctl start postgresqlBackup-piped --wait
|
||||
# '')
|
||||
#}/bin/backupPrepareCommand";
|
||||
secrets = hostSecrets;
|
||||
in {
|
||||
environment.systemPackages = with pkgs; [
|
||||
restic
|
||||
(pkgs.writeShellScriptBin "restic-piped" ''
|
||||
(pkgs.writeShellScriptBin "restic-piped-finland" ''
|
||||
env \
|
||||
RESTIC_PASSWORD_FILE=${secrets.piped_restic_password.path} \
|
||||
$(cat ${secrets.piped_restic_env.path}) \
|
||||
RESTIC_PASSWORD_FILE=${secrets.piped_finland_restic_password.path} \
|
||||
$(cat ${secrets.piped_finland_restic_env.path}) \
|
||||
${pkgs.restic}/bin/restic $@
|
||||
'')
|
||||
];
|
||||
|
||||
services.restic.backups.piped = {
|
||||
services.restic.backups.piped-finland = {
|
||||
user = "root";
|
||||
paths = [
|
||||
#"/var/backup/postgresql"
|
||||
"/var/lib/cockroachdb"
|
||||
"/var/lib/cockroachdb-certs"
|
||||
];
|
||||
|
||||
# repository is overrided in environmentFile to contain auth
|
||||
# make sure to keep up to date when changing repository
|
||||
repository = "rest:https://storage-restic.owo.monster/Piped";
|
||||
passwordFile = "${secrets.piped_restic_password.path}";
|
||||
environmentFile = "${secrets.piped_restic_env.path}";
|
||||
repository = "rest:https://storage-restic.owo.monster/Piped-Finland";
|
||||
passwordFile = "${secrets.piped_finland_restic_password.path}";
|
||||
environmentFile = "${secrets.piped_finland_restic_env.path}";
|
||||
|
||||
pruneOpts = [
|
||||
"--keep-last 5"
|
||||
|
@ -40,14 +36,5 @@ in {
|
|||
OnBootSec = "1m";
|
||||
OnCalendar = "daily";
|
||||
};
|
||||
|
||||
#inherit backupPrepareCommand;
|
||||
};
|
||||
|
||||
#services.postgresqlBackup = {
|
||||
# enable = true;
|
||||
# backupAll = false;
|
||||
# databases = ["piped"];
|
||||
# compression = "zstd";
|
||||
#};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
self,
|
||||
hostPath,
|
||||
tree,
|
||||
lib,
|
||||
inputs,
|
||||
|
@ -6,41 +8,34 @@
|
|||
pkgs,
|
||||
...
|
||||
}: let
|
||||
container-addresses = import ../../data/container-addresses.nix {};
|
||||
hostIP = container-addresses.host;
|
||||
containerIP = container-addresses.containers.quassel;
|
||||
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
|
||||
hostIP = containerAddresses.host;
|
||||
containerIP = containerAddresses.containers.quassel;
|
||||
|
||||
containerLib = import "${self}/lib/containerLib.nix" {
|
||||
inherit lib;
|
||||
};
|
||||
|
||||
# Using secrets from Host
|
||||
secrets = config.services.secrets.secrets;
|
||||
secrets_list = [
|
||||
secretsList = [
|
||||
"quassel_restic_env"
|
||||
"quassel_restic_password"
|
||||
];
|
||||
in {
|
||||
networking.nat.forwardPorts = [
|
||||
{
|
||||
sourcePort = 4242;
|
||||
destination = "${containerIP}\:4242";
|
||||
}
|
||||
];
|
||||
|
||||
containers.quassel = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = hostIP;
|
||||
localAddress = containerIP;
|
||||
bindMounts = lib.mkMerge (lib.forEach secrets_list (secret_name: let
|
||||
path = "${secrets.${secret_name}.path}";
|
||||
in {
|
||||
"${path}" = {
|
||||
hostPath = "${path}";
|
||||
};
|
||||
}));
|
||||
bindMounts = containerLib.genBindHostsForSecrets secrets secretsList;
|
||||
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
host_secrets = secrets;
|
||||
inherit self;
|
||||
inherit hostPath;
|
||||
hostSecrets = secrets;
|
||||
};
|
||||
|
||||
config = {config, ...}: {
|
||||
|
@ -48,18 +43,13 @@ in {
|
|||
|
||||
imports = with tree;
|
||||
[
|
||||
profiles.base
|
||||
inputs.home-manager-unstable.nixosModules.home-manager
|
||||
|
||||
presets.nixos.containerBase
|
||||
profiles.sshd
|
||||
|
||||
modules.nixos.secrets
|
||||
|
||||
users.root
|
||||
profiles.firewallAllow.ssh
|
||||
]
|
||||
++ (with hosts.hetzner-vm.containers.quassel; [
|
||||
profiles.quassel
|
||||
profiles.restic
|
||||
++ (with hosts.hetzner-vm.containers.quassel.profiles; [
|
||||
quassel
|
||||
restic
|
||||
]);
|
||||
|
||||
# For Shared Secrets
|
||||
|
@ -67,23 +57,19 @@ in {
|
|||
"d ${config.services.secrets.secretsDir} - root root"
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [22 4242];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [4242];
|
||||
|
||||
home-manager.users.root = {
|
||||
imports = with tree; [home.base home.dev.small];
|
||||
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
# Manually configure nameserver. Using resolved inside the container seems to fail
|
||||
# currently
|
||||
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
|
||||
home-manager.users.root.home.stateVersion = "23.05";
|
||||
system.stateVersion = "23.05";
|
||||
};
|
||||
};
|
||||
|
||||
networking.nat.forwardPorts = [
|
||||
{
|
||||
sourcePort = 4242;
|
||||
destination = "${containerIP}\:4242";
|
||||
}
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [4242];
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
interfaces = ["0.0.0.0"];
|
||||
};
|
||||
|
||||
services.postgresql.enable = true;
|
||||
services.postgresql.ensureDatabases = ["quassel"];
|
||||
services.postgresql.ensureUsers = [
|
||||
{
|
||||
name = "quassel";
|
||||
ensurePermissions."DATABASE quassel" = "ALL PRIVILEGES";
|
||||
}
|
||||
];
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = ["quassel"];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "quassel";
|
||||
ensurePermissions."DATABASE quassel" = "ALL PRIVILEGES";
|
||||
}
|
||||
];
|
||||
|
||||
services.postgresql.authentication = "host quassel quassel localhost trust";
|
||||
networking.firewall.allowedTCPPorts = [4242];
|
||||
authentication = "host quassel quassel localhost trust";
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
pkgs,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
secrets = host_secrets;
|
||||
secrets = hostSecrets;
|
||||
|
||||
backupPrepareCommand = "${
|
||||
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
{
|
||||
self,
|
||||
hostPath,
|
||||
tree,
|
||||
inputs,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
container-addresses = import ../../data/container-addresses.nix {};
|
||||
hostIP = container-addresses.host;
|
||||
containerIP = container-addresses.containers.social;
|
||||
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
|
||||
hostIP = containerAddresses.host;
|
||||
containerIP = containerAddresses.containers.social;
|
||||
|
||||
# Using secrets from Host
|
||||
secrets = config.services.secrets.secrets;
|
||||
|
@ -32,7 +34,9 @@ in {
|
|||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
host_secrets = secrets;
|
||||
inherit self;
|
||||
inherit hostPath;
|
||||
hostSecrets = secrets;
|
||||
};
|
||||
|
||||
config = {config, ...}: {
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
host_secrets,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
secrets = host_secrets;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
inherit (lib.lists) forEach;
|
||||
|
||||
secrets = hostSecrets;
|
||||
|
||||
# Because gotosocial-admin isn't a seporate package we need to generate a seperate config
|
||||
# and duplicate the wrapper for use in a systemd unit
|
||||
|
@ -22,8 +25,8 @@
|
|||
backupPrepareCommand = "${
|
||||
(pkgs.writeShellScriptBin "backupPrepareCommand" ''
|
||||
systemctl start ${
|
||||
lib.concatStringsSep " "
|
||||
(lib.forEach config.services.postgresqlBackup.databases
|
||||
concatStringsSep " "
|
||||
(forEach config.services.postgresqlBackup.databases
|
||||
(db: "postgresqlBackup-${db}"))
|
||||
} --wait
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{host_secrets, ...}: let
|
||||
container-addresses = import ../../../data/container-addresses.nix {};
|
||||
hostIP = container-addresses.host;
|
||||
containerIP = container-addresses.containers.social;
|
||||
{
|
||||
hostPath,
|
||||
hostSecrets,
|
||||
...
|
||||
}: let
|
||||
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
|
||||
hostIP = containerAddresses.host;
|
||||
containerIP = containerAddresses.containers.social;
|
||||
|
||||
secrets = host_secrets;
|
||||
secrets = hostSecrets;
|
||||
in {
|
||||
services.gotosocial = {
|
||||
enable = true;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{...}: {
|
||||
{
|
||||
rclone_serve_webdav_main = 4200;
|
||||
rclone_serve_webdav_media = 4201;
|
||||
rclone_serve_webdav_music_ro = 4202;
|
||||
|
@ -7,7 +7,7 @@
|
|||
rclone_serve_restic_vault = 4211;
|
||||
rclone_serve_restic_social = 4212;
|
||||
rclone_serve_restic_quassel = 4213;
|
||||
rclone_serve_restic_piped = 4214;
|
||||
rclone_serve_restic_piped_finland = 4214;
|
||||
rclone_serve_restic_mail = 4215;
|
||||
|
||||
rclone_serve_http_music = 4220;
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
{
|
||||
self,
|
||||
hostPath,
|
||||
tree,
|
||||
lib,
|
||||
inputs,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
container-addresses = import ../../data/container-addresses.nix {};
|
||||
hostIP = container-addresses.host;
|
||||
containerIP = container-addresses.containers.storage;
|
||||
inherit (lib.attrsets) attrValues;
|
||||
|
||||
containerAddresses = import "${hostPath}/data/containerAddresses.nix";
|
||||
hostIP = containerAddresses.host;
|
||||
containerIP = containerAddresses.containers.storage;
|
||||
|
||||
# 32GB
|
||||
clientMaxBodySize = "${toString (8192 * 4)}M";
|
||||
|
||||
ports = import ./data/ports.nix {};
|
||||
ports = import ./data/ports.nix;
|
||||
in {
|
||||
containers.storage = {
|
||||
autoStart = true;
|
||||
|
@ -23,6 +27,8 @@ in {
|
|||
specialArgs = {
|
||||
inherit inputs;
|
||||
inherit tree;
|
||||
inherit self;
|
||||
inherit hostPath;
|
||||
};
|
||||
|
||||
config = {...}: {
|
||||
|
@ -43,14 +49,11 @@ in {
|
|||
|
||||
users.root
|
||||
]
|
||||
++ (with hosts.hetzner-vm.containers.storage; [
|
||||
profiles.auto-secrets
|
||||
profiles.rclone-configs
|
||||
profiles.rclone-serve
|
||||
profiles.rclone-sync
|
||||
# doesn't work in container
|
||||
# profiles.storage-mount
|
||||
profiles.users
|
||||
++ (with hosts.hetzner-vm.containers.storage.profiles; [
|
||||
rcloneConfigs
|
||||
rcloneServe
|
||||
rcloneSync
|
||||
users
|
||||
]);
|
||||
|
||||
environment.systemPackages = with pkgs; [rclone];
|
||||
|
@ -63,7 +66,7 @@ in {
|
|||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [22] ++ lib.mapAttrsToList (_name: value: value) ports;
|
||||
allowedTCPPorts = attrValues ports;
|
||||
};
|
||||
|
||||
# Manually configure nameserver. Using resolved inside the container seems to fail
|
||||
|
@ -106,7 +109,7 @@ in {
|
|||
"/Vault/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_vault}";
|
||||
"/Social/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_social}";
|
||||
"/Quassel/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_quassel}";
|
||||
"/Piped/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_piped}";
|
||||
"/Piped-Finland/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_piped_finland}";
|
||||
"/Mail/".proxyPass = "http://${containerIP}:${toString ports.rclone_serve_restic_mail}";
|
||||
};
|
||||
extraConfig = ''
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
secrets = config.services.secrets.secrets;
|
||||
in {
|
||||
systemd.services.auto-secrets = {
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target"];
|
||||
path = with pkgs; [bash vault-bin getent];
|
||||
script = let
|
||||
vault_username = "storage";
|
||||
vault_password_file = "${secrets.vault_password.path}";
|
||||
in ''
|
||||
VAULT_ADDR="https://vault.owo.monster" \
|
||||
vault login -no-print -method=userpass username=${vault_username} password=$(cat ${vault_password_file})
|
||||
/run/current-system/sw/bin/secrets-init
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{config, ...}: let
|
||||
secrets = config.services.secrets.secrets;
|
||||
ports = import ../data/ports.nix {};
|
||||
ports = import ../data/ports.nix;
|
||||
in {
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /caches - storage storage"
|
||||
|
@ -8,16 +8,20 @@ in {
|
|||
"d /caches/media_webdav_serve - storage storage"
|
||||
];
|
||||
|
||||
services.rclone-serve = let
|
||||
serviceConfig = {
|
||||
after = ["auto-secrets.service"];
|
||||
partOf = ["auto-secrets.service"];
|
||||
};
|
||||
in {
|
||||
services.rclone-serve = {
|
||||
enable = true;
|
||||
remotes = [
|
||||
remotes = map (remote:
|
||||
{
|
||||
user = "storage";
|
||||
serviceConfig = {
|
||||
after = ["auto-secrets.service"];
|
||||
wants = ["auto-secrets.service"];
|
||||
partOf = ["auto-secrets.service"];
|
||||
};
|
||||
}
|
||||
// remote) [
|
||||
{
|
||||
id = "main";
|
||||
remote = "StorageBox:";
|
||||
type = "webdav";
|
||||
extraArgs = [
|
||||
|
@ -27,10 +31,9 @@ in {
|
|||
"--cache-dir=/caches/main_webdav_serve"
|
||||
"--vfs-cache-mode=full"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "media-combine";
|
||||
remote = "Media-Combine-Serve:";
|
||||
type = "webdav";
|
||||
extraArgs = [
|
||||
|
@ -42,10 +45,9 @@ in {
|
|||
"--vfs-cache-max-size=5g"
|
||||
"--vfs-cache-mode=full"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "music-ro";
|
||||
remote = "StorageBox:Music";
|
||||
type = "webdav";
|
||||
extraArgs = [
|
||||
|
@ -53,10 +55,9 @@ in {
|
|||
"--read-only"
|
||||
"--baseurl=/MusicRO/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "music-ro";
|
||||
remote = "StorageBox:Music";
|
||||
type = "http";
|
||||
extraArgs = [
|
||||
|
@ -64,10 +65,9 @@ in {
|
|||
"--baseurl=/Music/"
|
||||
"--read-only"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "public";
|
||||
remote = "StorageBox:Public";
|
||||
type = "http";
|
||||
extraArgs = [
|
||||
|
@ -75,10 +75,9 @@ in {
|
|||
"--baseurl=/Public/"
|
||||
"--read-only"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "restic-music";
|
||||
remote = "StorageBox:Backups/Restic/Music";
|
||||
type = "restic";
|
||||
extraArgs = [
|
||||
|
@ -86,10 +85,9 @@ in {
|
|||
"--htpasswd=${secrets.restic_music_htpasswd.path}"
|
||||
"--baseurl=/Music/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "restic-vault";
|
||||
remote = "StorageBox:Backups/Restic/Vault";
|
||||
type = "restic";
|
||||
extraArgs = [
|
||||
|
@ -97,10 +95,9 @@ in {
|
|||
"--htpasswd=${secrets.restic_vault_htpasswd.path}"
|
||||
"--baseurl=/Vault/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "restic-social";
|
||||
remote = "StorageBox:Backups/Restic/Social";
|
||||
type = "restic";
|
||||
extraArgs = [
|
||||
|
@ -108,10 +105,9 @@ in {
|
|||
"--htpasswd=${secrets.restic_social_htpasswd.path}"
|
||||
"--baseurl=/Social/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "restic-quassel";
|
||||
remote = "StorageBox:Backups/Restic/Quassel";
|
||||
type = "restic";
|
||||
extraArgs = [
|
||||
|
@ -119,21 +115,19 @@ in {
|
|||
"--htpasswd=${secrets.restic_quassel_htpasswd.path}"
|
||||
"--baseurl=/Quassel/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
remote = "StorageBox:Backups/Restic/Piped";
|
||||
id = "restic-piped-finland";
|
||||
remote = "StorageBox:Backups/Restic/Piped-Finland";
|
||||
type = "restic";
|
||||
extraArgs = [
|
||||
"--addr=0.0.0.0:${toString ports.rclone_serve_restic_piped}"
|
||||
"--htpasswd=${secrets.restic_piped_htpasswd.path}"
|
||||
"--baseurl=/Piped/"
|
||||
"--addr=0.0.0.0:${toString ports.rclone_serve_restic_piped_finland}"
|
||||
"--htpasswd=${secrets.restic_piped_finland_htpasswd.path}"
|
||||
"--baseurl=/Piped-Finland/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
{
|
||||
user = "storage";
|
||||
id = "restic-mail";
|
||||
remote = "StorageBox:Backups/Restic/Mail";
|
||||
type = "restic";
|
||||
extraArgs = [
|
||||
|
@ -141,7 +135,6 @@ in {
|
|||
"--htpasswd=${secrets.restic_mail_htpasswd.path}"
|
||||
"--baseurl=/Mail/"
|
||||
];
|
||||
inherit serviceConfig;
|
||||
}
|
||||
];
|
||||
};
|
|
@ -1,19 +1,22 @@
|
|||
{lib, ...}: {
|
||||
services.rclone-sync = let
|
||||
sync_defaults = {
|
||||
serviceConfig = {after = ["auto-secrets.service"];};
|
||||
timerConfig = {
|
||||
OnStartupSec = "60";
|
||||
OnCalendar = "4h";
|
||||
};
|
||||
extraArgs = [
|
||||
"--fast-list"
|
||||
];
|
||||
};
|
||||
in {
|
||||
{...}: {
|
||||
services.rclone-sync = {
|
||||
enable = true;
|
||||
user = "storage";
|
||||
sync_jobs = map (x: lib.mkMerge [x sync_defaults]) [
|
||||
syncJobs = map (syncJob:
|
||||
syncJob
|
||||
// {
|
||||
serviceConfig = {
|
||||
after = ["auto-secrets.service"];
|
||||
wants = ["auto-secrets.service"];
|
||||
};
|
||||
timerConfig = {
|
||||
OnStartupSec = "60";
|
||||
OnCalendar = "4h";
|
||||
};
|
||||
extraArgs = [
|
||||
"--fast-list"
|
||||
];
|
||||
}) [
|
||||
# My B2
|
||||
{
|
||||
source = "StorageBox:Backups";
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
secrets = config.services.secrets.secrets;
|
||||
in {
|
||||
systemd.services.storage-mount = {
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["network.target" "auto-secrets.service"];
|
||||
partOf = ["auto-secrets.service"];
|
||||
|
||||
path = with pkgs; [bash rclone mount umount];
|
||||
script = ''
|
||||
set -e
|
||||
umount /storage -fl || true
|
||||
sleep 2
|
||||
rclone --config ${secrets.rclone_config.path} mount StorageBox: /storage --allow-non-empty
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -2,10 +2,48 @@
|
|||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
}: let
|
||||
cfg = config.services.secrets;
|
||||
in {
|
||||
services.secrets = {
|
||||
enable = true;
|
||||
|
||||
vaultLogin = {
|
||||
enable = true;
|
||||
loginUsername = "hetzner-vm-container-storage";
|
||||
loginPasswordFile = cfg.secrets.vault_password.path;
|
||||
};
|
||||
|
||||
autoSecrets = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
requiredVaultPaths = [
|
||||
"api-keys/data/hetzner/storagebox"
|
||||
|
||||
"api-keys/data/putio"
|
||||
|
||||
"api-keys/data/backblaze/Chaos-Backups"
|
||||
"api-keys/data/backblaze/Chaos-Photos"
|
||||
"api-keys/data/backblaze/Chaos-Music"
|
||||
"api-keys/data/backblaze/Chaos-Personal"
|
||||
"api-keys/data/backblaze/Chaos-Public"
|
||||
"api-keys/data/backblaze/Chaos-Media"
|
||||
"api-keys/data/backblaze/Phoenix-Cryptidz-Storage"
|
||||
|
||||
"api-keys/data/storage/restic/Music"
|
||||
"api-keys/data/storage/restic/Vault"
|
||||
"api-keys/data/storage/restic/Social"
|
||||
"api-keys/data/storage/restic/Quassel"
|
||||
"api-keys/data/storage/restic/Piped-Finland"
|
||||
"api-keys/data/storage/restic/Mail"
|
||||
|
||||
"api-keys/data/storage/webdav/main"
|
||||
"api-keys/data/storage/webdav/media"
|
||||
|
||||
"private-public-keys/data/rclone/Chaos-Media-Crypt"
|
||||
];
|
||||
|
||||
packages = with pkgs; [
|
||||
# for music & mail passwd files
|
||||
apacheHttpd
|
||||
|
@ -94,12 +132,12 @@
|
|||
'';
|
||||
};
|
||||
|
||||
restic_piped_htpasswd = {
|
||||
restic_piped_finland_htpasswd = {
|
||||
user = "storage";
|
||||
group = "storage";
|
||||
fetchScript = ''
|
||||
username=$(simple_get "/api-keys/storage/restic/Piped" .username)
|
||||
password=$(simple_get "/api-keys/storage/restic/Piped" .password)
|
||||
username=$(simple_get "/api-keys/storage/restic/Piped-Finland" .username)
|
||||
password=$(simple_get "/api-keys/storage/restic/Piped-Finland" .password)
|
||||
htpasswd -bc "$secretFile" "$username" "$password" 2>/dev/null
|
||||
'';
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{}: {
|
||||
{
|
||||
host = "192.168.100.10";
|
||||
containers = {
|
||||
storage = "192.168.100.11";
|
||||
|
@ -6,6 +6,5 @@
|
|||
music = "192.168.100.13";
|
||||
quassel = "192.168.100.14";
|
||||
piped = "192.168.100.15";
|
||||
mail = "192.168.100.16";
|
||||
};
|
||||
}
|
|
@ -1,9 +1,13 @@
|
|||
{modulesPath, ...}: {
|
||||
imports = [(modulesPath + "/profiles/qemu-guest.nix")];
|
||||
{...}: {
|
||||
boot.loader = {
|
||||
grub = {
|
||||
enable = true;
|
||||
device = "/dev/sda";
|
||||
};
|
||||
};
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
boot.initrd.kernelModules = ["nvme"];
|
||||
|
||||
fileSystems."/" = {
|
||||
device = "/dev/sda1";
|
||||
fsType = "ext4";
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
{
|
||||
tree,
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
}: let
|
||||
inherit (lib.lists) forEach;
|
||||
in {
|
||||
imports = with tree;
|
||||
[
|
||||
users.root
|
||||
presets.nixos.serverBase
|
||||
presets.nixos.serverHetzner
|
||||
|
||||
profiles.base
|
||||
profiles.sshd
|
||||
profiles.nginx
|
||||
profiles.nginx-firewall
|
||||
profiles.nix-gc
|
||||
profiles.cross.arm64
|
||||
profiles.chaos-internal-wireguard
|
||||
profiles.firewallAllow.httpCommon
|
||||
|
||||
profiles.cross.arm64
|
||||
profiles.chaosInternalWireGuard
|
||||
|
||||
./networking.nix
|
||||
./hardware.nix
|
||||
./secrets.nix
|
||||
]
|
||||
++ (lib.forEach [
|
||||
++ (forEach [
|
||||
"social"
|
||||
"storage"
|
||||
"music"
|
||||
|
@ -30,45 +28,10 @@
|
|||
"mail"
|
||||
] (name: ./containers + "/${name}"))
|
||||
++ (with hosts.hetzner-vm.profiles; [
|
||||
vaultui
|
||||
gitlab-static-sites
|
||||
nginx-misc
|
||||
vaultUI
|
||||
gitlabStaticSites
|
||||
]);
|
||||
|
||||
boot.kernel.sysctl = {
|
||||
"fs.inotify.max_user_watches" = 1024 * 64 * 4;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs;
|
||||
[
|
||||
(pkgs.writeShellScriptBin "journalctl-vaccum-all" ''
|
||||
journalctl --vacuum-size=100M
|
||||
${lib.concatStringsSep "\n" (lib.forEach (lib.attrNames config.containers) (name: ''
|
||||
journalctl --vacuum-size=100M --root /var/lib/nixos-containers/${name}
|
||||
''))}
|
||||
'')
|
||||
(pkgs.writeShellScriptBin "systemctl-list-failed-all" ''
|
||||
echo "Host: "
|
||||
systemctl --failed
|
||||
${lib.concatStringsSep "\n" (lib.forEach (lib.attrNames config.containers) (name: ''
|
||||
echo "Container: ${name}"
|
||||
systemctl -M ${name} --failed
|
||||
''))}
|
||||
'')
|
||||
]
|
||||
++ lib.forEach (lib.attrNames config.containers) (name: (pkgs.writeShellScriptBin "journalctl-vaccum-${name}" ''
|
||||
journalctl --vacuum-size=100M --root /var/lib/nixos-containers/${name}
|
||||
''))
|
||||
++ lib.forEach (lib.attrNames config.containers) (name: (pkgs.writeShellScriptBin "systemctl-machine-${name}" ''
|
||||
systemctl -M ${name} $@
|
||||
''))
|
||||
++ lib.forEach (lib.attrNames config.containers) (name: (pkgs.writeShellScriptBin "journalctl-machine-${name}" ''
|
||||
journalctl -M ${name} $@
|
||||
''))
|
||||
++ lib.forEach (lib.attrNames config.containers) (name: (pkgs.writeShellScriptBin "shell-enter-${name}" ''
|
||||
machinectl shell ${name}
|
||||
''));
|
||||
|
||||
# For Containers
|
||||
networking.nat = {
|
||||
enable = true;
|
||||
|
@ -76,13 +39,8 @@
|
|||
externalInterface = "eth0";
|
||||
};
|
||||
|
||||
home-manager.users.root = {
|
||||
imports = with tree; [home.base home.dev.small];
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
networking.hostName = "hetzner-vm";
|
||||
time.timeZone = "Europe/London";
|
||||
|
||||
home-manager.users.root.home.stateVersion = "23.05";
|
||||
system.stateVersion = "23.05";
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{lib, ...}: {
|
||||
systemd.services.systemd-networkd-wait-online.enable = lib.mkForce false;
|
||||
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = true;
|
||||
networking.firewall.allowedTCPPorts = [22];
|
||||
|
||||
services.resolved.enable = false;
|
||||
environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
|
||||
|
||||
networking.enableIPv6 = true;
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
networking.dhcpcd.enable = true;
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks.eth0 = {
|
||||
name = "eth0";
|
||||
address = ["2a01:4f9:c010:8beb::1/64"];
|
||||
gateway = ["fe80::1"];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{...}: {
|
||||
services.nginx.virtualHosts."tablet-dev.owo.monster" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://10.69.42.2:8088";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -13,6 +13,22 @@ in {
|
|||
services.secrets = {
|
||||
enable = true;
|
||||
|
||||
vaultLogin = {
|
||||
enable = true;
|
||||
loginUsername = "hetzner-vm";
|
||||
};
|
||||
|
||||
autoSecrets = {
|
||||
enable = true;
|
||||
affectedSystemdServices = [
|
||||
"wg-quick-wg0"
|
||||
"container@music"
|
||||
"container@social"
|
||||
"container@quassel"
|
||||
"container@piped"
|
||||
];
|
||||
};
|
||||
|
||||
packages = with pkgs; [
|
||||
# for music & mail passwd files
|
||||
apacheHttpd
|
||||
|
@ -41,7 +57,7 @@ in {
|
|||
"api-keys/data/storage/restic/Mail"
|
||||
"api-keys/data/storage/restic/Social"
|
||||
"api-keys/data/storage/restic/Quassel"
|
||||
"api-keys/data/storage/restic/Piped"
|
||||
"api-keys/data/storage/restic/Piped-Finland"
|
||||
|
||||
"api-keys/data/chaos_mail/system"
|
||||
"api-keys/data/chaos_mail/gotosocial"
|
||||
|
@ -57,12 +73,16 @@ in {
|
|||
"private-public-keys/data/restic/Mail"
|
||||
"private-public-keys/data/restic/Social"
|
||||
"private-public-keys/data/restic/Quassel"
|
||||
"private-public-keys/data/restic/Piped"
|
||||
"private-public-keys/data/restic/Piped-Finland"
|
||||
|
||||
"infra/data/private-mail-aliases"
|
||||
];
|
||||
|
||||
secrets = {
|
||||
vault_password = {
|
||||
manual = true;
|
||||
};
|
||||
|
||||
# Used directly by server
|
||||
# for fetching gitlab static sites
|
||||
gitlab_env = {
|
||||
|
@ -205,16 +225,16 @@ in {
|
|||
};
|
||||
|
||||
# Container: piped
|
||||
piped_restic_password = {
|
||||
piped_finland_restic_password = {
|
||||
fetchScript = ''
|
||||
simple_get "/private-public-keys/restic/Piped" .password > "$secretFile"
|
||||
simple_get "/private-public-keys/restic/Piped-Finland" .password > "$secretFile"
|
||||
'';
|
||||
};
|
||||
piped_restic_env = {
|
||||
piped_finland_restic_env = {
|
||||
fetchScript = ''
|
||||
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped" .username)
|
||||
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Piped" .password)
|
||||
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Piped" > "$secretFile"
|
||||
RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/Piped-Finland" .username)
|
||||
RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/Piped-Finland" .password)
|
||||
echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/Piped-Finland" > "$secretFile"
|
||||
'';
|
||||
};
|
||||
piped_cockroachdb_ca_certificate = {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{tree, ...}: {
|
||||
imports = with tree; [presets.nixos.normalEncryptedDrive];
|
||||
|
||||
boot = {
|
||||
loader = {
|
||||
systemd-boot.enable = true;
|
||||
|
@ -21,6 +23,4 @@
|
|||
services.tlp.settings = {
|
||||
RUNTIME_PM_BLACKLIST = "05:00.3 05:00.4";
|
||||
};
|
||||
|
||||
imports = with tree; [presets.nixos.dual-encrypted-drive];
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
users.root
|
||||
users.chaos
|
||||
profiles.sshd
|
||||
profiles.kernels.latest
|
||||
|
||||
presets.nixos.desktop-sway
|
||||
presets.nixos.desktopSway
|
||||
presets.nixos.laptop
|
||||
presets.nixos.encrypted-usb
|
||||
presets.nixos.encryptedUSB
|
||||
|
||||
profiles.cross.arm64
|
||||
#profiles.remote-builders
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
{config, ...}: let
|
||||
secrets = config.services.secrets.secrets;
|
||||
data = import ../../../data/chaos_wireguard_internal.nix {};
|
||||
in {
|
||||
networking.firewall.trustedInterfaces = ["wg0"];
|
||||
networking.wg-quick.interfaces = {
|
||||
wg0 = {
|
||||
autostart = false;
|
||||
address = ["${data.hosts.lappy-t495.ip}/32"];
|
||||
privateKeyFile = "${secrets.wg_priv.path}";
|
||||
|
||||
peers = [
|
||||
# hetzner-vm
|
||||
{
|
||||
publicKey = "${data.hosts.hetzner-vm.public}";
|
||||
presharedKeyFile = "${secrets.wg_preshared_hetzner-vm.path}";
|
||||
allowedIPs = ["${data.hosts.hetzner-vm.ip}/24"];
|
||||
endpoint = "${data.hosts.hetzner-vm.endpoint}";
|
||||
persistentKeepalive = 25;
|
||||
}
|
||||
# vault
|
||||
{
|
||||
publicKey = "${data.hosts.vault.public}";
|
||||
presharedKeyFile = "${secrets.wg_preshared_vault.path}";
|
||||
allowedIPs = ["${data.hosts.vault.ip}/32"];
|
||||
endpoint = "${data.hosts.vault.endpoint}";
|
||||
persistentKeepalive = 25;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{tree, ...}: {
|
||||
users.users.chaos = {
|
||||
name = "chaos";
|
||||
home = "/Users/chaos";
|
||||
};
|
||||
home-manager.users.chaos = {
|
||||
programs.zsh.envExtra = ''
|
||||
export PATH=/run/current-system/sw/bin:$PATH
|
||||
'';
|
||||
imports = with tree; [
|
||||
# NOINLINE
|
||||
home.base
|
||||
home.dev
|
||||
home.programming.editors.vscode
|
||||
home.programming.languages.nix
|
||||
home.apps.mpv
|
||||
];
|
||||
};
|
||||
}
|
|
@ -4,7 +4,9 @@
|
|||
modulesPath,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
}: let
|
||||
inherit (lib.modules) mkForce;
|
||||
in {
|
||||
imports = with tree; [
|
||||
(modulesPath + "/installer/cd-dvd/installation-cd-graphical-gnome.nix")
|
||||
(modulesPath + "/installer/cd-dvd/channel.nix")
|
||||
|
@ -12,9 +14,8 @@
|
|||
users.root
|
||||
profiles.base
|
||||
profiles.sshd
|
||||
profiles.kernels.latest
|
||||
profiles.connectivity.ios
|
||||
profiles.connectivity.network_manager
|
||||
profiles.connectivity.iOS
|
||||
profiles.connectivity.networkManager
|
||||
];
|
||||
|
||||
# disable zfs
|
||||
|
@ -26,18 +27,16 @@
|
|||
})
|
||||
];
|
||||
|
||||
networking.wireless.enable = lib.mkForce false;
|
||||
networking.wireless.enable = mkForce false;
|
||||
|
||||
nixpkgs.config.allowBroken = true;
|
||||
|
||||
home-manager.users.root = {
|
||||
imports = with tree; [home.base home.dev];
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
home-manager.users.nixos = {
|
||||
imports = with tree; [home.base home.dev];
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
|
||||
isoImage = {
|
||||
|
@ -46,5 +45,5 @@
|
|||
squashfsCompression = "zstd -Xcompression-level 1";
|
||||
};
|
||||
|
||||
services.openssh.settings.PermitRootLogin = lib.mkForce "yes";
|
||||
services.openssh.settings.PermitRootLogin = mkForce "yes";
|
||||
}
|
||||
|
|
106
hosts/nixos.nix
106
hosts/nixos.nix
|
@ -30,8 +30,6 @@
|
|||
|
||||
inputs.home-manager-unstable.nixosModules.home-manager
|
||||
|
||||
inputs.nur.nixosModules.nur
|
||||
|
||||
inputs.vaultui.nixosModules.default
|
||||
inputs.gitlab_artifacts_sync.nixosModules.default
|
||||
inputs.piped-flake.nixosModules.default
|
||||
|
@ -39,90 +37,66 @@
|
|||
tree.modules.nixos.rclone-serve
|
||||
tree.modules.nixos.rclone-sync
|
||||
tree.modules.nixos.secrets
|
||||
tree.modules.nixos.cockroachdb-bin
|
||||
];
|
||||
|
||||
nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem;
|
||||
|
||||
nixosX86_64LiveWithExtraDepsForMachines = machines:
|
||||
nixosUnstableSystem {
|
||||
specialArgs =
|
||||
defaultSpecialArgs
|
||||
// {
|
||||
hostPath = ./nixos-live;
|
||||
};
|
||||
system = "x86_64-linux";
|
||||
modules =
|
||||
defaultModules
|
||||
++ [
|
||||
./nixos-live/nixos-live.nix
|
||||
({...}: {
|
||||
system.extraDependencies =
|
||||
forEach machines (system:
|
||||
self.nixosConfigurations.${system}.config.system.build.toplevel);
|
||||
})
|
||||
];
|
||||
};
|
||||
in {
|
||||
tablet = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "x86_64-linux";
|
||||
modules = defaultModules ++ [./tablet/tablet.nix ./tablet/hardware.nix];
|
||||
};
|
||||
lappy-t495 = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
specialArgs =
|
||||
defaultSpecialArgs
|
||||
// {
|
||||
hostPath = ./lappy-t495;
|
||||
};
|
||||
system = "x86_64-linux";
|
||||
modules = defaultModules ++ [./lappy-t495/lappy-t495.nix ./lappy-t495/hardware.nix];
|
||||
};
|
||||
|
||||
hetzner-vm = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
specialArgs =
|
||||
defaultSpecialArgs
|
||||
// {
|
||||
hostPath = ./hetzner-vm;
|
||||
};
|
||||
system = "x86_64-linux";
|
||||
modules = defaultModules ++ [./hetzner-vm/hetzner-vm.nix];
|
||||
};
|
||||
|
||||
vault = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
specialArgs =
|
||||
defaultSpecialArgs
|
||||
// {
|
||||
hostPath = ./vault;
|
||||
};
|
||||
system = "x86_64-linux";
|
||||
modules = defaultModules ++ [./vault/vault.nix];
|
||||
};
|
||||
|
||||
buildbox = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "x86_64-linux";
|
||||
modules = defaultModules ++ [./buildbox/buildbox.nix];
|
||||
};
|
||||
|
||||
# nix build .#nixosConfigurations.nixos-live-x86_64.config.system.build.isoImage
|
||||
nixos-live-x86_64 = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "x86_64-linux";
|
||||
modules = defaultModules ++ [./nixos-live/nixos-live.nix];
|
||||
};
|
||||
|
||||
nixos-live-x86_64-laptops = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "x86_64-linux";
|
||||
modules =
|
||||
defaultModules
|
||||
++ [
|
||||
./nixos-live/nixos-live.nix
|
||||
({...}: {
|
||||
system.extraDependencies =
|
||||
forEach ["lappy-t495" "tablet"] (system:
|
||||
self.nixosConfigurations.${system}.config.system.build.toplevel);
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
nixos-live-x86_64-servers = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "x86_64-linux";
|
||||
modules =
|
||||
defaultModules
|
||||
++ [
|
||||
./nixos-live/nixos-live.nix
|
||||
({...}: {
|
||||
system.extraDependencies =
|
||||
forEach ["vault" "hetzner-vm"] (system:
|
||||
self.nixosConfigurations.${system}.config.system.build.toplevel);
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
nixos-live-x86_64-all = nixosUnstableSystem {
|
||||
specialArgs = defaultSpecialArgs;
|
||||
system = "x86_64-linux";
|
||||
modules =
|
||||
defaultModules
|
||||
++ [
|
||||
./nixos-live/nixos-live.nix
|
||||
({...}: {
|
||||
system.extraDependencies =
|
||||
forEach ["lappy-t495" "tablet" "vault" "hetzner-vm"] (system:
|
||||
self.nixosConfigurations.${system}.config.system.build.toplevel);
|
||||
})
|
||||
];
|
||||
};
|
||||
nixos-live-x86_64 = nixosX86_64LiveWithExtraDepsForMachines [];
|
||||
nixos-live-x86_64-laptops = nixosX86_64LiveWithExtraDepsForMachines ["lappy-t495"];
|
||||
nixos-live-x86_64-servers = nixosX86_64LiveWithExtraDepsForMachines ["hetzner-vm" "vault"];
|
||||
nixos-live-x86_64-all = nixosX86_64LiveWithExtraDepsForMachines ["lappy-t495" "vault" "hetzner-vm"];
|
||||
|
||||
# nix --no-sandbox build .#nixosConfigurations.raspberry.config.system.build.sdImage
|
||||
raspberry = nixosUnstableSystem {
|
||||
|
|
|
@ -2,18 +2,30 @@
|
|||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
modulesPath,
|
||||
...
|
||||
}: {
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
}: let
|
||||
inherit (lib.modules) mkForce mkDefault;
|
||||
inherit (builtins) toFile;
|
||||
in {
|
||||
imports = [
|
||||
(modulesPath + "/installer/sd-card/sd-image.nix")
|
||||
];
|
||||
|
||||
boot.consoleLogLevel = lib.mkDefault 7;
|
||||
|
||||
boot.kernelParams = ["console=tty0"];
|
||||
boot = {
|
||||
supportedFilesystems = mkForce ["vfat"];
|
||||
consoleLogLevel = mkDefault 7;
|
||||
kernelParams = ["console=tty0"];
|
||||
loader = {
|
||||
grub.enable = false;
|
||||
generic-extlinux-compatible.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
sdImage = {
|
||||
compressImage = mkForce false;
|
||||
populateFirmwareCommands = let
|
||||
configTxt = pkgs.writeText "config.txt" ''
|
||||
configTxt = toFile "config.txt" ''
|
||||
[pi3]
|
||||
kernel=u-boot-rpi3.bin
|
||||
[pi4]
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
[connection]
|
||||
id=WIFI_ID
|
||||
uuid=554e0eeb-840a-4106-84c3-01c0e9d69569
|
||||
type=wifi
|
||||
|
||||
[wifi]
|
||||
mode=infrastructure
|
||||
ssid=WIFI_SSID
|
||||
|
||||
[wifi-security]
|
||||
auth-alg=open
|
||||
key-mgmt=wpa-psk
|
||||
psk=WIFI_PASSWORD
|
||||
|
||||
[ipv4]
|
||||
method=auto
|
||||
|
||||
[ipv6]
|
||||
addr-gen-mode=default
|
||||
method=auto
|
||||
|
||||
[proxy]
|
23
hosts/raspberry/profiles/cockroachDB.nix
Normal file
23
hosts/raspberry/profiles/cockroachDB.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
{self, ...}: let
|
||||
internalWireGuard = import "${self}/data/chaosInternalWireGuard.nix";
|
||||
in {
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/cockroachdb-certs - root root"
|
||||
];
|
||||
|
||||
services.cockroachdb-bin = {
|
||||
enable = true;
|
||||
certsDir = "/var/lib/cockroachdb-certs";
|
||||
join = "localhost:26257,${internalWireGuard.hosts.hetzner-vm.ip}:26257";
|
||||
# ssh -L 8080:127.0.0.1:8080 -L 26257:127.0.0.1:26257 raspberry
|
||||
extraArgs = ["--advertise-addr=${internalWireGuard.hosts.raspberry.ip}:26257"];
|
||||
listen = {
|
||||
port = 26257;
|
||||
address = "0.0.0.0";
|
||||
};
|
||||
http = {
|
||||
address = "0.0.0.0";
|
||||
port = 8080;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
{tree, ...}: let
|
||||
internal_wireguard = import ../../../data/chaos_wireguard_internal.nix {};
|
||||
in {
|
||||
imports = with tree; [
|
||||
profiles.cockroachdb-bin-fix
|
||||
];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/cockroachdb-certs - root root"
|
||||
];
|
||||
|
||||
services.cockroachdb = {
|
||||
enable = true;
|
||||
certsDir = "/var/lib/cockroachdb-certs";
|
||||
join = "localhost:26257,${internal_wireguard.hosts.hetzner-vm.ip}:26257";
|
||||
# ssh -L 8080:127.0.0.1:8080 -L 26257:127.0.0.1:26257 raspberry
|
||||
http = {
|
||||
address = "0.0.0.0";
|
||||
port = 8080;
|
||||
};
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue