This is based off a 12.04 reference image which I upgraded to 14.04, 16.04, 18.04, and then to 20.04.
I picked Newark for the location.
-
I picked 2048MB swap and used the rest for the single server
-
Don't forget to configure DNS
-
DNS servers:
- ns1.linode.com
- ns2.linode.com
- ns3.linode.com
- ns4.linode.com
- ns5.linode.com
-
And make sure to add an SPF record - it's a text record. By default, it's just:
v=spf1 mx ~all
- Which says "accept mail from any servers which have an a record, and if it's not, soft fail it."
-
Updates!
sudo apt update sudo apt dist-upgrade
-
Make accounts
adduser matt usermod -a -G sudo,adm matt adduser liz usermod -a -G sudo,adm liz
and for the boys' emails:
adduser miles18 usermod -L miles18 adduser max18 usermod -L max18
-
Install users'
authorized_keys
files in to~/.ssh
-
Set up ssh
-
For an old machine, use the old keys - you did save /etc, didn't you?
-
For a new machine, use the new keys generated by the distro.
-
make sure to add to the firewall
ufw allow ssh
-
In
/etc/ssh/ssh_config
, set:PermitRootLogin forced-commands-only
(the forced commands only is so we can run backups) and set
PasswordAuthentication no
-
restart it
service ssh restart
-
-
Enable firewall
sudo ufw enable
-
Set the hostname:
-
Edit
/etc/hostname
and set it to linode -
Edit
/etc/hosts
and set the 127.0.1.1 line to look like:127.0.1.1 linode
This will prevent bounce messages from some mailservers, since they rely on the host name that the server claims to be (which is gotten from /etc/hostname) and then try to reverse that and make sure they're the same.
-
-
Install useful things
sudo apt install tree emacs-nox git software-properties-common snapd iftop htop
-
Set up letsencrypt certbot
-
Install certbot snap
sudo snap install --classic certbot
-
Set it up semi-manually:
sudo certbot --standalone certonly -d mattcaron.net,www.mattcaron.net sudo certbot --standalone certonly -d owncloud.mattcaron.net sudo certbot --standalone certonly -d sympa.mattcaron.net sudo certbot --standalone certonly -d mail.mattcaron.net sudo certbot --standalone certonly -d lists.pfmbonsai.com sudo certbot --standalone certonly -d pfmbonsai.com sudo certbot --standalone certonly -d school.mattcaron.net sudo certbot --standalone certonly -d chat.mattcaron.net sudo certbot --standalone certonly -d video.mattcaron.net
-
Make the directories in /etc group accessible by ssl-cert and make the gid sticky
sudo chgrp -R ssl-cert /etc/letsencrypt sudo chmod -R g+rsX /etc/letsencrypt
-
Move everything in
/etc/ssl/private
to old, and then make new symlinks to the things in/etc/letsencrypt
. -
Add create
/etc/cron.d/letsencrypt
thusly:# /etc/cron.d/letsencrypt: crontab entries to check for new certs PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/snap/bin MAILTO=root 37 01 * * * root service apache2 stop; certbot renew; chmod -R g+r /etc/letsencrypt; service apache2 start; service dovecot reload; service exim4 reload
Note that:
- we restart services
- we fix up the permissions to be group readable, because new files will be created as 0600.
-
-
Install apache
-
Install packages:
sudo apt install apache2 libapache2-mod-php php php-cli php-pear php-db php-mysql mysql-server php-apcu
-
Enable the userdir and rewrite modules
sudo a2enmod userdir sudo a2enmod rewrite sudo a2enmod ssl sudo a2enmod php7.4
-
Fix up the php configuration by editing
/etc/apache2/mods-available/php7.4.conf
and commenting out this bit:# <IfModule mod_userdir.c> # <Directory /home/*/public_html> # php_admin_value engine Off # </Directory> # </IfModule>
-
Restart
sudo service apache2 restart
-
Go through this and apply all settings:
-
Allow it through the firewall
sudo ufw allow http sudo ufw allow https
-
-
Install dovecot (imap)
-
Install it:
sudo apt install dovecot-imapd
-
Configure it:
-
Edit
/etc/dovecot/conf.d/10-master.conf
and:-
find the
inet_listener imaps
line, and uncomment the body. -
find the
service auth
section and add to the bottom:#SASL unix_listener auth-client { mode = 0600 user = Debian-exim }
-
-
Edit
/etc/dovecot/conf.d/10-mail.conf
and find themail_location
line, uncomment it and set it to:mail_location = maildir:/home/%u/Maildir
-
Edit
/etc/dovecot/conf.d/10-ssl.conf
and:-
Change it to use the mattcaron.net cert:
ssl_cert = </etc/ssl/private/mail.mattcaron.net/fullchain.pem ssl_key = </etc/ssl/private/mail.mattcaron.net/privkey.pem
-
Change ssl to "required"
ssl = required
-
-
Edit
/etc/dovecot/conf.d/20-imap.conf
and set:mail_max_userip_connections = 100
(because I have a ton of machines that poll for email behind a NAT)
-
Edit /etc/dovecot/conf.d/15-lda.conf and set:
postmaster_address = postmaster
Yes, this is kind of stupid, especially in light of the comment in the config preceding this line, but I've been getting errors about how it's not set, to just explicitly set it to the sane default.
-
-
Pre-create the maildir for new users
sudo maildirmake.dovecot /etc/skel/Maildir sudo maildirmake.dovecot /etc/skel/Maildir/.Drafts sudo maildirmake.dovecot /etc/skel/Maildir/.Sent sudo maildirmake.dovecot /etc/skel/Maildir/.Trash sudo maildirmake.dovecot /etc/skel/Maildir/.Templates sudo maildirmake.dovecot /etc/skel/Maildir/.Junk
-
Set it up for any existing users:
sudo cp -r /etc/skel/Maildir /home/myuser/ sudo chown -R myuser:usergroup /home/myuser/Maildir sudo chmod -R 700 /home/myuser/Maildir
-
Allow it through the firewall
sudo ufw allow imaps
-
-
Exim
-
Install it
sudo apt install exim4-daemon-heavy exim4
-
Find the default exim configuration file (called
configure.default
, and found in thesrc/
directory of the source code and modify it as follows:primary_hostname = mattcaron.net domainlist local_domains = mattcaron.net : pfmbonsai.com domainlist relay_to_domains = hostlist relay_from_hosts = localhost tls_advertise_hosts = * tls_privatekey = /etc/ssl/private/mail.mattcaron.net/privkey.pem daemon_smtp_ports = 25 : 465 tls_on_connect_ports = 465 qualify_domain = mattcaron.net auth_advertise_hosts = ${if eq {$tls_cipher}{}{}{*}}
-
Find the system_aliases router and change the line:
data = ${lookup{$local_part}lsearch{SYSTEM_ALIASES_FILE}}
to:
data = ${lookup{$local_part}lsearch{/etc/aliases}}
Ref: https://github.com/Exim/exim/wiki/AuthenticatedSmtpUsingPam
-
At the bottom of the main section (before ACL CONFIGURATION), add:
# Only allow auth over TLS, otherwise folks would be sending plaintext passwords auth_advertise_hosts = ${if eq {$tls_cipher}{}{}{*}}
-
Down at the bottom, at the end of the AUTHENTICATION CONFIGURATION, add:
dovecot_plain: driver = dovecot public_name = PLAIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1
Note that we don't use the default debian config, as it is annoying.
-
-
Then copy the modified file to
/etc/exim4/exim4.conf
on the remote server. Make sure it's group readable and growned byDebian-exim
. -
Make the
Debian-exim
user a member of the shadow group so it can read/etc/shadow
and therefore do authentication. Also, thessl-cert
group, so it can read certs.sudo usermod -a -G ssl-cert Debian-exim sudo usermod -a -G shadow Debian-exim
-
Make a pam config for it - we'll just piggyback on the dovecot one, as it's reasonable and similar
cd /etc/pam.d sudo ln -s dovecot exim4
-
Allow through firewall
sudo ufw allow smtp sudo ufw allow ssmtp
-
-
Integrate exim with dovecot
-
Edit
/etc/exim4/exim4.conf
-
At the bottom of the routers section, add the following (or change existing to look the same):
localuser: driver = accept check_local_user # local_part_suffix = +* : -* # local_part_suffix_optional transport = dovecot_delivery cannot_route_message = Unknown user
-
Create a new transport for dovecot-lda:
dovecot_delivery: driver = pipe # You may or may not want to add -d $local_part@$domain depending on if # you need a userdb lookup done. command = /usr/lib/dovecot/dovecot-lda -f $sender_address message_prefix = message_suffix = log_output delivery_date_add envelope_to_add return_path_add #group = mail #mode = 0660 temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78
-
Create a new transport for dovecot-lda - spammy version
dovecot_spam_junk_delivery: driver = pipe # You may or may not want to add -d $local_part@$domain depending on if # you need a userdb lookup done. command = /usr/lib/dovecot/dovecot-lda -f $sender_address -m Junk message_prefix = message_suffix = log_output delivery_date_add envelope_to_add return_path_add #group = mail #mode = 0660 temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78
-
-
-
Set up DKIM signing (because, you know, spammers won't sign messages or spoofing is a problem or, something..)
-
Make some directories to hold things:
sudo mkdir /etc/exim4/dkim cd /etc/exim4/dkim
-
Generate keys for each domain:
sudo openssl genrsa -out mattcaron.net.private.pem 2048 -outform PEM sudo openssl rsa -in mattcaron.net.private.pem -out mattcaron.net.pem -pubout -outform PEM sudo openssl genrsa -out pfmbonsai.com.private.pem 2048 -outform PEM sudo openssl rsa -in pfmbonsai.com.private.pem -out pfmbonsai.com.pem -pubout -outform PEM
-
Publish the public keys in DNS using the date as the selector.
- IMPORTANT - my current exim config exim uses the same selector (date) for ALL domains, so they all need to match.
-
Fix perms on generated files:
sudo chown -R Debian-exim:Debian-exim /etc/exim4/dkim sudo chmod -R go-rwx /etc/exim4/dkim
-
In
/etc/exim4/exim4.conf
:-
Cchange the
remote_smtp
section to be like this:remote_smtp: driver = smtp dkim_canon = relaxed dkim_selector = 20151029 dkim_domain = ${sg{${lc:${domain:$h_from:}}}{^www\.}{}} dkim_private_key = ${if exists{/etc/exim4/dkim/${dkim_domain}.private.pem}{/etc/exim4/dkim/${dkim_domain}.private.pem}{0}}
-
Allow remote MUA's to set the sender for the envelope. This stops exim from stripping it and forcing it to be the canonical domain (so we can support multiple virtual domains). Anyway, go to the end of the Main Configuration section, right above ACL CONFIGURATION and add:
local_sender_retain = true local_from_check = false
-
-
-
Configure the time zone:
sudo dpkg-reconfigure tzdata
and set it to America/New York
-
Add spamassassin and other optional dependencies:
-
install
sudo apt install spamassassin libdigest-sha-perl libgeo-ip-perl libio-socket-ip-perl libencode-detect-perl libnet-patricia-perl libmodule-install-perl
Note: this is helpful for debugging:
spamassassin -D --lint 2>&1 | grep -i failed
-
In
/etc/exim4/exim4.conf
:-
add the following router right before the "localuser" router:
# router to send incoming email to spamchek transport for checking spamcheck_router: no_verify check_local_user # When to scan a message : # - it isn't already flagged as spam # - it isn't already scanned # - it isn't sent from my private home server # - it isn't sent from the server (linode or localhost) condition = "${if and { {!def:h_X-Spam-Flag:} {!eq {$received_protocol}{spam-scanned}} {!match {$sender_host_address} {${lookup dnsdb{a=mattandliz.dyndns.org}}}} {!match {$sender_host_address} {${lookup dnsdb{a=mattcaron.net}}}}} {1}{0}}" driver = accept transport = spamcheck # router to deliver spam to the junk folder spam_deliver_to_junk driver = accept check_local_user local_parts = !www:!root:!nobody:!postmaster:!abuse:!admin transport = dovecot_spam_junk_delivery condition = ${if def:h_X-Spam-Flag: {true}}
-
add the following transport (it can go anywhere, order doesn't matter)
# Scan for spam via spamassassin. Note that this works by calling exim # *again* and essentially redlivering the message, except that it has # already been scanned (see the "spam-scanned" add here, and the conditional # up in the router), so it only gets called the first time spamcheck: debug_print = "T: spamassassin_pipe for $local_part@$domain" driver = pipe command = /usr/sbin/exim4 -oMr spam-scanned -bS use_bsmtp # run the filter as debian-spamd because it has access to all of the # spamassassin files transport_filter = /usr/bin/spamc -u debian-spamd home_directory = "/tmp" current_directory = "/tmp" # must use a privileged user to set $received_protocol on the way back in! user = Debian-exim group = Debian-spamd return_fail_output message_prefix = message_suffix = # This delivers mail via dovecot to the Junk folder. dovecot_spam_junk_delivery: driver = pipe # You may or may not want to add -d $local_part@$domain depending on if # you need a userdb lookup done. command = /usr/lib/dovecot/dovecot-lda -f $sender_address -m Junk message_prefix = message_suffix = log_output delivery_date_add envelope_to_add return_path_add #group = mail #mode = 0660 temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78
-
-
Edit /etc/spamassassin/local.cf and change as follows:
rewrite_header Subject *****SPAM*****
-
Once all of the above is set up, edit
/etc/default/spamassassin
and set:ENABLED=1
and:
CRON=1
-
Set up the global bayes learning directory. It will be group rw for the
adm
group, as it's assumed that only those users would ssh in and teach it things. Also,spamd
changes uid toDebian-exim
, so make sure that user owns the DB and can read things. (You may have to run thechown
again after creating the databases withsa-learn
). It also likes to change group IDs on the files, so you need to make sure that all those are correct, and that any users who are going to train SA are in theDebian-exim
group (which implies that you trust them).sudo mkdir -p /var/spamassassin/bayes_db sudo chown -R Debian-exim:debian-spamd /var/spamassassin sudo chmod -R g+rwX /var/spamassassin sudo chmod g+s /var/spamassassin sudo usermod -a -G debian-spamd <user list>
The g+s looks a little odd here, but let me explain. The
spamcheck
transport runs as Debian-exim, which will create/var/spamassassin/bayes_journal
if it does not exist. However, thespamd
process likes to run asdebian-spamd
(so it can access all its files), which won't be able to read said journal and will complain bitterly. By setting the directory to be setgid, all created files will have the correct gid set, ensuring that bothDebian-exim
anddebian-spamd
can read and write everything in it. This also means that thesa_learn
wrapper that I run periodically will work, because I am in thedebian-spamd
group. -
Add the following to
/etc/spamassassing/local.cf
, so that it uses the above (note that the last part ofbayes_path
is a prefix, not a directory).use_bayes 1 bayes_path /var/spamassassin/bayes_db/bayes bayes_file_mode 0660
-
Also, because we only have a couple of users, limit children - edit
/etc/default/spamassassin
and set:OPTIONS="--create-prefs --max-children 5 --helper-home-dir"
to
OPTIONS="--create-prefs --max-children 2 --helper-home-dir"
-
restart
sudo service spamassassin restart
-
-
Edit
/etc/aliases
and:-
change root to go to matt:
root: matt
-
-
Add sympa
-
Establish base checkout:
cd ~/workspace/code git clone https://github.com/sympa-community/sympa.git cd sympa git checkout -b production 6.2.66
to upgrade later:
cd ~/workspace/code/sympa git fetch git checkout production git merge 6.2.66
(where 6.2.66 is the current version)
-
Copy this whole mess over to the linode server:
push_sympa
== All the rest of this is on the linode server ==
-
Install prerequisites
sudo apt install libapache2-mod-fcgid libdbd-mysql-perl apache2-suexec-pristine apache2-suexec-pristine intltool libclass-singleton-perl libdatetime-format-mail-perl libemail-simple-perl libnet-cidr-perl libproc-processtable-perl libcrypt-openssl-x509-perl libcrypt-smime-perl libdata-password-perl libauthcas-perl libdbd-odbc-perl libclone-perl libcrypt-eksblowfish-perl libdbd-csv-perl
-
Create a user w/ no shell and a given uid/gid which are the next available
sudo adduser sympa --uid 110 --gid 117 --disabled-login sudo usermod -s /bin/false sympa
-
Enable apache modules
sudo a2enmod suexec sudo a2enmod cgi
-
Set the versions in the environment (subsequent shells use this to save typing):
export VER=6.2.66 export OLDVER=6.2.64
-
Make the destination directory:
sudo mkdir /opt/sympa-${VER} sudo chown matt:matt /opt/sympa-${VER}
-
Build and install it:
cd ~/workspace/code/sympa autoreconf -i ./configure --prefix=/opt/sympa-${VER} --sysconfdir=/opt/sympa-${VER}/etc/ --with-initdir=/opt/sympa-${VER}/etc/init.d --with-cgidir=/opt/sympa-${VER}/cgi-bin --without-smrshdir make make install
-
Fix permissions
sudo chown -R sympa:sympa /opt/sympa-${VER} sudo chmod a+rX -R /opt/sympa-${VER} sudo chown -R sympa:sympa /var/spool/sympa sudo chown -R sympa:sympa /var/lib/sympa
-
Make some compatibilty symlinks:
sudo -E -u sympa -s cd /opt/sympa-${VER} ln -s /var/lib/sympa/expl . ln -s /var/lib/sympa/wwsarchive . ln -s /var/lib/sympa/x509-user-certs . cd /opt/sympa-${VER}/etc ln -s /etc/sympa . cd /opt/sympa-${VER}/static_content rmdir css ln -s /var/lib/sympa/static_content/css . ln -s /etc/mail/sympa/aliases /etc/mail/sympa_aliases cp -a /opt/sympa-${OLDVER}/spool /opt/sympa-${VER} exit sudo service sympa stop cd /opt sudo rm sympa sudo ln -s sympa-${VER}/ sympa cd /etc/init.d sudo ln -s /opt/sympa/etc/init.d/sympa . cd /etc/rc6.d ln -s ../init.d/sympa K99sympa cd /etc/rc5.d ln -s ../init.d/sympa S99sympa cd /etc/rc4.d ln -s ../init.d/sympa S99sympa cd /etc/rc3.d ln -s ../init.d/sympa S99sympa cd /etc/rc2.d ln -s ../init.d/sympa S99sympa cd /etc/rc1.d ln -s ../init.d/sympa K99sympa cd /etc/rc0.d ln -s ../init.d/sympa K99sympa cd /etc sudo ln -s /etc/sympa/sympa.conf . cd /var/lib/sympa/ mkdir pictures
-
Run the upgrade script (on upgrade)
sudo -u sympa /opt/sympa-${VER}/bin/sympa.pl --upgrade
-
Auto-install a pile of perl modules:
sudo /opt/sympa-${VER}/bin/sympa_wizard.pl --check
(hit enter a bunch of times)
-
Fix up supporting bits and bobs
sudo touch /etc/sympa/facility sudo chown sympa:sympa /etc/sympa/facility sudo mkdir -p /var/lock/subsys/sympa sudo chown sympa:sympa /var/lock/subsys/sympa sudo mkdir /var/spool/sympa/wwsbounce sudo chown sympa:sympa /var/spool/sympa/wwsbounce sudo chmod u+s /opt/sympa/bin/queue /opt/sympa/bin/bouncequeue
The queue needs to be suid root so that the mail server works when it calls queue and bouncequeue. Some of the routers call the filter and that needs to be as sympa, but we still want them to run other actions as exim.
-
Set up the configs:
-
Edit
/etc/sympa/wwsympa.conf
and comment out:#ldap_force_canonical_email 1
-
Edit
/etc/sympa/sympa.conf
and set the followinglistmaster [email protected] create_list listmaster wwsympa_url https://sympa.mattcaron.net/wws
-
Edit
/etc/exim4/exim4.conf
and add the following belowsystem_aliases
:sympa_aliases_domain: driver = redirect domains = +local_domains allow_fail allow_defer data = ${lookup{$local_part@$domain}lsearch{/etc/mail/sympa/aliases}} user = sympa group = sympa file_transport = address_file pipe_transport = address_pipe # Aliases for sympa sympa_aliases: driver = redirect domains = +local_domains allow_fail allow_defer data = ${lookup{$local_part}lsearch{/etc/mail/sympa/aliases}} user = sympa group = sympa file_transport = address_file pipe_transport = address_pipe
-
-
Remove
/etc/apache2/conf.d/sympa
(if it exists; it's just a symlink) and instead set up/etc/apache2/sites-available/sympa
as follows:<VirtualHost *:80> ServerName sympa.mattcaron.net ServerAdmin [email protected] Redirect permanent / https://sympa.mattcaron.net/wws </VirtualHost> <VirtualHost *:443> ServerName sympa.mattcaron.net ServerAdmin [email protected] SSLEngine on SSLCertificateFile /etc/ssl/private/sympa.mattcaron.net/fullchain.pem SSLCertificateKeyFile /etc/ssl/private/sympa.mattcaron.net/privkey.pem # Standard SSL protocol adustments for IE BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown Alias /static-sympa /opt/sympa/static_content ScriptAlias /wws /var/www/sympa/wwsympa.cgi SuexecUserGroup sympa sympa # Use simple cgi here. It's not heavily used and base cgi is the most # compatible AddHandler cgi-script .fcgi .cgi .pl .sh RewriteEngine On RewriteRule ^/$ /wws [R,L] <Directory "/var/www/sympa/"> AllowOverride None Options ExecCGI Order allow,deny Allow from all </Directory> </VirtualHost>
1. Fake out `suexec`, because it is hardcoded to want things in `/var/www`: 1. Make dir: sudo mkdir /var/www/sympa/ sudo chmod a+rx /var/www/sympa/ sudo chown sympa:sympa /var/www/sympa/ 1. Create `/var/www/sympa/wwsympa.cgi`: #!/bin/sh # The script we want Sympa to execute is accessed via a symlink but # suexec doesn't like that so this script is a wrapper which gets # executed directly to avoid that problem. exec /opt/sympa/cgi-bin/wwsympa.fcgi 1. Fix the perms on it: sudo chown sympa:sympa /var/www/sympa/wwsympa.cgi sudo chmod u+x /var/www/sympa/wwsympa.cgi
-
/etc/sympa/sympa.conf
changes:-
Limit number of spawned bulk processes, set:
bulk_max_count 1
-
Make sure
dmarc_protection_mode
is set in the config - add this to the bottom:# Munge email which would otherwise be dropped. dmarc_protection_mode dmarc_any
-
-
Fix up the mailserver aliases
/etc/aliases
and/etc/mail/sympa/aliases
by replacing/usr/lib/sympa/lib/sympa
with/opt/sympa/bin
(if necessary) -
Restart things as necesary.
sudo service apache2 restart sudo systemctl daemon-reload sudo service sympa restart
-
Don't forget to add sympa.mattcaron.net to DNS
-
Edit
/etc/sympa/topics.conf
, delete everything, then add:gaming title Gaming gaming/roleplaying_games title Role Playing Games gaming/wargaming title Wargaming
-
Add a second domain for sympa
-
In
/etc/exim4/exim4.conf
, add the following under ROUTERS CONFIGURATION before the big comment block preceding system_aliases(because order matters for exim):# This router does the same as system_aliases, except that it checks # the domain as well. # # IMPORTANT: Needs to go before things that match on ! +local_domains # and, most importantly, before the bl_server bit because that # forwards all non-local domains off to msex1. # # Remember - routers are run in order # system_aliases_domain: driver = redirect allow_fail allow_defer data = ${lookup{$local_part@$domain}lsearch{/etc/aliases}} # user = exim file_transport = address_file pipe_transport = address_pipe
-
Add any new domains to the top of
/etc/mail/sympa/aliases
, as necessary. As in:[email protected]: "| /opt/sympa/bin/queue [email protected]" [email protected]: "| /opt/sympa/bin/queue [email protected]" bounce+*@domain.com: "| /opt/sympa/bin/bouncequeue [email protected]"
-
And add the following to
/etc/exim4/exim4.conf
, in the ROUTERS CONFIGURATION section (doesn't matter where):# Aliases for sympa (robot virtual subdomains) sympa_aliases_robot: driver = redirect domains = +local_domains allow_fail allow_defer data = ${lookup{$domain-$local_part}lsearch{/etc/mail/sympa/aliases}} user = sympa group = sympa file_transport = address_file pipe_transport = address_pipe
-
Create bits / copy in defaults:
sudo mkdir /etc/sympa/domain.com sudo cp /home/matt/workspace/code/sympa/doc/samples/robot.conf /etc/sympa/domain.com/. sudo chown -R sympa:sympa /etc/sympa/domain.com sudo chmod 750 /etc/sympa/domain.com sudo chmod 640 /etc/sympa/domain.com/robot.conf sudo mkdir /var/lib/sympa/domain.com sudo chown sympa:sympa /var/lib/sympa/domain.com sudo chmod 750 /var/lib/sympa/domain.com
-
Edit
/etc/sympa/domain.com/robot.conf
-
Set as follows:
http_host sympa.domain.com listmaster [email protected] title New Domain MailingLists Service
and, below http_host, you'll want to add:
wwsympa_url https://sympa.domain.com/wws
-
-
Create
/etc/sympa/domain.com/topics.conf
topic1 title Some Topic topic2 title Some other topic general title General Membership
-
Restart
sudo service sympa restart
-
-
-
Set up mysql snapshot
-
Clone backup utils:
mkdir -p ~/workspace/code/scripts cd ~/workspace/code/scripts git clone https://github.com/mattcaron/backup_scripts.git mkdir ~/bin cd ~/bin ln -s ~/workspace/code/scripts/backup_scripts/mysql_backup . mkdir -p ~/attic/backup/`hostname`
-
Create
~/attic/backup/``hostname``/mysql.pw
and put the root password into it. -
fix perms:
chmod 600 ~/attic/backup/`hostname`/mysql.pw
-
Add to crontab:
@daily /home/matt/bin/mysql_backup > /dev/null
-
-
Lock root account
sudo usermod -L root
-
Add monitoring:
-
Make sure landscape is installed (to get landscape-sysinfo):
sudo apt install landscape-common
-
Then add the following to my crontab:
@daily /usr/bin/ntpq -p; echo; df -lh; echo; landscape-sysinfo
-
-
OwnCloud / NextCloud
-
Make sure to add owncloud.mattcaron.net to linode DNS
-
Optimization ref (probably obsolete)
-
Install deps:
sudo apt install apache2 php php-mbstring php-gd php-xml php-intl php-sqlite3 php-mysql curl libcurl4 php-curl libapache2-mod-xsendfile php-apcu php-bz2 php-zip php-pclzip php-imagick php-bcmath php-gmp
-
Download tarball (add to source control, etc.)
-
Make the xsendfile cache:
sudo mkdir /tmp/oc-noclean sudo chown www-data:www-data /tmp/oc-noclean
-
Increase PHP's memory limit:
-
Edit
/etc/php/7.4/apache2/php.ini
-
Find:
memory_limit = 128M
and set it to:
memory_limit = 512M
-
-
Log in to the DB server and create a user and password
CREATE DATABASE owncloud; GRANT ALL PRIVILEGES ON owncloud.* TO "owncloud"@"localhost" IDENTIFIED BY "password";
-
Make an
/etc/apache2/sites-available/owncloud.mattcaron.net
as follows:<VirtualHost *:80> ServerName owncloud.mattcaron.net ServerAdmin [email protected] DocumentRoot /home/matt/public_html/owncloud.mattcaron.net <Directory /home/matt/public_html/owncloud.mattcaron.net> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all SetEnv MOD_X_SENDFILE_ENABLED 1 XSendFile On XSendFilePath /tmp/oc-noclean </Directory> </VirtualHost> <VirtualHost *:443> ServerName owncloud.mattcaron.net ServerAdmin [email protected] SSLEngine on SSLCertificateFile /etc/ssl/private/owncloud.mattcaron.net/fullchain.pem SSLCertificateKeyFile /etc/ssl/private/owncloud.mattcaron.net/privkey.pem # Standard SSL protocol adustments for IE BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown DocumentRoot /home/matt/public_html/owncloud.mattcaron.net <Directory /home/matt/public_html/owncloud.mattcaron.net> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all SetEnv MOD_X_SENDFILE_ENABLED 1 XSendFile On XSendFilePath /tmp/oc-noclean </Directory> </VirtualHost>
-
Enable headers and rewrite modules:
sudo a2enmod headers sudo a2enmod rewrite
-
Enable it:
sudo a2ensite owncloud.mattcaron.net sudo service apache2 reload
-
Set mysql binlogs to 1 day.
There is a bug in Nextcloud (and possibly Ownclound) 21.x and later where it updates auth tokens and sessions in the DB every time someone logs in which, given the nature of the application is a lot. As such, it generates a LOT of data per day and fills up disks. We really only need this if the server crashes to restore intermediate state, and we have backups from the previous night. So, only keep one day.
- Edit
/etc/my.cnf.migrated
and setskip-log-bin
.
- Edit
-
Go to:
https://owncloud.mattcaron.net/
and do the initial setup, entering random admin credentials and choosing MySQL for the DB. Enter the DB credentials for the owncloud user on the owncloud DB you established above.
The data folder is
/usr/share/owncloud/data
(the default) which links to/var/lib/owncloud/data/
(which should be backed up).Anyway, once that's all done it will let you in.
-
Once logged in:
-
Under the "Apps" menu, office & text section, enable:
- Calendar
- Contacts
- Notes
- Collabora Online
(these are all official apps)
-
Under the "Users" menu
- Give appropriate people admin access
- Delete the admin account
-
Set up cron:
sudo -u www-data crontab -e
and add:
*/5 * * * * php -f /home/matt/public_html/owncloud.mattcaron.net/cron.php
-
Then, in the Admin panel, tell it to use cron.
-
A note on backups:
These are already handled by the mysql_backup script and backing up homedirs. So, nothing additional need be done here, so long as the previous stuff is set up.
-
-
Notes on configuring apps:
- Thunderbird
- Refs:
- Basically:
- Install the "TBSync" and the "Provider for CalDAV & CardDAV" Add-ons for Thunderbird.
- Edit -> Synchronization Settings (TbSync)
- Account Settings -> Add New Account -> CalDAV and CardDAV
- Automatic Configuration
- Fill in the boxes, and select what you want to sync.
- Android
- Address book
- Install "CardDAV sync free" or "CardDAV sync" from Google play.
- Launch CardDAV.
- Add account.
- Use the same URL as Thunderbird: https://owncloud.mattcaron.net/remote.php/carddav/addressbooks/matt/contacts
- Tick "Use SSL".
- Enter credentials.
- Next.
- Enter an appropriate name.
- Untick "Sync from server to phone only".
- Next.
- Calendar
- Install "CalDAV sync free" or "CalDAV sync" from google play.
- Open Calendar.
- Top right corner, click "Add Account".
- Choose "CalDAV sync adapter".
- Enter creds, and use the same URL as Thunderbird: https://owncloud.mattcaron.net/remote.php/caldav/calendars/matt/familycalendar
- Of note - under account name, use your email, because that's used as the address of the organizer.
- Click "sign in or register".
- Once the account is there, click on it, and click "Accounts & sync".
- Click the "CalDav sync adapter" account when that comes up.
- Tick the box next to the sync state to turn it on
- Calendar should now work.
- Theoretically, a long press on the calendar name during set up will change the ugly poop color, but I couldn't get that to work, so I left it.
- Address book
- Thunderbird
-
-
MySQL and Apache tuning
The default MySQL and Apache configs that ship with Ubuntu do not seem particularly suited to "low RAM boxes" (though, the old curmudgeon in me is amazed that 1.5GB if "low ram" these days, but I don't build a box with less than 1GB, as it's so cheap....)
-
Apache
-
Disable unused modules
sudo a2dismod auth_basic sudo a2dismod authn_file sudo a2dismod authz_groupfile sudo a2dismod authz_user sudo a2dismod fcgid sudo a2dismod status
-
Edit
/etc/apache2/mods-enabled/mpm_prefork.conf
and tweak values thusly.Original:
<IfModule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 150 MaxRequestsPerChild 0 </IfModule>
Revised:
<IfModule mpm_prefork_module> StartServers 2 MinSpareServers 1 MaxSpareServers 5 MaxClients 50 MaxRequestsPerChild 0 </IfModule>
-
Restart:
sudo service apache2 restart
-
-
MySQL
-
TODO - revisit this because it has been many years.
-
Refs:
-
Edit
/etc/mysql/my.conf
and change parameters in the[mysql]
section as follows:Original:
key_buffer_size = 16M #max_connections = 100
Modified:
key_buffer_size = 8M max_connections = 50
-
Restart:
sudo service mysql restart
-
-
-
MegaMek
-
Create a user, then disable it.
sudo adduser megamek sudo usermod -s /usr/sbin/nologin -L megamek
-
Install a JRE:
sudo apt install default-jre
-
Open up a firewall port:
sudo ufw allow from any to any port 2346 proto tcp comment 'megamek'
-
Create
/lib/systemd/system/megamek.service
with the following (and the correct password):[Unit] Description=MegaMek service After=network.target auditd.service [Service] ExecStart=/usr/bin/java -Xmx1024m -jar /home/megamek/megamek/MegaMek.jar -dedicated -port 2346 -password XXX ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=always RestartPreventExitStatus=255 Type=simple WorkingDirectory=/home/megamek/megamek RuntimeDirectoryMode=0755 User=megamek [Install] Alias=megamek.service
-
Enable and start the service:
sudo systemctl enable megamek sudo systemctl start megamek
-
Notes:
- It lives in
/home/megamek/
/home/megamek/megamek
is a symlink to the current version.- Download from https://megamek.org/downloads.html (just MegaMek stable)
- It lives in
-
-
MediaWiki (school.mattcaron.net)
-
Make the dir.
-
Grab the mediawiki tarball and untar it in the root.
-
Make
/etc/apache2/sites-available
and enable it:sudo a2ensite rpg.mattcaron.net && sudo systemctl reload apache2
-
Create the database and user:
CREATE DATABASE mw_school; GRANT ALL PRIVILEGES ON mw_school.* TO "mw_school"@"localhost" IDENTIFIED BY "password";
-
Push everything up and then go to https://school.mattcaron.net/ to configure it, grab the
LocalSettings.php
file and stuff it where it needs to be. Yay.
-
-
Coturn (STUN/TURN server, used by Synapse for VoIP stuff)
-
Install it from the repos:
sudo apt install coturn
-
Make the server user a member of the
ssl-cert
group so it can read the certs, and a member of thesyslog
file so it can write/var/log
sudo usermod -a -G ssl-cert turnserver sudo usermod -a -G syslog turnserver
-
Configure it by editing
/etc/turnserver.conf
:- Uncomment the following options to enable them:
tls-listening-port
fingerprint
use-auth-secret
secure-stun
no-cli
no-tcp-relay
- Set the
log-file
to/var/log/turn.log
. - Set
static-auth-secret
to something strongish. - Set the
realm
tochat.mattcaron.net
. - Set the cert and key files to appropriate values for
chat.mattcaron.net
. - Set the
user-quota
andtotal-quota
. - Set the
proc-user
andproc-group
toturnserver
.
- Uncomment the following options to enable them:
-
Set it to start by editing
/etc/default/coturn
and uncommentingTUNSERVER_ENABLED=1
. -
Allow through firewall:
sudo ufw allow 5349 comment "turn tls"
-
-
Synapse (matix server)
-
Install it from the latest stable repo:
sudo wget -qO /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/matrix-org.list sudo apt update sudo apt install matrix-synapse-py3
follow the instruction prompts, setting the domain and sumbitting anonymous usage statistics.
-
Configure it by editing
/etc/matrix-synapse/homeserver.yml
- Set the
admin_contact
. - Disable federation by setting
federation_domain_whitelist
to this server and only this server (so it federates with itself). - Enable URL previews and uncomment the blacklist, as recommended.
- We do not explicitly blacklist the external IP because we want previews for those to work, and it's all externally accessible already anyway.
- Set
enable_registration
to false.- I don't want people to register themselves; only me.
- Set the registration shared secret.
- Set
allow_guest_access
to false. - Set it to auto-join admin-help, as a minimal room set.
- Comment out the trusted keyservers - we don't trust anyone.
- Set the TURN server config
- Set the
turn_uris
to havechat.mattcaron.net
as the list. - Set the
turn_shared_secret
to be the same as the one in/etc/turnserver.conf
. - Set
turn_allowed_guests
tofalse
.
- Set the
- Note that we don't:
- Set the certs because we run this unencrypted on localhost and then proxy it through apache, which does our TLS termination.
- Set it up to send emails - the app notifies one of new messages, so I'm not enabling this unless people ask for it.
- Of course, not setting email (and not setting a 3PID server) means we can't set email and phone numbers.
- Push notifications - again, the app notifies one of new messages, so why annoy people more?
- Set the
-
Set up the VHost proxy.
-
Create
/etc/apache2/sites-available/chat.mattcaron.net
thusly:<VirtualHost *:80> ServerName chat.mattcaron.net ServerAdmin [email protected] RewriteEngine on RewriteRule ^/(.*)$ https://chat.mattcaron.net/$1 [R,L] </VirtualHost> <VirtualHost *:443> ServerName chat.mattcaron.net ServerAdmin [email protected] SSLEngine on SSLCertificateFile /etc/ssl/private/chat.mattcaron.net/fullchain.pem SSLCertificateKeyFile /etc/ssl/private/chat.mattcaron.net/privkey.pem Include ssl_common.fragment AllowEncodedSlashes NoDecode ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix ProxyPass /_synapse/client http://127.0.0.1:8008/_synapse/client nocanon ProxyPassReverse /_synapse/client http://127.0.0.1:8008/_synapse/client </VirtualHost> # Server to server comms (disabled for now as we do not want federation) #<VirtualHost *:8448> # SSLEngine on # ServerName example.com; # # AllowEncodedSlashes NoDecode # ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon # ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix #</VirtualHost>
-
Enable it:
sudo a2enmod proxy sudo a2enmod proxy_http sudo a2ensite chat.mattcaron.net sudo service apache2 reload
-
Create users:
register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008
and then follow the prompts.
-
Set up DB snapshot - add to /etc/cron.d/matrix:
# /etc/cron.d/matrix: crontab entries to backup matrix sqlite database PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/snap/bin MAILTO=root @daily root service matrix-synapse stop && /home/matt/bin/matrix-synapse_sqlite_backup > /dev/null ; service matrix-synapse start ; chown matt:matt /home/matt/attic/backup/linode/matrix-synapse_sqlite_backup.*
-
-
-
Element Web (frontend for Matrix server)
- Copy over
~/public_html/chat.mattcaron.net
. - In
/etc/apache2/sites-available/chat.mattcaron.net
, set theDocumentRoot
to/home/matt/public_html/chat.mattcaron.net
.
- Copy over
-
Jitsi
-
Add video.mattcaron.net to DNS and get a cert.
-
Add the repo and key.
-
From: https://www.digitalocean.com/community/tutorials/how-to-install-jitsi-meet-on-ubuntu-20-04
wget https://download.jitsi.org/jitsi-key.gpg.key sudo apt-key add jitsi-key.gpg.key rm jitsi-key.gpg.key echo "deb https://download.jitsi.org stable/" | sudo tee /etc/apt/sources.list.d/jitsi-stable.list
-
-
Install from repo:
sudo apt update sudo apt install jitsi-meet
-
When prompted:
- Set the hostname to
video.mattcaron.net
- Tell it to use my own certificate
- Key is at
/etc/ssl/private/video.mattcaron.net/privkey.pem
- Certificated is at
/etc/ssl/private/video.mattcaron.net/fullchain.pem
- Set the hostname to
-
It automatically detects apache being there, installs a config file for it, and enables it.
-
Configure the Element clients to use the correct Jisti domain. Create
/.well-known/matrix/client
and add the following to it:{ "im.vector.riot.jitsi": { "preferredDomain": "video.mattcaron.net" } }
-
It uses prosody for authentication, and need to be set up to lock it down:
-
Edit
/etc/prosody/conf.avail/video.mattcaron.net.cfg.lua
-
Change:
authentication = "anonymous"
to
authentication = "internal_plain"
-
-
But we want invited guests to be able to create temporary accounts:
-
Add the following VirtualHost entry in the file:
VirtualHost "guest.video.mattcaron.net" authentication = "anonymous" c2s_require_encryption = false
-
Edit
/etc/jitsi/meet/video.mattcaron.net-config.js
and change:// anonymousdomain: 'guest.example.com',
to
anonymousdomain: 'guest.video.mattcaron.net',
and find and set the following as follows (often just uncommenting them):
maxFullResolutionParticipants: 5, requireDisplayName: true, prejoinPageEnabled: true, disableThirdPartyRequests: true, doNotStoreRoom: true, disableTileView: true,
-
Edit
/etc/jitsi/jicofo/sip-communicator.properties
and add the following line to the end:org.jitsi.jicofo.auth.URL=XMPP:video.mattcaron.net
-
Restart everything:
sudo service prosody restart sudo service jicofo restart sudo service jitsi-videobridge2 restart
-
Once configured, add users as follows:
sudo prosodyctl register user your_domain password
-
-
Allow media port through the firewall:
sudo ufw allow 10000 comment "jitsi media"
-