====== Verschlüsselter Docker-Server thinc ======
Siehe [[computer:debian:hp-thinclient:ritter.local]]
Hardware: HP t520 thin client mit 120GB SSD
OS: debian-bookworm
* Minimum-Installation
* Alle Updates
apt update && apt upgrade
apt install \
vim \
openssh-server \
dropbear-initramfs \
apache2-utils \
mc \
rcs \
rsync \
swaks \
ufw \
inetutils-tools \
net-tools \
fuse \
at \
samba \
nullmailer \
mailutils \
hdparm \
sudo \
golang \
ethtool \
hwinfo \
hdparm \
pv \
gdu \
iw wpasupplicant wireless-tools
====== springm zur Gruppe sudoers hinzufügen ======
su -
usermod -aG sudo springm
Achtung: wird erst nach ausloggen wirksam
Netzwerk: *.zalmoxis.aberdoch.de registriert
Boot-Disk verschlüsseln
====== ssh passwordless login ======
ssh-copy-id -i .ssh/id_ecdsa.pub 192.168.2.251
ssh zalmoxis
sudo cp ~/.ssh/authorized_keys /root/.ssh
====== dropbear-initramfs ======
Entsprechend c't-Artikel {{ :computer:luks_verschluesselte_linux-systeme_ueber_ssh_entsperren_c_t_magazin.pdf |}}
Die ssh-public-keys der Benutzer, die das System per ssh entsperren sollen können, liegen in ''/etc/dropbear/initramfs/authorized_keys'' (kopieren von hermes...).
Minimum-Inhalt für die Konfigurationsdatei:
#
# Command line options to pass to dropbear(8)
#
DROPBEAR_OPTIONS="-p 20022 -c cryptroot-unlock"
Die ''.ssh/authorized_keys'' von springm nach ''/root/.ssh'' kopieren
sudo cp ~springm/.ssh/authorized_keys /root/.ssh
Nach Änderung muss das initramfs aktualisiert werden:
update-initramfs -u
Entsperren mit ''ssh -v -p 20022 ''
Das ganze mit Wifi:
* https://www.marcfargas.com/2017/12/enable-wireless-networks-in-debian-initramfs/
* https://www.dwarmstrong.org/remote-unlock-dropbear/
===== Wifi in initramfs einschalten =====
Wird gebraucht um später die Platte nach dem Booten über WLAN entschlüsseln zu können.
Rezept von https://www.marcfargas.com/2017/12/enable-wireless-networks-in-debian-initramfs/ ( {{ :computer:hp-thinclient:enable_wireless_networks_in_debian_initramfs_marcfargas.com.pdf |}} )
wlan0 beim Boot bekanntmachen:
...
GRUB_CMDLINE_LINUX="net.ifnames=0 ip=:::::wlan0:dhcp"
...
Benötigte Module für das initramfs
rtlwifi
rtl8xxxu
mac80211
usbcore
rtl8192eu_nic.bin
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /scripts/functions
AUTH_LIMIT=30
INTERFACE="wlan0"
alias WPACLI="/sbin/wpa_cli -p /tmp/wpa_supplicant -i $INTERFACE "
log_begin_msg "Starting WLAN connection"
### mws
rmmod rtl8xxxu
modprobe rtl8xxxu
sleep 2
### end mws
/sbin/wpa_supplicant -i $INTERFACE -c /etc/wpa_supplicant.conf -P /run/initram-wpa_supplicant.pid -B -f /tmp/wpa_supplicant.log
# Wait for AUTH_LIMIT seconds, then check the status
limit=${AUTH_LIMIT}
echo -n "Waiting for connection (max ${AUTH_LIMIT} seconds)"
while [ $limit -ge 0 -a `WPACLI status | grep wpa_state` != "wpa_state=COMPLETED" ]
do
sleep 1
echo -n "."
limit=`expr $limit - 1`
done
echo ""
if [ `WPACLI status | grep wpa_state` != "wpa_state=COMPLETED" ]; then
ONLINE=0
log_failure_msg "WLAN offline after timeout"
panic
else
ONLINE=1
log_success_msg "WLAN online"
fi
configure_networking
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
echo "Killing wpa_supplicant so the system takes over later."
kill `cat /run/initram-wpa_supplicant.pid`
Eintrag in /etc/network/interfaces
...
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
...
Passwort in /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=/run/wpa_supplicant
update_config=1
network={
ssid="Your ESSID"
psk=langundverschlüsselt
}
Die wpa_supplicant.conf findet sich identisch an 3 verschiedenen Stellen :(
* /etc/wpa_supplicant.conf
* /etc/wpa_supplicant/wpa_supplicant.conf
* /etc/initramfs-tools/wpa_supplicant.conf
==== ESSID und/oder Wifi-Passwort ändern ====
wpa_passphrase "Eleven Ways" wifipassword >> /etc/wpa_supplicant.conf
/etc/wpa_supplicant.conf editieren und alte Konfiguration auskommentieren
rm /etc/wpa_supplicant/wpa_supplicant.conf
cp -l /etc/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf
rm /etc/initramfs-tools/wpa_supplicant.conf
cp -l /etc/wpa_supplicant.conf /etc/initramfs-tools/wpa_supplicant.conf
Kontrollieren auf Gleichheit mit
sum $(find / -name wpa_supplicant.conf -not -path "/backupdisk")
Dann initramfs neu erstellen
update-initramfs -u -k all
==== Wlan als Dienst starten ====
Nach dem Entsperren wird das Wlan über einen Dienst gestartet ( https://www.skerit.com/en/configure-wifi-on-minimal-debian-11-server )
{{ :computer:hp-thinclient:configure_wifi_on_a_minimal_debian_11_server_skeritcom.pdf |}}
[Unit]
Description=DHCP Client
Before=network.target
After=wpa_supplicant.service
[Service]
Type=forking
ExecStart=/sbin/dhclient wlan0 -v
ExecStop=/sbin/dhclient wlan0 -r
Restart=always
[Install]
WantedBy=multi-user.target
Starten mit
systemctl enable dhclient
systemctl restart wpa_supplicant
systemctl restart networking
Kontrollieren mit
ip a
===== ufw =====
ufw allow proto tcp from any to any port 22,80,139,443,445
ufw allow proto udp from any to any port 137,138
ufw enable
===== email senden =====
Emails sollen für Statusmails versendet werden können. Nullmailer ist einfach, 3 Konfigurationsdateien stehen in ''/etc/nullmailer''
Links
* https://wiki.debian.org/nullmailer
* https://dan.langille.org/2013/10/16/using-nullmailer-instead-of-a-full-blown-mail-server/
===== debian packages sichern (und später wiederherstellen) =====
von https://unix.stackexchange.com/questions/79125/reinstalling-all-debian-packages
dpkg --get-selections | grep -v deinstall | awk '{print $1}' | awk '$1=$1' ORS=' ' > /etc/installed_debs.txt
kommt in die /etc/crontab.
Restore erfolgt dann mit
apt-get clean && apt-get update && apt-get install --reinstall $(/etc/installed_debs.txt)
===== docker =====
from https://computingforgeeks.com/how-to-install-docker-on-debian-12-bookworm/
sudo apt install -y \
lsb-release \
gnupg2 \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/debian.gpg
add-apt-repository "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt update
apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
usermod -aG docker springm
newgrp docker
systemctl status docker
docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabl>
Active: active (running) since Mon 2023-08-28 15:07:09 CEST; 27s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 9365 (dockerd)
Tasks: 9
Memory: 29.0M
CPU: 1.391s
CGroup: /system.slice/docker.service
└─9365 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/cont>
Aug 28 15:07:04 debian-thinc systemd[1]: Starting docker.service - Docker Appli>
Aug 28 15:07:04 debian-thinc dockerd[9365]: time="2023-08-28T15:07:04.749035874>
Aug 28 15:07:06 debian-thinc dockerd[9365]: time="2023-08-28T15:07:06.254635497>
Aug 28 15:07:08 debian-thinc dockerd[9365]: time="2023-08-28T15:07:08.360733123>
Aug 28 15:07:08 debian-thinc dockerd[9365]: time="2023-08-28T15:07:08.565571357>
Aug 28 15:07:08 debian-thinc dockerd[9365]: time="2023-08-28T15:07:08.566231451>
Aug 28 15:07:09 debian-thinc dockerd[9365]: time="2023-08-28T15:07:09.476426543>
Aug 28 15:07:09 debian-thinc systemd[1]: Started docker.service - Docker Applic>
docker version
Client: Docker Engine - Community
Version: 24.0.5
API version: 1.43
Go version: go1.20.6
Git commit: ced0996
Built: Fri Jul 21 20:35:35 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 24.0.5
API version: 1.43 (minimum version 1.12)
Go version: go1.20.6
Git commit: a61e2b4
Built: Fri Jul 21 20:35:35 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.22
GitCommit: 8165feabfdfe38c65b599c4993d227328c231fca
runc:
Version: 1.1.8
GitCommit: v1.1.8-0-g82f18fe
docker-init:
Version: 0.19.0
GitCommit: de40ad0
==== lazydocker ====
https://github.com/jesseduffield/lazydocker
go install github.com/jesseduffield/lazydocker@latest
mv /root/go /usr/local
ln -s /usr/local/go/bin/lazydocker /usr/local/bin
==== Docker-Dienste ====
=== Traefik ===
=== pihole ===
=== restic-restserver ===
=== resticinfo ===
=== mailserver ===
=== calibre ===
===== Wake-on-Lan =====
* https://wiki.debian.org/WakeOnLan
* https://www.thomas-krenn.com/de/wiki/Wake_on_LAN_unter_Linux
Datei ''/etc/network/interfaces.d/enp1s0'' erzeugen:
auto enp1s0
iface enp1s0 inet dhcp
ethernet-wol g
booten um die Änderung wirksam zu machen.
===== Zeitgesteuert schlafen/aufwachen =====
von https://www.baeldung.com/linux/auto-suspend-wake
Achtung: Mit Verschlüsselung funktioniert nur suspend-to-memory
===== Traefik =====
Traefik ist der router für die Docker-Container. Da alle Dienste nur im LAN zur Verfügung stehen, müssen dafür *keine* Zertifikate zur Verfügung gestellt werden.
===== pihole =====
# from https://codecaptured.com/blog/self-hosting-pi-hole-with-docker-and-traefik/
# adapted for usage of .env file
version: "3"
services:
pihole:
image: pihole/pihole:latest
container_name: pihole
restart: always
ports:
- "53:53/tcp"
- "53:53/udp"
dns:
- 127.0.0.1
- 9.9.9.9
environment:
TZ: 'Europe/Berlin'
WEBPASSWORD: ${WEBPASSWORD}
PIHOLE_DNS_: 9.9.9.9;149.112.112.112;1.1.1.1
DNSSEC: 'true'
ServerIP: ${SERVERIP}
VIRTUAL_HOST: ${VIRTUAL_HOST}
DNSMASQ_LISTENING: all
DHCP_ACTIVE: ${DHCP_ACTIVE}
DHCP_START: ${DHCP_START}
DHCP_END: ${DHCP_END}
DHCP_ROUTER: ${DHCP_ROUTER}
DHCP_LEASETIME: ${DHCP_LEASETIME}
WEBTHEME: default-dark
PIHOLE_DOMAIN: ${PIHOLE_DOMAIN}
volumes:
- './services/pihole:/etc/pihole/'
- './services/dnsmasq.d:/etc/dnsmasq.d/'
cap_add:
- NET_ADMIN
restart: unless-stopped
networks:
lan: {}
backend:
ipv4_address: ${BACKEND_IPV4_ADDRESS}
labels:
- "traefik.enable=true"
- "traefik.http.routers.pihole.rule=Host(`${VIRTUAL_HOST}`)"
- "traefik.http.services.pihole.loadbalancer.server.port=80"
- "traefik.http.routers.pihole.entrypoints=web"
depends_on:
- dhcphelper
dhcphelper:
image: noamokman/dhcp-helper
container_name: dhcp-helper
restart: unless-stopped
network_mode: "host"
command: -s ${BACKEND_IPV4_ADDRESS}
cap_add:
- NET_ADMIN
networks:
backend:
ipam:
config:
- subnet: ${BACKEND_SUBNET}
lan:
external: true
PIHOLE_DOMAIN=
WEBPASSWORD=
# Actual server IP. Matches DHCP conf file IP
SERVERIP=
# Same as port traefik config
VIRTUAL_HOST=
DHCP_ACTIVE=
DHCP_START=
DHCP_END=
DHCP_ROUTER=
DHCP_LEASETIME=
BACKEND_IPV4_ADDRESS=
BACKEND_SUBNET=
* https://codecaptured.com/blog/self-hosting-pi-hole-with-docker-and-traefik/
* https://github.com/mirdaki/computer-config/blob/blog-pihole/services/local/README.md
* https://jurian.slui.mn/posts/pi-hole-web-interface-behind-traefik/
==== dnscrypt-proxy ====
Vorher die Versionsnummer von https://github.com/DNSCrypt/dnscrypt-proxy/releases holen
cd /opt/ && \
wget https://github.com/DNSCrypt/dnscrypt-proxy/releases/download/2.1.5/dnscrypt-proxy-linux_x86_64-2.1.5.tar.gz && \
tar xvzf dnscrypt-proxy-linux_x86_64-2.1.5.tar.gz
cd linux-x86_64/
cp ~springm/dnscrypt-proxy/dnscrypt-proxy.toml .
sudo ./dnscrypt-proxy -service install
sudo ./dnscrypt-proxy -service start
===== Backup =====
Das Backup passiert mit Restic: https://restic.net
Das binary liegt in ''/usr/local/bin''
Backups erfolgen in das Verzeichnis ''/backupdisk/restic-repo''
Das restic-Passwort für das Restic-Repository wird in ''/root/resticpw'' gespeichert.
==== Eigenes Backup ====
#!/bin/bash
export RESTIC_REPOSITORY=/backupdisk/restic-repo
export RESTIC_PASSWORD_FILE=/root/resticpw
export RESTIC_EXCLUDE_FILE=/root/restic_exclude
export HOME=/root
/usr/local/bin/restic backup /root /etc /usr/local/bin /usr/local/sbin /home/springm/docker
Zu starten via cron, ebenso ''restic forget''
==== Restic-Server ====
Der restic-Server läuft in einem docker-Container unter der URL ''http://resticserver.ritter.local''
==== Restic-Info ====
Läuft in einem Docker-Containern. Liest die JSON-Datei aus ''/var/lib/restic/snapshots.json''
''/var/lib/restic/snapshots.json'' wird per inotify bei Änderungen im Verzeichnis ''/backupdisk/restic-repo/snapshots'' erzeugt.
Die Informationen stehen unter der URL http://resticinfo.ritter.local zur Verfügung.
=== Erzeugen der /var/lib/restic/snapshots.json ===
Ein inotify-Eintrag auf das snapshots-Verzeichnis im Restic-Repository triggert das Schreiben einer JSON-Zustandsdatei mit dem Befehl
restic snapshots -c --json > /var/lib/restic/snapshots.json
Dieser Befehl ist zusammen mit dem Restic-Passwort und dem Repository in ''/usr/local/sbin/restic_snapshots_json.sh'' niedergelegt:
#!/bin/bash
/usr/bin/date >> /tmp/restic_monitoring.log
export RESTIC_REPOSITORY=/backupdisk/restic-repo
export RESTIC_PASSWORD_FILE=/root/resticpw
export HOME=/root
#/usr/local/bin/restic snapshots -c --json
/usr/local/bin/restic snapshots -c --json > /var/lib/restic/snapshots.json 2>>/tmp/restic_monitoring.log
Die Automatisierung erfolgt über einen systemd-Service (vgl. https://www.putorius.net/systemd-path-units.html)
[Unit]
Description="Monitor restic snapshots for changes"
[Path]
PathModified=/backupdisk/restic-repo/snapshots/
Unit=restic-snapshots-mon.service
[Install]
WantedBy=multi-user.target
[Unit]
Description="Recreate /var/lib/restic/snapshots.json when snapshots have changed"
[Service]
ExecStart=/usr/local/sbin/restic_snapshots_json.sh
#!/bin/bash
/usr/bin/date >> /tmp/restic_monitoring.log
export RESTIC_REPOSITORY=/backupdisk/restic-repo
export RESTIC_PASSWORD_FILE=/root/resticpw
export HOME=/root
/usr/local/bin/restic snapshots -c --json > /var/lib/restic/snapshots.json 2>>/tmp/restic_monitoring.log
Analysieren mit ''systemd-analyze verify /etc/systemd/system/restic-snapshots-mon*''
Starten mit ''systemctl start restic-snapshots-mon.path''
Beim Systemstart hochfahren mit ''systemctl enable restic-snapshots-mon.path''
Status überprüfen mit ''systemctl status restic-snapshots-mon.path''
Log-Einträge ansehen mit ''journalctl -u restic-snapshots-mon.path''
Erzeugen der ''/var/lib/restic/snapshots.json'' beim booten durch einen cron-eintrag
@reboot root /usr/local/sbin/restic_snapshots_json.sh
==== Backuptree für Kontrolle und Restore ====
Backups werden readonly im Verzeichnis ''/restic_restore'' zur Verfügung gestellt.
Der restic-mount-Prozess wird täglich zu einer festgesetzten Zeit gekillt und neu gestartet, damit die neuesten Änderungen sichtbar werden.
/etc/crontab ruft regelmäßig folgendes Script auf:
#!/bin/bash
#chmod 755 /restic-restore
/usr/bin/umount /restic-restore
sleep 3
/usr/local/bin/restic -r /backupdisk/restic-repo/ \
-p /root/resticpw \
mount \
--allow-other \
--no-default-permissions \
--no-lock \
/restic-restore
Links:
* https://wiki.debian.org/Samba/ServerSimple
* https://www.thomas-krenn.com/en/wiki/Simple_Samba_Shares_in_Debian
* https://superuser.com/questions/1069044/how-to-set-up-anonymous-read-only-samba-shares