title: Debian Server
breadcrumbs:
- title: Configuration
- title: Linux Server
---
{% include header.md %}
Using Debian 10 (Buster).
Basic Setup
Installation
- Always verify the downloaded installation image after downloading it.
- Use UEFI if possible.
- Use the non-graphical installer. It's basically the same as the graphical one.
- Localization:
- Language: United States English.
- Location: Your location.
- Locale: United States UTF-8 (
en_US.UTF-8
).
- Keymap: Your keyboard's keymap.
- Use an FQDN as the hostname. It'll set both the shortname and the FQDN.
- Use separate password for root and your personal admin user.
- System disk partitioning:
- "Simple" system: Guided, single partition, use all available space.
- "Complex" system: Manually partition, see system storage.
- Swap can be set up later as a file or LVM volume.
- When using LVM: Create the partition for the volume group, configure LVM (separate menu), configure the LVM volumes (filesystem and mount).
- At the software selection menu, select only "SSH server" and "standard system utilities".
- If it asks to install non-free firmware, take note of the packages so they can be installed later.
- Install GRUB to the used disk (not partition).
Reconfigure Clones
If you didn't already configure this during the installation. Typically the case if cloning a template VMs or something.
- Check the system status:
- Check for failed services:
systemctl --failed
- Check that AppArmor is operational:
apparmor_status
- Update the root password:
passwd
- Localization:
- Check current locale:
locale
should return en_US.UTF-8
.
- Update if wrong:
update-locale LANG=en_US.UTF-8
- Check the keymap:
- Try typing characters specific to your keyboard.
- Update if wrong:
dpkg-reconfigure keyboard-configuration
- Set the hostname:
- Set the shortname:
hostnamectl set-hostname <shortname>
- Set both the shortname and FQDN in
/etc/hosts
using the following format: 127.0.0.1 <fqdn> <shortname>
- If the server has a static IP address, use that instead of 127.0.0.1.
- Check the hostnames with
hostname
(shortname) and hostname --fqdn
(FQDN).
Basic Configuration
- Packages:
- (Optional) Enable the
contrib
and non-free
repo areas by setting main contrib non-free
for every deb
/deb-src
in /etc/apt/sources.list
.
- Update, upgrade and auto-remove.
- Install basics:
sudo ca-certificates
- Install tools:
tree vim screen curl net-tools dnsutils htop iotop irqtop nmap
- (Optional) Install per-user tmpdirs:
libpam-tmpdir
- (Optional) Configure editor (Vim):
- Update the default editor:
update-alternatives --config editor
- Disable mouse globally: In
/etc/vim/vimrc.local
, add set mouse=
and set ttymouse=
.
- Fix YAML formatting globally: In
/etc/vim/vimrc.local
, add autocmd FileType yaml setlocal ts=2 sts=2 sw=2 expandtab
.
- Add mount options:
- Setup hidepid:
- Add PID monitor group:
groupadd -g 500 hidepid
(example GID)
- Add your personal user to the PID monitor group:
usermod -aG hidepid <user>
- Enable hidepid in
/etc/fstab
: proc /proc proc defaults,hidepid=2,gid=500 0 0
- (Optional) Disable the tiny swap partition added by the guided installer by commenting it in the fstab.
- (Optional) Setup extra mount options: See Storage.
- Run
mount -a
to validate fstab.
- (Optional) Restart the system.
- Setup your personal user:
- If it doesn't exist, create it:
adduser <username>
- Add the relevant groups (using
usermod -aG <group> <user>
):
sudo
for sudo access.
systemd-journal
for system log access.
hidepid
(whatever it's called) if using hidepid, to see all processes.
- Add your personal SSH pubkey to
~/.ssh/authorized_keys
and fix the owner and permissions (700 for dir, 600 for file).
- Hint: Get
https://github.com/<user>.keys
and filter the results.
- Try logging in remotely and gain root access through sudo.
Setup SSHD:
In /etc/ssh/sshd_config
, set:
PermitRootLogin no
PasswordAuthentication no
# Optional, disable TCP port forwarding
AllowTcpForwarding no
GatewayPorts no
# Comment out to avoid locale issues (or fix it some proper way)
#AcceptEnv ...
Restart sshd
.
Update MOTD:
- Clear
/etc/motd
, /etc/issue
and /etc/issue.net
.
- (Optional) Add a MOTD script (see below).
(Optional) Enable persistent logging:
- In
/etc/systemd/journald.conf
, under [Journal]
, set Storage=persistent
.
- Note:
auto
(the default) is like persistent
, but does not automatically create the log directory.
- Note: The default journal directory is
/var/log/journal
.
Machine-Specific Configuration
Physical Host
- Install extra firmware:
- Enable the
non-free
repo areas.
- Update microcode: Install
intel-microcode
(for Intel) or amd64-microcode
(for AMD) and reboot (now or later).
- Note: APT package examples:
firmware-atheros -bnx2 -bnx2x -ralink -realtek
- If it asked to install non-free firmware in the initial installation installation, try to install it now.
- Install firmware from other sources (e.g. for some Intel NICs).
- (Optional) To install all common common firmware and microcode, install
firmware-linux
(or firmware-linux-free
) (includes e.g. microcode packages).
- Setup smartmontools to monitor S.M.A.R.T. disks:
- Install:
apt install smartmontools
- (Optional) Monitor disk:
smartctl -s on <dev>
.
- Setup lm_sensors to monitor sensors:
- Install:
apt install lm-sensors
- Run
sensors
to make sure it runs without errors and shows some (default-ish) sensors.
- For further configuration (more sensors) and more info, see Linux Server Applications: lm_sensors.
- Check the performance governor and other frequency settings:
- Install
linux-cpupower
.
- Show:
cpupower frequency-info
- Check the boost state should be on (Intel).
- Check the current performance governor (e.g. "powersave", "ondemand" or "performance").
- (Optional) Temporarily change performance governor:
cpupower frequency-set -g <governor>
- (Optional) Permanently change performance governor: TODO
- (Optional) Mask
ctrl-alt-del.target
to disable CTRL+ALT+DEL reboot at the login screen.
QEMU Virtual Host
- Install QEMU guest agent:
apt install qemu-guest-agent
Networking
Network Manager
Using ifupdown (Alternative 1)
This is used by default and is the simplest to use for simple setups.
- For VLAN support, install
vlan
.
- For bonding/LACP support, install
ifenslave
.
- Configure
/etc/network/interfaces
.
- Reload the config (per interface):
systemctl restart ifup@<if>.service
- Don't restart
networking.service
or call ifup
/ifdown
directly, this is deprecated and may cause problems.
Using systemd-networkd (Alternative 2)
This is the systemd way of doing it and is recommended for more advanced setups as ifupdown is riddled with legacy/compatibility crap.
- Add a simple network config: Create
/etc/systemd/network/lan.network
based on main.network.
- Disable/remove the ifupdown config:
mv /etc/network/interfaces /etc/network/interfaces.old
- Enable the service:
systemctl enable --now systemd-networkd
- Purge
ifupdown
and ifupdown2
.
- Check status:
networkctl [status [-a]]
- Restart the system to make sure all ifupdown stuff is stopped (like orphaned dhclients).
Configure IPv6/NDP/RA Securely
Prevent enabled (and potentially untrusted) interfaces from accepting router advertisements and autoconfiguring themselves, unless autoconfiguration is what you intended.
- Using ifupdown: Set
accept_ra 0
for all inet6
interface sections.
- Using systemd-networked TODO
- Using firewall: If the network manager can't be set to ignore RAs, just block them. Alternatively, block all ICMPv6 in/out if IPv6 shouldn't be used on this interface at all.
Firewall
- Install
apt install iptables iptables-persistent netfilter-persistent
- Don't save the current rules when it asks.
- Manually add IPTables rules or make a simple iptables script or something.
- Open a new SSH session and make sure you can still log in without closing the current one.
- Note: If you flush the firewall and reconfigure it, remember to restart services modifying it (like libvirt, Docker, Fail2Ban).
DNS
Using resolv.conf (Alternative 1)
The simplest alternative, without any local system caching.
- Manually configure
/etc/resolv.conf
.
Using systemd-resolved (Alternative 2)
- (Optional) Make sure no other local DNS servers (like dnsmasq) is running.
- Configure
/etc/systemd/resolved.conf
DNS
: A space-separated list of DNS servers.
Domains
: A space-separated list of search domains.
- (Optional) If you're hosting a DNS server on this machine, set
DNSStubListener=no
to avoid binding to port 53.
- Enable the service:
systemctl enable --now systemd-resolved.service
- Point
resolv.conf
to the one generated by systemd: ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
- Check status:
resolvectl
NTP
This is typically correct by default.
- Check the timezome and network time status:
timedatectl
- (Optional) Fix the timezone:
timedatectl set-timezone Europe/Oslo
- (Optional) Fix enable network time:
timedatectl set-ntp true
- Configure
/etc/systemd/timesyncd.conf
:
NTP
(optional): A space-separated list of NTP servers. The defaults are fine.
- Restart
systemd-timesyncd
.
- Check status works:
timedatectl
and timedatectl timesync-status
(check which servers are used)
Miscellanea
- Make sure IPv6 and NDP is configured securely (prevent accidental autoconfiguration on untrusted interfaces):
- For ifupdown, set
accept_ra 0
for all inet6
interface sections which should not use SLAAC.
- If configuring the interface to not accept RAs, ICMPv6/NDP may be firewalled on the untrusted interfaces.
- Reboot and make sure everything still works.
Extra
Everything here is optional.
- Setup Fail2Ban:
- Recommended for public-facing servers.
- Fix the firewall first so it configures itself correctly wrt. which firewall is used.
- Install:
apt install fail2ban
- Check status:
fail2ban-client status [sshd]
- See Linux Server Applications: Fail2Ban for more info.
- Set up a swap file:
- Note: You should have enough memory installed to never need swapping, but it's a nice backup to prevent the system from potentially crashing if anything bugs out and eats up too much memory.
- Show if swap is already enabled:
swapon --show
- Allocate the swap file:
fallocate -l <size> /swapfile
- Fix the permissions:
chmod 600 /swapfile
- Setup the swap file:
mkswap /swapfile
- Activate the swap file:
swapon /swapfile
- Add it to fstab using this line:
/swapfile swap swap defaults 0 0
- Setup Postfix mail relay: See Linux Server Applications: Postfix.
- Prevent root local login:
- Alternatively, keep it enabled with a strong password as a local backdoor for recovery or similar.
- Add a personal user first.
- Check that the password field (the second field) for root in
/etc/shadow
is something invalid like "*" or "!", but not empty and not valid password hash. This prevents password login.
- Clear
/etc/securetty
to prevent root local/console login.
- Extra package security:
- Install
apt-listbugs
and apt-listchanges
and run them before upgrading a package.
- Install
needrestart
and run it after upgrading.
- Install
debsums
and run it after upgrading to check deb checksums.
- Install
debsecan
to get automatically alerted when new vulnerabilities are discovered and security updates are available.
- Google Authenticator 2FA:
- Potentially useful for public-facing servers.
- TODO
- Install and run Lynis security auditor:
- Install:
apt install lynis
- Run:
lynis audit system
- MOTD:
- Clear
/etc/motd
and /etc/issue
.
- Download dmotd.sh to
/etc/profile.d/
.
- Install the dependencies:
neofetch lolcat
- Add an ASCII art (or Unicode art) logo to
/etc/logo
, using e.g. TAAG.
- (Optional) Add a MOTD to
/etc/motd
.
- (Optional) Clear or change the pre-login message in
/etc/issue
.
- Test it:
su - <some-normal-user>
- Setup monitoring:
- Use Prometheus with node exporter or something and set up alerts.
Troubleshooting
network-online.target
is stalling during boot:
- See all services it depends on:
systemctl show -p WantedBy network-online.target
- Disable the unused services which stall.
- Firmware for the network card fails to load:
- Causes a syslog record like "firmware: failed to load rtl_nic/rtl8168g-3.fw (-2)" when trying to up the interface.
- Might happen after installation even if working initially (for some reason).
- Realtek solution: Enable the "non-free" repo and install "firmware-realtek".
- Perl complains about a locale error:
- Test with
perl -e exit
. It will complain if there's an error.
- Check the locale:
locale
- Comment
AcceptEnv LANG LC_*
in /etc/ssh/sshd_config
to prevent clients bringing their own locale.
Miscellanea
Cron
- Don't use periods (including file extensions) in the hourly/daily/weekly/monthly scripts.
{% include footer.md %}