From 372e8007aa59a1b036296094ab604e546dd95e23 Mon Sep 17 00:00:00 2001 From: Andre Date: Wed, 4 Sep 2024 10:39:03 -0400 Subject: [PATCH] Hosts: unretire Haven due to networking problems with Dimaga, rename to 'Hevana' for consistency --- flake.nix | 9 + hosts/Dimaga/default.nix | 1 - hosts/{_retired/Haven => Hevana}/default.nix | 149 +++++--- hosts/Hevana/etc/apcupsd.conf | 333 ++++++++++++++++++ hosts/Hevana/hardware-configuration.nix | 63 ++++ hosts/Hevana/start-services.sh | 26 ++ .../_retired/Haven/hardware-configuration.nix | 62 ---- 7 files changed, 534 insertions(+), 109 deletions(-) rename hosts/{_retired/Haven => Hevana}/default.nix (56%) create mode 100644 hosts/Hevana/etc/apcupsd.conf create mode 100644 hosts/Hevana/hardware-configuration.nix create mode 100644 hosts/Hevana/start-services.sh delete mode 100644 hosts/_retired/Haven/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index 4448405..735b510 100644 --- a/flake.nix +++ b/flake.nix @@ -97,6 +97,15 @@ ]; }; + Hevana = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = defaultModules ++ [ + nixos-hardware.nixosModules.common-cpu-amd-pstate + nixos-hardware.nixosModules.common-gpu-amd + ./hosts/Hevana + ]; + }; + Khanda = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = defaultModules ++ [ diff --git a/hosts/Dimaga/default.nix b/hosts/Dimaga/default.nix index 4692210..71f8039 100644 --- a/hosts/Dimaga/default.nix +++ b/hosts/Dimaga/default.nix @@ -1,6 +1,5 @@ { config, - lib, pkgs, ... }: diff --git a/hosts/_retired/Haven/default.nix b/hosts/Hevana/default.nix similarity index 56% rename from hosts/_retired/Haven/default.nix rename to hosts/Hevana/default.nix index 5f1f68a..7e6e033 100644 --- a/hosts/_retired/Haven/default.nix +++ b/hosts/Hevana/default.nix @@ -1,19 +1,20 @@ -{ pkgs, config, ... }: +{ + config, + pkgs, + ... +}: + let - stateVersion = "24.05"; - hostName = "Haven"; - - start-haven = pkgs.writeShellScriptBin "start-haven" (builtins.readFile ./start-haven.sh); + # Do not change this value! This tracks when NixOS was installed on your system. + stateVersion = "24.11"; + hostName = "Hevana"; + # Where to store service files services-root = "/storage/services"; + # Script to start services + start-services = pkgs.writeShellScriptBin "start-services" (builtins.readFile ./start-services.sh); - subdomains = [ - config.secrets.services.airsonic.url - config.secrets.services.cache.url - config.secrets.services.forgejo.url - config.secrets.services.gremlin-lab.url - ]; - + # Credentials for interacting with the Namecheap API namecheapCredentials = { "NAMECHEAP_API_USER_FILE" = "${pkgs.writeText "namecheap-api-user" '' ${config.secrets.networking.namecheap.api.user} @@ -22,6 +23,15 @@ let ${config.secrets.networking.namecheap.api.key} ''}"; }; + + # List of subdomains to add to the TLS certificate + subdomains = [ + config.secrets.services.deluge.url + config.secrets.services.forgejo.url + config.secrets.services.gremlin-lab.url + config.secrets.services.jellyfin.url + config.secrets.services.netdata.url + ]; in { imports = [ ./hardware-configuration.nix ]; @@ -29,9 +39,45 @@ in system.stateVersion = stateVersion; networking.hostName = hostName; + ###*** Configure your system below this line. ***### + # Set your time zone. + # To see all available timezones, run `timedatectl list-timezones`. + time.timeZone = "America/New_York"; + + # Build Nix packages for other hosts. + # Runs every day at 4 AM + systemd = { + services."build-hosts" = { + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + path = config.aux.system.corePackages; + script = '' + cd ${config.secrets.nixConfigFolder} + nh os build . --hostname Khanda + ''; + }; + timers."build-hosts" = { + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "04:00"; + Persistent = true; + Unit = "build-hosts.service"; + }; + }; + }; + + # Configure the system. aux.system = { - apps.tmux.enable = true; - # Configure the bootloader. + # Enable to allow unfree (e.g. closed source) packages. + # Some settings may override this (e.g. enabling Nvidia GPU support). + # https://nixos.org/manual/nixpkgs/stable/#sec-allow-unfree + allowUnfree = true; + + # Enable Secure Boot support. bootloader = { enable = true; secureboot.enable = true; @@ -41,15 +87,16 @@ in # Change the default text editor. Options are "emacs", "nano", or "vim". editor = "nano"; + # Enable GPU support. gpu.amd.enable = true; - packages = [ - start-haven - pkgs.htop - ]; + packages = [ start-services ]; - # Keep old generations for one month. - retentionPeriod = "monthly"; + # Enable support for primary RAID array + raid.sapana.enable = true; + + # Change how long old generations are kept for. + retentionPeriod = "30d"; services = { acme = { @@ -73,12 +120,6 @@ in enable = true; configText = builtins.readFile ./etc/apcupsd.conf; }; - airsonic = { - enable = true; - home = "${services-root}/airsonic-advanced"; - domain = config.secrets.networking.domains.primary; - url = config.secrets.services.airsonic.url; - }; autoUpgrade = { enable = false; # Don't update the system... pushUpdates = true; # ...but do push updates remotely. @@ -87,14 +128,15 @@ in user = config.users.users.aires.name; }; boinc.enable = true; - cache = { - enable = false; # Disable for now - secretKeyFile = "${services-root}/nix-cache/cache-priv-key.pem"; + deluge = { + enable = true; + home = "${services-root}/deluge"; + domain = config.secrets.networking.domains.primary; + url = config.secrets.services.deluge.url; }; duplicacy-web = { enable = true; - autostart = false; - environment = "/storage/backups/settings/Haven"; + home = "/storage/backups/settings/Haven"; }; forgejo = { enable = true; @@ -106,7 +148,24 @@ in token = config.secrets.services.forgejo.runner-token; }; }; + jellyfin = { + enable = true; + home = "${services-root}/jellyfin"; + domain = config.secrets.networking.domains.primary; + url = config.secrets.services.jellyfin.url; + }; msmtp.enable = true; + netdata = { + enable = true; + domain = config.secrets.networking.domains.primary; + type = "parent"; + url = config.secrets.services.netdata.url; + auth = { + user = config.users.users.aires.name; + password = config.secrets.services.netdata.password; + apiKey = config.secrets.services.netdata.apiKey; + }; + }; nginx = { enable = true; autostart = false; @@ -137,29 +196,27 @@ in }; ssh = { enable = true; - ports = [ config.secrets.hosts.haven.ssh.port ]; + ports = [ config.secrets.hosts.dimaga.ssh.port ]; }; - virtualization = { - host = { + virtualization.host = { + enable = true; + user = "aires"; + vmBuilds = { enable = true; - user = "aires"; - vmBuilds = { - enable = true; - cores = 3; - ram = 4096; - }; + cores = 3; + ram = 4096; }; }; }; + users.aires = { enable = true; - services.syncthing = { - enable = true; - autostart = false; + services = { + syncthing = { + enable = true; + autostart = false; + }; }; }; }; - - # Allow Haven to be a build target for other architectures (mainly ARM64) - boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; } diff --git a/hosts/Hevana/etc/apcupsd.conf b/hosts/Hevana/etc/apcupsd.conf new file mode 100644 index 0000000..fd5b232 --- /dev/null +++ b/hosts/Hevana/etc/apcupsd.conf @@ -0,0 +1,333 @@ +## apcupsd.conf v1.1 ## +# +# for apcupsd release 3.14.12 (29 March 2014) - debian +# +# "apcupsd" POSIX config file + +# +# ========= General configuration parameters ============ +# + +# UPSNAME xxx +# Use this to give your UPS a name in log files and such. This +# is particulary useful if you have multiple UPSes. This does not +# set the EEPROM. It should be 8 characters or less. +#UPSNAME + +# UPSCABLE +# Defines the type of cable connecting the UPS to your computer. +# +# Possible generic choices for are: +# simple, smart, ether, usb +# +# Or a specific cable model number may be used: +# 940-0119A, 940-0127A, 940-0128A, 940-0020B, +# 940-0020C, 940-0023A, 940-0024B, 940-0024C, +# 940-1524C, 940-0024G, 940-0095A, 940-0095B, +# 940-0095C, 940-0625A, M-04-02-2000 +# +UPSCABLE usb + +# To get apcupsd to work, in addition to defining the cable +# above, you must also define a UPSTYPE, which corresponds to +# the type of UPS you have (see the Description for more details). +# You must also specify a DEVICE, sometimes referred to as a port. +# For USB UPSes, please leave the DEVICE directive blank. For +# other UPS types, you must specify an appropriate port or address. +# +# UPSTYPE DEVICE Description +# apcsmart /dev/tty** Newer serial character device, appropriate for +# SmartUPS models using a serial cable (not USB). +# +# usb Most new UPSes are USB. A blank DEVICE +# setting enables autodetection, which is +# the best choice for most installations. +# +# net hostname:port Network link to a master apcupsd through apcupsd's +# Network Information Server. This is used if the +# UPS powering your computer is connected to a +# different computer for monitoring. +# +# snmp hostname:port:vendor:community +# SNMP network link to an SNMP-enabled UPS device. +# Hostname is the ip address or hostname of the UPS +# on the network. Vendor can be can be "APC" or +# "APC_NOTRAP". "APC_NOTRAP" will disable SNMP trap +# catching; you usually want "APC". Port is usually +# 161. Community is usually "private". +# +# netsnmp hostname:port:vendor:community +# OBSOLETE +# Same as SNMP above but requires use of the +# net-snmp library. Unless you have a specific need +# for this old driver, you should use 'snmp' instead. +# +# dumb /dev/tty** Old serial character device for use with +# simple-signaling UPSes. +# +# pcnet ipaddr:username:passphrase:port +# PowerChute Network Shutdown protocol which can be +# used as an alternative to SNMP with the AP9617 +# family of smart slot cards. ipaddr is the IP +# address of the UPS management card. username and +# passphrase are the credentials for which the card +# has been configured. port is the port number on +# which to listen for messages from the UPS, normally +# 3052. If this parameter is empty or missing, the +# default of 3052 will be used. +# +# modbus /dev/tty** Serial device for use with newest SmartUPS models +# supporting the MODBUS protocol. +# +UPSTYPE usb +DEVICE + +# POLLTIME +# Interval (in seconds) at which apcupsd polls the UPS for status. This +# setting applies both to directly-attached UPSes (UPSTYPE apcsmart, usb, +# dumb) and networked UPSes (UPSTYPE net, snmp). Lowering this setting +# will improve apcupsd's responsiveness to certain events at the cost of +# higher CPU utilization. The default of 60 is appropriate for most +# situations. +#POLLTIME 60 + +# LOCKFILE +# Path for device lock file. Not used on Win32. +LOCKFILE /var/lock + +# SCRIPTDIR +# Directory in which apccontrol and event scripts are located. +SCRIPTDIR /etc/apcupsd + +# PWRFAILDIR +# Directory in which to write the powerfail flag file. This file +# is created when apcupsd initiates a system shutdown and is +# checked in the OS halt scripts to determine if a killpower +# (turning off UPS output power) is required. +PWRFAILDIR /etc/apcupsd + +# NOLOGINDIR +# Directory in which to write the nologin file. The existence +# of this flag file tells the OS to disallow new logins. +NOLOGINDIR /etc + + +# +# ======== Configuration parameters used during power failures ========== +# + +# The ONBATTERYDELAY is the time in seconds from when a power failure +# is detected until we react to it with an onbattery event. +# +# This means that, apccontrol will be called with the powerout argument +# immediately when a power failure is detected. However, the +# onbattery argument is passed to apccontrol only after the +# ONBATTERYDELAY time. If you don't want to be annoyed by short +# powerfailures, make sure that apccontrol powerout does nothing +# i.e. comment out the wall. +ONBATTERYDELAY 6 + +# +# Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so +# the first that occurs will cause the initation of a shutdown. +# + +# If during a power failure, the remaining battery percentage +# (as reported by the UPS) is below or equal to BATTERYLEVEL, +# apcupsd will initiate a system shutdown. +BATTERYLEVEL 5 + +# If during a power failure, the remaining runtime in minutes +# (as calculated internally by the UPS) is below or equal to MINUTES, +# apcupsd, will initiate a system shutdown. +MINUTES 5 + +# If during a power failure, the UPS has run on batteries for TIMEOUT +# many seconds or longer, apcupsd will initiate a system shutdown. +# A value of 0 disables this timer. +# +# Note, if you have a Smart UPS, you will most likely want to disable +# this timer by setting it to zero. That way, you UPS will continue +# on batteries until either the % charge remaing drops to or below BATTERYLEVEL, +# or the remaining battery runtime drops to or below MINUTES. Of course, +# if you are testing, setting this to 60 causes a quick system shutdown +# if you pull the power plug. +# If you have an older dumb UPS, you will want to set this to less than +# the time you know you can run on batteries. +TIMEOUT 0 + +# Time in seconds between annoying users to signoff prior to +# system shutdown. 0 disables. +ANNOY 300 + +# Initial delay after power failure before warning users to get +# off the system. +ANNOYDELAY 60 + +# The condition which determines when users are prevented from +# logging in during a power failure. +# NOLOGON [ disable | timeout | percent | minutes | always ] +NOLOGON disable + +# If KILLDELAY is non-zero, apcupsd will continue running after a +# shutdown has been requested, and after the specified time in +# seconds attempt to kill the power. This is for use on systems +# where apcupsd cannot regain control after a shutdown. +# KILLDELAY 0 disables +KILLDELAY 0 + +# +# ==== Configuration statements for Network Information Server ==== +# + +# NETSERVER [ on | off ] on enables, off disables the network +# information server. If netstatus is on, a network information +# server process will be started for serving the STATUS and +# EVENT data over the network (used by CGI programs). +NETSERVER on + +# NISIP +# IP address on which NIS server will listen for incoming connections. +# This is useful if your server is multi-homed (has more than one +# network interface and IP address). Default value is 0.0.0.0 which +# means any incoming request will be serviced. Alternatively, you can +# configure this setting to any specific IP address of your server and +# NIS will listen for connections only on that interface. Use the +# loopback address (127.0.0.1) to accept connections only from the +# local machine. +NISIP 127.0.0.1 + +# NISPORT default is 3551 as registered with the IANA +# port to use for sending STATUS and EVENTS data over the network. +# It is not used unless NETSERVER is on. If you change this port, +# you will need to change the corresponding value in the cgi directory +# and rebuild the cgi programs. +NISPORT 3551 + +# If you want the last few EVENTS to be available over the network +# by the network information server, you must define an EVENTSFILE. +EVENTSFILE /var/log/apcupsd.events + +# EVENTSFILEMAX +# By default, the size of the EVENTSFILE will be not be allowed to exceed +# 10 kilobytes. When the file grows beyond this limit, older EVENTS will +# be removed from the beginning of the file (first in first out). The +# parameter EVENTSFILEMAX can be set to a different kilobyte value, or set +# to zero to allow the EVENTSFILE to grow without limit. +EVENTSFILEMAX 10 + +# +# ========== Configuration statements used if sharing ============= +# a UPS with more than one machine + +# +# Remaining items are for ShareUPS (APC expansion card) ONLY +# + +# UPSCLASS [ standalone | shareslave | sharemaster ] +# Normally standalone unless you share an UPS using an APC ShareUPS +# card. +UPSCLASS standalone + +# UPSMODE [ disable | share ] +# Normally disable unless you share an UPS using an APC ShareUPS card. +UPSMODE disable + +# +# ===== Configuration statements to control apcupsd system logging ======== +# + +# Time interval in seconds between writing the STATUS file; 0 disables +STATTIME 0 + +# Location of STATUS file (written to only if STATTIME is non-zero) +STATFILE /var/log/apcupsd.status + +# LOGSTATS [ on | off ] on enables, off disables +# Note! This generates a lot of output, so if +# you turn this on, be sure that the +# file defined in syslog.conf for LOG_NOTICE is a named pipe. +# You probably do not want this on. +LOGSTATS off + +# Time interval in seconds between writing the DATA records to +# the log file. 0 disables. +DATATIME 0 + +# FACILITY defines the logging facility (class) for logging to syslog. +# If not specified, it defaults to "daemon". This is useful +# if you want to separate the data logged by apcupsd from other +# programs. +#FACILITY DAEMON + +# +# ========== Configuration statements used in updating the UPS EPROM ========= +# + +# +# These statements are used only by apctest when choosing "Set EEPROM with conf +# file values" from the EEPROM menu. THESE STATEMENTS HAVE NO EFFECT ON APCUPSD. +# + +# UPS name, max 8 characters +#UPSNAME UPS_IDEN + +# Battery date - 8 characters +#BATTDATE mm/dd/yy +BATTDATE 07/08/19 + +# Sensitivity to line voltage quality (H cause faster transfer to batteries) +# SENSITIVITY H M L (default = H) +#SENSITIVITY H + +# UPS delay after power return (seconds) +# WAKEUP 000 060 180 300 (default = 0) +#WAKEUP 60 + +# UPS Grace period after request to power off (seconds) +# SLEEP 020 180 300 600 (default = 20) +#SLEEP 180 + +# Low line voltage causing transfer to batteries +# The permitted values depend on your model as defined by last letter +# of FIRMWARE or APCMODEL. Some representative values are: +# D 106 103 100 097 +# M 177 172 168 182 +# A 092 090 088 086 +# I 208 204 200 196 (default = 0 => not valid) +#LOTRANSFER 208 + +# High line voltage causing transfer to batteries +# The permitted values depend on your model as defined by last letter +# of FIRMWARE or APCMODEL. Some representative values are: +# D 127 130 133 136 +# M 229 234 239 224 +# A 108 110 112 114 +# I 253 257 261 265 (default = 0 => not valid) +#HITRANSFER 253 + +# Battery charge needed to restore power +# RETURNCHARGE 00 15 50 90 (default = 15) +#RETURNCHARGE 15 + +# Alarm delay +# 0 = zero delay after pwr fail, T = power fail + 30 sec, L = low battery, N = never +# BEEPSTATE 0 T L N (default = 0) +BEEPSTATE N + +# Low battery warning delay in minutes +# LOWBATT 02 05 07 10 (default = 02) +#LOWBATT 2 + +# UPS Output voltage when running on batteries +# The permitted values depend on your model as defined by last letter +# of FIRMWARE or APCMODEL. Some representative values are: +# D 115 +# M 208 +# A 100 +# I 230 240 220 225 (default = 0 => not valid) +#OUTPUTVOLTS 230 + +# Self test interval in hours 336=2 weeks, 168=1 week, ON=at power on +# SELFTEST 336 168 ON OFF (default = 336) +#SELFTEST 336 diff --git a/hosts/Hevana/hardware-configuration.nix b/hosts/Hevana/hardware-configuration.nix new file mode 100644 index 0000000..25231f7 --- /dev/null +++ b/hosts/Hevana/hardware-configuration.nix @@ -0,0 +1,63 @@ +# Minisforum UM340 +{ modulesPath, ... }: +let + bootUUID = "0120-A755"; # The UUID of the boot partition. + luksUUID = "2c76c660-3573-4622-8771-f23fa7ee302a"; # The UUID of the locked LUKS partition. +in +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot = { + supportedFilesystems = [ "btrfs" ]; + kernelModules = [ "kvm-amd" ]; + + initrd = { + supportedFilesystems = [ "btrfs" ]; + availableKernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "usb_storage" + "usbhid" + "sd_mod" + "btrfs" + ]; + kernelModules = [ ]; + }; + + # Enable support for building ARM64 packages + binfmt.emulatedSystems = [ "aarch64-linux" ]; + }; + + # Configure the main filesystem. + aux.system.filesystem = { + enable = true; + partitions = { + boot = "/dev/disk/by-uuid/${bootUUID}"; + luks = "/dev/disk/by-uuid/${luksUUID}"; + }; + swapFile = { + enable = true; + size = 16384; + }; + }; + + # Automatically scrub the RAID array monthly + systemd.services."raid-scrub" = { + description = "Periodically scrub RAID volumes for errors."; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + script = "echo check > /sys/block/md127/md/sync_action"; + }; + systemd.timers."raid-scrub" = { + description = "Periodically scrub RAID volumes for errors."; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = "monthly"; + Persistent = true; + Unit = "raid-scrub.service"; + }; + }; +} diff --git a/hosts/Hevana/start-services.sh b/hosts/Hevana/start-services.sh new file mode 100644 index 0000000..e80969a --- /dev/null +++ b/hosts/Hevana/start-services.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Script to unlock the /storage partition and start up services that depend on it. + +# check if the current user is root +if [ "$(id -u)" != "0" ]; then + echo "This script must be run as root" 1>&2 + exit 1 +fi + +# Unlock and mount storage directory if we haven't already +if [ -e "/dev/mapper/storage" ]; then + echo "Storage partition already mounted." +else + echo "Unlocking storage partition..." + cryptsetup luksOpen /dev/md/Sapana storage + mount /dev/mapper/storage /storage + echo "Storage partition mounted." +fi + +echo "Starting services..." +systemctl restart deluged.service delugeweb.service duplicacy-web.service forgejo.service jellyfin.service +systemctl --machine aires@.host --user start syncthing.service +systemctl restart nginx.service +echo "Services started. $(hostname) is ready to go!" + +exit 0 diff --git a/hosts/_retired/Haven/hardware-configuration.nix b/hosts/_retired/Haven/hardware-configuration.nix deleted file mode 100644 index 8ab9605..0000000 --- a/hosts/_retired/Haven/hardware-configuration.nix +++ /dev/null @@ -1,62 +0,0 @@ -# Minisforum UM340 -{ config, modulesPath, ... }: -{ - imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - - boot = { - supportedFilesystems = [ "btrfs" ]; - kernelModules = [ "kvm-amd" ]; - - initrd = { - supportedFilesystems = [ "btrfs" ]; - availableKernelModules = [ - "nvme" - "xhci_pci" - "ahci" - "usb_storage" - "usbhid" - "sd_mod" - "btrfs" - ]; - kernelModules = [ ]; - }; - - # Enable mdadm for Sapana (RAID 5 primary storage). - swraid = { - enable = true; - mdadmConf = '' - ARRAY /dev/md/Sapana metadata=1.2 UUID=51076daf:efdb34dd:bce48342:3b549fcb - MAILADDR ${config.secrets.users.aires.email} - ''; - }; - }; - - fileSystems = { - "/" = { - device = "/dev/disk/by-uuid/2c76c660-3573-4622-8771-f23fa7ee302a"; - fsType = "btrfs"; - options = [ "subvol=@,compress=zstd,discard" ]; - }; - "/home" = { - device = "/dev/disk/by-uuid/2c76c660-3573-4622-8771-f23fa7ee302a"; - fsType = "btrfs"; - options = [ "subvol=@home,compress=zstd,discard" ]; - }; - "/swap" = { - device = "/dev/disk/by-uuid/2c76c660-3573-4622-8771-f23fa7ee302a"; - fsType = "btrfs"; - options = [ "subvol=@swap" ]; - }; - "/boot" = { - device = "/dev/disk/by-uuid/0120-A755"; - fsType = "vfat"; - }; - }; - - swapDevices = [ - { - device = "/swap/swapfile"; - size = 16384; - } - ]; -}