LVM in Debian

LVM bietet unter Debian die fatastische Möglichkeit, Volumes im laufenden Betrieb zu erstellen, formatieren und einzuhängen. Mit Ausnahme des root Systems, können somit alle Volumes verkleinert oder vergrössert werden. Das root System kann im Nachhinein nur mit einem Live-System oder im rescue-Modus verkleinert oder vergrössert werden.

Wichtiger Schritt bei der geführten Partitionierung mittels LVM. Hier wählen wir die Grösse unseres root-Dateisystems. Es macht durchaus Sinn, nur einen kleinen Teil des gesamten Volumes zu verwenden. Alles Anderes kann im Nachhinein erstellt, formatiert und eingehängt werden.

Ist die Installation durch und der Server neu gestartet zeigen wir uns mit lvs alle Volumes an:

# lvs
  LV     VG            Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   example-vg -wi-ao----  <8.36g                                                    
  swap_1 example-vg -wi-ao---- 976.00m

freien Speicherplatz auf der Volumgruppe finden wir mit:

# vgdisplay | grep Free
Free  PE / Size       7259 / <28.36 GiB

in diesem Beispiel stehen uns noch rund 28 GB freier Speicher zu Verfügung. Mittels lvcreate erstellen wir hier ein Volume mit dem Namen volume1 auf der Gruppe example-vg, formatieren dies als ext4 und hängen es unter /mnt ein:

# lvcreate -l 100%FREE -n volume1 example-vg
# mkfs.ext4 /dev/example-vg/volume1
# mount /dev/example-vg/volume1 /mnt

das Volume ist nun unter /mnt eingehängt:

# df -h | grep volume1
/dev/mapper/example--vg-volume1   28G     24K   27G    1% /mnt

Um das Volume permanent einzuhängen muss es unter /etc/fstab eingetragen werden.

Ein paar Beispiele:
Falls dein Server ein rescue-Modus hat, aktiviere diesen. Es ist wesentlich angenehmer, mit einem Live-System oder im rescue-Modus auf dem Server zu arbeiten, wenn Volumes verkleinert oder vergrössert werden müssen. Wird ein Volume vergrössert, muss es danach formatiert werden um den neuen Speicherplatz auch nutzen zu können. Dabei gehen alle Daten verloren. Sei also vorsichtig!

«Logical volume must be activated before resizing filesystem»
Falls diese Meldung erscheint, aktiviere zuerst das LV. Hier am Beispiel mit example-vg/root:

# lvchange -a y /dev/example-vg/root

SWAP auf 2GB vergrössern und anschliessend formatieren:

# lvresize -L 2GB /dev/example-vg/swap_1
# mkswap /dev/example-vg/swap_1
# swapon /dev/example-vg/swap_1

beanspruche allen freien Speicherplatz für volume und formatiere als ext4

# lvcreate -l 100%FREE -n volume example-vg
# mkfs.ext4 /dev/example-vg/volume

Das root-Volume auf 4GB reduzieren:

# lvreduce --resizefs -L 4GB /dev/example-vg/root

muss ich den Server neu starten?

Nicht nach jedem apt update und apt upgrade muss der Server neu gestartet werden. Steht jedoch ein Update vom Kernel an, muss der Server neu gestartet werden. In den Log-Files während des Update gibt es Anzeichen, wann ein Neustart unausweichlich wird. Dann stehen dort typische Infozeilen, welche sich auf den Linuxkernel beziehen wie:

I: /vmlinuz.old is now a symlink to boot/vmlinuz-6.1.0-31-amd64
I: /initrd.img.old is now a symlink to boot/initrd.img-6.1.0-31-amd64
I: /vmlinuz is now a symlink to boot/vmlinuz-6.1.0-32-amd64
I: /initrd.img is now a symlink to boot/initrd.img-6.1.0-32-amd64

oder sowas:

intel-microcode: microcode will be updated at next boot

Übrigens…
falls du dich fragst, warum oben vmlinuz und nicht vmlinux steht, hier die Erklärung:

The kernel binary on ancient AT&T versions was called ‹unix›.
When Berkeley wrote a new kernel with virtual memory, they called it
‹vmunix›. So naturally the Linux kernel is ‹vmlinux› and the
compressed version is ‹vmlinuz› as above.

suchen und ersetzen innerhalb einer Datei

Suchen und ersetzen innerhalb einer Datei geht bequem via Kommandozeile. In diesem Beispiel möchten wir in der Datei datenbank.sql alle 192.168.1.1 durch example.com ersetzen, ohne die Datei in einem Editor zu öffnen.
Der allgemeine Syntax dazu lautet:

$ sed -i -e "s/(suchen)/(ersetzen)/" "(dateiname)"

Angewendet auf unser Beispiel wird dadurch:

$ sed -i -e "s/192.168.1.251/example.com/g" "DATENBANK.sql"

aus https://192.168.1.1 wird dann überall https://example.com. /g steht dabei für global und ersetzt alle Muster in der Datei.

Dateien nach Muster suchen und löschen

In diesem Beispiel entfernen wir unter dem Pfad /pfad/zum/ordner/ alle Dateinamen, welche das Muster «400x» enthalten.

$ ls
(...)
a-super-real-2dfdefa9-7bf6-4d4f-9b79-39b8dc68cdd4-400x250.jpeg
a-super-real-2dfdefa9-7bf6-4d4f-9b79-39b8dc68cdd4-400x284.jpeg
a-super-real-2dfdefa9-7bf6-4d4f-9b79-39b8dc68cdd4-400x516.jpeg
(...)

Abhilfe schafft hier der Befehl find, kombiniert mit rm:

find . /pfad/zum/ordner/ -name "*400x*" -exec rm {} \;

Damit sind alle Dateien gelöscht, welche dem Suchbegriff 400x entsprechen.

rsnapshot für Server

rsnapshot erstellt uns periodisch Schnappschüsse von unserem Server. Installiere das Programm mit:

# apt install rsnapshot

und navigiere zur Konfigurationsdatei unter:

# nano /etc/rsnapshot.conf

Hinweis: alle Einzüge müssen mit der Taste TAB gemacht werden und keinesfalls mit der Space-Taste (Leertaste)

01. Snapshot root directory

hier geben wir das Zielverzeichnis aller snapshots an.
# All snapshots will be stored under this root directory.
#
snapshot_root /BACKUP/snapshot/

02. Backup Levels / Intervals

hier geben wir einmalig den Namen unseres snapshots und den Intervall an, wie viele snapshots aufbewahrt werden
retain snapshot 24

03. include & exclude

include und exclude gibt an, welche Verzeichnisse zusätzlich eingeschlossen oder ausgeschlossen werden. Bei meinen snapshots schliesse ich jeweils den Papierkorb / Trash aus:
exclude Recycled/
exclude Trash/
exclude lost+found/

04. Backup Points / Scripts

# LOCALHOST
backup /etc/ localhost/
backup /var/www/html/ localhost/

05. Script testen

teste das Script mit:

# rsnapshot configtest
Syntax OK
06. Teste den Snapshot mit der Eingabe von:
rsnapshot -t snapshot
07. snapshot mittels crontab ausführen

In diesem Beispiel schreiben wir nun ein Backups-Script und weisen den Crontab an, das Script alle 3 Stunden auszuführen.
Wir erstellen ein Backup-Script mit:

nano backup.sh

# !/bin/bash
rsnapshot snapshot

mache das Script ausführbar:

# chmod +x backup.sh

nun weisen wir dem Crontab zu, das Backupscript aller 3 Stunden auszuführen:

# crontab -e

# snapshot erstellen alle 3 Stunden
0 */3 * * * bash /root/backup.sh
#

rsnapshot erstellt nun alle 3 Stunden einen Snapshot und behält unter Punkt 2 insgesamt 24 Snapshots davon. Danach werden die ältesten Snapshots überschrieben.

Hinweis: das Erstellen des ersten Snapshot kann lange dauern, da ja noch keine ältere Version vorliegt. Die nachfolgenden Snapshots dauern dann in der Regeln ein paar Sekunden. Falls wirklich viele Daten beim ersten Snapshot gespeichert werden müssen, kann der snapshot.0 auch manuell angestossen werden. Dazu startest du einfach das Backup-Script manuell.

Cockpit für Debian (Server)

Cockpit ist ein Webbasiertes Interface für Server. Auf einen Blick kriegen wir so Informationen über die Systemauslastung, Speichermedien, Hardware, Log-Files und vieles mehr.

 

Das Paket wird mit:

# apt install cockpit

installiert und ist danach via Browser erreichbar.
http://123.456.7.890:9090
falls eine Firewall wie ufw läuft, muss Port 9090 freigegeben werden.

Failed to initialize any backend for Jail sshd

Nach der Installation von fail2ban zeigt systemctl status fail2ban folgendes an:

Hinweis (April 2025): Dieser Bug wurde aus Debian entfernt. Das fehlende Paket python3-systemd wird nun aus den Paketquellen automatisch installiert.

# systemctl status fail2ban
× fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Fri 2024-05-03 10:30:22 CEST; 54s ago
   Duration: 163ms
       Docs: man:fail2ban(1)
    Process: 4115 ExecStart=/usr/bin/fail2ban-server -xf start (code=exited, status=255/EXCEPTION)
   Main PID: 4115 (code=exited, status=255/EXCEPTION)
        CPU: 142ms

Mai 03 10:30:22 backup systemd[1]: Started fail2ban.service - Fail2Ban Service.
Mai 03 10:30:22 backup fail2ban-server[4115]: 2024-05-03 10:30:22,685 fail2ban.configreader   [4115]: WARNING 'allowipv6' not defined in 'Definition'. Using default one: 'auto'
Mai 03 10:30:22 backup fail2ban-server[4115]: 2024-05-03 10:30:22,698 fail2ban                [4115]: ERROR   Failed during configuration: Have not found any log file for sshd jail
Mai 03 10:30:22 backup fail2ban-server[4115]: 2024-05-03 10:30:22,702 fail2ban                [4115]: ERROR   Async configuration of server failed
Mai 03 10:30:22 backup systemd[1]: fail2ban.service: Main process exited, code=exited, status=255/EXCEPTION
Mai 03 10:30:22 backup systemd[1]: fail2ban.service: Failed with result 'exit-code'.

Lösung:
1. erstelle die Datei jail.local unter /etc/fail2ban/jail.local und trage folgendes ein:

# nano /etc/fail2ban/jail.local

[sshd]
enabled = true
backend = systemd

2. installiere das Paket python3-systemd:

# apt install python3-systemd

3. starte fail2ban neu:

# systemctl restart fail2ban

docker in Debian installieren

Docker lässt sich in wenigen Schritten installieren. Dafür gehen wir hier den Weg über die repository und erstellen uns ein Installationscript:

# nano docker_install.sh

kopiere nun den Installationscode in das File. Für Debian ist sudo nicht notwendig und wurde im Beispiel entfernt:
# Add Docker's official GPG key:
apt-get update
apt-get install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

speichere das Script ab, mache es ausführbar und starte es:

# chmod +x docker_install.sh
# ./docker_install.sh

überprüfe ob docker läuft:

# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

ein Script erleichtert die Installation von Docker. Es muss nicht alles Zeilenweise abgetippt werden.

Portainer

Zur Verwaltung der Container ist Portainer eine gute Wahlt. Damit könne mittels grafischer Oberfläche im Browser die Container gesteuert werden. Docker läuft bei mir hier auf einem Raspberry Pi 5. Das geniale an Docker ist die schnelle Verfügbarkeit von Entwicklungsumgebungen. So kann innert Sekunden eine Umgebung mit Drupal gestartet werden. Ist man damit fertig, werden die Containers gestoppt. Da wir uns hier im lokalen Netzwerk bewegen, ist eine https-Verbindung absolut nicht notwendig. WordPress, Drupal und Joomla laufen auf Docker im lokalen Netzwerk problemlos auch ohne https.

 

Eine neue Festplatte einhängen

In diesem Beispiel erstellen wir eine Partition mit dem Dateisystem ext4 auf der Festplatte und hängen anschliessend die Festplatte permanent unter /mnt/Volume ein.

01. fdisk -l  zeigt uns alle verfügbaren Laufwerke an. Die Disk unter /dev/sda hat noch keine Partition.

# fdisk -l
# fdisk -l
Disk /dev/sda: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: WDC WD10EZEX-60M
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xc64dfc2f

02. Starte fdisk mittels Angabe der Disk. Dabei gilt:

# fdisk /dev/sda

(o) = erstellt ein neues Disklabel (create a new empty MBR (DOS) partition table)
(n) = erstellt eine neue Partition
(p) = primäre Partition
(w) = schreibt die Änderungen final auf die Disk

# fdisk /dev/sda

Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): o
Created a new DOS (MBR) disklabel with disk identifier 0x7ad53c78.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): ENTER
First sector (2048-1953525167, default 2048): ENTER
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1953525167, default 1953525167): 

Created a new partition 1 of type 'Linux' and of size 931.5 GiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

03. fdisk -l zeigt uns die neu erstellte Partition an:

# fdisk -l
# fdisk -l
(...)
Device     Boot Start        End    Sectors   Size Id Type
/dev/sda1        2048 1953525167 1953523120 931.5G 83 Linux

04. erstelle ein Dateisystem (hier ext4) für die soeben neue Partition /dev/sda1:

# mkfs.ext4 /dev/sda1
# mkfs.ext4 /dev/sda1
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 244190390 4k blocks and 61054976 inodes
Filesystem UUID: 923b9fb1-5760-4125-9c8a-7140c0f15ee2
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
	102400000, 214990848

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

05. Um die Partition dauerhaft einzuhängen, benötigen wir die UUID:

# blkid | grep sda
# blkid | grep /dev/sda
/dev/sda1: UUID="923b9fb1-5760-4125-9c8a-7140c0f15ee2" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="7ad53c78-01"

06. öffne die /etc/fstab:

# nano /etc/fstab

# HDD einhängen
UUID=923b9fb1-5760-4125-9c8a-7140c0f15ee2 /mnt/Volume ext4 defaults 0 2


07. falls nötig, ändere den Benutzer. Aktuell hat hier nur root die Berechtigung:

# chown -cR BENUTZER:BENUTZER /mnt/Volume
# chown -cR BENUTZER:BENUTZER /mnt/Volume/
der Eigentümer von '/mnt/Volume/lost+found' wurde von root:root in BENUTZER:BENUTZER geändert
der Eigentümer von '/mnt/Volume/' wurde von root:root in BENUTZER:BENUTZER geändert

read: Connection reset by peer

Bei meinem neuen Backup-Server binde ich die Pfade jeweils mit sshfs ein und starte rsync. Dabei kam es zu folgender Fehlermeldung:
read: Connection reset by peer
Der ssh-Key benötigt auf dem Server chmod = 600. Besitzer (owner) und Gruppe ist der normale Benutzer.

# chmod 600 KEYFILE