Home

ITA - debian installazione headless

linux debian

Introduzione

Negli ultimi giorni mi è capitato di acquistare un server remoto e di doverlo installare senza l’uso della console di amministrazione.

Di seguito racconto il percorso che ho seguito.

Processo di installazione

Passo 1 - avvio del sistema

Per poter procedere è necessario avviare il server in modalità rescue ( in altre parole usando una live image messa a disposizione del fornitore ) via ssh; in questa maniera saremo completamente liberi di operare senza nessun impaccio.

Passo 2 - partizionamento dei dischi

schema di partizionamento1

Per garantire mia privacy e la sicurezza del sistema su una piattaforma remota ho deciso di criptare l’intero sistema; il server dispone di un unico disco rigido che verrà formattato cosi:

partizione mount fs note
sda2 /boot ext4 partizione di boot
sda1      
  /dev/mapper/sys_crypt cryopto partizione cryptata
  /dev/mapper/sys_lvm/root ext4 lvm
  /dev/mapper/sys_lvm/swap   lvm
  /dev/mapper/sys_lvm/data ext4 lvm

In parole: ci saranno due partizioni fisiche: la prima conterrà le informazioni di boot, la seconda sarà cryptata con LUKS e conterrà un array lvm con il resto delle partizioni.

In questa maniera configurando correttamente dropbear ( vedi passo 5 ) quando il server si avvia sarà possibile connettersi via ssh e inserire la password per decriptare le partizioni di sistema e sbloccare il processo di avvio.

Procedura

Lanciamo il tool di partizionamento:

root@rescue:~# cfdisk /dev/sda

fino ad ottenere:

cfdic

Controlliamo il risultato con il comando:

root@rescue:~# lsblk 
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  1.8T  0 disk 
├─sda2   8:2    0  512M  0 part 
├─sda3   8:3    0    2M  0 part 
└─sda1   8:1    0  1.8T  0 part 
root@rescue:~# 

Preparazione della partizione di boot

Formatto la partizione in ext4:

root@rescue:~# mkfs.ext4 /dev/sda2
mke2fs 1.42.12 (29-Aug-2014)
/dev/sda2 contains a swap file system labelled 'swap-sda2'
Proceed anyway? (y,n) y
Creating filesystem with 131072 4k blocks and 32768 inodes
Filesystem UUID: e1abb7d2-f112-4a39-aa85-171cccda3d47
Superblock backups stored on blocks: 
	32768, 98304

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

root@rescue:~# 

Preparazione delle partizioni di sistema

Per questa fase ho fatto riferimento alla bellissima documentazione da archwiki:

Inizio con il creare la partizione cryptata:

root@rescue:~# cryptsetup luksFormat /dev/sda1

WARNING!
========
This will overwrite data on /dev/sda1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
Verify passphrase: 
root@rescue:~# cryptsetup luksOpen /dev/sda1 sys_crypt
Enter passphrase for /dev/sda1: 
root@rescue:~# lsblk 
NAME          MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sda             8:0    0  1.8T  0 disk  
├─sda2          8:2    0  512M  0 part  
├─sda3          8:3    0    2M  0 part  
└─sda1          8:1    0  1.8T  0 part  
  └─sys_crypt 251:0    0  1.8T  0 crypt 
root@rescue:~# 

Quando il sistema chiede la password :

Enter passphrase 

Ho inserito la chiave di decriptazione generata con il comando pwgen, questa stringa va conservata con cura.

Il passo successivo consiste nella creazione dei volumi lvm:

Volume fisico

root@rescue:~# pvcreate /dev/mapper/sys_crypt
  Physical volume "/dev/mapper/sys_crypt" successfully created
root@rescue:~#  pvdisplay -v -m
    DEGRADED MODE. Incomplete RAID LVs will be processed.
    Scanning for physical volume names
  "/dev/mapper/sys_crypt" is a new physical volume of "1.82 TiB"
  --- NEW Physical volume ---
  PV Name               /dev/mapper/sys_crypt
  VG Name               
  PV Size               1.82 TiB
  Allocatable           NO
  PE Size               0   
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               hUuzwh-Jrmz-ymLi-celV-HE2k-8324-bjPfk9

Gruppo di volumi fisici

root@rescue:~# vgcreate syslvm /dev/mapper/sys_crypt
  Volume group "syslvm" successfully created
root@rescue:~# vgdisplay 
  --- Volume group ---
  VG Name               syslvm
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               1.82 TiB
  PE Size               4.00 MiB
  Total PE              476802
  Alloc PE / Size       0 / 0   
  Free  PE / Size       476802 / 1.82 TiB
  VG UUID               sDXdXw-sK3W-ffH3-U0i0-6D2u-r0GV-czDRt4

Volumi logici

root@rescue:~# lvcreate -L 50G syslvm -n root
  Logical volume "root" created
root@rescue:~# lvcreate -L 4G syslvm -n swapp
  Logical volume "swapp" created
root@rescue:~# lvcreate -l 100%FREE syslvm -n data
  Logical volume "data" created
root@rescue:~# lvdisplay 
  --- Logical volume ---
  LV Path                /dev/syslvm/root
  LV Name                root
  VG Name                syslvm
  LV UUID                AVQOKX-2N4B-iz5P-QIUp-OJOI-zwEl-bjj91j
  LV Write Access        read/write
  LV Creation host, time rescue.ovh.net, 2021-06-02 10:17:11 +0200
  LV Status              available
  # open                 0
  LV Size                50.00 GiB
  Current LE             12800
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           251:1
   
  --- Logical volume ---
  LV Path                /dev/syslvm/swapp
  LV Name                swapp
  VG Name                syslvm
  LV UUID                S99dgF-ly5i-PbQN-iPZQ-Gmbc-oCHV-TW3e22
  LV Write Access        read/write
  LV Creation host, time rescue.ovh.net, 2021-06-02 10:17:22 +0200
  LV Status              available
  # open                 0
  LV Size                4.00 GiB
  Current LE             1024
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           251:2
   
  --- Logical volume ---
  LV Path                /dev/syslvm/data
  LV Name                data
  VG Name                syslvm
  LV UUID                pOn7MH-u0zB-09bD-wtsK-qgdU-1HZh-E3dYOy
  LV Write Access        read/write
  LV Creation host, time rescue.ovh.net, 2021-06-02 10:17:42 +0200
  LV Status              available
  # open                 0
  LV Size                1.77 TiB
  Current LE             462978
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           251:3
   
root@rescue:~# 

Al termine di questi passaggi ho ottenuto una struttura simile:

root@rescue:~# lsblk 
NAME               MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sda                  8:0    0  1.8T  0 disk  
├─sda2               8:2    0  512M  0 part  
├─sda3               8:3    0    2M  0 part  
└─sda1               8:1    0  1.8T  0 part  
  └─sys_crypt      251:0    0  1.8T  0 crypt 
    ├─syslvm-root  251:1    0   50G  0 lvm   
    ├─syslvm-swapp 251:2    0    4G  0 lvm   
    └─syslvm-data  251:3    0  1.8T  0 lvm   
root@rescue:~#

Poi procedo con la formattazione:

root@rescue:~# mkfs.ext4 /dev/mapper/syslvm-root 
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 13107200 4k blocks and 3276800 inodes
Filesystem UUID: 6d3601f8-67c8-493a-8808-3b78f3edd398
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000, 7962624, 11239424

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

root@rescue:~# mkfs.ext4 /dev/mapper/syslvm-data 
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 474089472 4k blocks and 118530048 inodes
Filesystem UUID: c548c7aa-dea2-437d-bb8f-66da7e4db447
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 (32768 blocks): done
Writing superblocks and filesystem accounting information: done 
                      
root@rescue:~# mkswap /dev/mapper/syslvm-swapp 
Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=96730e50-2d3e-45c2-912a-556ef9d121af
root@rescue:~# 

Passo 3 - Installazione del sistema base

Una volta partizionato il disco si deve procedere al montaggio ordinato delle partizioni e all’installazione del sistema base; i passi che seguono sono tratti da questa pagina della documentazione di debian e richiedono un po di tempo.

Il prossimo step consiste nel montare le partizioni nel modo giusto

root@rescue:~# ls /mnt/
root@rescue:~# mount /dev/mapper/syslvm-root /mnt/
root@rescue:~# mkdir /mnt/boot
root@rescue:~# mkdir /mnt/media/data -p
root@rescue:~# mount /dev/sda2 /mnt/boot/
root@rescue:~# mount /dev/mapper/syslvm-data /mnt/media/data/
root@rescue:~# lsblk 
NAME               MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sda                  8:0    0  1.8T  0 disk  
├─sda2               8:2    0  512M  0 part  /mnt/boot
├─sda3               8:3    0    2M  0 part  
└─sda1               8:1    0  1.8T  0 part  
  └─sys_crypt      251:0    0  1.8T  0 crypt 
    ├─syslvm-root  251:1    0   50G  0 lvm   /mnt
    ├─syslvm-swapp 251:2    0    4G  0 lvm   
    └─syslvm-data  251:3    0  1.8T  0 lvm   /mnt/media/data
root@rescue:~# 

Successivamente eseguo il debootstrap del sistema base:

root@rescue:~# debootstrap --arch amd64 buster /mnt

output completo

Il passo successivo serve a creare il contenuto della cartella /dev nel nuovo sistema, quindi procedo con chroot:

 LANG=C.UTF-8 chroot /mnt/ /bin/bash
export TERM=xterm-color
apt install makedev
root@rescue:/# mount none /proc -t proc
root@rescue:/# cd /dev
root@rescue:/dev# MAKEDEV generic

Una volta che questo comando è termino è necessario uscire dal chroot e montare in bind le seguenti partizioni

root@rescue:~# mount --bind /dev/ /mnt/dev/
root@rescue:~#  mount -t proc proc /mnt/proc
root@rescue:~# mount --bind /sys/ /mnt/sys/

Da questo momento in avanti tutte le operazioni sono eseguite all’interno del chroot con i bind attivi

Generare il file fstab

Uso le informazioni di questi due comandi per generare il vile /etc/fstab manualmente:

root@rescue:/# blkid
/dev/sda1: UUID="e3942b82-cbc4-46e9-9d27-0da8076a7d3d" TYPE="crypto_LUKS" PARTUUID="8453be7e-01"
/dev/sda2: UUID="e1abb7d2-f112-4a39-aa85-171cccda3d47" TYPE="ext4" PARTUUID="8453be7e-02"
/dev/sda3: UUID="2021-05-31-22-54-46-00" LABEL="config-2" TYPE="iso9660" PARTUUID="8453be7e-03"
/dev/mapper/sys_crypt: UUID="hUuzwh-Jrmz-ymLi-celV-HE2k-8324-bjPfk9" TYPE="LVM2_member"
/dev/mapper/syslvm-root: UUID="6d3601f8-67c8-493a-8808-3b78f3edd398" TYPE="ext4"
/dev/mapper/syslvm-swapp: UUID="96730e50-2d3e-45c2-912a-556ef9d121af" TYPE="swap"
/dev/mapper/syslvm-data: UUID="c548c7aa-dea2-437d-bb8f-66da7e4db447" TYPE="ext4"
root@rescue:/# lsblk
NAME               MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sda                  8:0    0  1.8T  0 disk
|-sda1               8:1    0  1.8T  0 part
| `-sys_crypt      251:0    0  1.8T  0 crypt
|   |-syslvm-root  251:1    0   50G  0 lvm   /
|   |-syslvm-swapp 251:2    0    4G  0 lvm
|   `-syslvm-data  251:3    0  1.8T  0 lvm   /media/data
|-sda2               8:2    0  512M  0 part  /boot
`-sda3               8:3    0    2M  0 part
root@rescue:/#

Il risultato dovrebbe essere:

root@rescue:/# cat /etc/fstab
# <file system>                                          <dir>        <type>   <options>    <dump>  <pass>
UUID=6d3601f8-67c8-493a-8808-3b78f3edd398                 /            ext4     defaults       1      1
UUID=e1abb7d2-f112-4a39-aa85-171cccda3d47                 /boot		 ext4     defaults       0      0
UUID=c548c7aa-dea2-437d-bb8f-66da7e4db447                 /media/data  ext4     defaults       0      0
UUID=96730e50-2d3e-45c2-912a-556ef9d121af                 none         swap     defaults       0      0

Per maggiori info su questo file vedere qui

Generare il file crypttab

Il secondo file importante da configurare /etc/crypttab con il seguente contenuto :

sys_crypt UUID=e3942b82-cbc4-46e9-9d27-0da8076a7d3d none discard

Dove l’UUID specificato è quello del device TYPE="crypto_LUKS" che nel mio caso è /dev/sda1.

Riconfigurare la timezone

Per configurare la timezone e l’ora riconfiguro il pacchetto tzdata:

root@rescue:/# dpkg-reconfigure tzdata
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = "en_US:en",
	LC_ALL = "en_US.UTF-8",
	LANG = "C.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("C.UTF-8").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
/usr/bin/locale: Cannot set LC_CTYPE to default locale: No such file or directory
/usr/bin/locale: Cannot set LC_MESSAGES to default locale: No such file or directory
/usr/bin/locale: Cannot set LC_ALL to default locale: No such file or directory

Current default time zone: 'Europe/Rome'
Local time is now:      Wed Jun  2 11:15:55 CEST 2021.
Universal Time is now:  Wed Jun  2 09:15:55 UTC 2021.

cfdic

Configurazione di apt

Nel file /etc/apt/sources.list inserisco il seguente contenuto :

deb http://deb.debian.org/debian buster main contrib non-free
deb-src http://deb.debian.org/debian buster main contrib non-free

deb http://deb.debian.org/debian-security/ buster/updates main contrib non-free
deb-src http://deb.debian.org/debian-security/ buster/updates main contrib non-free

deb http://deb.debian.org/debian buster-updates main contrib non-free
deb-src http://deb.debian.org/debian buster-updates main contrib non-free

Come descritto qui

Configurare locale e tastiera

Per rigenerare il locale:

root@rescue:/#  apt install locales

A me piace avere il locale in inglese americano sulle macchine, ma se volessi riconfigurarlo, dovrei usare il comando:

dpkg-reconfigure locales

output completo

Per aggiornare la configurazione della tastiera:

root@rescue:/# apt install console-setup

cfdic

output completo

Installare il kernel

Per installare il kernel sul host è necessario installare il pacchetto linux-image-amd64:

root@rescue:/# apt install linux-image-amd64/stable

output completo

Passo 4 - Configurazione di rete

Questo è un passaggio veramente delicato, sbagliando qualcosa non sarà possibile accedere al sistema remoto.

Viviamo sereni il server di solito può essere riavviato in modalità rescue in qualsiasi momento, il debug di un problema può essere affrontato riavviando il server in modalità rescue, decriptando i di dischi, montare le partizioni come ho fatto precedentemente e aprendo una chroot per correggere eventuali errori

Configurare hostname

Scelgo il nome host :

echo DebianHostName > /etc/hostname

Configurare file hosts

Creo il file /etc/hosts e aggiungere le seguenti linee:

127.0.0.1 localhost
127.0.1.1 DebianHostName

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

Configurare udev

Questo passo è importante per semplificarsi la vita negli step successivi (configurazione di dropbear e grub).

Raccolgo le informazioni con il seguente comando:

root@rescue:~# ip link show eth0

6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:22:4d:ad:bc:4b brd ff:ff:ff:ff:ff:ff

Ed edito il file ` /etc/udev/rules.d/70-persistent-net.rules` in questa maniera:

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:22:4d:ad:bc:4b", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

Riporto correttamente il mac adr dell’interfaccia.

Configurare le interfaccie

Raccolgo le informazioni utili dal sistema di rescue:

root@rescue:~# ip addr show eth0
 eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:22:4d:ad:bc:4b brd ff:ff:ff:ff:ff:ff
    inet 37.187.121.17/24 brd 37.187.121.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:41d0:a:f211::1/128 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::222:4dff:fead:bc4b/64 scope link 
       valid_lft forever preferred_lft forever
root@rescue:~# ip route
default via 37.187.121.254 dev eth0 
37.187.121.0/24 dev eth0  proto kernel  scope link  src 37.187.121.17 
root@rescue:~# 

Configuro di conseguenza il file /etc/network/interfaces

root@rescue:/# cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    address 37.187.121.17
    network 37.187.121.0
    netmask 255.255.255.0
    broadcast 37.187.121.255
    gateway 37.187.121.254

Configurare i DNS

Edito il file /etc/resolv.conf e aggiungo le linee contenenti i server dns:

nameserver 208.67.222.222 
nameserver  208.67.220.220

Io personalmente uso i server forniti da opendns

Passo 5 - Configurazione di drop bear e GRUB

grub

Prima di installare il boot loader devo installare i pacchetti necessari per supportare lo schema di partizionamento utilizzato:

root@rescue:~# apt install cryptsetup lvm2

Questi due pacchetti andranno a installare degli hook nelle cartelle di configurazione per initarm-fs permettendo di sbloccare il server da remoto.

Adesso posso installare grub usiamo il seguente comando:

root@rescue:~# apt install grub-pc

Installo il boot loader sul disco:

root@rescue:~# grub-install /dev/sda

dropbear Questo tool è un server ssh leggero da includere dentro l’initramfs e che permette di collegarsi da remoto e sbloccare manualemnte i dischi criptati.

root@rescue:~# apt install dropbear-initramfs

Edito /etc/dropbear-initramfs/config aggiungendo i parametri con cui lanciare dropbear :

root@rescue:~# cat /etc/dropbear-initramfs/config 
#
# Configuration options for the dropbear-initramfs boot scripts.
# You must run update-initramfs(8) to effect changes to this file (like
# for other files under the '/etc/dropbear-initramfs' directory).

#
# Command line options to pass to dropbear(8)
#
DROPBEAR_OPTIONS="-I 180 -j -k -p 2222 -s"

#
# On local (non-NFS) mounts, interfaces matching this pattern are
# brought down before exiting the ramdisk to avoid dirty network
# configuration in the normal kernel.
# The special value 'none' keeps all interfaces up and preserves routing
# tables and addresses.
#
#IFDOWN=*

Edito il file /etc/initramfs-tools/initramfs.conf aggiungendo questa linea:

IP=37.187.121.17::37.187.121.254:255.255.255.0:kenningar

Questa linea serve per abilitare la rete.

Edito il file /etc/dropbear-initramfs/authorized_keys per aggiungere la mia chiave pubblica al server ssh, ciò mi permettarà di loggarmi senza password sul server.

Come ultimo passo aggiorno l’immagine dell’init con il comando :

root@rescue:~# update-initramfs -u

Mi assicuro che dropbear non sia abibilitato all’avvio del sistema:

root@rescue:~# systemctl disable dropbear

Questo passo ci assicura che dropbear non parta prima del server ssh (che andrò ad installare nel passo successivo) evitando conflitti.

Passo 6 - Configurazione di ssh

Installo il server open ssh con il seguente comando :

root@rescue:~#  apt install ssh

Mi assicuro che il servizio sia abilitato al’avvio:

root@rescue:~# systemctl enable ssh

NB: non lo faccio ora, ma dopo il primo riavvio installerò fail2ban e proteggendo il server ssh dagli attacchi brute-force.

NB: non lo faccio ora, ma dopo il primo riavvio disabiliterò la possibilità di loggarsi con l’utente root via ssh

Passo 8 - Configurazione degli utenti

Come ultimo passo non mi rimane che configurare gli utenti remoti.

NB: le password usate nei passi successivi sono state generate con il comando pwgen

Utente non privilegiato

Creoo l’utente myadmin

root@rescue:~# adduser myadmin

Imposto la password per questo utente:

root@rescue:~# passwd myadmin

Password utente root

Imposto la password dell’utente root con il comando:

root@rescue:~# passwd 

Passo 9 - Riavvio

Dopo aver riavviato il server dovrei potermi loggare dentro il server drop bear con in comando:

ssh root@37.187.121.17 -p 2222

Sbloccare i dischi criptati uso il comando cryptroot-unlock:

BusyBox v1.30.1 (Debian 1:1.30.1-4) built-in shell (ash)
Enter 'help' for a list of built-in commands.

~ # cryptroot-unlock 
Please unlock disk sys_crypt: 
cryptsetup: sys_crypt set up successfully
~ # Connection to 37.187.121.17 closed by remote host.
Connection to 37.187.121.17 closed.

A questo punto vengo scollegato e il server riprende la normale procedura di boot, al termine del quale sarà possibile collegarsi normalmente.

Conclusione

Questa è una procedura lunga e in certi casi può richiedere alcuni tentativi prima di imbroccare la configurazione corretta e la uso solamente se in fase di installazione non si ha accesso diretto alla macchina, ovviamente nel caso si abbia accesso alla console al momento dell’esecuzione dell’installer di una distribuzione linux consiglio di usare l’installer di default.

Riferimenti