Server Configuration: MPM Operations Server¶
This documentation outlines how the Linode “mpmop” server was built.
Initial Setup¶
We are using a Linode 4 GB with an Ubuntu 20.04 disk instance deployed from Marketplace. Be sure to add an SSH key, and then log in as root user.
Updates¶
Before we continue, we need to check for any updates.
$ apt update
$ apt full-upgrade
Setting Hostname and Timezone¶
We’ll start by defining the name of our host.
$ echo "mpmdev" > /etc/hostname
$ hostname -F /etc/hostname
$ vim /etc/hosts
In that file, add the following lines below the first line, substituting the actual IPv4 and IPv6 of the Linode in place of the NNN.NNN values:
`
NNN.NNN.NNN.NNN mpmdev
NNNN:NNNN::NNNN:NNNN:NNNN:NNNN mpmdev
`
Save and quit.
Now we set the timezone.
$ dpkg-reconfigure tzdata
Use the arrow and ENTER keys to set your timezone. We’ll be using US/Central.
Reboot the system.
Defining a Non-Root User¶
Next, we’ll use the root account to set up the regular user account.
$ adduser mpm
Define the password for the new user, and other information if desired.
Then, we add the user to the sudo
group.
$ usermod -aG sudo mpm
$ groups mpm
The second command will list all of the groups mpm
is in. Ensure
it includes the sudo
group.
SSH¶
Note
For security reasons, the SSH port we changed to has been
scrubbed to 123
.
The necessary packages for SSH were installed on installation. We need to change a few settings and start the service.
# Make a backup of the default SSH configuration.
$ sudo cp /etc/ssh/sshd_config{,.bak}
# Edit the SSH configuration.
$ sudo vim /etc/ssh/sshd_config
Change Port 22
to Port 123
and PermitRootLogin yes
to
PermitRootLogin no
. Also add the line DebianBanner no
(you can put it under
“PermitRootLogin”). The rest of the default settings should be fine for now.
Save and close the file.
Now we’ll restart the service.
# Restart the SSH service.
$ sudo systemctl restart ssh
On the remote machine (the computer you’re connecting from), run the
following command, where NNN.NNN.NNN.NNN
is the IP address of the
Linode you’re connecting to.
ssh-copy-id mpm@NNN.NNN.NNN.NNN -p 123
You can now connect to the non-root user account on the server via SSH.
SOURCE: How to Use SSH To Connect To A Remote Server (Digital Ocean)
Set Up Longview¶
It will be beneficial for us to use the free plan for Longview, a service provided through Linode. Let’s install that now.
On the Linode Cloud Manager web interface, go to Longview and add a new client. After a moment, a box will pop up with a command to run in the server terminal.
It will take a few minutes for Longview to start working, so just close the window on the Linode Manager.
Setup LAMP¶
Apache2¶
We’ll start by setting up Apache2.
$ sudo apt install apache2
$ sudo vim /etc/apache2/apache2.conf
Next, we’ll edit the configuration file to turn off KeepAlive
, as that
uses up extra memory (and we don’t have that much to spare). We’ll also set
the ServerName
(you may need to add this entry).
ServerName 127.0.0.1
KeepAlive Off
Scroll down to the section with all the directories, and add this entry. (Be mindful to use tabs, not spaces, to be consistent with the rest of the file.)
<DirectoryMatch /\.git/>
Options FollowSymLinks
AllowOverride None
Require all denied
</DirectoryMatch>
Save and close.
Next, we’ll change the settings for the mpm_prefork
module.
$ sudo vim /etc/apache2/mods-available/mpm_prefork.conf
Set the file to the following…
<IfModule mpm_prefork_module>
StartServers 2
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 39
MaxConnectionsPerChild 3000
</IfModule>
Save and close. Now we’ll enable the prefork module and restart Apache2.
$ sudo a2dismod mpm_event
$ sudo a2enmod mpm_prefork
$ sudo systemctl restart apache2
Next, we will add our user to the www-data
group, which will be
helpful for permissions.
$ sudo usermod -aG www-data mpm
Browse to the web server using the IP or whatever address is most convenient, and ensure the Apache2 default page is appearing.
MySQL¶
Now we will set up our database software.
$ sudo apt install mysql-server
$ sudo mysql_secure_installation
Validate Password is optional; you should specify the root password
and answer Y
to the following:
Remove anonymous users?
Disallow root login remotely?
Remove test database and access to it?
Reload privilege tables now?
PHP¶
We’ll be using PHP 7.4, which is the default in Ubuntu 20.04, for this server.
$ sudo apt install php7.4 libapache2-mod-php7.4 php7.4-cli php7.4-common php7.4-curl php7.4-dev php7.4-gd php7.4-json php7.4-mbstring php7.4-mysql php7.4-opcache php7.4-readline php7.4-xml
$ sudo vim /etc/php/7.4/apache2/php.ini
Edit the contents of that file so the following lines match the given values:
max_input_time = 30
error_reporting = E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR
error_log = /var/log/php/error.log
Create the log directory for PHP, and give ownership to the Apache2 system user. Finally, restart Apache2 to start using the changes.
$ sudo mkdir /var/log/php
$ sudo chown www-data /var/log/php
$ sudo systemctl restart apache2
Scripts¶
We need to save a number of scripts for regular use.
$ sudo mkdir -p /opt/scripts/sys
$ sudo mkdir -p /opt/scripts/root
$ sudo chown root:root /opt/scripts/root
$ sudo chmod 700 /opt/scripts/root
Now we add the system scripts to the path for the main user.
$ vim ~/.bashrc
Add the following to that file:
PATH=$PATH:/opt/scripts/sys
Save and close. Log in as root and repeat, only with the following instead:
PATH=$PATH:/opt/scripts/sys:/opt/scripts/root
Save and close that too. You can immediately update the path for your current
login session with source ~/.bashrc
.
Let’s Encrypt Certbot¶
We need to install the Let’s Encrypt Certbot for generating certificates.
$ sudo snap install core; sudo snap refresh core
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
$ sudo certbot register
Follow the instructions to register with Let’s Encrypt.
We’ll actually generate certificates in a later step.
Scheduling Auto-Renewal¶
Now we need to schedule the autorenewal task.
$ sudo crontab -e
Add the following line to the end:
41 5 * * * /usr/bin/certbot renew
This will run the renewal script once a day at 5:41am. (Let’s Encrypt asks that a random time be used by each user, to spread out server load.)
Server Hardening¶
Let’s improve our system security before continuing.
SSH Security¶
We need to lock down SSH for further security.
$ sudo vim /etc/ssh/sshd_config
Edit the file so the following lines have the given settings:
PermitRootLogin no
PasswordAuthentication no
AuthorizedKeysFile .ssh/authorized_keys
Save and close the file, and then run…
$ sudo systemctl restart sshd
Firewall Settings¶
Now we need to open the firewall to allow SSH and HTML to pass through,
and enable it. Be sure to change 123
to your SSL port from previously.
$ sudo ufw allow 123
$ sudo ufw allow 80
$ sudo ufw allow 443
$ sudo ufw enable
Lock Down sudo
Privilege¶
We’ll limit sudo
privileges to only users in the admin
group.
$ sudo groupadd admin
$ sudo usermod -a -G admin <YOUR ADMIN USERNAME>
$ sudo dpkg-statoverride --update --add root admin 4750 /bin/su
Harden Network with sysctl
Settings¶
$ sudo vi /etc/sysctl.conf
Edit the file, uncommenting or adding the following lines:
# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Block SYN attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
# Log Martians
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# Ignore Directed pings
net.ipv4.icmp_echo_ignore_all = 1
Finally, reload sysctl
. If there are any errors, fix the associated lines.
$ sudo sysctl -p
Harden PHP¶
$ sudo vim /etc/php/7.4/apache2/php.ini
Add or edit the following lines and save:
disable_functions = exec,system,shell_exec,passthru
register_globals = Off
expose_php = Off
display_errors = Off
track_errors = Off
html_errors = Off
magic_quotes_gpc = Off
mail.add_x_header = Off
session.name = NEWSESSID
Restart the Apache2 server and make sure it still works.
$ sudo systemctl restart apache2
Harden Apache2¶
Edit the Apache2 security configuration file…
$ sudo vim /etc/apache2/conf-available/security.conf
Change or add the following lines:
ServerTokens Prod
ServerSignature Off
TraceEnable Off
FileETag None
Restart the Apache2 server and make sure it still works.
$ sudo systemctl restart apache2
Setup ModSecurity¶
First, install the necessary dependencies. We’ll also need to create a symbolic link to work around a bug on 64-bit systems. Finally, we’ll install the package itself.
$ sudo apt install libxml2 libxml2-dev libxml2-utils libaprutil1 libaprutil1-dev
$ sudo ln -s /usr/lib/x86_64-linux-gnu/libxml2.so.2 /usr/lib/libxml2.so.2
$ sudo apt install libapache2-mod-security2
Now we’ll copy the default configuration.
$ sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
Now we download the latest OWASP security rules.
$ cd /etc/modsecurity
$ sudo wget https://github.com/coreruleset/coreruleset/archive/v3.3.0.tar.gz
$ sudo tar -xvf v3.3.0.tar.gz
$ sudo mv coreruleset-3.3.0 owasp-modsecurity-crs
$ cd owasp-modsecurity-crs
$ sudo mv crs-setup.conf.example crs-setup.conf
$ cd rules
$ sudo mv REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
$ sudo mv RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
You may need to edit /etc/modsecurity/owasp-modsecurity-crs/crs-setup.conf
to match your server’s situation. For example, we enabled Project Honeypot.
Edit the configuration for the ModSecurity Apache module…
$ sudo vim /etc/apache2/mods-available/security2.conf
Change the IncludeOptional
entries to match the following:
IncludeOptional /etc/modsecurity/*.conf
IncludeOptional /etc/modsecurity/owasp-modsecurity-crs/crs-setup.conf
IncludeOptional /etc/modsecurity/owasp-modsecurity-crs/plugins/*-before.conf
IncludeOptional /etc/modsecurity/owasp-modsecurity-crs/rules/*.conf
IncludeOptional /etc/modsecurity/owasp-modsecurity-crs/plugins/*-after.conf
Enable the modules and restart Apache2, ensuring that it still works.
$ sudo a2enmod headers security2
$ sudo systemctl restart apache2
Finally, to make sure it works, go to http://<serveraddress>/?param="><script>alert(1);</script>
.
Check /var/log/apache2/error.log
for an error report from mod_security
.
If one is there, the configuration worked!
Setup Fail2Ban¶
Fail2Ban locks out IP addresses that repeatedly attempt invalid or malicious actions.
$ sudo apt install fail2ban
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
$ sudo vim /etc/fail2ban/jail.local
To turn on various “jails”, scroll down to the # JAILS
section. Place
enabled = true
under each jail name you want turned on. This is the list
of jails we enabled for this server:
sshd
sshd-ddos
apache-auth
apache-badbots
apache-noscript
apache-overflows
apache-nohome
apache-botsearch
apache-fakegooglebot
apache-modsecurity
apache-shellshock
php-url-fopen
recidive
slapd
phpmyadmin-syslog
I also added sshd-ddos
by including this entry:
[sshd-ddos]
mode = ddos
enabled = true
port = ssh
logpath = %(sshd_log)s
filter = sshd
Be sure you look through the jails and enable any additional jails that will be appropriate to your server’s configuration and applications.
For the [recidive]
jail to work correctly, a couple of settings need to
be changed in Fail2Ban’s configuration:
$ sudo cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
$ sudo vim /etc/fail2ban/fail2ban.local
Change the following values:
# NEVER SET TO DEBUG!!! [recidive] jail is enabled
loglevel = INFO
dbpurgeage = 648000
Save and close. Run the following command to ensure there are no errors:
$ sudo systemctl stop fail2ban
$ sudo fail2ban-client -x start
Finally, restart the fail2ban process.
$ sudo systemctl restart fail2ban
Setup PSAD¶
$ sudo apt install psad
$ sudo iptables -A INPUT -j LOG
$ sudo iptables -A FORWARD -j LOG
$ sudo ip6tables -A INPUT -j LOG
$ sudo ip6tables -A FORWARD -j LOG
$ sudo vim /etc/psad/psad.conf
Change the following values:
EMAIL_ADDRESS mpm@localhost;
HOSTNAME mpmdev;
ALERTING_METHODS noemail;
EMAIL_THROTTLE 100;
ALERT_ALL N;
ENABLE_AUTO_IDS_EMAIL N;
EMABLE_DNS_LOOKUPS N;
ENABLE_WHOIS_LOOKUPS N;
Save and close, and then reload like this:
$ sudo psad -R; sudo psad --sig-update; sudo psad -H; sudo psad --Status
When you run that last command, it may whine about not finding a pidfile. It appears we can ignore that error.
We also need to tweak Fail2Ban so that it doesn’t start up before psad
does.
Otherwise, psad
won’t be able to log correctly.
$ sudo vim /lib/systemd/system/fail2ban.service
In that file, add ufw.service
and psad.service
to the After=
directive,
so it looks something like this:
After=network.target iptables.service firewalld.service ufw.service psad.service
Save and close, and then reload the daemons for systemctl and restart fail2ban.
$ sudo systemctl daemon-reload
$ sudo systemctl restart fail2ban
Now we need to adjust the UFW settings.
$ sudo ufw logging high
$ sudo vim /etc/ufw/before.rules
Add the following lines before the final commit message:
-A INPUT -j LOG
-A FORWARD -j LOG
Save and close. Repeat this with before6.rules
. Then, restart ufw and
reload PSAD.
SOURCE: PSAD Is Giving a Firewall Setup Warning (Ubuntu Forums)
$ sudo systemctl restart ufw
$ sudo psad --fw-analyze
Restart the computer, and ensure PSAD isn’t sending any system emails
complaining about the firewall configuration. (Check system email by
running $ mail
).
Rootkit Checks¶
We use two different rootkit checkers.
$ sudo apt install rkhunter chkrootkit
$ sudo vim /opt/scripts/root/rootkitscan
Set the contents of that file to the following:
#!/bin/bash
chkrootkit
rkhunter --update
rkhunter --propupd
rkhunter --check --cronjob -l
echo "Rootkit Check Done!"
Miscellaneous¶
These are a few other useful programs.
$ sudo apt install nmap logwatch libdate-manip-perl apparmor apparmor-profiles tiger clamav
# Ensure apparmor is working.
$ sudo apparmor_status
To use logwatch, run…
$ sudo logwatch | less
To scan for vulnerabilites with Tiger, run…
$ sudo tiger
$ sudo less /var/log/tiger/security.report.*
Adding Sites¶
For each site, we need to configure Apache2 and get an SSL certificate.
First, we need to enable the SSL module for Apache2. This usually only needs to be done the first time.
$ sudo a2enmod ssl
$ sudo systemctl restart apache2
We start by generating a certificate for the domain being added.
The 000-default
Apache site is what we’ll use for initially generating on
a domain name. After generating the cert, we disable that site again so the
other sites will work.
$ sudo a2ensite 000-default
$ sudo systemctl reload apache2
$ sudo certbot certonly --apache -d eco.mousepawmedia.com
In the output for the certbot command, take note of the paths where the certificate and chain were saved. You’ll need that in the next step.
$ sudo vim /etc/apache2/sites-available/eco.conf
Set the contents of that file to the following, substituting the
domain name in place for ServerName
, and fixing the paths for
the SSLCertificateFile
and SSLCertificateKeyFile
.
Also set the DocumentRoot
to the desired directory.
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName eco.mousepawmedia.com
ServerAdmin webmaster@mousepawmedia.com
DocumentRoot /opt/eco
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/eco.mousepawmedia.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/eco.mousepawmedia.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Strict-Transport-Security "max-age=31536000"
Header always set Content-Security-Policy upgrade-insecure-requests
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
</IfModule>
Save and close. Now we’ll create the directory we specified
in DocumentRoot
.
$ cd /opt
$ sudo mkdir eco
$ sudo chown www-data:www-data eco
$ sudo chmod 775 eco
We need to tell Apache2 to read this directory.
$ sudo vim /etc/apache2/apache2.conf
Scroll down to the section with all the directories, and add these entries:
<Directory /opt/eco/>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Save and close.
Consider creating an index.html
in that folder, with the text “Hello, world!”,
just to make sure the site works.
Now we disable the default site, enable the new site, and restart Apache2.
$ sudo a2dissite 000-default
$ sudo a2ensite eco
$ sudo systemctl restart apache2
Ensure the new domain works over http.
Port Forward 80 to 443¶
With that set up, we want to redirect port 80 to port 443.
$ sudo vim /etc/apache2/sites-available/000-redirect.conf
Set the contents of that file to…
<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>
Save and close. Load the site, make sure mod_rewrite
is enabled, and then
restart Apache2.
$ sudo a2ensite 000-redirect
$ sudo a2enmod rewrite
$ sudo systemctl restart apache2
Navigating to http://<serveraddress>
should now redirect properly to
Navigate to https://<serveraddress>
. The same will apply for any subdirectory
thereof, such as http://<serveraddress>/docs
.
Note
Apache2 sites are loaded in alphabetical order. Addresses and ports are first come, first served, so the first site that defines on a port gets all addresses on that port, unless something else snatches away a specific address.
Server Controls¶
PHPMyAdmin¶
$ sudo apt install phpmyadmin
On the configuration dialog, select apache2
by selecting it and tapping
Space. Enter an application password (different from the MySQL root
password) and confirm it.
Edit the configuration for PHP, to force HTTPS.
$ sudo vim /etc/phpmyadmin/config.inc.php
Add the following line to the bottom of that file.
$cfg['ForceSSL'] = true;
Save and close.
Now enable one necessary PHP module and restart Apache2.
$ sudo phpenmod mbstring
$ sudo systemctl restart apache2
Validate that you can access https://<serveraddress>/phpmyadmin
. Log
in there with the username phpmyadmin
and the password you defined.
Warning
You may need to disable the Apache2 module security2
before you can access PHPMyAdmin. Otherwise, it throws an internal 404.
We’re not sure why. To fix the problem, run sudo a2dismod security2
and
restart the Apache2 service.
By default, you can’t do much of anything from this account. To enable access to all databases, run the following:
$ sudo mysql -u root
Run the following commands in the MySQL shell:
GRANT ALL PRIVILEGES ON *.* TO 'phpmyadmin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
\q
Then refresh PHPMyAdmin in your browser. You should be able to edit all databases now.
Control Access Switch¶
For security reasons, we want to be able to turn on and off controls like PHPMyAdmin using a script.
$ sudo vim /opt/scripts/sys/controls
The contents of that file are as follows.
#!/bin/bash
set -e
case $1 in
'on')
sudo a2enconf phpmyadmin
sudo systemctl restart apache2
echo "Admin control panels are turned ON."
;;
'off')
sudo a2disconf phpmyadmin
sudo systemctl restart apache2
echo "Admin control panels are turned OFF."
;;
*)
echo "You must specify 'on' or 'off'."
exit 1
;;
esac
Save and close, and then make executable.
$ sudo chmod +x /opt/scripts/sys/controls
Now you can run controls on
or controls off
to toggle
access to PHPMyAdmin.
LDAP Server¶
In this section, I’ll set up an LDAP Server which uses StartTLS for
security. Start by following the Apache setup instructions to create
a virtual host and certificate for id.mousepawmedia.com
.
Installation¶
$ sudo apt install slapd ldap-utils ldap-account-manager
$ sudo dpkg-reconfigure slapd
During the configuration, use these settings:
Omit OpenLDAP server configuration? No
DNS domain name? id.mousepawmedia.com
Organization name? mousepawmedia
Administrator password? (enter one)
Database backend to use? MDB
Remove the database when slapd is purged? No
Move old database? Yes
Allow LDAPv2 protocol? No
Now we open the LDAP port and check that LDAP is working:
$ sudo ufw allow 389
$ ldapwhoami -H ldap:// -x
The last command should return anonymous
.
Now we need to set up LDAP to use the Let’s Encrypt certificates we created.
$ sudo vim /opt/scripts/root/postrenew
Set the contents of that file to:
cp /etc/letsencrypt/live/id.mousepawmedia.com/* /etc/ldap/sasl2
chown -R openldap:openldap /etc/ldap/sasl2
chmod 700 /etc/ldap/sasl2
Save and close. Then, make executable and run.
$ sudo chmod +x /opt/scripts/root/postrenew
$ sudo /opt/scripts/root/postrenew
That script will need to be run every time certificates are renewed, so let’s update our cron job.
$ sudo crontab -e
Modify the crontab for certbot to the following (without changing the time you have already specified, of course):
17 3 * * * /usr/bin/certbot renew --post-hook /opt/scripts/root/postrenew
Save and close.
LDAP is modified through commands and scripts. We need to create an ldif
file in our current directory (e.g. home) like this:
$ sudo vim ssl.ldif
Set the contents to the following, changing the path to the certificates if necessary.
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ldap/sasl2/fullchain.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/sasl2/privkey.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/sasl2/cert.pem
Save and close, and then modify LDAP with that file.
$ sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /home/mpm/ssl.ldif
Check the output. If you get the infamous ldap_modify: Other (e.g., implementation specific) error (80)
,
check that all of the above are correct, especially permissions.
Once the command works, restart LDAP and ensure that StartTLS is working.
$ sudo systemctl restart slapd
$ ldapwhoami -H ldap://id.mousepawmedia.com -x -ZZ
That should return anonymous
if it’s working.
SOURCE: How to Configure OpenLDAP with StartTLS Mode on Ubuntu 16.04 (Medium)
SOURCE: OpenLDAP with TLS and LetsEncrypt on UBuntu 16.04 (Peter Hicks)
LDAP Account Manager Config¶
Now we need to adjust LDAP Account Manager’s configuration. Go to
https://id.mousepawmedia.com/lam and click LAM Configuration
in the upper-right
corner.
Click General settings
. If this is your first time logging in, the Master
Password is lam
.
On the page that appears, enter a new master password. Be sure not to lose it!
You can adjust other settings here as needed, but the defaults should be fine.
Click Ok
.
Now go to LAM Configuration
and Edit server profiles
. Click Manage
server profiles
and rename the profile to admin
. Click OK
.
Now go to LAM Configuration
and Edit server profiles
. Log in.
The first time you do so, the password is lam
. Be sure to change it.
Ensure the following settings on the General settings tab:
Server address:
ldap://id.mousepawmedia.com:389
Activate TLS: yes
Tree suffix:
dc=id,dc=mousepawmedia,dc=com
Advanced options > Display name:
MousePaw Media ID
Default language:
English (USA)
Time zone:
America/Chicago
Scroll down to Security settings. Set the Login method to Fixed list, and then
set List of valid users
to cn=admin,dc=id,dc=mousepawmedia,dc=com
.
Click Save
.
Configuring LDAP Schema¶
Go to LAM Configuration
and Edit server profiles
. Log in.
Then, go to the Account types tab. Create two account types:
- Users
LDAP suffix:
ou=Users,dc=id,dc=mousepawmedia,dc=com
List attributes:
#uid;#cn;#mail;#uidNumber;#gidNumber
- Groups
LDAP suffix:
ou=Groups,dc=id,dc=mousepawmedia,dc=com
List attributes:
#cn;#gidNumber;#memberUID;#description
Go to the Modules tab. For Users, select these modules:
Personal (inetOrgPerson)(*)
Unix (posixAccount)
Shadow (shadowAccount)
For Groups, select these modules:
Unix (posixGroup)(*)
On the Module settings, you can hide some options. Customize this as you like.
Then, click Save
.
Login on the main page with the admin
LDAP account.
Click the Groups tab and create the groups you want. Here are ours:
user
admin
alumni
community
contentdev
designproduction
former
hiring
management
masscomm
programming
repomaster
staff
The user
group will be the base group for everyone, while the others will
be used by other applications for permissions and group membership.
Go to Tools
and Profile editor
. Modify the default Users
group
to have the following defaults:
Profile name:
default
RDN identifier:
uid
Primary group:
user
Password warning: (empty)
Password expiration: (empty)
Minimum password age: (empty)
Maximum password age: (empty)
Save the profile.
Now click Users
and create the user accounts, with the following
fields at minimum. (Notes about the fields are in parentheses below.)
RDN identifier: uid
- Personal
First name
Last name
Email address
- Unix
Username
Common name (full name with middle initial)
Primary group (always set to
user
)Additional groups (set as desired for user)
Now click Save
and Edit again
. Click Set password
at the top to
set the user password.
Static Websites¶
We host all our websites public Git repositories. We can leverage that to easily publish websites and documentation.
$ sudo mkdir /opt/sources
$ sudo chown www-data:www-data /opt/sources
$ cd /opt/sources
$ sudo -u www-data git clone git://github.com/mousepawmedia/mpm-websites.git
$ sudo ln -sf /opt/sources/mpm-websites/mousepawmedia.com /opt/mpm
$ sudo chown www-data:www-data /opt/mpm
$ sudo ln -sf /opt/sources/mpm-websites/mousepawmedia.com /opt/mpg
$ sudo chown www-data:www-data /opt/mpg
$ sudo ln -sf /opt/sources/mpm-websites/eco.mousepawmedia.com /opt/eco
$ sudo chown www-data:www-data /opt/eco
$ sudo ln -sf /opt/sources/mpm-websites/id.mousepawmedia.com /opt/id
$ sudo chown www-data:www-data /opt/id
$ sudo a2enmod rewrite include
$ sudo vim /etc/apache2/apache2.conf
Add the following:
<Directory /opt/sources/>
Options FollowSymLinks
Require all granted
</Directory>
Save and close.
Kimai¶
Installing Composer¶
First, we need to install the lastest Composer:
$ sudo apt install php7.4-cli php7.4-intl unzip
$ cd /tmp
$ curl -sS https://getcomposer.org/installer -o composer-setup.php
$ HASH=`curl -sS https://composer.github.io/installer.sig`
$ php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
You should see “Installer verified”. If so, we can install.
$ sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
$ composer
If that works (displaying a help menu), we can move on to installing Kimai.
SOURCE: How to Install Composer on Ubuntu 20.04 (DigitalOcean)
Installing Kimai¶
Next, in MyPHPAdmin, create a user and a database called kimai2
. You’ll
need the password for that user shortly.
In my case, I’m importing from a prior Kimai2 database:
gunzip -c /home/mpm/IMPORTED/backup.sql.gz | sudo mysql -u root
Now I create the kimai2
user and grant its permissions.
$ sudo mysql -u root
Run the following:
CREATE USER 'kimai2'@'localhost' IDENTIFIED BY 'some_password';
GRANT ALL PRIVILEGES ON `kimai2`.* TO 'kimai2'@'localhost' WITH GRANT OPTION;
\q
We install Kimai like this:
$ cd /tmp
$ git clone -b 1.13 --depth 1 https://github.com/kevinpapst/kimai2.git
$ sudo mv kimai2 /opt/time
$ cd /opt/time/
$ composer install --no-dev --optimize-autoloader
$ vim .env
Now edit that file so it contains something like the following, changing the
values CHANGE_ME
(two places below) as appropriate.
# This file is a "template" of which env vars need to be defined for your application
# Copy this file to .env file for development, create environment variables when deploying to production
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
###> symfony/framework-bundle ###
APP_ENV=prod
APP_SECRET=CHANGE_ME
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
#TRUSTED_HOSTS=localhost,example.com
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For a MySQL database, use: "mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=10.2.12&charset=utf8"
# For a MariaDB database, use: "mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=mariadb-10.2.12"
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data/kimai.sqlite"
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
DATABASE_URL=mysql://kimai2:CHANGE_ME@127.0.0.1:3306/kimai2
#DATABASE_URL=sqlite:///%kernel.project_dir%/var/data/kimai.sqlite
###< doctrine/doctrine-bundle ###
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN=^https?://localhost(:[0-9]+)?$
###< nelmio/cors-bundle ###
### Email configuration
# SMTP: smtp://localhost:25?encryption=&auth_mode=
# Google: gmail://username:password@default
# Amazon: ses://ACCESS_KEY:SECRET_KEY@default?region=eu-west-1
# Mailchimp: mandrill://KEY@default
# Mailgun: mailgun://KEY:DOMAIN@default
# Postmark: postmark://ID@default
# Sendgrid: sendgrid://KEY@default
# Disable emails: null://null
MAILER_URL=null://null
MAILER_FROM=eco@mousepawmedia.com
Save and close, and then run the following:
$ bin/console kimai:install -n
$ sudo chown -R mpm:www-data /opt/time
$ chmod -R g+r /opt/time
$ chmod -R g+rw /opt/time/var/
$ chmod -R g+rw /opt/time/public/avatars/
Kimai itself is now installed.
Setting Up Apache2 for Kimai¶
To setup Apache, first follow the instructions earlier for adding a new domain name and Let’s Encrypt certificate. Then add or modify the following file:
$ sudo vim /etc/apache2/sites-available/time.conf
Set the contents of that file to:
<IfModule mod_ssl.c>
<VirtualHost time.mousepawmedia.com:443>
ServerName time.mousepawmedia.com
DocumentRoot /opt/time/public
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/time.mousepawmedia.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/time.mousepawmedia.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Strict-Transport-Security "max-age=31536000"
Header always set Content-Security-Policy upgrade-insecure-requests
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /opt/time/public>
Options +FollowSymLinks
AllowOverride All
<IfModule mod_dave.c>
Dav off
</IfModule>
Require all granted
FallbackResource /index.php
</Directory>
<Directory /opt/time>
Options FollowSymLinks
</Directory>
<Directory /opt/time/public/bundles>
FallbackResource disabled
</Directory>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
</IfModule>
Save and close, and then run this:
$ sudo vim /etc/apache2/apache2.conf
Add the following section:
<Directory /opt/time>
Options FollowSymLinks
</Directory>
<Directory /opt/time/public>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Save and close, and then enable the site and restart Apache2:
$ sudo a2ensite time
$ sudo systemctl restart apache2
Now go to https://time.<serveraddress>
and verify that everything works so far.
Reload/Repair Script¶
Kimai is particularly vulnerable to getting its permissions messed up. This script will (usually hopefully) fix that:
$ vim /opt/time/cache.sh
Set the contents of that file to this:
#!/bin/bash
cd /opt/time
sudo chown -R mpm:www-data .
chmod -R g+r .
chmod -R 775 var/
chmod -R g+rw public/avatars/
if [[ ! -d "var/" || ! -d "var/cache/prod/" ]];
then
echo "Cache directory does not exist at: var/cache/prod/"
exit 1
fi
if [[ ! -f "bin/console" ]];
then
echo "Kimai console does not exist at: bin/console"
exit 1
fi
sudo rm -rf var/cache/prod/*
sudo -u www-data bin/console kimai:reload --env=prod
sudo chown -R mpm:www-data .
chmod -R g+r .
chmod -R 775 var/
chmod -R g+rw public/avatars/
Save and close, and then make that script executable.
$ chmod +x /opt/time/cache.sh
Finally, run the script.
$ /opt/time/cache.sh
Kimai should be working now.
LDAP for Kimai¶
Let’s set up LDAP for Kimai.
$ cd /opt/time
$ composer update
$ composer require laminas/laminas-ldap --update-no-dev --optimize-autoloader
$ vim /opt/time/config/packages/local.yaml
Set the contents of that file to this:
kimai:
user:
registration: false
password_reset: false
permissions:
roles:
ROLE_USER: ['!password_own_profile']
ROLE_TEAMLEAD: ['!password_own_profile']
ROLE_ADMIN: ['!password_own_profile']
ldap:
connection:
host: id.mousepawmedia.com
port: 389
useStartTls: true
#bindRequiresDn: true
user:
baseDn: ou=Users, dc=id, dc=mousepawmedia, dc=com
usernameAttribute: uid
filter: (&(objectClass=inetOrgPerson))
attributes:
- { ldap_attr: "usernameAttribute", user_method: setUsername }
- { ldap_attr: mail, user_method: setEmail }
- { ldap_attr: cn, user_method: setAlias }
role:
baseDn: ou=Groups, dc=id, dc=mousepawmedia, dc=com
filter: (&(objectClass=posixGroup)(|(cn=management)(cn=admin)))
usernameAttribute: uid
userDnAttribute: memberUid
nameAttribute: cn
groups:
- { ldap_value: management, role: ROLE_TEAMLEAD }
- { ldap_value: admin, role: ROLE_SUPER_ADMIN }
security:
providers:
chain_provider:
chain:
providers: [kimai_ldap]
firewalls:
secured_area:
kimai_ldap: ~
Save and close. Finally, reload Kimai.
sudo -u www-data bin/console kimai:reload --env=prod
Now you should be able to browse to Kimai and log in with LDAP.
Nextcloud¶
Installation¶
Let’s install the other PHP packages we need for this. Most of these are probably already installed, but we’re putting them here to be certain.
$ sudo apt install php7.4-bz2 php7.4-intl php7.4-xml php7.4-zip php7.4-curl php7.4-gd php-imagick php7.4-mbstring php7.4-ldap php7.4-imap php-7.4-apcu php7.4-bcmath php7.4-gmp imagick ffmpeg libmagickcore-6.q16-6-extra
$ sudo phpenmod bcmath gmp
Now we can install Nextcloud itself.
Note
While we are installing 21.0.2 below, Nextcloud has been upgraded many times since. Adjust commands below according to the latest stable version of Nextcloud.
$ cd /tmp
$ curl -LO https://download.nextcloud.com/server/releases/nextcloud-21.0.2.tar.bz2
$ curl -LO https://download.nextcloud.com/server/releases/nextcloud-21.0.2.tar.bz2.sha256
$ shasum -a 256 -c nextcloud-21.0.2.tar.bz2.sha256 < nextcloud-21.0.2.tar.bz2
Ensure that last command says “OK” before continuing, as that confirms the tarball hasn’t been tampered with or spoofed.
$ rm nextcloud-21.0.2.tar.bz2.sha256
$ sudo tar -C /opt -xvjf /tmp/nextcloud-21.0.2.tar.bz2
$ vim /tmp/nextcloud.sh
Set the contents of that file to…
ocpath='/opt/cloud'
htuser='www-data'
htgroup='www-data'
rootuser='root'
printf "Creating possible missing Directories\n"
mkdir -p $ocpath/data
mkdir -p $ocpath/assets
mkdir -p $ocpath/updater
printf "chmod Files and Directories\n"
find ${ocpath}/ -type f -print0 | xargs -0 chmod 0640
find ${ocpath}/ -type d -print0 | xargs -0 chmod 0750
chmod 755 ${ocpath}
printf "chown Directories\n"
chown -R ${rootuser}:${htgroup} ${ocpath}/
chown -R ${htuser}:${htgroup} ${ocpath}/apps/
chown -R ${htuser}:${htgroup} ${ocpath}/assets/
chown -R ${htuser}:${htgroup} ${ocpath}/config/
chown -R ${htuser}:${htgroup} ${ocpath}/data/
chown -R ${htuser}:${htgroup} ${ocpath}/themes/
chown -R ${htuser}:${htgroup} ${ocpath}/updater/
chmod +x ${ocpath}/occ
printf "chmod/chown .htaccess\n"
if [ -f ${ocpath}/.htaccess ]
then
chmod 0644 ${ocpath}/.htaccess
chown ${rootuser}:${htgroup} ${ocpath}/.htaccess
fi
if [ -f ${ocpath}/data/.htaccess ]
then
chmod 0644 ${ocpath}/data/.htaccess
chown ${rootuser}:${htgroup} ${ocpath}/data/.htaccess
fi
Save and close, and then run the file.
$ sudo bash /tmp/nextcloud.sh
After that finishes, we can start configuring Apache2.
Apache2 Configuration¶
Let’s create an Apache2 site configuration for Nextcloud.
$ sudo vim /etc/apache2/sites-available/cloud.conf
Set the contents to…
<IfModule mod_ssl.c>
<VirtualHost cloud.mousepawmedia.com:443>
ServerName cloud.mousepawmedia.com
DocumentRoot /opt/cloud
SSLCertificateFile /etc/letsencrypt/live/cloud.mousepawmedia.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/cloud.mousepawmedia.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Strict-Transport-Security "max-age=31536000"
Header always set Content-Security-Policy upgrade-insecure-requests
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /opt/cloud>
Options +FollowSymLinks
AllowOverride All
Satisfy Any
<IfModule mod_dave.c>
Dav off
</IfModule>
SetEnv HOME /opt/cloud
SetEnv HTTP_HOME /opt/cloud
</Directory>
BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
</IfModule>
Save and close. Now, we need to also allow access to the Nextcloud directory in Apache2’s core directory.
$ sudo vim /etc/apache2/apache2.conf
Add the following below the other <Directory>
entries…
<Directory /opt/cloud>
Options Indexes FollowSymLinks
Require all granted
</Directory>
Then, enable the site and restart Apache2.
$ sudo a2ensite cloud
$ sudo a2enmod headers
$ sudo systemctl restart apache2
Database Setup¶
Before setting up the database, we need to change a couple of things in the MySQL configuration.
$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
Add or change the following lines:
transaction_isolation = READ-COMMITTED
binlog_format = ROW
Save and close, and restart the database.
$ sudo systemctl restart mysql
We need to create a nextcloud
database and a nextcloud
user in MySQL.
$ sudo mysql -u root
Run the following:
CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'some_password';
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost' WITH GRANT OPTION;
FLUSH privileges;
\q
Now ensure that PHP is set up to work with MySQL.
$ sudo phpenmod pdo_mysql
Nextcloud Configuration¶
Go to the new Nextcloud site. On the setup screen, specify an admin account.
Click Storage and Database
, set the Data folder to /opt/cloud/data
.
Select MySQL
for the database, and provide the database user, password,
and database name. The fourth field should be localhost
.
Click Finish setup
.
Note
If you have problems logging into the database on this screen,
check PHPmyadmin → nextcloud
(database) → Privileges. The nextcloud
user should be listed, with Grant Yes
.
SOURCE How To Install and Configure Nextcloud on Ubuntu 16.04 (DigitalOcean)
Preventing Lockouts¶
Due to a glitch in Nextcloud, we have to configure fail2ban to prevent lockouts.
$ sudo vim /etc/fail2ban/filter.d/apache-auth.conf
Change or add the following lines:
# ignore intentional auth failures from nextcloud admin page
ignoreregex = cloud/[data/.ocdata|config]
Configuring Memory Caching¶
To improve performance, we’ll enable memory caching. We are using APCu (since we’re using PHP 7.4), so we simply need to enable this for Nextcloud.
$ sudo vim /opt/cloud/config/config.php
Add the following line before the end:
'memcache.local' => '\OC\Memcache\APCu',
Save and close, and then restart Apache2.
PHP Configuration¶
Nextcloud recommends a few tweaks to php.ini. Run…
$ sudo vim /etc/php/7.4/apache2/php.ini
Find and edit (or uncomment) the following lines:
date.timezone = America/Chicago
memory_limit = 512M
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1
Save and close, and restart Apache2.
Also edit Nextcloud’s configuration:
$ sudo vim /opt/cloud/config/config.php
Add or edit the following line
'default_phone_region' => 'US',
Save and close.
Set Up Cronjob¶
It is recommended to use Cron for background tasks. We will set this up now.
$ sudo crontab -u www-data -e
Add the following line:
*/15 * * * * php -f /opt/cloud/cron.php
Save and close.
Finally, in the Nextcloud Admin pane, go to Basic settings
and select the Cron
option.
S3 Bucket Storage¶
We’ll be setting an S3 Object Storage Bucket as the primary data host.
Note
Do NOT enable the Encryption app; it’s not compatible with S3!
In Linode, activate Object Storage and create a bucket, as well as an access key.
Then edit the Nextcloud configuration:
$ sudo vim /opt/cloud/config/config.php
Add the following to that file, before the closing );
:
'objectstore' => array(
'class' => '\\OC\\Files\\ObjectStore\\S3',
'arguments' => array(
'bucket' => 'mpm-cloud',
'autocreate' => false,
'key' => '2T67FBD41Z99MJ6HY70O',
'secret' => 'xpGOIP7I9pSmuWh9QwXDpdS2s8hESPQw8TTMSGIK',
'hostname' => 'us-east-1.linodeobjects.com',
'port' => 443,
'use_ssl' => true,
'region' => 'us-east-1',
),
),
Save and close. Restart Apache2. Nextcloud will start storing in that bucket instead of on the system disk.
SOURCE: How to Configure Nextcloud to use Linode Object Storage as an External Storage Mount
LDAP Authentication¶
In Nextcloud, go to Apps
and enable LDAP. Then, go to Admin
and LDAP
.
Set the following options:
Server
Host:
id.mousepawmedia.com
Port:
389
Base DN:
ou=Users, dc=id, dc=mousepawmedia, dc=com
Click Test Base DN
, and then Continue
.
Set Only these object classes:
to just inetOrgPerson
, and click
Verify settings and count users
, and then Continue
.
Check LDAP/AD Username
and LDAP/AD Email Address
, and then click
Advanced.
Set…
Directory Settings
User Display Name Field:
uid
2nd User Display Name Field:
cn
Base User Tree:
ou=Users, dc=id, dc=mousepawmedia, dc=com
Group Display Name Field:
cn
Base Group Tree:
ou=Groups, dc=id, dc=mousepawmedia, dc=com
Group-Member association:
memberUid
Special Attributes
Email field:
mail
Also, click the Groups tag and select all the Groups that you want to use
in Nextcloud. We use all but users
and disabled
.
Click Test Configuration
.
The settings are automatically saved. Log in as an LDAP user to test.
Note
If a user profile picture (jpegPhoto
) is specified on the
LDAP account, it will be used automatically on Nextcloud.
Changing Default Files¶
To change or remove the default files, change what is found in
/opt/cloud/core/skeleton
. For our instance of Nextcloud, we’ve removed
all these files.
Collabora Office Online¶
These instructions assume you’ve already set up Collabora Office Online on its own separate cloud.
To connect Collabora Office Online to Nextcloud, go to Nextcloud. Click the menu, and go to Apps –> Productivity. Install the “Collabora Online connector”. Then, go to Admin –> Additional settings –> Collabora Online.
Set Collabora Online server to https://office.mousepawmedia.com/
(or whatever the url is) and click Apply.
Now you can go to the Office app in Nextcloud to access Collabora Office!
SOURCE: Getting started in 3 steps (Nextcloud)
Last, we need to modify fail2ban so it won’t lock users out when using CollaboraOffice.
$ sudo nano /etc/fail2ban/filter.d/cloud.conf
Set the contents of that file to:
[Definition]
failregex={"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<host>'\)","level":2,"time":".*"}
ignoreregex =
Save and close. Then, run…
$ sudo vim /etc/fail2ban/jail.local
Set the contents of that file to:
[nextcloud]
enabled = true # set to false to disable
filter = nextcloud
port = http,https # Change this to https if you aren't using http
logpath = /opt/cloud/data/nextcloud.log # Make sure this is the right path.
ignoreip = 10.0.2.1/24 # Change/Delete this if you want to Ignore one or more IP's
Save and close. Then, restart fail2ban.
$ sudo systemctl restart fail2ban
Mattermost¶
We’ll be using Mattermost self-hosted on the free plan. We won’t be integrating with LDAP at this time. Rather, anyone can create accounts. Invites must be issued to join the Staff team.
Start by creating the certificate for the chat domain. You need to decide on your domain before starting the installation of Mattermost.
$ sudo a2ensite 000-default
$ sudo systemctrl restart apache2
$ sudo certbot certonly --apache -d chat.mousepawmedia.com
$ sudo a2dissite 000-default
$ sudo systemctrl restart apache2
Install Mattermost¶
To set up Mattermost, we need to first create the database:
$ sudo mysql -u root
Run the following:
CREATE USER 'mattermost'@'%' IDENTIFIED BY 'mmuser-password';
CREATE DATABASE mattermost;
GRANT ALL PRIVILEGES ON mattermost.* to 'mattermost'@'%';
exit;
Now we download and install the latest version of Mattermost. The version and download link are on mattermost.com/deploy
$ cd /tmp
$ wget https://releases.mattermost.com/6.0.0/mattermost-6.0.0-linux-amd64.tar.gz
$ tar -xvzf mattermost*.gz
$ sudo mv mattermost /opt/mattermost
$ sudo mkdir /opt/mattermost/data
$ sudo useradd --system --user-group mattermost
$ sudo chown -R mattermost:mattermost /opt/mattermost
$ sudo chmod -R g+w /opt/mattermost
$ sudo vim /opt/mattermost/config/config.json
Change the following sections of that file to match the following, subtituting in your own values as appropriate:
{
"ServiceSettings": {
"SiteURL": "https://chat.mousepawmedia.com",
}
"SqlSettings": {
"DriverName": "mysql",
"DataSource": "mattermost:mmuser-password@tcp(localhost:3306)/mattermost?charset=utf8mb4,utf8&writeTimeout=30s",
}
}
Save and close.
Now test Mattermost by running:
$ cd /opt/mattermost
$ sudo -u mattermost ./bin/mattermost
Watch for the text Server is listening on :8065
. If you see it, everything
worked. Now we set this up to work in production.
sudo vim /lib/systemd/system/mattermost.service
Set the contents of that file to:
[Unit]
Description=Mattermost
After=network.target
After=mysql.service
BindsTo=mysql.service
[Service]
Type=notify
ExecStart=/opt/mattermost/bin/mattermost
TimeoutStartSec=3600
KillMode=mixed
Restart=always
RestartSec=10
WorkingDirectory=/opt/mattermost
User=mattermost
Group=mattermost
LimitNOFILE=49152
[Install]
WantedBy=mysql.service
Save and close, and then run:
$ sudo systemctl daemon-reload
$ sudo systemctl status mattermost.service
Ensure the unit was loaded, and then…
$ sudo systemctl start mattermost.service
$ curl http://localhost:8065
Ensure that responds, then…
$ sudo systemctl enable mattermost.service
Apache2 Proxy¶
We’ll use Apache2 as the proxy. The recommended technique is actually to use NGINX, but as we’re already using Apache2 on this server, we’ll stick with it.
$ sudo vim /etc/apache2/sites-available/chat-mattermost.conf
Set the contents of that file to:
<VirtualHost chat.mousepawmedia.com:443>
ServerName chat.mousepawmedia.com
DocumentRoot /opt/mattermost
ServerAdmin webmaster@mousepawmedia.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/chat.mousepawmedia.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/chat.mousepawmedia.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
ProxyPreserveHost on
RewriteEngine On
RewriteCond %{REQUEST_URI} /api/v[0-9]+/(users/)?websocket [NC]
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} \bUpgrade\b [NC]
RewriteRule .* ws://127.0.0.1:8065%{REQUEST_URI} [P,QSA,L]
<Location />
Require all granted
ProxyPass http://127.0.0.1:8065/
ProxyPassReverse http://127.0.0.1:8065/
ProxyPassReverseCookieDomain 127.0.0.1 mysubdomain.mydomain.com
</Location>
</VirtualHost>
Save and close. Now run:
$ sudo a2enmod rewrite proxy proxy_http proxy_wstunne
$ sudo a2ensite chat-mattermost
$ sudo systemctl restart apache2
SOURCE: Configuring Apache2 as a proxy for Mattermost Server (Unofficial) (Mattermost)
Mattermost Configuration¶
You should be able to go to chat.mousepawmedia.com
now and proceed with
Mattermost setup. Create the initial super user and the team. In this case,
the team is “MousePaw Media”, with the URL “staff”.
After setup, select the product menu in the top-left and select System Console.
Email Notifications¶
On the System Console, from the left menu, go to Environment and SMTP. Set the following settings:
SMTP Server:
mail.mousepawmedia.com
SMTP Server Port:
465
Enable SMTP Authentication: True
SMTP Server Username:
noreply@mousepawmedia.com
SMTP Server Password: (Password for email account)
Connection Security: TLS
Click Save, and then Test Connection. (The other way around will not use the new settings in the test.)
S3 Integration¶
On the System Console, from the left menu, go to Environment and File Storage. Set the following settings:
File System Storage: Amazon S3
Amazon S3 Bucket:
mpm-mattermost`
Amazon S3 Region:
us-east-1
Amazon S3 Access Key ID: (Your access key id here)
Amazon S3 Endpoint:
us-east-1.linodeobjects.com
Amazon S3 Secret Access Key: (Your secret access key here)
Enable Secure Amazon S3 Connections: Yes
Click Save, and then Test Connection. (The other way around will not use the new settings in the test.)
Mattermost IRC Integration¶
We’ll connect to our IRC room via Matterbridge.
Go to the Matterbridge GitHub Releases
page and copy the link address for matterbridge-x.xx.x-linux-64bit. You’ll use
that in the following bash commands, in place of the URLHERE
. You will
also need to revise the other reference to matterbridge-x.xx.x-linux-64bit
:
$ sudo mkdir /opt/matterbridge
$ cd /opt/matterbridge
$ sudo wget URLHERE
$ sudo mv matterbridge-x.xx.x-linux-64bit matterbridge
$ sudo chmod a+x /opt/matterbridge
$ sudo vim /opt/matterbridge/matterbridge.toml
Set the contents of that file to the following, replacing PASSWORD with the password as appropriate. Notice that we are using dedicated accounts on both services for Matterbridge’s use:
[irc.myirc] Nick=”mousepawmedia” NickServNick=”mousepawmedia” NickServPassword=”PASSWORD” Server=”irc.libera.chat:6697” UseTLS=true UseSASL=true SkipTLSVerify=false RemoteNickFormat=”[{PROTOCOL}] <{NICK}> “
[mattermost.mymattermost] #The mattermost hostname. (do not prefix it with http or https) Server=”chat.mousepawmedia.com”
#the team name as can be seen in the mattermost webinterface URL #in lowercase, without spaces Team=”staff”
#login/pass of your bot. #Use a dedicated user for this and not your own! Login=”developers@mousepawmedia.com” Password=”PASSWORD”
RemoteNickFormat=”[{PROTOCOL}] <{NICK}> ” PrefixMessagesWithNick=true
[[gateway]] name=”gateway1” enable=true
[[gateway.inout]] account=”irc.myirc” channel=”#mousepawmedia”
[[gateway.inout]] account=”mattermost.mymattermost” channel=”town-square”
Save and close. Now run the following to start Matterbridge. Watch the output here; ensure it works.
/opt/matterbridge/matterbridge -conf /opt/matterbridge/matterbridge.toml
If that works, we can disown the process, so it keeps running separate from the current SSH session…
bg
jobs
disown -h %1
Now we edit cron to start Matterbridge automatically:
$ crontab -e
Add the following line:
@reboot /opt/matterbridge/matterbridge -conf /opt/matterbridge/matterbridge.toml
Save and close.
LimeSurvey¶
Let’s install LimeSurvey.
Install the dependencies.
$ sudo apt install php-gd php-ldap php-zip php-imap php-ldap
Get the download link from LimeSurvey Community Edition, which we’ll use in the next step.
Download and unzip the latest version. Be sure to replace the URL and filename with the one appropriate for your download. We’ll also set our permissions here.
Note
If you’re paranoid like me about unzipping directly in an important
directory like /opt/password_providers
, you can always unzip it in another folder and
move the limesurvey
folder to /opt/papers
.
$ cd /tmp
$ sudo wget https://download.limesurvey.org/latest-stable-release/limesurvey5.0.8+210712.zip
$ sudo unzip limesurvey2.67.2+170719.zip
$ sudo mv /tmp/limesurvey /opt/papers
$ sudo chown -R mpm:www-data /opt/papers
$ sudo chmod -R 755 /opt/papers
$ sudo chmod -R 775 /opt/papers/tmp
$ sudo chmod -R 775 /opt/papers/upload
$ sudo chmod -R 775 /opt/papers/application/config
We gave the webserver group write permissions to three specific directories, and read-only access to the rest of the folders for LimeSurvey.
Apache2¶
Let’s set up the subsite for LimeSurvey. Before proceeding, ensure you’ve created the certificate for the domain you’re using via the Certbot steps described earlier in this document.
We must allow Apache2 to access the directory we just set up:
$ sudo vim /etc/apache2/apache2.conf
Add the following Directory block to that file:
<Directory /opt/papers/>
Options FollowSymLinks
AllowOverride all
Require all granted
</Directory>
Save and close. Then, we create the Apache2 site.
$ sudo vim /etc/apache2/sites-available/papers.conf
Set the contents of that file to the following:
<IfModule mod_ssl.c>
<VirtualHost papers.mousepawmedia.com:443>
ServerName papers.mousepawmedia.com
ServerAdmin webmaster@mousepawmedia.com
DocumentRoot /opt/papers
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /opt/papers>
Options -MultiViews -Indexes
AllowOverride All
</Directory>
# prevent iframing this site
#Header set X-Frame-Options DENY
# SSL
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/papers.mousepawmedia.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/papers.mousepawmedia.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>
Save and close. Now we can enable the site.
$ sudo a2ensite survey
$ sudo systemctl restart apache2
The site should now be accessible at papers.mousepawmedia.com
. However,
before continuing with the installer, we need to set up a couple more things.
Database¶
Let’s set up the LimeSurvey database:
$ sudo mysql -u root
Run the following:
CREATE USER 'limesurvey'@'localhost' IDENTIFIED BY 'some_password';
CREATE DATABASE IF NOT EXISTS limesurvey;
GRANT SELECT, CREATE, INSERT, UPDATE, DELETE, ALTER, DROP, INDEX ON limesurvey.* TO 'limesurvey'@'localhost' WITH GRANT OPTION;
FLUSH privileges;
\q
LDAP¶
We want Limesurvey to use LDAP for user authentication.
Setup¶
Go to https://survey.mousepawmedia.com
and follow the setup wizard.
On the new installation, log in with the administrator account you set up in the setup wizard.
Go to Configuration -> Settings -> Global, and set the following:
Email settings: * Email method:
SMTP
* SMTP host:mail.mousepawmedia.com:465
* SMTP username:noreply@mousepawmedia.com
* SMTP password: (the password for the email account) * SMTP encryption:SSL/TLS
Bounce settings: * Default site bounce email:
noreply@mousepawmedia.com
* Server type:IMAP
* Server name & port:mail.mousepawmedia.com:993
* User name:noreply@mousepawmedia.com
* Password: (the password for the email account) * Encryption type:SSL/TLS
Security * Force HTTPS:
On
Be sure to save your settings changes.
LDAP¶
Go to Configuration -> Plugins and enable AuthLDAP. Click the title of the plugin to go to its overview, and then click Settings.
Set the following settings:
LDAP server:
ldap://id.mousepawmedia.com
Port number:
389
LDAP version:
LDAPv3
Enable Start-TLS:
Yes
Select how to perform authentication:
Search and bind
Attribute to compare to the given login:
uid
Base DN for the user search operation:
ou=Users,dc=id,dc=mousepawmedia,dc=com
Optional extra LDAP filter to be ANDed…:
(objectClass=inetOrgPerson)
LDAP attribute of email address:
mail
LDAP attribute of full name:
cn
Check to make default authentication method:
Yes
Automatically create user if it exists in LDAP server:
Yes
Grant survey creation permission to automatically created users:
No
Optional base DN for group restriction:
ou=Groups,dc=id,dc=mousepawmedia,dc=com
Optional filter for group restriction:
(&(|(cn=management)(cn=hiring)(cn=admin))(memberUid=$username))
Allow initial user to login via LDAP:
No