Updated mail alerts. Added automatic DNS records creation with cloudflare

This commit is contained in:
Raphaël Numbus
2026-01-17 14:51:41 +01:00
parent 6d1d3be3b3
commit 98a144d408
4 changed files with 127 additions and 85 deletions
+108 -73
View File
@@ -7,10 +7,10 @@ export GUM_SPIN_SPINNER_BOLD=true
export GUM_SPIN_SHOW_ERROR=true
export GUM_SPIN_TITLE_BOLD=true
NECESSARY_VARIABLES_LIST=("TARGET_HOST" "REMOTE_PASS" "SSH_PUBLIC_KEY" "DOMAIN_NAME" \
NECESSARY_VARIABLES_LIST=( "TARGET_HOST" "REMOTE_PASS" "SSH_PUBLIC_KEY" "DOMAIN_NAME" \
"EMAIL_ADDRESS" "CF_DNS_API_TOKEN" "SENDER_EMAIL_ADDRESS" "SENDER_EMAIL_ADDRESS_PASSWORD" \
"SENDER_EMAIL_DOMAIN" "SENDER_EMAIL_PORT" "HOME_ROUTER_SUBNET" "HOME_ROUTER_IP" \
"HOME_SERVER_IP" "SELECTED_SERVICES" "SERVER_OWNER_NAME")
"HOME_SERVER_IP" "SELECTED_SERVICES" "SERVER_OWNER_NAME" )
### Default settings <--
user_input() {
@@ -141,7 +141,7 @@ hardware_detection() {
ssh_to_host 'bash -s' << SSHEND
for brand in Intel AMD NVIDIA; do
if lspci -nn 2>/dev/null | grep -i "vga" | grep -iq "\${brand}"; then
if lspci -nn > /dev/null 2>&1 | grep -i "vga" | grep -iq "\${brand}"; then
TARGET_GRAPHICS="true"
TARGET_GRAPHICS_BRAND+=("\${brand}")
else
@@ -149,14 +149,14 @@ for brand in Intel AMD NVIDIA; do
fi
done
ls /dev/dri/ 2>/dev/null | grep -iq "renderD128" && TARGET_GRAPHICS_RENDERER="true" || TARGET_GRAPHICS_RENDERER="false"
lsusb 2>/dev/null | grep -iq "google" && TARGET_USB_CORAL="true" || TARGET_USB_CORAL="false"
lspci -nn 2>/dev/null | grep -iq "089a" && TARGET_PCIE_CORAL="true" || TARGET_PCIE_CORAL="false"
ls /dev/serial/by-id/ 2>/dev/null | grep -i "zigbee" && TARGET_ZIGBEE_DEVICE=\$(ls /dev/serial/by-id/ 2>/dev/null | grep -i "zigbee" | head -n 1) || TARGET_ZIGBEE_DEVICE=""
ls /dev/dri/ > /dev/null 2>&1 | grep -iq "renderD128" && TARGET_GRAPHICS_RENDERER="true" || TARGET_GRAPHICS_RENDERER="false"
lsusb > /dev/null 2>&1 | grep -iq "google" && TARGET_USB_CORAL="true" || TARGET_USB_CORAL="false"
lspci -nn > /dev/null 2>&1 | grep -iq "089a" && TARGET_PCIE_CORAL="true" || TARGET_PCIE_CORAL="false"
ls /dev/serial/by-id/ > /dev/null 2>&1 | grep -i "zigbee" && TARGET_ZIGBEE_DEVICE=\$(ls /dev/serial/by-id/ > /dev/null 2>&1 | grep -i "zigbee" | head -n 1) || TARGET_ZIGBEE_DEVICE=""
TARGET_INTERFACE=\$(ip -4 route show default | awk '{print \$5}' | head -n1)
if ls -l /sys/class/tpm/tpm0/ >/dev/null 2>&1; then
if ls -l /sys/class/tpm/tpm0/ > /dev/null 2>&1; then
TARGET_TPM="true"
TARGET_TPM_VERSION=\$(cat /sys/class/tpm/tpm0/tpm_version_major)
else
@@ -186,7 +186,7 @@ for DISK in \$(lsblk -x SIZE -d -n -e 7,11 -o NAME); do
else DISK_TYPE+=("Other")
fi
# Disk health
if [[ \$(echo "$REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then
if [[ \$(echo "$REMOTE_PASS" | sudo -S smartctl -H /dev/\$DISK > /dev/null 2>&1 | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then
DISK_HEALTH+=("PASSED")
else
DISK_HEALTH+=("N/A")
@@ -239,7 +239,7 @@ SSHEND
}
services_selection() {
echo -e "\n\n➡️ You will now select the services you want installed on your server:"
echo -e "\n\n ➡️ You will now select the services you want installed on your server:"
local AVAILABLE_SERVICES=( "frigate" "gitea" "home-assistant" "immich" "it-tools" \
"nextcloud" "passbolt" "pi-hole" "virtualization" )
@@ -258,12 +258,20 @@ services_selection() {
local SELECTED_SERVICES_DESCRIPTION=$(gum choose --no-limit --header "Homelab services:" "${SERVICES_DESCRIPTION[@]}")
for i in ${!AVAILABLE_SERVICES[@]}; do
if printf '%s' "$SELECTED_SERVICES_DESCRIPTION" | grep -iq "${AVAILABLE_SERVICES[$i]}"; then
SELECTED_SERVICES+=(${AVAILABLE_SERVICES[$i]})
if printf '%s' "${SELECTED_SERVICES_DESCRIPTION}" | grep -iq "${AVAILABLE_SERVICES[${i}]}"; then
SELECTED_SERVICES+=("${AVAILABLE_SERVICES[${i}]}")
if [[ "${AVAILABLE_SERVICES[${i}]}" == "nextcloud" ]]; then
SELECTED_SERVICES_DNS+=("nextcloud.${DOMAIN_NAME}" "nextcloud-aio.${DOMAIN_NAME}")
elif [[ "${AVAILABLE_SERVICES[${i}]}" == "virtualization" ]]; then
:
else
SELECTED_SERVICES_DNS+=("${AVAILABLE_SERVICES[${i}]}.${DOMAIN_NAME}")
fi
fi
done
export SELECTED_SERVICES
export SELECTED_SERVICES_DNS
}
disks_selection() {
@@ -274,14 +282,14 @@ disks_selection() {
!! ALL DATA WILL BE WIPED ON THE DISKS YOU CHOOSE !!
Please press CTRL+C to abort.
"
gum confirm "Do you understand and wish to proceed?" || { echo -e "\n\n❌ Aborting as requested."; exit 1; }
gum confirm "Do you understand and wish to proceed?" || { echo -e "\n\n ❌ Aborting as requested."; exit 1; }
echo -e "\n\n🔎 Fetching and analyzing disks from target host... (This may take a moment)"
echo -e "\n\n 🔎 Fetching and analyzing disks from target host... (This may take a moment)"
### Disk wiping warning <--
### --> Disk selection
if [[ "${#DISK_NAME[@]}" -eq 0 ]]; then
echo -e "\n❌ No disks found on the target host. Aborting."
echo -e "\n ❌ No disks found on the target host. Aborting."
exit 1
fi
@@ -291,13 +299,13 @@ disks_selection() {
local GUM_PRINTED_ELEMENT=$(printf "%-12s %-12s %-12s %-12s %s" \
"${DISK_NAME[${i}]}" "${DISK_TYPE[${i}]}" "${DISK_SIZE[${i}]}" \
"${DISK_HEALTH[${i}]}" "${DISK_DEVPATH[${i}]}")
local GUM_PRINTED_ELEMENTS+=("$GUM_PRINTED_ELEMENT")
local GUM_PRINTED_ELEMENTS+=("${GUM_PRINTED_ELEMENT}")
done
echo ""
gum style --foreground 212 "➡️ Please choose one (stripe) or two (mirror) disks for your NixOS boot installation :"
local SELECTED_BOOT_DISK=$(gum choose --limit 2 --header "$HEADER" "${GUM_PRINTED_ELEMENTS[@]}")
local SELECTED_BOOT_DISK=$(gum choose --limit 2 --header "${HEADER}" "${GUM_PRINTED_ELEMENTS[@]}")
for i in ${!DISK_NAME[@]}; do
if printf '%s' "$SELECTED_BOOT_DISK" | grep -iqw "${DISK_NAME[${i}]}"; then
@@ -308,23 +316,23 @@ disks_selection() {
done
if [[ "${#BOOT_DISKS_ID[@]}" -eq 0 ]]; then
echo -e "\n\n❌ No boot disk selected. Aborting."
echo -e "\n\n ❌ No boot disk selected. Aborting."
exit 1
elif [[ "${#BOOT_DISKS_ID[@]}" -eq 1 ]]; then
echo -e "\n\n⚠️ One boot disk selected, continuing with striped boot disk configuration."
echo -e "\n\n ⚠️ One boot disk selected, continuing with striped boot disk configuration."
echo -e "Consider using 2 boot disks instead to get data protection features on the boot disks."
export BOOT_DISK_1_ID="${BOOT_DISKS_ID[0]}"
export BOOT_DISK_1_NAME="${DISK_NAME[0]}"
elif [[ "${#BOOT_DISKS_ID[@]}" -eq 2 ]]; then
echo -e "\n\n✅ Two boot disks selected, continuing with mirrored boot disks configuration."
echo -e "\n\n⚠️ If the two disks are different sizes, the resulting usable space size will be \
echo -e "\n\n ✅ Two boot disks selected, continuing with mirrored boot disks configuration."
echo -e "\n\n ⚠️ If the two disks are different sizes, the resulting usable space size will be \
the one of the smallest disk."
export BOOT_DISK_1_ID="${BOOT_DISKS_ID[0]}"
export BOOT_DISK_2_ID="${BOOT_DISKS_ID[1]}"
export BOOT_DISK_1_NAME="${BOOT_DISKS_NAME[0]}"
export BOOT_DISK_2_NAME="${BOOT_DISKS_NAME[1]}"
else
echo -e "\n\n❌ Unexpected bug. Please contact the developer. Aborting."
echo -e "\n\n ❌ Unexpected bug. Please contact the developer. Aborting."
exit 1
fi
@@ -384,7 +392,7 @@ services_generation() {
export "${SERVICE_UPPER}_DB_PASSWORD"="$(xkcdpass -d "-")"
}
echo -e "\n✅ Writing configuration files for the selected homelab services..."
echo -e "\n ✅ Writing configuration files for the selected homelab services..."
cp templates/nix-config/podman/traefik.nix final-nix-config/etc/nixos/podman/traefik.nix
cp -avu templates/nix-config/configuration.nix final-nix-config/etc/nixos/configuration.nix
envsubst < templates/podman-config/traefik/traefik.yaml > final-nix-config/mnt/config/traefik/traefik.yaml
@@ -473,7 +481,7 @@ services_generation() {
disks_generation() {
# Boot disk(s)
echo -e "\n\n✅ Generating disko configuration from templates..."
echo -e "\n\n ✅ Generating disko configuration from templates..."
local TEMPLATE_FILE="templates/nix-config/disks/boot-${#BOOT_DISKS_ID[@]}.nix"
(envsubst < "$TEMPLATE_FILE") > final-nix-config/etc/nixos/disks/disko.nix
@@ -527,7 +535,7 @@ disks_generation() {
MOUNT_DEPENDENCIES_STOP+=" \${pkgs.util-linux}/bin/umount /mnt/content-${j}"$'\n'
MOUNT_DEPENDENCIES_STOP+=" \${pkgs.cryptsetup}/bin/cryptsetup close crypted-content-${j}"$'\n'
done
echo -e "\n✅ Generated $CONTENT_DISK_NUMBER data disk configuration(s)."
echo -e "\n ✅ Generated $CONTENT_DISK_NUMBER data disk configuration(s)."
j=0
for i in $(seq $CONTENT_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do
export j=$((j + 1))
@@ -541,7 +549,7 @@ disks_generation() {
MOUNT_DEPENDENCIES_STOP+=" \${pkgs.util-linux}/bin/umount /mnt/parity-${j}"$'\n'
MOUNT_DEPENDENCIES_STOP+=" \${pkgs.cryptsetup}/bin/cryptsetup close crypted-parity-${j}"$'\n'
done
echo -e "\n✅ Generated $PARITY_DISK_NUMBER parity disk configuration(s)."
echo -e "\n ✅ Generated $PARITY_DISK_NUMBER parity disk configuration(s)."
export SNAPRAID_CONTENT_FILES
export SNAPRAID_DATA_DISKS
export SNAPRAID_PARITY_FILES
@@ -557,7 +565,7 @@ disks_generation() {
}
EOF
echo -e "\n✅ Final disko configuration created."
echo -e "\n ✅ Final disko configuration created."
if [[ -n "${DATA_DISKS_ID[@]}" ]]; then
for i in ${!DATA_DISKS_ID[@]}; do
@@ -572,7 +580,7 @@ EOF
FORMATTED_DISKS+=" \"$disk\"\n"
done
sed -i "s|DISK_LIST|${FORMATTED_DISKS}|" final-nix-config/etc/nixos/disks/spindown.nix
echo -e "\n✅ Disk spindown configuration created."
echo -e "\n ✅ Disk spindown configuration created."
fi
fi
### Config generation <--
@@ -601,20 +609,20 @@ EOF
PASS="$(xkcdpass)"
echo -n "$PASS" > "final-nix-config/etc/secrets/disks/parity-${i}"
chmod 600 "final-nix-config/etc/secrets/disks/parity-${i}"
ssh_to_host 'bash -s' << EOF
ssh_to_host 'bash -s' << EOF
echo "$REMOTE_PASS" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/parity-${i}"
EOF
done
### Generate disk keys <--
echo -e "\n✅ Generating sops-nix keys..."
echo -e "\n ✅ Generating sops-nix keys..."
ssh-to-age -private-key -i final-nix-config/home/numbus-admin/.ssh/id_ed25519 > final-nix-config/var/lib/sops-nix/key.txt
export SOPS_PUBLIC_KEY=$(age-keygen -y final-nix-config/var/lib/sops-nix/key.txt)
echo -e "\n✅ Generating sops-nix configuration files..."
echo -e "\n ✅ Generating sops-nix configuration files..."
envsubst < templates/nix-config/sops-nix/.sops.yaml > final-nix-config/etc/nixos/.sops.yaml
echo -e "\n✅ Encrypting secrets in the correct file..."
echo -e "\n ✅ Encrypting secrets in the correct file..."
envsubst < "templates/nix-config/sops-nix/secrets.yaml" \
| sops encrypt --filename-override secrets.yaml \
--input-type yaml --output-type yaml \
@@ -623,12 +631,12 @@ EOF
}
nix_generation() {
echo -e "\n✅ Copying the configuration to the new machine..."
echo -e "\n ✅ Copying the configuration to the new machine..."
cp -avu templates/nix-config/flake.nix final-nix-config/etc/nixos/
cp -avu templates/nix-config/misc/* final-nix-config/etc/nixos/misc/
echo "${SERVER_OWNER_NAME:-User}" > final-nix-config/etc/numbus-server/owner
echo -e "\n✅ Writing correct ips to configuration.nix..."
echo -e "\n ✅ Writing correct ips to configuration.nix..."
sed -i "s|HOME_SERVER_IP|${HOME_SERVER_IP}|g" final-nix-config/etc/nixos/misc/networking.nix
sed -i "s|HOME_ROUTER_IP|${HOME_ROUTER_IP}|g" final-nix-config/etc/nixos/misc/networking.nix
sed -i "s|TARGET_INTERFACE|${TARGET_INTERFACE}|g" final-nix-config/etc/nixos/misc/networking.nix
@@ -668,7 +676,7 @@ EOF
)
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "$(gum format <<< "${DISK_RECAP_CONTENT}")"
gum confirm "Proceed with this disk configuration?" || { echo -e "\n\n❌ Aborting as requested."; exit 1; }
gum confirm "Proceed with this disk configuration?" || { echo -e "\n\n ❌ Aborting as requested."; exit 1; }
### Disk selection recap <--
### Keys recap <--
@@ -701,7 +709,7 @@ EOF
)
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "$(gum format <<< "${KEYS_RECAP_CONTENT}")"
gum confirm "Do you want to deploy NixOS on the target host?" || { echo -e "\n\n❌ Aborting as requested"; exit 1; }
gum confirm "Do you want to deploy NixOS on the target host?" || { echo -e "\n\n ❌ Aborting as requested"; exit 1; }
### Keys recap <--
}
@@ -729,59 +737,86 @@ export_configuration() {
echo -e "\n# Podman SETTINGS" >> $CONFIG_EXPORT_FILE
echo "export PODMAN_NETWORKS=\"${PODMAN_NETWORKS}\"" >> $CONFIG_EXPORT_FILE
echo "export TRAEFIK_NETWORKS=\"${TRAEFIK_NETWORKS}\"" >> $CONFIG_EXPORT_FILE
echo "export TRAEFIK_REF_NETWORKS=\"${TRAEFIK_REF_NETWORKS}\"" >> $CONFIG_EXPORT_FILE
echo "export TRAEFIK_REF_NETWORKS=\"${TRAEFIK_REF_NETWORKS}\"" >> $CONFIG_EXPORT_FILE
}
cloudflare_dns_setup() {
echo -e "\n\n☁️ Configuring Cloudflare DNS records..."
local ZONE_ID && local RECORD_COUNT && local IS_MATCHING
local DNS_RECORDS && local CREATION_STATUS
# 1. Get Zone ID
local ZONE_ID
create_records() {
local SUBDOMAIN="${1}"
local CREATION_STATUS
CREATION_STATUS=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"${SUBDOMAIN}\",\"content\":\"${HOME_SERVER_IP}\",\"ttl\":1,\"proxied\":false}" | jq -r '.success')
if [[ "${CREATION_STATUS}" == "true" ]]; then
echo " ✅ Successfully create a DNS record for ${SUBDOMAIN}"
else
echo -e " ❌ Failed to create a DNS record for ${SUBDOMAIN}. Check documentation to \n
learn how you can create them manually."
fi
}
erase_records() {
local SUBDOMAIN="${1}"
local DELETION_STATUS
gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "
⚠️ $(gum style --foreground 212 'WARNING:') One or more existing type A DNS records found for \`${SUBDOMAIN}\`.
This script can clear those DNS records for you and create the correct ones needed for the server.
If you are unsure that these records are actually in use, please select \"no\"."
gum confirm "Select \"yes\" to clear ALL EXISTING type A DNS records for this subdomain and automatically create the correct ones." \
|| { echo -e "\n ⚠️ DNS records for ${SUBDOMAIN} will not be updated"; return 0; }
RECORD_IDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${SUBDOMAIN}&type=A" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" | jq -r '.result[].id')
for id in ${RECORD_IDS}; do
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${id}" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" > /dev/null 2>&1
done
create_records "${SUBDOMAIN}"
}
echo -e "\n\n ☁️ Configuring Cloudflare DNS records..."
# Get Zone ID
ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN_NAME}" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" | jq -r '.result[0].id')
if [[ "${ZONE_ID}" == "null" || -z "${ZONE_ID}" ]]; then
echo -e "\n\n⚠️ Could not fetch Zone ID for ${DOMAIN_NAME}. Please check your Cloudflare \"DNS ZONE\" API token"
echo "Check out the Numbus-Server documentation to see out to get one."
echo -e "\n\n ⚠️ Could not fetch Zone ID for ${DOMAIN_NAME}. Please check your Cloudflare \"DNS ZONE\" API token"
echo "Check the Numbus-Server documentation to learn how to get one."
fi
# 2. Iterate services
for service in "${SELECTED_SERVICES[@]}"; do
if [[ "${service}" == "virtualization" ]]; then continue; fi
local SUBDOMAIN="${service}.${DOMAIN_NAME}"
echo -n " - Checking for existing record : ${SUBDOMAIN}..."
# Check existence
local RECORD_ID
RECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${SUBDOMAIN}&type=A" \
# Check for existing records and create them if non-existent
for service_domain in "${SELECTED_SERVICES_DNS[@]}"; do
DNS_RECORDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${service_domain}&type=A" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" | jq -r '.result[0].id')
-H "Content-Type: application/json")
if [[ "${RECORD_ID}" != "null" && -n "${RECORD_ID}" ]]; then
RECORD_ID_CONTENT=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${SUBDOMAIN}&type=A" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" | jq -r '.result[0].content')
if [[ "${RECORD_ID_CONTENT}" == "${HOME_SERVER_IP}" ]]; then
echo " ✅ Already configured"
else
echo " ⚠️ A DNS record is configured but does not point to the correct IP"
echo "Do you want to update it? It could break past DNS record you defined"
fi
else
echo -n " ⏳ Creating..."
local CREATE_RES
CREATE_RES=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "Authorization: Bearer ${CF_DNS_API_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"${SUBDOMAIN}\",\"content\":\"${HOME_SERVER_IP}\",\"ttl\":1,\"proxied\":false}" | jq -r '.success')
RECORD_COUNT=$(echo "${DNS_RECORDS}" | jq '.result | length')
if [[ "${CREATE_RES}" == "true" ]]; then
echo " ✅ Created."
if [[ "${RECORD_COUNT}" -eq 0 ]]; then
echo -e "\n ⚠️ No DNS record found for ${service_domain}"
create_records "${service_domain}"
elif [[ "${RECORD_COUNT}" -eq 1 ]]; then
if [[ $(echo "${DNS_RECORDS}" | jq ".result[0].content == \"${HOME_SERVER_IP}\"") == "true" ]]; then
echo -e "\n ✅ DNS record already configured for ${service_domain}"
else
echo " ❌ Failed."
echo -e "\n ⚠️ No DNS record found for ${service_domain}"
erase_records "${service_domain}"
fi
elif [[ "${RECORD_COUNT}" -gt 1 ]]; then
erase_records "${service_domain}"
fi
done
}
+1 -1
View File
@@ -44,7 +44,7 @@
boot.initrd.systemd.enable = true;
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.swraid.mdadmConf = "MAILADDR ${config.email.toAddress}";
boot.swraid.mdadmConf = "MAILADDR ${config.email.userAddress},${config.email.adminAddress}";
# boot.initrd.systemd.tpm2.enable = true;
# TPM2 PCR check
+3 -3
View File
@@ -13,7 +13,7 @@ in
type = lib.types.str;
default = "no-reply@DOMAIN_NAME";
};
toAddress = lib.mkOption {
userAddress = lib.mkOption {
description = "The 'to' address";
type = lib.types.str;
default = "EMAIL_ADDRESS";
@@ -47,8 +47,8 @@ in
config = lib.mkIf cfg.enable {
environment.etc."aliases".text = ''
root: ${config.email.toAddress}, ${config.email.adminAddress}
default: ${config.email.toAddress}, ${config.email.adminAddress}
root: ${config.email.userAddress}, ${config.email.adminAddress}
default: ${config.email.userAddress}, ${config.email.adminAddress}
'';
programs.msmtp = {
+15 -8
View File
@@ -10,6 +10,7 @@ let
TECH_BODY="
SMARTD Alert Details:
Server owner: $OWNER_NAME
Device: $SMARTD_DEVICE
Type: $SMARTD_DEVICETYPE
Failure Type: $SMARTD_FAILTYPE
@@ -22,17 +23,23 @@ let
# 2. Send Friendly Email to Owner
OWNER_NAME=$(cat /etc/numbus-server/owner 2>/dev/null || echo "User")
USER_EMAIL="${config.email.toAddress}"
USER_EMAIL="${config.email.userAddress}"
FRIENDLY_BODY="Hello $OWNER_NAME,
FRIENDLY_BODY="Cher/Chère $OWNER_NAME,
We detected a potential hardware issue on your server ($SMARTD_DEVICE).
Don't panic! The administrator has been notified and received the technical details.
They will contact you if any action is required on your part.
Votre serveur a automatiquement détecté une panne matérielle de disque dur.
Ce genre de panne est tout à fait normal selon l'âge de votre matériel et n'entraîne
dans la grande majorité des cas aucune perte de données grâce au système de
stockage redondant préventif.
Your Numbus Server"
Votre administrateur a été notifié de cette panne. Il vous recontactera dans de très
brefs délais afin de procéder au remplacement, si nécessaire, du disque dur défaillant.
Merci de votre confiance,
L'équipe de support,
Numbus-Server."
printf "Subject: [Alert] Hardware check on your server\n\n$FRIENDLY_BODY" | /run/wrappers/bin/sendmail -t "$USER_EMAIL"
printf "Subject: [Alerte] Défaillance matérielle sur votre serveur Numbus\n\n$FRIENDLY_BODY" | /run/wrappers/bin/sendmail -t "$USER_EMAIL"
'';
in
{
@@ -47,7 +54,7 @@ in
mail = {
enable = true;
sender = config.email.fromAddress;
recipient = "${config.email.toAddress},${config.email.adminAddress}";
recipient = "${config.email.userAddress},${config.email.adminAddress}";
};
};
};