Matteo Mattei

Hello, my name is Matteo Mattei and this is my personal website. I am computer engineer with a long experience in Linux system administration and web software development.

linkedin rss twitter google+ github facebook

Full web server setup with Debian 12 (Bookworm)

Setup bash and update the system

apt update
apt dist-upgrade

Configure hostname correctly

Make sure to have the following two lines (with the same format) at the top of your /etc/hosts file

127.0.0.1       localhost.localdomain localhost
xxx.xxx.xxx.xxx web1.myserver.com web1

Note: xxx.xxx.xxx.xxx is the public IP address assigned to your server.

Add you full hostname (for example web1.myserver.com) to /etc/hostname and apply it:

hostname -F /etc/hostname

Then to validate that the FQDN is valid and correctly applied type this:

hostname -f
// the answer should be web1.myserver.com

Install all needed packages

apt install wget vim git acl screen rsync net-tools pwgen mariadb-server mariadb-client nginx iptables shorewall php php-cli php-curl php-dev php-gd php-imagick php-imap php-memcache php-pspell php-tidy php-xmlrpc php-pear php-fpm php-mbstring php-mysql certbot phpmyadmin python3-pip python3-tld postfix ntp ca-certificates bsd-mailx tree

Postfix:

Web server to reconfigure automatically:

Configure database for phpmyadmin with dbconfig-common?

MySQL application password for phpmyadmin:

Setup Nginx

Stop Nginx web server:

/etc/init.d/nginx stop

Backup Nginx configuration:

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

Add the following lines in /etc/nginx/nginx.conf after tcp_nopush on;:

tcp_nodelay on;
keepalive_timeout 65;

And the following lines after gizp on;:

gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

# max body size
client_max_body_size 10M;

Copy some nginx configuration files:

mkdir -p /etc/nginx/certs
ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/nginx/certs/server.crt
ln -s /etc/ssl/private/ssl-cert-snakeoil.key /etc/nginx/certs/server.key

mkdir -p /etc/nginx/global
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/codeigniter_production.conf > /etc/nginx/global/codeigniter_production.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/codeigniter_testing.conf > /etc/nginx/global/codeigniter_testing.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/common.conf > /etc/nginx/global/common.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/dokuwiki.conf > /etc/nginx/global/dokuwiki.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/phpmyadmin.conf > /etc/nginx/global/phpmyadmin.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/plainphp.conf > /etc/nginx/global/plainphp.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/ssl.conf > /etc/nginx/global/ssl.conf
wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/nginx/global/wordpress.conf > /etc/nginx/global/wordpress.conf

Restart Nginx:

/etc/init.d/nginx restart

Setup let’s encrypt

certbot register --agree-tos -m <your@email>

Setup MariaDB

Secure MariaDB installation:

mysql_secure_installation

Set MariaDB root password in a configuration file (the same password configured before!)

cat << EOF > /root/.my.cnf
[client]
user = root
password = MARIADB_ROOT_PASSWORD
EOF

Optional enable MySQL slow query logging (often useful during slow page load debugging):

sed -i "{s/^#slow_query_log_file /slow_query_log_file /g}" /etc/mysql/mariadb.conf.d/50-server.cnf
sed -i "{s/^#long_query_time /long_query_time /g}" /etc/mysql/mariadb.conf.d/50-server.cnf
sed -i "{s/^#log_slow_verbosity /log_slow_verbosity /g}" /etc/mysql/mariadb.conf.d/50-server.cnf
sed -i "{s/^#log-queries-not-using-indexes/log-queries-not-using-indexes/g}" /etc/mysql/mariadb.conf.d/50-server.cnf

MySQL is now configured, so restart it:

/etc/init.d/mariadb restart

Configure Shorewall firewall rules

Copy the default configuration for one interface:

cd /usr/share/doc/shorewall/examples/one-interface
cp interfaces /etc/shorewall/
cp policy /etc/shorewall/
cp rules /etc/shorewall/
cp zones /etc/shorewall/

Now open /etc/shorewall/policy file and change the line:

net             all             DROP            info

removing info directive given it fills the system logs:

net             all             DROP

Now open /etc/shorewall/rules and add the following rules at the bottom of the file:

HTTP/ACCEPT     net             $FW
HTTPS/ACCEPT    net             $FW
SSH/ACCEPT      net             $FW

NOTE: in case you want to allow ICMP (Ping) traffic from a specific remote hosts you need to add a rule similar to the following where xxx.xxx.xxx.xxx is the remote IP address, before the Ping(DROP) rule:

Ping(ACCEPT)    net:xxx.xxx.xxx.xxx       $FW

Now edit /etc/default/shorewall and change startup=0 to startup=1 You are now ready to start the firewall:

/etc/init.d/shorewall start

Setup Postfix

Stop postfix server:

/etc/init.d/postfix stop

Edit /etc/mailname and set your server domain name, for example:

server1.mycompany.com

Restart Postfix:

/etc/init.d/postfix start

Select correct timezone

dpkg-reconfigure tzdata
# Select your timezone (for example Europe/Rome)

Log rotation

In order to correctly log files you need to adjust logrotate configuration for Nginx:

cat << EOF >> /etc/logrotate.d/nginx
/home/*/*/logs/*.log {
        daily
        missingok
        rotate 14
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                invoke-rc.d nginx rotate >/dev/null 2>&1
        endscript
}
EOF

Install virtualhost manager

wget -q -O - https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/lemp_manager.py > /usr/local/sbin/lemp_manager.py
chmod 770 /usr/local/sbin/lemp_manager.py

Download also the tools that will be used with cron:

mkdir /root/cron_scripts
cd /root/cron_scripts
wget https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/cron_scripts/backup_mysql.sh
wget https://raw.githubusercontent.com/matteomattei/servermaintenance/master/Debian12/cron_scripts/mysql_optimize.sh
chmod 770 *.sh

Configure CRON

Edit /etc/crontab and add the following lines at the bottom:

# mysql optimize tables
3  4  *  *  7   root    /root/cron_scripts/mysql_optimize.sh

# mysql backup
32 4  *  *  *   root    /root/cron_scripts/backup_mysql.sh

How to use virtualhost manager

You can use the virtualhost manager for adding or removing virtualhosts:

# lemp_manager

Usage:
/usr/local/sbin/lemp_manager -a|--action=<action> [-d|--domain=<domain>] [-A|--alias=<alias>] [options]

Parameters:
	-a|--action=ACTION
		it is mandatory
	-d|--domain=domain.tld
		can be used only with [add_domain, remove_domain, add_alias, get_certs, get_info]
	-A|--alias=alias.domain.tld
		can be used only with [add_alias, remove_alias, get_info]

Actions:
	add_domain	Add a new domain
	add_alias	Add a new domain alias to an existent domain
	remove_domain	Remove an existent domain
	remove_alias	Remove an existent domain alias
	get_certs	Obtain SSL certificate and deploy it
	get_info	Get information of a domain or a domain alias (username)

Options:
	-f|--fakessl	Use self signed certificate (only usable with [add_domain, add_alias])
comments powered by Disqus