# Simpler server setup

I use my private server setup notes as a cheatsheet occasionally, but below is a simplified version of that, the way I adjusted it to set with a temporary free domain name (from afraid.org, without DNSSEC, so did not set DANE, either), without a secondary DNS server, without mailing lists, with uacme instead of certbot, and without mail submission via Postfix, since mail can be handled either completely over SSH, or Dovecot can handle both IMAP and submission. XMPP is also configured, for textual chats only: without a TURN server, a web interface, or file upload. A private IRC server is set to be accessible via a private network without TLS (by both clients and other servers) and client authentication, or from the Internet over TLS and with authentication. Using multiple domain names for the services.

## Initial setup

In this section we update the system, add users, configure SSH access, optionally set a text editor.

    # Check /etc/apt/sources.list
    apt update
    apt upgrade
    apt install sudo emacs-nox
    # Add a user
    adduser defanor
    adduser defanor sudo
    su defanor
    # The text editor setup is optional
    echo 'EDITOR="emacsclient -a emacs -t"' >> .profile
    source .profile
    echo 'alias em="emacsclient -a emacs -t"' >> .bashrc
    source .bashrc
    systemctl --user enable --now emacs
    # Enable linger to achieve persistent Emacs sessions
    sudo loginctl enable-linger $USER
    # Add SSH keys, configure sshd
    mkdir .ssh
    $EDITOR .ssh/authorized_keys
    sudo -e /etc/ssh/sshd_config
    # Ensure "PermitRootLogin no" and "PasswordAuthentication no"
    sudo systemctl reload sshd
    # Check that logging in as a user and sudo work, lock the root password
    sudo passwd -l root
    # Set time zone to UTC, locale to C.UTF-8
    sudo dpkg-reconfigure tzdata
    sudo -e /etc/default/locale

## DNS

We will set knot for authoritative DNS. This can be used for an ACME challenge afterwards, though a web server is also usable for that. It is convenient to host authoritative DNS servers, though some hosting companies may disable UDP while under DDoS attacks, which leads to lookup failures (even when TCP is supported, as in this case). Often one may use registrar-provided nameservers, or free ones, like those provided by Cloudflare.

    apt install knot knot-dnsutils
    sudo -e /etc/knot/knot.conf
    # A knot.conf example is in the next listing
    sudo -e /var/lib/knot/steady.mooo.com.zone
    sudo -e /var/lib/knot/beep.boop.ip-dynamic.org.zone
    # A zone file example is below

`/etc/knot/knot.conf` changes:

    --- original_configs/knot.conf  2024-08-29 18:41:48.485534350 +0000
    +++ /etc/knot/knot.conf 2024-09-29 12:20:50.446108496 +0000
    @@ -5,7 +5,7 @@
         rundir: "/run/knot"
         user: knot:knot
         automatic-acl: on
    -    listen: [ 127.0.0.1@53, ::1@53 ]
    +    listen: [ 127.0.0.1@53, ::1@53, 89.110.126.39@53 ]

     log:
       - target: syslog
    @@ -26,7 +26,26 @@
         storage: "/var/lib/knot"
         file: "%s.zone"

    +key:
    +  - id: uacme
    +    algorithm: hmac-sha512
    +    secret: SECRET_TSIG_KEY
    +
    +acl:
    +  - id: uacme_acl
    +    address: [127.0.0.1, ::1]
    +    action: update
    +    key: uacme
    +
     zone:
    +  - domain: steady.mooo.com
    +    acl: uacme_acl
    +    semantic-checks: on
    +
    +  - domain: beep.boop.ip-dynamic.org
    +    acl: uacme_acl
    +    semantic-checks: on
    +
     #    # Primary zone
     #  - domain: example.com
     #    notify: secondary

A zone file example, `/var/lib/knot/steady.mooo.com.zone`:

    @       10800   SOA     steady.mooo.com. hostmaster.steady.mooo.com. 726 43200 7200 2419200 86400
    @       10800   A       89.110.126.39
    @       10800   NS      steady.mooo.com.
    @       10800   TXT     "v=spf1 a mx ~all"
    @       10800   CAA     0 issue "letsencrypt.org"
    @       10800   MX      10 steady.mooo.com.
    _dmarc  10800   TXT     "v=DMARC1; p=quarantine"
    _adsp._domainkey        10800   TXT     "dkim=all"
    strudel2024._domainkey  10800   TXT     "v=DKIM1; h=sha256; k=rsa; p=KEY_HERE"
    _xmpp-client._tcp       10800   SRV     10 5 5222 steady.mooo.com.
    _xmpp-server._tcp       10800   SRV     10 5 5269 steady.mooo.com.
    _xmpp-server._tcp.chat  10800   SRV     10 5 5269 steady.mooo.com.

The zone file for beep.boop.ip-dynamic.org is similar. Had to use the fourth level domain for it, since cloudns.net serves SOA records itself (not allowing to override those on free plans), so third-level domain name delegation does not quite work.

## WWW

A web server is easy to set now:

    sudo apt install nginx
    sudo -e /etc/nginx/sites-available/general.conf
    sudo ln -s /etc/nginx/sites-available/general.conf /etc/nginx/sites-enabled/

And sample site configuration, `general.conf`:

    server {
            listen 80;
            listen 443 ssl;
            server_name steady.mooo.com beep.boop.ip-dynamic.org;
            ssl_certificate /etc/ssl/uacme/steady.mooo.com/cert.pem;
            ssl_certificate_key /etc/ssl/uacme/private/steady.mooo.com/key.pem;
            index index.xhtml index.html index.txt;

            location / {
                root   /var/www/general;
            }

            # User directories
            location ~ ^/~([^/]+)(.*)$ {
                alias /home/$1/public_html/$2;
            }

    }

## ACME

Listing two setups for X.509 certificate retrieval using the ACME protocol, the uacme client. In either case, `apt install uacme`, and do general configuration to run it under a dedicated user:

    sudo adduser --system uacme
    sudo mkdir /etc/ssl/uacme
    sudo chown uacme /etc/ssl/uacme
    sudo -u uacme uacme -v new
    # A DNS- or HTTP-specific "uacme issue" command here, see below.
    # Set the same uacme command on cron.daily, followed by "systemctl reload ..."
    sudo -e /etc/cron.daily/uacme-cert-update
    sudo chmod +x /etc/cron.daily/uacme-cert-update

### With DNS

    sudo keymgr -t uacme hmac-sha512
    sudo cp /usr/share/uacme/nsupdate.sh /usr/local/bin/uacme-nsupdate.sh
    sudo -e /usr/local/bin/uacme-nsupdate.sh
    # An uacme-nsupdate.sh adjusted for knot is below
    sudo -u uacme -e /etc/ssl/uacme/private/uacme.tsig
    # uacme.tsig contains the key produced by keymgr above
    sudo chmod 600 /etc/ssl/uacme/private/uacme.tsig
    sudo -u uacme uacme -h /usr/local/bin/uacme-nsupdate.sh issue \
      steady.mooo.com '*.steady.mooo.com' \
      beep.boop.ip-dynamic.org '*.beep.boop.ip-dynamic.org'

The `uacme-nsupdate.sh` hook script adjustments (though it is not suitable for a separate zone for `_acme-challenge`: the sample script's `ns_getdomain` procedure would fail to retrieve the domain):

    --- /usr/share/uacme/nsupdate.sh        2023-02-15 20:31:43.000000000 +0000
    +++ /usr/local/bin/uacme-nsupdate.sh    2024-09-30 11:29:02.484954804 +0000
    @@ -21 +21 @@
    -NSUPDATE=nsupdate
    +NSUPDATE=knsupdate
    @@ -29 +29 @@
    -RNDC_KEY_NSUPDATE=
    +RNDC_KEY_NSUPDATE=/etc/ssl/uacme/private/uacme.tsig
    @@ -106 +106,2 @@
    -            server ${nameserver}
    +            zone ${IDENT}.
    +            origin ${IDENT}.
    @@ -109,0 +111,4 @@
    +
    +    # Wait a little, since otherwise somehow Let's Encrypt sees old
    +    # records.
    +    sleep 5

The CAA DNS RR can be set to `0 issue "letsencrypt.org;validationmethods=dns-01"` then.

### With WWW

    sudo mkdir -p /var/www/general/.well-known/acme-challenge
    sudo chown uacme /var/www/general/.well-known/acme-challenge
    sudo -u uacme \
      UACME_CHALLENGE_PATH=/var/www/general/.well-known/acme-challenge/ \
      uacme -h /usr/share/uacme/uacme.sh issue \
      steady.mooo.com beep.boop.ip-dynamic.org

sudo -u uacme UACME_CHALLENGE_PATH=/var/www/general/.well-known/acme-challenge/ uacme -s -h /usr/share/uacme/uacme.sh issue steady.mooo.com beep.boop.ip-dynamic.org uberspace.net strudel.uberspace.net

## Email

### Postfix

Setting Postfix with OpenDKIM and SPF Engine first, for a basic mail server.

    sudo apt install postfix postfix-policyd-spf-python opendkim opendkim-tools
    sudo -u opendkim opendkim-genkey -D /etc/dkimkeys -d steady.mooo.com -s strudel2024
    sudo -e /etc/opendkim.conf
    # opendkim.conf adjustments are listed below
    # Aiming multiple domains, so using keytable and signingtable
    sudo tee /etc/dkimkeys/keytable <<EOF
    steady steady.mooo.com:strudel2024:/etc/dkimkeys/strudel2024.private
    beepboop beep.boop.ip-dynamic.org:strudel2024:/etc/dkimkeys/strudel2024.private
    EOF
    sudo tee /etc/dkimkeys/signingtable <<EOF
    *@steady.mooo.com steady
    *@beep.boop.ip-dynamic.org beepboop
    EOF
    sudo mkdir /var/spool/postfix/opendkim
    sudo chown opendkim:opendkim /var/spool/postfix/opendkim
    sudo systemctl restart opendkim
    sudo adduser postfix opendkim
    sudo -e /etc/postfix/master.cf
    sudo -e /etc/postfix/main.cf
    # master.cf and main.cf adjustments are listed below
    # Adjust access rules and mail aliases
    sudo -e /etc/postfix/postscreen_access.cidr
    sudo -e /etc/postfix/client_checks
    sudo postmap /etc/postfix/client_checks
    sudo -e /etc/postfix/sender_checks
    sudo postmap /etc/postfix/sender_checks
    sudo -e /etc/aliases
    sudo postalias /etc/aliases
    sudo systemctl restart postfix

`opendkim.conf` edits:

    --- original_configs/opendkim.conf      2024-08-30 06:36:30.982553576 +0000
    +++ /etc/opendkim.conf  2024-08-30 06:38:37.435019550 +0000
    @@ -24,0 +25,2 @@
    +KeyTable                file:/etc/dkimkeys/keytable
    +SigningTable            refile:/etc/dkimkeys/signingtable
    @@ -37 +39 @@
    -Socket                 local:/run/opendkim/opendkim.sock
    +#Socket                        local:/run/opendkim/opendkim.sock
    @@ -40 +42 @@
    -#Socket                        local:/var/spool/postfix/opendkim/opendkim.sock
    +Socket                 local:/var/spool/postfix/opendkim/opendkim.sock

The Postfix's `master.cf`:

    --- original_configs/master.cf  2024-08-30 06:48:45.213250773 +0000
    +++ /etc/postfix/master.cf      2024-08-30 07:01:25.308043639 +0000
    @@ -12,5 +12,5 @@
    -smtp      inet  n       -       y       -       -       smtpd
    -#smtp      inet  n       -       y       -       1       postscreen
    -#smtpd     pass  -       -       y       -       -       smtpd
    -#dnsblog   unix  -       -       y       -       0       dnsblog
    -#tlsproxy  unix  -       -       y       -       0       tlsproxy
    +#smtp      inet  n       -       y       -       -       smtpd
    +smtp      inet  n       -       y       -       1       postscreen
    +smtpd     pass  -       -       y       -       -       smtpd
    +dnsblog   unix  -       -       y       -       0       dnsblog
    +tlsproxy  unix  -       -       y       -       0       tlsproxy
    @@ -137,0 +138,4 @@
    +
    +# SPF with postfix-policyd-spf-python
    +policyd-spf  unix  -       n       n       -       0       spawn
    +  user=policyd-spf argv=/usr/bin/policyd-spf

And `main.cf`:

    --- original_configs/main.cf    2024-08-30 07:24:12.265070083 +0000
    +++ /etc/postfix/main.cf        2024-09-01 16:10:52.553840094 +0000
    @@ -27,2 +27,2 @@
    -smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
    -smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
    +smtpd_tls_cert_file=/etc/ssl/uacme/steady.mooo.com/cert.pem
    +smtpd_tls_key_file=/etc/ssl/uacme/private/steady.mooo.com/key.pem
    @@ -37 +37 @@
    -myhostname = strudel.uberspace.net
    +myhostname = steady.mooo.com
    @@ -41 +41 @@
    -mydestination = $myhostname, steady.mooo.com, strudel.uberspace.net, localhost.uberspace.net, localhost
    +mydestination = $myhostname, steady.mooo.com, beep.boop.ip-dynamic.org, strudel.uberspace.net, localhost
    @@ -44 +44,2 @@
    -message_size_limit = 0
    +message_size_limit = 20971520
    +mailbox_size_limit = 1073741824
    @@ -48,0 +50,53 @@
    +# Store messages in ~/Maildir/
    +home_mailbox = Maildir/
    +
    +# OpenDKIM
    +smtpd_milters = unix:opendkim/opendkim.sock
    +non_smtpd_milters = $smtpd_milters
    +milter_default_action = accept
    +internal_mail_filter_classes = bounce
    +
    +# Postscreen
    +postscreen_access_list = permit_mynetworks,
    +                         cidr:/etc/postfix/postscreen_access.cidr
    +postscreen_blacklist_action = drop
    +postscreen_greet_action = drop
    +postscreen_pipelining_enable = yes
    +postscreen_non_smtp_command_enable = yes
    +postscreen_bare_newline_enable = yes
    +postscreen_bare_newline_action = enforce
    +postscreen_dnsbl_action = enforce
    +postscreen_dnsbl_sites = zen.spamhaus.org*3
    +        b.barracudacentral.org*2
    +        bl.spameatingmonkey.net*2
    +        bl.spamcop.net
    +        dnsbl.sorbs.net
    +        psbl.surriel.com
    +        bl.mailspike.net
    +        list.dnswl.org=127.0.[0..14;16..255].0*-2
    +        list.dnswl.org=127.0.[0..14;16..255].1*-3
    +        list.dnswl.org=127.0.[0..9;11..14;16..255].[2..3]*-4
    +postscreen_dnsbl_threshold = 3
    +postscreen_dnsbl_whitelist_threshold = -1
    +
    +# Other anti-UCE
    +smtpd_helo_required = yes
    +disable_vrfy_command = yes
    +smtpd_recipient_restrictions =
    +        reject_invalid_hostname,
    +        reject_non_fqdn_hostname,
    +        reject_non_fqdn_sender,
    +        reject_non_fqdn_recipient,
    +        reject_unknown_sender_domain,
    +        reject_unknown_recipient_domain,
    +        permit_mynetworks,
    +        reject_unauth_destination,
    +        check_sender_access hash:/etc/postfix/sender_checks,
    +        check_client_access hash:/etc/postfix/client_checks,
    +        reject_rbl_client bl.spamcop.net,
    +        reject_rbl_client cbl.abuseat.org,
    +        check_policy_service unix:private/policyd-spf,
    +        permit
    +smtpd_data_restrictions =
    +                        reject_unauth_pipelining,
    +                        permit

At this point, the mail server's core is configured. It can be used with `sendmail(1)`, `mail(1)` from GNU mailutils (installed with Emacs), or Emacs clients, on the server itself. For instance, with mu4e:

    sudo apt install mu4e
    mu init --maildir=~/Maildir --my-address=defanor@steady.mooo.com --my-address=defanor@beep.boop.ip-dynamic.org

Then `M-x mu4e` in Emacs, and it is works for mail reading and composition, without additional configuration. But for external IMAP and SMTP clients, we could set Dovecot.

### Dovecot

Now to set IMAP access and submission over SMTP, with Dovecot: `sudo apt install dovecot-imapd dovecot-submissiond`, then adjust the following three configuration files:

    --- original_configs/10-mail.conf       2024-08-30 17:37:12.441632067 +0000
    +++ /etc/dovecot/conf.d/10-mail.conf    2024-08-30 16:51:40.139684081 +0000
    @@ -29,3 +29,3 @@
     #
    -mail_location = mbox:~/mail:INBOX=/var/mail/%u
    +mail_location = maildir:~/Maildir:LAYOUT=fs

This makes Dovecot to write files into `~/Maildir`, and to use the regular hierarchical directory layout, compatible with mu4e and other MUAs, as opposed to the Maildir++ directory layout, which prefixes mail folders with a dot. That way, maildirs on servers and clients are interchangeable, and MUAs ran on mail servers behave the same as those on personal computers.

    --- original_configs/10-ssl.conf        2024-08-30 17:37:51.361773007 +0000
    +++ /etc/dovecot/conf.d/10-ssl.conf     2024-08-30 16:53:20.508051171 +0000
    @@ -6 +6 @@
    -ssl = yes
    +ssl = required
    @@ -12,2 +12,2 @@
    -ssl_cert = </etc/dovecot/private/dovecot.pem
    -ssl_key = </etc/dovecot/private/dovecot.key
    +ssl_cert = </etc/ssl/uacme/steady.mooo.com/cert.pem
    +ssl_key = </etc/ssl/uacme/private/steady.mooo.com/key.pem

    --- original_configs/20-submission.conf 2024-08-30 17:31:46.480451752 +0000
    +++ /etc/dovecot/conf.d/20-submission.conf      2024-08-30 18:01:07.070829241 +0000
    @@ -45 +45 @@
    -#submission_relay_host =
    +submission_relay_host = localhost
    @@ -52 +52 @@
    -#submission_relay_trusted = no
    +submission_relay_trusted = yes

Reload the service, and it should work. Can be set with Emacs mail clients, but here is a basic mutt configuration (`~/.muttrc`) that works with this setup:

    set folder=imaps://defanor@steady.mooo.com/
    set spoolfile=+inbox
    mailboxes +inbox

    set record = +sent
    set realname=defanor
    set from=defanor@steady.mooo.com
    set smtp_url=smtp://defanor@steady.mooo.com:587/
    set ssl_starttls=yes
    unset smtp_pass

When I had to migrate the maildir to a new server, I have ultimately moved it with rsync, after attempting to simply synchronize with mbsync, removing its `.uidvalidity` and `.mbsyncstate` files, running into duplicated messages due to mbsync's X-TUID headers. Fortunately I backed up the maildir (made a tar archive) before the manipulations, so it was safe and easy to restore, did not have to clean up the duplicates. One may also employ `doveadm` for synchronization.

## XMPP

A basic XMPP setup here, just for textual chats.

    sudo apt install prosody
    sudo rm /etc/prosody/conf.d/localhost.cfg.lua
    sudo -e /etc/prosody/prosody.cfg.lua
    sudo chgrp ssl-cert /etc/ssl/uacme/private/{,steady.mooo.com/{,key.pem}}
    sudo chmod g+r /etc/ssl/uacme/private/steady.mooo.com/key.pem
    sudo chmod g+rx /etc/ssl/uacme/private/{,steady.mooo.com/}
    sudo adduser prosody ssl-cert
    sudo prosodyctl restart
    sudo prosodyctl adduser defanor@steady.mooo.com

And the configuration adjustments:

    --- original_configs/prosody.cfg.lua    2024-08-31 19:47:49.024239057 +0000
    +++ /etc/prosody/prosody.cfg.lua        2024-08-31 21:02:37.783514208 +0000
    @@ -24 +24 @@
    -admins = { }
    +admins = { "defanor@steady.mooo.com" }
    @@ -65 +65 @@
    -               --"mam"; -- Store recent messages to allow multi-device synchronization
    +               "mam"; -- Store recent messages to allow multi-device synchronization
    @@ -199,2 +199,2 @@
    -       info = "/var/log/prosody/prosody.log";
    -       error = "/var/log/prosody/prosody.err";
    +       -- info = "/var/log/prosody/prosody.log";
    +       -- error = "/var/log/prosody/prosody.err";
    @@ -202 +202 @@
    -       { levels = { "error" }; to = "syslog";  };
    +       { levels = { "info" }; to = "syslog";  };
    @@ -233,3 +233,5 @@
    -VirtualHost "localhost"
    --- Prosody requires at least one enabled VirtualHost to function. You can
    --- safely remove or disable 'localhost' once you have added another.
    +VirtualHost "steady.mooo.com"
    +ssl = {
    +  certificate = "/etc/ssl/uacme/steady.mooo.com/cert.pem";
    +  key = "/etc/ssl/uacme/private/steady.mooo.com/key.pem";
    +}
    @@ -245,2 +247,2 @@
    ----Set up a MUC (multi-user chat) room server on conference.example.com:
    ---Component "conference.example.com" "muc"
    +---Set up a MUC (multi-user chat) room server on chat.steady.mooo.com:
    +Component "chat.steady.mooo.com" "muc"
    @@ -248 +250 @@
    ---modules_enabled = { "muc_mam" }
    +modules_enabled = { "muc_mam" }

## IRC

This server is a part of a small private IRC network, using InspIRCd without IRC services; it is open to both virtual private network addresses (without TLS or client authentication) and via the Internet (with TLS and a password). It also binds a websocket on 127.0.0.1, to connect via a reverse proxy set with nginx (which is awkward and hides user IP addresses, but the KiwiIRC web interface does not support regular PASS authentication, so HTTP basic authentication with a secret websocket path is a hacky workaround). The setup is done as follows:

    sudo apt install inspircd
    sudo adduser irc ssl-cert
    sudo -e /etc/inspircd/inspircd.conf
    sudo systemctl reload inspircd

The relevant configuration changes for this particular setup are:

    --- original_configs/inspircd.conf      2024-12-08 13:28:17.188260631 +0000
    +++ /etc/inspircd//inspircd.conf        2024-11-30 14:18:19.958889434 +0000
    @@ -6,15 +6,42 @@

    -<server name="irc.local"
    -        description="Local IRC Server"
    -        network="Localnet">
    +<server name="10.0.255.62"
    +        description="The 0xa00ff3e IRC Server"
    +        network="Womblenet">

    -<admin name="Root Penguin"
    -       nick="Nick"
    -       email="root@localhost">
    +<admin name="defanor"
    +       nick="defanor"
    +       email="defanor@steady.mooo.com">

    -<bind address="127.0.0.1" port="6667" type="clients">
    +<bind address="10.0.255.62" port="6667" type="clients">

    -<power diepass="3456" restartpass="7890">
    +<power diepass="PASSWORD" restartpass="PASSWORD">

    -<connect allow="*"
    +<module name="ssl_gnutls">
    +
    +<gnutls onrehash="yes">
    +
    +<sslprofile name="Clients"
    +            provider="gnutls"
    +            certfile="/etc/ssl/uacme/steady.mooo.com/cert.pem"
    +            keyfile="/etc/ssl/uacme/private/steady.mooo.com/key.pem">
    +
    +<bind address="89.110.126.39" port="6697" sslprofile="Clients" type="clients">
    +
    +<connect name="Secure"
    +         parent="Main"
    +         allow="*"
    +         port="6697"
    +         password="PASSWORD">
    +
    +<connect name="Plain"
    +         parent="Main"
    +         allow="*"
    +         port="6667">
    +
    +<connect name="Websocket"
    +         parent="Main"
    +         allow="*"
    +         port="6687">
    +
    +<connect name="Main"
              timeout="60"
    @@ -26,3 +53,4 @@
              localmax="3"
    -         globalmax="3">
    +         globalmax="3"
    +        resolvehostnames="no">

    @@ -40,14 +68,11 @@
     <type name="NetAdmin"
    -      classes="OperChat BanControl HostCloak Shutdown ServerLink"
    -      host="netadmin.omega.org.za">
    +      classes="OperChat BanControl HostCloak Shutdown ServerLink">
     <type name="GlobalOp"
    -      classes="OperChat BanControl HostCloak ServerLink"
    -      host="ircop.omega.org.za">
    +      classes="OperChat BanControl HostCloak ServerLink">
     <type name="Helper"
    -      classes="HostCloak"
    -      host="helper.omega.org.za">
    +      classes="HostCloak">

    -<oper name="root"
    -      password="12345"
    -      host="*@localhost"
    +<oper name="defanor"
    +      password="PASSWORD"
    +      host="*@10.0.255.66/30 *@10.0.255.62/30"
           type="NetAdmin">
    @@ -59,3 +84,3 @@

    -<dns server="127.0.0.1" timeout="5">
    +<dns enabled="no" server="127.0.0.1" timeout="5">

    @@ -93 +118,19 @@
     <badnick nick="MemoServ" reason="Reserved For Services">
    +
    +<module name="spanningtree">
    +<bind address="10.0.255.62" port="7000" type="servers" defer="5s">
    +<link name="10.0.255.66"
    +      ipaddr="10.0.255.66"
    +      port="7000"
    +      allowmask="10.0.255.66/32"
    +      sendpass="PASSWORD"
    +      recvpass="PASSWORD">
    +
    +
    +<module name="sha1">
    +<module name="websocket">
    +<wsorigin allow="*">
    +<bind address="127.0.0.1"
    +      port="6687"
    +      type="clients"
    +      hook="websocket">

## nftables and fail2ban

To reduce spam in the logs:

    apt install fail2ban
    sudo -e /etc/fail2ban/jail.local
    sudo systemctl restart fail2ban

A jail.local example from the old notes works, but with `backend = systemd` in the DEFAULT section, now that there are no traditional textual log files by default.

Likewise with nftables: I took the old nftables configuration, only slightly adjusting it.