Homserver Schnellanleitung
Ich schreibe mir hier nur ein paar Notizen für die Installation eines Homeservers mit FreeBSD auf. Ohne Anspruch auf Vollständigkeit. Als Hardware kann z.B. ein Fujitsu TX1320 M3 dienen: https://watchmysys.com/blog/2023/03/fujitsu-tx1320-m3/
Installation
Zunächst einmal muss FreeBSD vom USB-Stick oder remote per KVM installiert werden.
SSH
Um SSH rudimentär abzusichern, wird die Datei /etc/ssh/sshd_config_custom
erstellt, um ein paar SSH-Einstellungen zu ändern:
PermitRootLogin prohibit-password
PubkeyAuthentication yes
KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org
PasswordAuthentication no
KbdInteractiveAuthentication no
UseBlacklist yes
Include /etc/ssh/sshd_config
Und folgenden Befehl ausführen, um die Custom-Config zu nutzen:
sysrc sshd_flags="-f /etc/ssh/sshd_config_custom"
E-Mailversand
Damit der Server Mails versenden kann, muss ein Smarthost (Relay) konfiguriert werden. Für den E-Mailversand empfehle ich den Dragonfly Mail Agent. Er ist bei FreeBSD im Basissystem. In der Datei /etc/dma/dma.conf
zum Beispiel eintragen:
# Your smarthost (also called relayhost).
SMARTHOST mail.example.com
PORT 587
# SMTP authentication
AUTHPATH /etc/dma/auth.conf
# Uncomment if yout want TLS/SSL support and STARTTLS support
SECURETRANSFER
STARTTLS
# Masquerade envelope from addresses with this address/hostname.
MASQUERADE no-reply@example.com
Außerdem die Zugangsdaten in /etc/dma/auth.conf
in folgender Form ablegen:
no-reply@example.com|mail.example.com:password
Und mit chmod 640 /etc/dma/auth.conf
passende Zugriffsberechtigungen setzen.
Zuletzt in /etc/mail/mailer.conf
(bei FreeBSD 14.2 schon voreingestellt):
# mailer.conf for use with dma(8)
sendmail /usr/libexec/dma
mailq /usr/libexec/dma
newaliases /usr/libexec/dma
Auch nicht vergessen, in /etc/aliases
die gewünschten Mail-Aliases zu setzen!
Hardware
CPU checken
Der verwendete CPU kann mit folgendem Befehl angezeigt werden:
sysctl hw.model hw.machine hw.ncpu
IPMI
Um IPMI zu nutzen, muss das Kernelmodul geladen und die Tools installiert werden:
kldload ipmi
sysrc kld_list+=ipmi
pkg install ipmitools
Dann können z.B. die Sensoren über IPMI abgefragt werden:
ipmitool sensor | cut -f1-4 -d '|'
Stromverbrauch senken
ASPM im BIOS aktivieren und prüfen, ob es von den PCIe-Geräten genutzt wird:
pciconf -lcv | grep ASPM
In die rc.conf
eintragen:
performance_cx_lowest="Cmax"
economy_cx_lowest="Cmax"
Und prüfen, welche C-States tatsächlich genutzt werden:
sysctl dev.cpu | grep cx
USV
Auch für den Homeserver kann man sich eine kleine USV gönnen, z.B. eine günstige Eaton Ellipse ECO. Die verbrät selbst nicht sonderlich viel Strom, lässt sich per USB anschließen und erfüllt ihren Job.
pkg install nut
rm /usr/local/etc/nut/ups.conf
printf "# Set maxretry to 3 by default, this should mitigate race with slow devices:\nmaxretry = 3\n\n" > /usr/local/etc/nut/ups.conf
nut-scanner -U >> /usr/local/etc/nut/ups.conf
Dann die /usr/local/etc/nut/ups.conf
kontrollieren, bzw. editieren. Ich ändere z.B. den Namen der USV schlicht in “ups”.
Es stellt sich die Frage: Soll nur dieser Server heruntergefahren werden (MODE=standalone
) oder sollen sich auch andere Server verbinden können, um bei Stromausfall sicher herunterzufahren (MODE=netserver
). Das muss dann in /usr/local/etc/nut/nut.conf
eingetragen werden:
rm /usr/local/etc/nut/nut.conf
printf "MODE=netserver\n" > /usr/local/etc/nut/nut.conf
rm /usr/local/etc/nut/upsd.conf
printf "LISTEN 127.0.0.1 3493\nLISTEN 10.0.0.10 3493" > /usr/local/etc/nut/upsd.conf
chmod 640 /usr/local/etc/nut/upsd.conf
Jetzt die Monitoring-User mit Passwörtern festlegen:
rm /usr/local/etc/nut/upsd.users
cat << EOF > /usr/local/etc/nut/upsd.users
[admin]
password = mypass
actions = SET
instcmds = ALL
[monuser]
password = pass
upsmon primary
[monclients]
password = pass
upsmon secondary
EOF
chown nut:nut /usr/local/etc/nut/upsd.users
chmod 640 /usr/local/etc/nut/upsd.users
Und schließlich noch das Monitoring einrichten:
sed -i '' '/^#/d; /^$/d' /usr/local/etc/nut/upsmon.conf
printf "MONITOR ups@localhost 1 monuser pass primary\n" >> /usr/local/etc/nut/upsmon.conf
Auf das USV-USB-Gerät müssen die richtigen Berechtigungen gesetzt werden (Schreibzugriff für nut User). Das nut
Paket bringt entsprechende Einstellungen für devfs
mit, deshalb am besten neustarten:
sysrc nut_enable="YES"
reboot
Nach dem Reboot die Berechtigungen prüfen und die USV abfragen:
ls -l /dev/usb/
upsc ups
Standardtools
Ein paar Standardtools für den täglichen Gebrauch installieren:
pkg install nano micro freecolor tmux fish curl git bat zoxide
ZFS und Fileserver
Festplatten
Festplatten sollten mit den smartmontools
, bzw. smartd
überwacht werden:
pkg install smartmontools
Fehlerbehandlung und Benachrichtigung
Den zfsd aktivieren, der einige ZFS-Fehler automatisch behandeln kann, vor allem, wenn man ein Hot-Spare einsetzt:
sysrc zfsd_enable="YES"
ZFS Tuning
Ein paar Infos über ZFS-Tuning finden sich in diesem Tuning-Guide:
ashift 12 4KiB block size
atime off Do not update atime on file read
recordsize 64KiB Smaller record sizes for databases (match the database block size)
recordsize 128Kib Standard usage (mixture of file sizes)
recordsize 1Mb Recommended for large files
compression lz4 Set compression to use the lz4 algorithm
Pool erstellen
Einen Pool auf sechs SATA SSDs erstellen. Das dazugehörige Dataset soll nicht gemountet werden:
zpool create -o ashift=12 -O canmount=off -m none ozzy raidz2 ada0 ada1 ada2 ada3 ada4 ada5
Verschlüsseltes Dataset erstellen
Prinzipiell sollten alle Daten verschlüsselt werden, dann muss man sich bei Verkauf der Festplatten keine Gedanken machen. Dazu in der Keydatei das Passwort speichern und ein verschlüsseltes Dataset erstellen:
mkdir /root/keys
chmod 700 /root/keys
echo "mypassword" > /root/keys/ozzy_encrypted.key
chmod 600 /root/keys/ozzy_encrypted.key
zfs create -o encryption=aes-256-gcm -o keyformat=passphrase -o keylocation=file:///root/keys/ozzy_encrypted.key -o mountpoint=none -o canmount=off ozzy/encrypted
Alle anderen Datasets können dann darunter erstellt werden und sind automatisch verschlüsselt.
Beim Systemstart sollen die Keys automatisch geladen werden:
sysrc zfskeys_enable="YES"
Datasets für Shares erstellen
Für Datasets kann die Recordsize angepasst werden. Dabei ist 128K die Standardgröße, für Datasets mit großen Dateien bietet sich eine größere Recordsize an. Software, die in festen Datensatzgrößen schreibt (z.B. Datenbanken), profitiert von der Verwendung einer passenden Datensatzgröße, z.B. 16K.
- Für mittelgroße Dateien (1-50 MiB): 512K
- Für große Dateien (> 100 MiB): 1M
- Für Disk-Images von Virtuellen Maschinen: 64K
zfs create -o recordsize=128K -o mountpoint=/mnt/dokumente ozzy/encrypted/dokumente
zfs create -o recordsize=512K -o mountpoint=/mnt/fotos ozzy/encrypted/fotos
zfs create -o recordsize=512K -o mountpoint=/mnt/musik ozzy/encrypted/musik
zfs create -o recordsize=1M -o mountpoint=/mnt/videos ozzy/encrypted/videos
Daten migrieren
Daten lassen sich mit syncoid
sehr einfach von einem Server auf den anderen migrieren. syncoid
ist Bestandteil von sanoid
:
pkg install sanoid
Auf dem alten Server z.B. ausführen:
syncoid --no-sync-snap --delete-target-snapshots --recvoptions="o recordsize=512K" ozzy/musik root@newserver:ozzy/encrypted/musik
Samba
Der Homeserver soll natürlich auch als Fileserver dienen. Dazu wird Samba benutzt:
pkg install samba419
- Die Samba-Konfigurationsdatei:
/usr/local/etc/smb4.conf
- Alle Samba-Datenbanken liegen in:
/var/db/samba4
- Alle Logs sind in:
/var/log/samba4
Eine einfache /usr/local/etc/smb4.conf
für den Heimgebrauch erstellen:
[global]
workgroup = WORKGROUP
netbios name = MYSERVER
unix extensions = yes
security = user
encrypt passwords = yes
passdb backend = tdbsam
server signing = mandatory
# Login-Versuche loggen
# log level = 1 auth:3
vfs objects = fruit streams_xattr zfsacl
access based share enum = yes
# DOS attribute stuff
store dos attributes = yes
map hidden = no
map system = no
map archive = no
map readonly = no
# macOS optimization: https://wiki.samba.org/index.php/Configure_Samba_to_Work_Better_with_Mac_OS_X
fruit:metadata = stream
fruit:model = MacSamba
fruit:posix_rename = yes
fruit:veto_appledouble = no
fruit:nfs_aces = no
fruit:wipe_intentionally_left_blank_rfork = yes
fruit:delete_empty_adfiles = yes
[homes]
comment = User %u's Data Share
path = /mnt/homes/%S
browseable = no
valid users = %S
writable = yes
hide unreadable = no
[fotos]
comment = Foto Share
path = /mnt/fotos
writable = yes
hide unreadable = no
[musik]
comment = Musik Share
path = /mnt/musik
writable = yes
hide unreadable = no
[public]
comment = Public Share
path = /mnt/pub
writable = yes
hide unreadable = no
Benutzer erstellen, die Zugriff auf den Samba-Server erhalten sollen:
pw user add -s /usr/sbin/nologin -n usera
pw user add -s /usr/sbin/nologin -n userb
pw user add -s /usr/sbin/nologin -n userc
pw user add -s /usr/sbin/nologin -n userd
Passwörter für Samba erstellen:
smbpasswd -a usera
smbpasswd -a userb
smbpasswd -a userc
smbpasswd -a userd
Samba-Service aktivieren:
sysrc samba_server_enable="YES"
service samba_server start
NFSv4
NFS verwende ich nur, um Ordner mit “öffentlichen” Daten in VMs zu mounten, z.B. die Musiksammlung im Lyrion-Mediaserver. Dazu NFSv4 aktivieren:
sysrc nfs_server_enable="YES"
sysrc nfsv4_server_enable="YES"
sysrc nfsv4_server_only="YES"
sysrc mountd_enable="YES"
Ein ZFS-Dataset readonly freigeben:
zfs set sharenfs=ro ozzy/encrypted/musik
Und eine /etc/exports
erstellen:
# Set nfs sharing in the datasets, e.g. "zfs set sharenfs=ro tank/data"
#
# NFSv4 root filesystem, make sure there are only ZFS datasets mounted below this dir!
V4: /mnt -network 10.0.0.0 -mask 255.255.255.0
Nach dem editieren der /etc/exports
muss mountd
die Datei neu einlesen: service mountd reload
Backup
Backups lassen sich mit restic
erstellen und auf einen externen Server übertragen:
pkg install restic
Siehe dazu https://github.com/thenktor/restic-dataset-backup
Virtualisierung
Auf dem Server sollen die eigentlichen Services in VMs oder Jails ausgeführt werden. Dazu Tools für Virtuelle Maschinen und Jails installieren:
pkg install vm-bhyve bhyve-firmware grub2-bhyve qemu-tools bastille
Netzwerk
Für VMs und Jails ist eine Netzwerkbridge nötig. Die Bridge wird manuell erstellt, damit die Tools das nicht jeweils selbst versuchen:
sysrc cloned_interfaces="bridge0"
sysrc ifconfig_bridge0="inet 10.0.0.10 netmask 255.255.255.0 addm igb0 up"
sysrc ifconfig_igb0="up"
sysrc defaultrouter="10.0.0.1"
VMs mit vm-bhyve
VMs lassen sich mit vm-bhyve verwalten. Als erstes ein Dataset erstellen, in dem die VMs liegen sollen:
zfs create -o recordsize=64K -o mountpoint=/mnt/vm ozzy/encrypted/vm
vm-bhyve aktivieren und das VM-Dataset festlegen:
sysrc vm_enable="YES"
sysrc vm_dir="zfs:ozzy/encrypted/vm"
Die Kosnolenausgabe der VMs soll in tmux erfolgen:
vm set console=tmux
Bridge konfigurieren:
vm switch create -t manual -b bridge0 public
VM Templates kopieren und bearbeiten
cp /usr/local/share/examples/vm-bhyve/* /mnt/vm/.templates
Die Templates kann man dann dort bearbeiten, z.B. die /mnt/vm/.templates/debian.conf
:
loader="grub"
cpu=2
memory=4096M
network0_type="virtio-net"
network0_switch="public"
disk0_type="nvme"
disk0_name="disk0.img"
grub_run_partition="1"
grub_run_dir="/boot/grub"
VM aus img installieren
Um eine VM aus einem vorgefertigten img (Cloud-Images) zu installieren:
vm img https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.raw
vm create -t debian -i debian-12-nocloud-amd64.raw -s 16G debianvm
vm start debianvm
vm console debianvm
Die Cloud-Images haben eine vorgegebene Partitionierung. Um die root-Partition (Partition 1) auf maximale Größe des Geräts (/dev/nvme0n1) zu erweitern, macht man in Debian:
apt install cloud-guest-utils
growpart /dev/nvme0n1 1
Hinweis: Die Debian “nocloud” Images haben cloud-init
nicht installiert, stattdessen erlauben sie root-Login ohne Passwort. Passwort nach dem Login (vm console
) setzen!
VM von iso installieren
vm iso https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.9.0-amd64-netinst.iso
vm create -t debian -s 16G debianvm
vm install debianvm debian-12.9.0-amd64-netinst.iso
vm console debianvm
Jails mit Bastille
Für die Verwaltung der Jails bietet sich das Tool bastille an, das in Shell geschrieben ist und keine weiteren Abhängigkeiten benötigt. Die Konfiguration liegt in /usr/local/etc/bastille/bastille.conf
und kann mit dem Tool sysrc
einfach verwaltet werden.
ZFS aktivieren, den Pool und das Dataset festlegen, das für Bastille genutzt werden soll. Das Dataset wird unter /usr/local/bastille
gemountet:
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_zfs_enable="YES"
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_zfs_zpool="ozzy"
sysrc -f /usr/local/etc/bastille/bastille.conf bastille_zfs_prefix="encrypted/bastille"
Limitierungen
Um Jails zu limitieren, z.B. bei der Speichernutzung, muss RACCT/RCTL im Kernel aktiviert werden. Danach neustarten:
echo "kern.racct.enable=1" > /boot/loader.conf.d/racct.conf
reboot
Image herunterladen
Das aktuellste Jail-Image für das System runterladen:
bastille bootstrap 14.2-RELEASE update
Oder automatisch das aktuellste für das laufende System in der Fish-Shell:
bastille bootstrap (string split -f1 -- '-p' (uname -r)) update
Eine jail erstellen
Eine Jail lässt sich dann folgendermaßen erstellen:
bastille create --bridge myjailname 14.2-RELEASE 10.0.0.123/24 bridge0
Oder mit dem gleichen Image wie das laufende System in der Fish-Shell:
bastille create --bridge myjailname (string split -f1 -- '-p' (uname -r)) 10.0.0.123/24 bridge0