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 11 (Bullseye)

Setup bash and update the system

apt-get update
apt-get 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       localhost.localdomain localhost web1

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

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 postfix ntp ca-certificates bsd-mailx tree


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 - > /etc/nginx/global/codeigniter_production.conf
wget -q -O - > /etc/nginx/global/codeigniter_testing.conf
wget -q -O - > /etc/nginx/global/common.conf
wget -q -O - > /etc/nginx/global/dokuwiki.conf
wget -q -O - > /etc/nginx/global/phpmyadmin.conf
wget -q -O - > /etc/nginx/global/plainphp.conf
wget -q -O - > /etc/nginx/global/ssl.conf
wget -q -O - > /etc/nginx/global/wordpress.conf

Restart Nginx:

/etc/init.d/nginx restart

Setup let’s encrypt

pip3 install tld
certbot register --agree-tos -m <your@email>

Setup MariaDB

Secure MariaDB installation:


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

cat << EOF > /root/.my.cnf
user = root

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 is the remote IP address, before the Ping(DROP) rule:

Ping(ACCEPT)       $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:

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 {
        rotate 14
        create 0640 www-data adm
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
                invoke-rc.d nginx rotate >/dev/null 2>&1

Install virtualhost manager

wget -q -O - > /usr/local/sbin/
chmod 770 /usr/local/sbin/

Download also the tools that will be used with cron:

cd /root/cron_scripts
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 backup
32 4  *  *  *   root    /root/cron_scripts/

How to use virtualhost manager

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

# lemp_manager

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

		it is mandatory
		can be used only with [add_domain, remove_domain, add_alias, get_certs, get_info]
		can be used only with [add_alias, remove_alias, get_info]

	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)

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