This page is mostly for my own reference regarding the configuration and management of servers running Debian Linux.
Refer to here for information
Add "contrib" to the all the lines in "/etc/apt/sources.list".
# apt update # apt install dpkg-dev linux-headers-$(uname -r) linux-image-amd64 # apt install zfs-dkms zfsutils-linux
To create a mirrored pool, use the mirror keyword, followed by any number of storage devices that will comprise the mirror. Multiple mirrors can be specified by repeating the mirror keyword on the command line. The following command creates a pool with a mirror:
NOTE: when creating the zpools, it's better to use the /dev/disks/by-id names of the disks instead of the /dev/sdX names.
# zpool create $POOL_NAME mirror $DISK_1 $DISK_2
Create pool with RAID-Z array:
# zpool create $POOL_NAME raidz{1,2,3} $DISK_1 $DISK_2 $DISK_3 $DISK_{...}
Create Dataset
# zfs create $POOL_NAME/$DATASET_NAME
You can also specify a mountpoint when you create the dataset
# zfs create -o mountpoint=/$MOUNTPOINT $POOL_NAME/$DATASET_NAME
Install Samba software
# apt install samba
Create a user for Samba. This is the user and password you use to access whatever is being shared to the network. The user must already exist as a Unix user on the system.
# smbpasswd -a $SAMBA_USER
You can use the "built in" smb sharing capabilities that ZFS has as long as you have Samba installed on the system. Set the "smbshare" property of the dataset to "on" with the zfs command:
# zfs set smbshare=on $POOL_NAME/$DATASET_NAME
Reminder: If you cannot access the network share, you probably don't have permission to the dataset on the server. Check where the dataset is mounted:
# zfs list
change the permissions of the directory so that the Samba user has full permission to the directory
ZED monitors events generated by the ZFS kernel module. When a zevent (ZFS Event) is posted, ZED will run any ZEDLETs (ZFS Event Daemon Linkage for Executable Tasks) that have been enabled for the corresponding zevent class.
Edit /etc/zfs/zed.d/zed.rc with your favorite text editor
# vim /etc/zfs/zed.d/zed.rc
There are several lines in this file that you should uncomment and edit. Find the following lines in your file and make sure they match the ones below:
ZED_EMAIL_ADDR="youremail@example.com" ZED_EMAIL_PROG="mail" ZED_EMAIL_OPTS="ZED_EMAIL_OPTS="-s '@SUBJECT@' @ADDRESS@ -r youremail@example.com" ZED_NOTIFY_INTERVAL_SECS=3600 ZED_NOTIFY_VERBOSE=1 ZED_NOTIFY_DATA=1
# apt install clamav clamav-daemon
Create a cron job in the root's crontab
# crontab -e
Add the following line to the file. This job will run a scan the third day of every month at 12am and will only send you an email if it finds any infected files:
0 0 3 * * mail -s "Fileserver ClamAV Scan Report" youremail@example.com -r youremail@example.com <<< $(clamscan --max-filesize=2000M --max-scansize=2000M --recursive=yes --infected /)
Restart your server.
Install required packages
# apt install smartmontools
You can do manual tests on storage devices with the "smartctl" command, but you can configure it to do them automatically with smartd. The config file for smartd is at "/etc/smartd.conf".
You should see something similar to the following line in the beginning of the config file:
DEVICESCAN -d removable -n standby -m root -M exec /usr/share/smartmontools/smartd-runner
When smartd starts up, it first reads this config file to figure out what to do. When it comes across a "DEVICESCAN" line, it stops processing the file and scans for all SMART enabled storage devices attached to the computer. If you want to configure it for a particular drive then replace "DEVICESCAN" with a drive of your choice (/dev/sdX).
Here is an example line to use:
DEVICESCAN -a -o on -S on -s (S/../.././01|L/../01/./03) -m $EMAIL_ADDRESS
This will scan for all SMART enabled storage devices on the computer and then process the following for each drive found:
-a Equivalent to turning on all of the following Directives: '-H' to check the SMART health status, '-f' to report failures of Usage (rather than Prefail) Attributes, '-t' to track changes in both Prefailure and Usage Attributes, '-l error' to report increases in the number of ATA errors, '-l selftest' to report increases in the number of Self-Test Log errors, '-l selfteststs' to report changes of Self-Test execution status, '-C 197' to report nonzero values of the current pending sector count, and '-U 198' to report nonzero values of the offline pending sector count.
-o VALUE [ATA only] Enables or disables SMART Automatic Offline Testing when smartd starts up and has no further effect. The valid arguments to this Directive are on and off.
-S VALUE Enables or disables Attribute Autosave when smartd starts up and has no further effect. The valid arguments to this Directive are on and off. Also affects SCSI devices.
-s This is where you can set self-tests to run at scheduled times. This particular example will run a Short test every Saturday at 1am and a Long test on the first day of every month at 3am.
-m ADDRESS Send a warning email to the email address ADD if the '-H', '-l', '-f', '-C', or '-O' Directives detect a failure or a new error, or if a SMART command to the disk fails.
Install required packages
# apt install bsd-mailx msmtp msmtp-mta
Next you’ll need to configure msmtp. There are two places to configure msmtp, you can setup a default configuration file (/etc/msmtprc) or you can setup a per user configuration file located under that user’s home directory. The file under the user directory is named .msmtprc If you decide to use a per user config file, you should chmod 600 that file. Unless you have a reason to setup a per user config file, setting up the default file /etc/msmtprc is simpler. You can also setup both a default config file, and then a per user config file if you prefer. Neither of these files already exist and you will have to create them. Here is an example of the configuration file:
# Set default values for all following accounts. defaults auth on tls on tls_trust_file /etc/ssl/certs/ca-certificates.crt logfile ~/.msmtp.log account alerts host smtp.youremail.com port 587 from from@addresstosendfrom.com user userforemail@user.com password putpasswordhere # Set a default account account default : alerts
This file assumes you are using STARTTLS and the port number is 587. If you need to use TLS/SSL, but not use STARTTLS add the following entry:
tls_starttls off
Perform a test email with the following command:
echo test | mail -s "test subject" $EMAIL_ADDRESS
Install the required packages:
# apt install unattended-upgrades apt-listchangesConfigure Unattended-Upgrades
The default config file for unattended-upgrades is at "/etc/apt/apt.conf.d/50unattended-upgrades". Comment out the following line to receive email alerts:
Unattended-Upgrade::Mail "$EMAIL_ADDRESS or $USER";
You should make sure to uncomment the following line in the "/etc/apt/apt.conf.d/50unattended-upgrades" file:
// "${distro_id}:${distro_codename}-updates";
Make sure that the following lines exist exactly as they appear in the "/etc/apt/apt.conf.d/20auto-upgrades" file to be sure that unattended upgrades are enabled
APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1";
Reminder: If the "/etc/apt/apt.conf.d/20auto-upgrades" file does not exist then run dpkg-reconfigure to create it:
# dpkg-reconfigure -plow unattended-upgradesConfigure Apt-Listchanges
Below is an example of a configuration for the file for "/etc/apt/listchanges.conf". Change the value for "email_address" to get alerts for what packages were installed by unattended-upgrades
[apt] frontend=pager email_address=root confirm=0 save_seen=/var/lib/apt/listchanges.db which=bothIf The Above Does Not Work
If you are having trouble configuring the unattended upgrades doing it the way I have outlined above, you can just add a simple cron job.
Enter into the root crontab:
# crontab -e
Enter or paste the following at the bottom of the file:
0 * * * * /usr/bin/apt-get update && /usr/bin/apt-get --with-new-pkgs upgrade -y
This cron job will update the repo and upgrade any packages at the start of every hour.
NOTE: This will upgrade every package including the kernel. If you don't want to upgrade the kernel, then remove the "--with-new-pkgs" option.
Ensure you have "cryptsetup" installed
# apt install cryptsetup
Ensure that the "dm-mod" module is loaded into the kernel:
# modprobe dm-mod
Make a partition the size of the entire drive with fdisk:
# fdisk /dev/sd*
Setup encryption on that partition and pick a good passphrase to use:
# cryptsetup -v --cipher serpent-xts-plain64 --key-size 512 --hash whirlpool --use-random --verify-passphrase luksFormat /dev/sd*{1}
Open(unlock) the encrypted partition. The actual block storage device will be available at "/dev/mapper/$NAME"
# cryptsetup luksOpen /dev/sd*{1} $NAME
Create a filesystem on the unlocked partition to store files on it:
# mkfs.ext4 /dev/mapper/$NAME
Now mount to directory of your choice and store files on it:
# mount /dev/mapper/$NAME /mnt
To properly close the encrypted volume:
# umount /dev/mapper/$NAME # cryptsetup luksClose /dev/mapper/$NAME
Install Required Packages
# apt install ufw
You can install the GUI version with (optional):
# apt install gufw
Enable it to start it and allow it to start on boot
# ufw enable
Set the default to deny all incoming traffic
# ufw default deny incoming
Set the default to allow all outgoing traffic
# ufw default allow outgoing
Allow the SSH service as incoming traffic like this:
# ufw allow ssh
Allow port range like this:
# ufw allow 1000:2000/{tcp,udp}
Allow IP address like this:
# ufw allow from 192.168.1.1
Delete a rule
# ufw delete allow {$SERVICE, $PORTS, $IP_ADDRESS}
Reload the firewall after adding or deleting rules
# ufw reload
Check the current rules:
# ufw status verbose
This is a more condensed version of how to setup an email server. Refer to here for a detailed version of how to do it.
Create a dummy nginx config file for your mail domain with your text editor of choice
# vim /etc/nginx/sites-available/mail
Copy or type the following into the file:
server { listen 80 ; listen [::]:80 ; root /var/www/mail; index index.html index.htm index.nginx-debian.html; server_name mail.$YOUR_DOMAIN www.mail.$YOUR_DOMAIN; location / { try_files $uri $uri/ =404; } }
Link the file to "sites-enabled"
# ln -s /etc/nginx/sites-available/mail /etc/nginx/sites-enabled/mail
Reload nginx
# systemctl reload nginx
Generate certificates with cerbot
# certbot --nginx
If you have Postfix or Dovecot installed previously, completely uninstall it and delete all related files.
Setup the email software with a script. Get the script from Github
# git clone https://github.com/LukeSmithxyz/emailwiz
Enter the "emailwiz" directory and execute the script.
NOTE: On installation of Postfix, select "Internet Site" and put in TLD without the "mail." before it.
# sh emailwiz.sh
If the script is successful it will generate some TXT records that you are supposed to enter in your domains DNS records. You should see something like this:
mail._domainkey TXT v=DKIM1; k=rsa; p=... _dmarc TXT v=DMARC1; p=none; rua=...; fo=1; @ TXT v=spf1; mx a:mail.$YOURDOMAIN -all
The left part is the "host" part of the TXT record and the right part is the "value" of the TXT record. Input these into your DNS records.
Add a user on the server, add them to the "mail" group and give them a password. This is the passord they use to log in remotely through a mail client.
# useradd -m -G mail $USER # passwd $USER
To allow an existing user to receive mail, add them to the "mail" group
# usermod -a -G mail $USER
If you want to access your mail remotely through a client like Thunderbird, here is the server information:
mxtoolbox.com is a great site for testing various E-mail server configurations to verify that your server is working properly. mail-tester.com is a good site for testing your spam score of your emails.
This is a more condensed version of how to setup the webserver with the certificates. Refer to here for a detailed version of how to do it
Install the required packages
# apt install nginx python3-certbot-nginx
Create config file for your site with a text-editor of your choice
# vim /etc/nginx/sites-available/$FILENAME
Copy or type the following into the file:
server { listen 80 ; listen [::]:80 ; root /var/www/$DIRECTORY_NAME; index index.html index.htm index.nginx-debian.html; server_name $YOUR_DOMAIN www.$YOUR_DOMAIN; location / { try_files $uri $uri/ =404; } }
Link the file to the "sites-enabled" directory
# ln -s /etc/nginx/sites-available/$FILENAME /etc/nginx/sites-enabled/$FILENAME
Create the root directory if you haven't already that you specified in the config file above. This is where you will put the files you want nginx to serve to clients.
# mkdir /var/www/$DIRECTORY_NAME
Reload nginx
# systemctl reload nginx
Check the journal for any errors. If you have any, its probably due to an error in the config file
# systemctl status nginx
Generate certificates for the site with certbot. It will prompt you with some questions. Use option 2 to redirect HTTP to HTTPS.
# certbot --nginx
There are a couple pieces to the Linux virtualization puzzle that we need: QEMU, KVM, Libvirt and its associated tools (virsh, virt-install, virt-manager). KVM is a module that is already included in the mainline Linux kernel so we only have to download the other things. Technically, you only need QEMU and KVM to run virtual machines however, it is a bit tricky to manage virtual machines with just QEMU commands. That is where Libvirt and its associated tools steps in.
The package names can vary on each distribution, but here are the packages for Debian:
# apt install qemu-system libvirt-clients libvirt-daemon-system virtinst qemu-utils
If installing on a headless server, you can choose to not install all the graphical related packages:
# apt install --no-install-recommends qemu-system libvirt-clients libvirt-daemon-system virtinst qemu-utils
Add your user to libvirt group to use virtual machines as non-root
# adduser $USER libvirt
By default, if virsh is run as a normal user it will connect to libvirt using "qemu:///session" URI string. This URI allows virsh to manage only the set of VMs belonging to this particular user. To manage the system set of VMs (i.e., VMs belonging to root) virsh should be run as root or with "qemu:///system" URI:
# virsh --connect qemu:///system list --all
The easiest way to create VMs is through a GUI tool such as virt-manager. If you don't have a GUI on your server because you are running it headless, you can create VMs using the CLI based tools which are virsh and virt-install
Create a VM with virt-install. Here is an example:
# virt-install \ -n myDebianVM \ --description "Test VM with Debian 11" \ --os-type=Linux \ --os-variant=debian10 \ --ram=2048 \ --vcpus=2 \ --disk path=/var/lib/libvirt/images/myDebianVM.img,bus=virtio,size=10 \ --graphics none \ --cdrom /var/debian-11.0.0-amd64-netinst.iso \ --network bridge:br0 \ --noautoconsole
The virt-install command will essentially create an XML file which contains the entire configuration for a particular VM. In the above virt-install command the parameters have the following meaning:
When you first create a VM, the operating system must be installed which means you will have to access the console to go through the installation process just as you would on a normal physical computer. This is a bit of a problem on a headless server since it has no GUI, so then how can we get to a VMs console?
One of the ways is to use virt-viewer and connect to the hypervisor host remotely over SSH. So basically we install virt-viewer on a separate desktop computer that does have a GUI and then connect to the hypervisor host with SSH and tunnel over that.
Make sure that you have virt-viewer installed on the separate desktop computer and SSH configured on your hypervisor host server. Then, execute the following command but plug in your own information:
NOTE: You must make sure that you use "--graphics vnc" when creating the VM with virt-install. If you don't give it that parameter then this method will not work.
# virt-viewer --connect qemu+ssh://user@host/system $VM_NAME
With the above, you’ll have to enter your SSH password twice – first to establish the connection to the hypervisor and secondly to establish a tunnel to the VM’s VNC/SPICE session.
Once again, the easiest way to manage VMs is with a GUI tool such as virt-manager. Your other option is to use the CLI tools like virsh if you are doing this on a headless server with no GUI.
A VMs configuration can be modified by editing it's XML file that was generated by the virt-install command. We can easily edit a specific VMs configuration with this command:
# virsh edit $VM_NAME
You can use the virsh command to start and stop virtual machines. VMs can be generated from virt-install as mentioned above. For more details visit the libvirt page.
Start a VM:
# virsh start $VM_NAME
Gracefully shutdown a VM:
# virsh shutdown $VM_NAME
If a VM hangs when attempting to shutdown, you can force it with:
# virsh destroy #VM_NAME
You can delete a VM only once it is shutdown with this command:
# virsh undefine $VM_NAME
Install the required packages
# apt install dnsmasq-base bridge-utils iptables
Libvirt provides a NATed bridged network named "default" that allows the host to communicate with the guests. This network is available only for the system domains (that is VMs created by root or using the qemu:///system connection URI). VMs using this network end up in 192.168.122.1/24 and DHCP is provided to them via dnsmasq. This network is not automatically started. To start it use:
# virsh net-start default
Start it automatically:
# virsh net-autostart default
If you get an error that says that the "default" network does not exist, then you have to define it:
# virsh net-define /usr/share/libvirt/networks/default.xml
Install the required packages:
# apt install ethtool
Manually enable WOL on an interface:
# ethtool -s $IFACE_NAME wol g
This setting does not stick on reboot so you can create a systemd service to run the command on start:
# vim /etc/systemd/system/wol@.service
[Unit] Description=Wake-on-LAN for %i Requires=network.target After=network.target [Service] ExecStart=/usr/bin/ethtool -s %i wol g Type=oneshot [Install] WantedBy=multi-user.target
Start and enable the service for your particular interface:
# systemctl start wol@$IFACE_NAME
# systemctl enable wol@$IFACE_NAME