Home / Linux Servers
- Apache
- Apticron
- Avahi Daemon
- AWS CLI
- BIND
- VaultWarden (Formerly bitwarden_rs)
- Ceph
- Certbot
- Chrony
- DDNS
- Fail2ban
- Google Authenticator
- Home Assistant
- Intel SSD Data Center Tool (isdct)
- ISC DHCP Server
- lm_sensors
- Linux PTP
- MariaDB
- NFS
- ntopng
- ntpd
- Network UPS Tools (NUT)
- OpenLDAP
- OpenSSL
- Pi-hole (Docker)
- Processor Counter Monitor (PCM)
- Portainer
- Postfix
- Pterodactyl
- Router Advertisement Daemon (radvd)
- Samba (CIFS)
- smartmontools
- NetSNMP
- SSHD
- TFTP-HPA
- Unbound
- UniFi
- WireGuard
- ZFS
If not stated then the instructions are for Debian. Some may be for CentOS (5?) and extremely outdated. Some applications may be located in different sections/pages on this wiki.
Outdated
apt install apache2
security.conf
:
ServerTokens Prod
ServerSignature Off
a2<en|dis><conf|mod|site> <...>
apache2ctl
Sends an emails when APT updates are available.
apt install apticron
/etc/apticron/apticron.conf
cp /usr/lib/apticron/apticron.conf /etc/apticron/apticron.conf
/etc/cron.d/apticron
(e.g. 30 23 * * *
).IPADDRESSNUM
and always print all IP adresses:
/usr/sbin/apticron
.IPADDRESSES=`(echo $( /bin/hostname --all-ip-addresses ) ;
IPADDRESSES=`(
apticron
TODO
apt install avahi-daemon
Possibly outdated
awscli
through pip3chmod +x /usr/local/bin/aws
aws configure [--profile <profile>]
eu-west-2
json
aws s3 cp <local_file> s3://<bucket>/
-g
CLI arg forces all output to stderr, which breaks logging. Use -f
instead.named-checkconf -p
bind9utils
package.named-compilezone -f raw -F text -o zone.tmp <zone> <zone-file>.signed
dnssec-dsfromkey <dnskey-file>
(use the one with digest type 2 (SHA-256))named-checkconf
dig cloudflare.com @<server>
should give status NOERROR
and contain the ad
flag (for “authentic data”, i.e. it passed DNSSEC validation).dig www.dnssec-failed.org @<server>
should give status SERVFAIL
.dig www.dnssec-failed.org @<server> +cd
(for “checking disabled”, useful for DNSSEC debugging) should give status NOERROR
but no ad
flag.dig chaos txt version.bind @<server>
dig chaos txt hostname.bind @<server>
A free community backend for Bitwarden.
TODO
See Storage: Ceph.
apt install certbot
/etc/letsencrypt/cli.ini
, add renew-hook = systemctl reload nginx
or equivalent.certbot -d <domain> --preferred-challenges=http --webroot --webroot-path=<webroot> certonly
certbot -d <domain> --preferred-challenges=dns --manual certonly
certbot renew --dry-run [--staging]
certbot revoke --cert-path <cert>
An NTP client and server. By design more accurate than e.g. ntpd and systemd-timesyncd.
See NTP for more info about NTP.
apt install chrony
/etc/chrony/chrony.conf
):
server <address> iburst
pool <address> iburst
allow {all|<network>}
systemctl restart chrony
chronyc tracking
chronyc sources
chronyc ntpdata
chronyc serverstats
chronyc clients
fail2ban
.fail2ban-client status [sshd]
.Possibly outdated
This setup requires pubkey plus MFA (if configured) plus password.
apt install libpam-google-authenticator
/etc/pam.d/sshd
, add auth required pam_google_authenticator.so nullok
after @include common-auth
./etc/ssh/sshd_config
, set:
ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
sshd
and check that you can login with pubkey and MFA now./etc/profile.d/
to ask user to configure Google Auth on login./etc/ssh/sshd_config
, add Match Group no-mfa
containing AuthenticationMethods publickey
(indented) at the bottom.no-mfa
and add special users to it.google-authenticator -tduW
See Home Assistant.
See Storage: isdct.
isc-dhcp-server
./etc/dhcp/dhcpd.conf
/etc/dhcp/dhcpd6.conf
authorative
statement in subnet declarations so that the server will reply with DHCPNAK for misconfigured clients.
This may significantly reduce reconfiguration delay when a client moves between subnets.range6
, prefer using CIDR notation.
If using range notation, try to align the start and end on a CIDR block to avoid excessive memory usage./116
gives 8191 addresses.pool[6]
are not applied to e.g. host
s with addresses in the same defined subnet. Don’t use pool[6]
s if you don’t need to.Get sensor values like temperature, voltage, fan speeds, etc.
apt install lm-sensors
sensors
sensors-detect
. When it asks, add the modules to /etc/modules
.systemctl restart kmod
sensors
journalctl
:
chip "<chip>"\n ignore <sensor>
in /etc/sensors3.conf
. Re-run sensors
. (See Kernel ACPI Error SMBus/IPMI/GenericSerialBus (ServerAdminBlog) for an example on certain HP servers.)sensors
. If it worked, then remove it from /etc/modules
to make it permanent.Link: linuxptp.sourceforge.net
See PTP for more info about PTP.
Configure LinuxPTP as a GM using the default PTPv2 profile, with Chrony as the time source.
ethtool -T <interface>
git clone --depth=1 --branch=v4.1 http://git.code.sf.net/p/linuxptp/code linuxptp
cd linuxptp
make
sudo make install
cd ..
cp linuxptp/configs/default.cfg /etc/ptp4l.conf
sudo systemctl daemon-reload && sudo systemctl enable --now ptp4l.service
sudo journalctl -u ptp4l.service -f
sudo tcpdump -nn -i <interface> host 224.0.1.129
Service config (/etc/systemd/system/ptp4l.service
):
[Unit]
Description=LinuxPTP daemon
After=network.target
[Service]
ExecStart=ptp4l -4S -f /etc/ptp4l.conf -i eth0
[Install]
WantedBy=multi-user.target
A MySQL fork that is generally MySQL compatible.
apt install mariadb-server
mysql_secure_installation
mariadb [-u <user> [-p]]
root
.-p
.GRANT ALL ON *.* TO '<user>'@'127.0.0.1' IDENTIFIED BY '<password>' WITH GRANT OPTION;
The instructions below use NFSv4 without Kerberos. This should only be used on trusted networks and requires manual user and group ID management.
As a general guide, a home directory filesystem, which is normally exported at the root and may see lots of file renames, should be exported with subtree checking disabled. A filesystem which is mostly readonly, and at least doesn’t see many file renames (e.g. /usr or /var) and for which subdirectories may be exported, should probably be exported with subtree checks enabled.
apt install nfs-kernel-server
portmap
if you need support for NFSv2 and v3 (not NFSv4)./etc/default/nfs-common
, set:
NEED_STATD="no"
NEED_IDMAPD="yes"
/etc/default/nfs-kernel-server
, set:
RPCNFSDOPTS="-N 2 -N 3"
RPCMOUNTDOPTS="--manage-gids -N 2 -N 3"
systemctl disable --now rpcbind.service
systemctl mask rpcbind.service
systemctl mask rpcbind.socket
systemctl restart nfs-server.service
cat /proc/fs/nfsd/versions
(-
means disabled)mkdir /export
/zfspool/alpha /export/alpha none bind,defaults,nofail,x-systemd.requires=zfs-mount.service 0 0
/etc/exports
.
exports(5)
.exportfs -ra
systemctl restart nfs-server.service
exportfs -v
Example /etc/exports
:
# "fsid=root" is a special root export in NFSv4 where other exports are accessible relative to it.
# "sync" should generally always be used. While "async" gives better performance, it violates the spec and may cause data loss in case of power loss.
# "root_squash" maps client root users to an anon user to prevent remote root access. If that's desired, set "no_root_squash" instead.
# "no_subtree_check" disables subtree checking. Subtree checking may be appropriate for certain file systems, but in general it may cause more problems than it solves.
# "insecure" allows clients connecting from non-well-known ports.
/export/ *(fsid=root,ro,sync,root_squash,no_subtree_check,insecure)
/export/projects/ *(rw,sync,root_squash,no_subtree_check,insecure)
apt install nfs-common
mount -t nfs4 <server-hostname>:<export> <mountpoint>
/etc/fstab
entry: <nfs-server>:<export> <local-dir> nfs4 defaults 0 0
ntopng
.ntopng
is enabled and running.chown nobody:nogroup /var/log/ntopng
/etc/ntopng.conf
.-W=<new_port>
to enable HTTPS.-w=0
to disable HTTP.Note: I recommend Chrony instead of ntpd. It’s newer and by design more accurate.
systemd-timesyncd
.ntp
./etc/ntp.conf
, with the iburst
option.ntpq -pn
(it may take a minute to synchronize).Instructions for both primary nodes (netserver mode) and secondary nodes (netclient mode). Exclusive steps are marked “(Primary)” or “(Secondary)”. (Since “primary/secondary” was only recently introduced as a replacement, we’re using “master/slave” in the configs to avoid silent errors.)
apt install nut
/etc/nut/nut.conf
and set MODE=netserver
for primaries or MODE=netclient
for secondaries./etc/nut/ups.conf
and add a declaration for all UPSes (see example below).
usbhid-ups
driver if using USB. Otherwise, check the hardware compatibility list to find the correct driver. If the exact model isn’t there, try a similar one.usbhid-ups
, see the example below and usbhid-ups(8).systemctl restart nut-driver.service
/etc/nut/upsd.conf
and set LISTEN :: 3493
and LISTEN 0.0.0.0
(unrestricted access).
LISTEN ::1 3493
and LISTEN 127.0.0.1
./etc/nut/upsd.users
and add users (see example below).
systemctl restart nut-server.service
/etc/nut/upsmon.conf
and add MONITOR <ups>@<host>[:<port>] <powervalue> <user> <password> <master|slave>
.
powervalue
is how many power supplies this system has which is supplied by the UPS. It’s used to calculate how many supplies are allowed to go offline. For single-PSU systems, use 1.
For dual-PSU systems with both connected to this PSU, use 2
. If this system is not powered by the UPS but you want to monitor it without shutting down when it goes critical, set it to 0
.RBWARNTIME
(how often upsmon should complain about batteries needing replacement) to an appropriate value, e.g. 604800 (1 week)./etc/nut/upsmon.conf
, add EXEC
to all NOTIFYFLAG
entries you want to run the script for (typically all except LOWBATT
)./etc/nut/upsmon.conf
, set the script to run using format NOTIFYCMD /opt/scripts/nut-notify.sh
.systemctl restart nut-monitor.service
nut-monitor
successfully connected to the server.
journalctl -u nut-monitor.service
upsc
uses the driver directly, so it’s not useful for debugging the server or monitoring services.upsrw -s battery.runtime.low=<seconds> <ups>
and upsrw -s battery.charge.low=<percent> <ups>
usbhid-ups
, this is set using offdelay
and ondelay
. Otherwise, it’s set using ups.delay.shutdown
and ups.delay.start
. The start delay must be greater than the stop delay.
upsmon -c fsd
Example /etc/nut/ups.conf
(uding usbhid-ups
driver):
[alpha]
desc = "PowerWalker VI 3000 RLE"
# usbhid-ups should work for most UPSes with
driver = usbhid-ups
# Required but ignored by this driver
port = auto
# Sets "ups.delay.shutdown", the delay between the shutdown command and when the UPS powers off (default 20s)
offdelay = 60
# Sets "ups.delay.start", which has something to do with letting the UPS charge enough to make sure devices may fully boot (default 30s, must be greater than offdelay)
ondelay = 120
Example /etc/nut/upsd.users
:
[admin]
password = <password>
actions = set
actions = fsd
instcmds = all
[upsmon_local]
password = <password>
upsmon master
[upsmon_remote]
password = <password>
upsmon slave
(Notice the lack of =
for upsmon
.)
Example /etc/nut/upsmon.conf
:
MONITOR alpha@localhost:3493 1 upsmon_local password1234 master
MINSUPPLIES 1
POLLFREQ 5
POLLFREQALERT 5
DEADTIME 20
HOSTSYNC 20
FINALDELAY 5
POWERDOWNFLAG /etc/killpower
NOTIFYCMD "/usr/bin/true"
SHUTDOWNCMD "/sbin/shutdown -h +0"
NOCOMMWARNTIME 3600
RBWARNTIME 604800
# See the original for NOTIFYMSG and NOTIFYFLAG examples.
Example notify script:
#!/bin/bash
echo -e "Time: $(date)\nMessage: $@" | mail -s "NUT: $@" root
upsc -l
upsc <ups>
upsdrvctl -t shutdown
upsmon -c fsd
Note: Anonymous users have read-only access to everything.
telnet localhost 3493
LIST UPS
LIST VAR <ups>
sudo pacman -S openldap
sudo apt install ldap-utils
ldapsearch -x -b ou=people,dc=example,dc=net -H ldap://ldap.example.net uid=hon
-noout -text
prints the data as formatted text instead of raw Base64.openssl x509 -in <cert-file> [-inform der] -noout -text
openssl s_client -servername <host> -connect <site>:443 </dev/null | openssl x509 -noout -text
openssl pkcs12 -in hon.wtf.pfx -clcerts -nokeys -out hon.wtf.key-2023
openssl pkcs12 -in hon.wtf.pfx -nocerts -out hon.wtf.key.enc-2023
openssl rsa -in hon.wtf.key.enc-2023 -out hon.wtf.key-2023
openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -out localhost.crt -keyout localhost.key -config <(
cat <<-EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = ext
distinguished_name = dn
[ext]
subjectAltName = @alt_names
basicConstraints = CA:FALSE
#keyUsage = digitalSignature, keyEncipherment
#extendedKeyUsage = serverAuth
[dn]
C = ZZ
ST = Localhost
L = Localhost
O = Localhost
OU = Localhost
emailAddress = webmaster@localhost
CN = localhost
[alt_names]
DNS.1 = *.localdomain.
EOF
)
docker logs pihole 2>&1 | grep "random password"
/etc/pihole/adlists.list
./etc/pihole/whitelist.txt
.pihole -g
to update lists.modprobe msr
apt install linux-tools-generic
git clone https://github.com/opcm/pcm
make
.x
suffixes.pcm
pcm-memory
pcm-latency
pcm-pcie
pcm-iio
pcm-numa
pcm-power
pcm-tsx
pcm-core
pcm-query
pcm-raw
pcm-hw-histogram
pcm-sensor-server
).pcm-sensor
pcm-service
pcm-sensor-server
Is typically run on a Docker host. Includes the agent.
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v ./data:/data portainer/portainer:<version>
/var/run/docker.sock
was mounted, use “local”.Must be run on a Docker host. For extra Docker hosts you want to control with another Portainer server.
docker run -d -p 9001:9001 --name portainer_agent --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent:<version>
_dmarc
subdomain: v=DMARC1; adkim=r; aspf=r; p=quarantine;
postfix libsasl2-modules mailutils
/etc/aliases
, add root: [email protected]
(to forward everything to [email protected]
).newaliases
to update the alias DB file. (Optionally restart postfix.service
to make it pick up the change instantly.)main.cf
config.
inet_interfaces = loopback-only
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
smtpd_banner = $myhostname ESMTP
compatibility_level = 2
apikey
as the username for API key access.touch sasl_passwd && chmod 600 sasl_passwd
[relay_domain]:port user@domain:password
postmap sasl_passwd
postfix
.echo "Test from $(hostname) at time $(date)." | mail -s "Test" root
Use this mess to change the ugly From: [email protected]
and To: [email protected]
to From: "Node" <[email protected]>
and To: "Admin" <[email protected]>
when most/all email coming from the system is from root to some root alias.
smtp_header_checks
file (arbitrary name).
main.cf
: smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
postmap -fq "From: root@$(hostname --fqdn)" regexp:smtp_header_checks
postfix
.echo "Test from $HOSTNAME at time $(date)." | mail -s "Test" root
postconf > /dev/null
postconf -n
mailq
tells you mails are stuck in the mail queue because of previous errors, run postqueue -f
to flush them.TODO
Logs are located in /app/storage/logs/laravel/
inside the container.
unzip
.{ "dns": ["1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"] }
to /etc/docker/daemon.json
.See Counter-Strike: Global Offensive (CS:GO).
radvd
./etc/radvd.conf
apt install samba
systemctl disable --now nmbd
and systemctl mask nmbd
global
section.server string
security = user
server min protocol = SMB3
map to guest = never
guest account = <username>
(typically defaults to nobody
)guest
) to use the guest user: map to guest = bad user
guest ok = {yes|no}
guest ok
is set) (share option): only guest = yes
disable netbios = yes
netbios name = <name>
(defaults to hostname)workgroup = <workgroup>
smb encrypt = required
server smb encrypt = required
server multi channel support
rss
interface option and stuff. Maybe multiple NICs/IP addresses are required.socket options = SO_KEEPALIVE TCP_NODELAY IPTOS_LOWDELAY
socket options = SO_KEEPALIVE IPTOS_THROUGHPUT
aio read size = 1
and aio write size = 1
use sendfile = yes
min receivefile size = 16384
/etc/samba/smb.conf
testparm -t
systemctl restart smbd
useradd -r <name>
smbpasswd -a <user>
sudo pdbedit -L -v
apt install cifs-utils
/root/.credentials/smb/<whatever>
):
user=<user>
password=<password>
/etc/fstab
, add: //<share> <mountpoint> cifs vers=3.1.1,uid=<uid>,gid=<gid>,credentials=<file>,iocharset=utf8 0 0
mount -a
mount -a
)./etc/fstab
entry, add ,noauto,x-systemd.automount,x-systemd.idle-timeout=30
.systemctl daemon-reload && systemctl restart remote-fs.target
apt install smartmontools
smartctl -a <dev>
smartctl -t <short|long|conveyance|select> [-C] <dev>
-C
: Foreground mode.apt install snmpd
/etc/snmp/snmpd.conf
systemctl enable --now snmpd
PermitRootLogin without-password
in case you need root access to the server with tools that don’t play nice with sudo.apt install tftpd-hpa
(note the d
)/etc/default/tftpd-hpa
TFTP_DIRECTORY="<dir>"
(e.g. /var/tftp
)TFTP_OPTIONS="[opt]*"
(see the most relevant options below)--secure
: Change the root directory to the specified TFTP_DIRECTORY
directory.--create
: Allow clients to upload new files. Existing files may be changed regardless.tftp:tftp
has read access.tftp:tftp
has write access to it.systemctl restart tftpd-hpa
apt install unbound dns-root-data
/etc/unbound/unbound.conf
/etc/hosts
contains the short and FQDN hostnames./etc/resolv.conf
.DNSStubListener=no
.DNS=::1
.systemd-resolved
./etc/resolv.conf
. nameserver 127.0.0.1
nameserver ::1
domain <domain>
search <domain-list>
systemctl restart unbound
drill sigfail.verteiltesysteme.net
should give an rcode of SERVFAIL
.drill sigok.verteiltesysteme.net
should give an rcode of NOERROR
./usr/share/dns/root.hints
.See Ubiquiti UniFi Controllers.
apt install wireguard
resolvconf
: ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf
/etc/wireguard/*.conf
wg-quick {up|down} <conf>
systemctl enable [email protected]
(for config /etc/wireguard/wg0.conf
)Example tunnel config:
[Interface]
# Generate with "wg genkey"
PrivateKey = <HIDDEN>
# Address for the local tunnel interface
Address = 10.234.0.3/31, 2a0f:9400:800f:ff01::1/127
DNS = 1.1.1.1, 2606:4700:4700::1111
[Peer]
# Get with "echo <privkey> | wg pubkey"
PublicKey = <HIDDEN>
# Add static route and reverse path filtering
# "0.0.0.0/0, ::/0" means this will be the default gateway, capturing all traffic
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = vpn.oolacile.hon.systems.:51823
# Keep the connection alive to keep firewall state alive (not very stealthy, though)
PersistentKeepalive = 25
See Storage: ZFS.