Ubuntu LEMP 7.3
Last updated: September 9th 2022
The Perfect Server - Ubuntu LEMP 7.3
This document details how we've set up our Ubuntu LEMP (Linux (E)Nginx Mysql and PHP) 7.3 stack. By provisioning a base Ubuntu Bionic image, and following these steps exactly, you would be able to duplicate our server image.
This is a living document. Based on on-going experience and community feedback we tweak our stacks and keep this doc continuously updated.
This stack has been deprecated in favor of the Ubuntu LEMP 7.4 stack
Install fail2ban and enable firewall
apt-get update; apt-get upgrade -y; apt-get install -y fail2ban ufw;
ufw allow 21 ufw allow 50000:50099/tcp ufw allow out 20/tcp ufw allow 22 ufw allow 80 ufw allow 443 ufw --force enable
Add some PPAs to stay current
apt-get install -y software-properties-common apt-add-repository ppa:nginx/development -y apt-add-repository ppa:ondrej/apache2 -y apt-add-repository ppa:ondrej/nginx-mainline -y apt-add-repository ppa:ondrej/php -y
Set up MariaDB repositories
apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
add-apt-repository 'deb [arch=amd64] http://mariadb.mirror.nucleus.be/repo/10.3/ubuntu bionic main' -y
Install base packages
apt-get update; apt-get install -y build-essential curl nano wget lftp unzip bzip2 arj nomarch lzop htop openssl gcc git binutils libmcrypt4 libpcre3-dev make python2.7 python-pip supervisor unattended-upgrades whois zsh imagemagick uuid-runtime
Set the timezone to UTC
ln -sf /usr/share/zoneinfo/UTC /etc/localtime
Install PHP7.3 and common PHP packages
apt-get install -y php7.3-cli php7.3-dev php7.3-pgsql php7.3-sqlite3 php7.3-gd php7.3-curl php-memcached php7.3-imap php7.3-mysql php7.3-mbstring php7.3-xml php-imagick php7.3-zip php7.3-bcmath php7.3-soap php7.3-intl php7.3-readline php7.3-common php7.3-pspell php7.3-tidy php7.3-xmlrpc php7.3-xsl php7.3-opcache php-apcu
Install Composer
curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer
Install and configure Memcached
apt-get install -y memcached sed -i 's/-l 0.0.0.0/-l 127.0.0.1/' /etc/memcached.conf systemctl restart memcached
Update PHP CLI configuration
sed -i "s/error_reporting = .*/error_reporting = E_ALL/" /etc/php/7.3/cli/php.ini sed -i "s/display_errors = .*/display_errors = On/" /etc/php/7.3/cli/php.ini sed -i "s/memory_limit = .*/memory_limit = 512M/" /etc/php/7.3/cli/php.ini sed -i "s/;date.timezone.*/date.timezone = UTC/" /etc/php/7.3/cli/php.ini
Configure sessions directory permissions
chmod 733 /var/lib/php/sessions chmod +t /var/lib/php/sessions
Install Nginx and PHP-FPM
apt-get install -y nginx php7.3-fpm
Generate dhparam file for stronger Nginx SSL security
openssl dhparam -out /etc/nginx/dhparams.pem 2048
Tweak PHP-FPM settings
Please note: We are suppressing PHP error output here by setting these options to production values
sed -i "s/error_reporting = .*/error_reporting = E_ALL \& ~E_NOTICE \& ~E_STRICT \& ~E_DEPRECATED/" /etc/php/7.3/fpm/php.ini sed -i "s/display_errors = .*/display_errors = Off/" /etc/php/7.3/fpm/php.ini sed -i "s/memory_limit = .*/memory_limit = 512M/" /etc/php/7.3/fpm/php.ini sed -i "s/upload_max_filesize = .*/upload_max_filesize = 256M/" /etc/php/7.3/fpm/php.ini sed -i "s/post_max_size = .*/post_max_size = 256M/" /etc/php/7.3/fpm/php.ini sed -i "s/;date.timezone.*/date.timezone = UTC/" /etc/php/7.3/fpm/php.ini
Tune PHP-FPM pool settings
sed -i "s/;listen\.mode.*/listen.mode = 0666/" /etc/php/7.3/fpm/pool.d/www.conf sed -i "s/;request_terminate_timeout.*/request_terminate_timeout = 60/" /etc/php/7.3/fpm/pool.d/www.conf sed -i "s/pm\.max_children.*/pm.max_children = 70/" /etc/php/7.3/fpm/pool.d/www.conf sed -i "s/pm\.start_servers.*/pm.start_servers = 20/" /etc/php/7.3/fpm/pool.d/www.conf sed -i "s/pm\.min_spare_servers.*/pm.min_spare_servers = 20/" /etc/php/7.3/fpm/pool.d/www.conf sed -i "s/pm\.max_spare_servers.*/pm.max_spare_servers = 35/" /etc/php/7.3/fpm/pool.d/www.conf sed -i "s/;pm\.max_requests.*/pm.max_requests = 500/" /etc/php/7.3/fpm/pool.d/www.conf
Tweak Nginx settings
sed -i "s/worker_processes.*/worker_processes auto;/" /etc/nginx/nginx.conf sed -i "s/# multi_accept.*/multi_accept on;/" /etc/nginx/nginx.conf sed -i "s/# server_names_hash_bucket_size.*/server_names_hash_bucket_size 128;/" /etc/nginx/nginx.conf sed -i "s/# server_tokens off/server_tokens off/" /etc/nginx/nginx.conf
If you want XDebug - install it and follow the on-screen instructions
This is not installed per default on Webdock stacks - included here for reference.
pecl install xdebug
Configure Gzip for Nginx
Create /etc/nginx/conf.d/gzip.conf and add the following
gzip_comp_level 5; gzip_min_length 256; gzip_proxied any; gzip_vary on; gzip_types application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component;
Install latest NodeJS LTS
curl --silent --location https://deb.nodesource.com/setup_10.x | bash -; apt-get update; apt-get install -y nodejs;
Install MariaDB (MySQL) and set a strong root password
Remember to make a note of your password, you are going to need it in a minute
apt-get install -y mariadb-server;
Secure your MariaDB installation
mysql_secure_installation
Install phpMyAdmin
We will install phpMyAdmin using Composer as Ubuntu packages are no longer being maintained.
cd /var/www composer create-project phpmyadmin/phpmyadmin cp /var/www/phpmyadmin/config.sample.inc.php /var/www/phpmyadmin/config.inc.php mysql -u root -pYOUR_ROOT_PASSWORD < /var/www/phpmyadmin/sql/create_tables.sql sed -i "s/\$cfg\['blowfish_secret'\] = '';.*/\$cfg\['blowfish_secret'\] = '$(uuidgen)';/" /var/www/phpmyadmin/config.inc.php mkdir /var/www/phpmyadmin/tmp; chown www-data:www-data /var/www/phpmyadmin/tmp;
Symlink phpMyAdmin, create logs dir and set permissions and ownership on /var/www
ln -s /var/www/phpmyadmin/ /var/www/html/phpmyadmin; mkdir /var/www/logs; chown www-data:www-data /var/www/html; chown www-data:www-data /var/www/logs; chown www-data:www-data /var/www; chmod -R g+rw /var/www;
Install Mongodb
apt-get install -y libcurl4-openssl-dev pkg-config libssl-dev mongodb pecl install mongodb
add extension=mongodb.so to PHP-fpm and PHP-cli configuration:
echo "extension=mongodb.so" > /etc/php/7.3/fpm/conf.d/30-mongodb.ini echo "extension=mongodb.so" > /etc/php/7.3/cli/conf.d/30-mongodb.ini
Install Redis
apt install redis-server -y;
Set systemd for supervised and restart Redis
sed -i "s/supervised.*/supervised systemd/" /etc/redis/redis.conf; systemctl restart redis.service;
You may want to further secure your Redis installation
Create Nginx virtual host config
Create the file /etc/nginx/sites-available/webdock and input the following
Now disable the default and symlink in your config
rm /etc/nginx/sites-enabled/default ln -s /etc/nginx/sites-available/webdock /etc/nginx/sites-enabled/webdock
Install Letsencrypt Certbot
add-apt-repository ppa:certbot/certbot -y; apt-get update; apt-get install -y python-certbot-nginx;
Restart PHP-FPM and Nginx
systemctl restart php7.3-fpm; systemctl restart nginx;
Setup and configure FTP
apt-get install -y pure-ftpd-common
Set some configuration
echo "no" > /etc/pure-ftpd/conf/PAMAuthentication echo "yes" > /etc/pure-ftpd/conf/ChrootEveryone echo "1" > /etc/pure-ftpd/conf/TLS
By setting TLS to a value of "2" you can force TLS connections. However, as we are self-signing our certificate here, you may encounter problems connecting with your FTP client and may need to forcibly ignore certificate errors.
Set MinUID to 33 (to allow www-data as user)
echo "33" > /etc/pure-ftpd/conf/MinUID
Add our chosen passive portrange to config
echo "50000 50099" > /etc/pure-ftpd/conf/PassivePortRange
Setup SSL Certificate for FTP
openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 2048
openssl req -x509 -days 36500 -nodes -newkey rsa:2048 -sha256 -keyout \ /etc/ssl/private/pure-ftpd.pem \ -out /etc/ssl/private/pure-ftpd.pem
chmod 600 /etc/ssl/private/*.pem
Complete the configuration
touch /etc/pure-ftpd/pureftpd.passwd; /usr/bin/pure-pw mkdb; ln -s /etc/pure-ftpd/pureftpd.passwd /etc/pureftpd.passwd ln -s /etc/pure-ftpd/pureftpd.pdb /etc/pureftpd.pdb ln -s /etc/pure-ftpd/conf/PureDB /etc/pure-ftpd/auth/PureDB systemctl restart pure-ftpd
Activate Fail2Ban for Pure-FTPd
cat > /etc/fail2ban/jail.d/pure-ftpd.conf << EOF [pure-ftpd] enabled=true maxretry=5 EOF
Restart Fail2Ban
systemctl restart fail2ban
Set up logrotate for our Nginx logs
Edit /etc/logrotate.d/vhost and add the following - this gives you 10 days of logs, rotated daily
/var/www/logs/*.log { rotate 10 daily compress delaycompress sharedscripts postrotate systemctl reload nginx > /dev/null endscript }
Setup unattended security upgrades
cat > /etc/apt/apt.conf.d/50unattended-upgrades << EOF Unattended-Upgrade::Allowed-Origins { "Ubuntu bionic-security"; }; Unattended-Upgrade::Package-Blacklist { // }; EOF
cat > /etc/apt/apt.conf.d/10periodic << EOF APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "7"; APT::Periodic::Unattended-Upgrade "1"; EOF
Restart your server
Make sure all services come up properly. You can see what services are listening on which ports on your server by running
netstat -tap
Congratulations. All services should now come up and you have a production-ready webserver stack running. You can further tune your webserver and PHP-FPM settings based on your use-case (e.g. whether you have a high or low traffic site, mostly serve static or dynamic content etc.). Try Googling "optimize php-fpm" or "optimize apache" for example and pick settings that fit your requirements and chosen Webdock profile. If you find some optimized defaults you would like us to include in our stacks, please let us know and we will take a look.
Related articles
-
Ubuntu Jammy LAMP 8.2
Learn how to set up the Perfect Ubuntu Jammy Web Server - Linux Apache and the latest PHP version
Last updated: August 19th 2024
-
Ubuntu Jammy LEMP 8.2
Learn how to set up the Perfect Ubuntu Web Server on Ubuntu Jammy - Linux NginX and the latest PHP version
Last updated: August 19th 2024
-
Ubuntu LEMP 8.1
Learn how to set up the Perfect Ubuntu Web Server - Linux NginX PHP 8.1
Last updated: May 10th 2023
-
Ubuntu Focal LEMP 8.1
Learn how to set up the Perfect Focal Ubuntu Web Server - Linux NginX PHP 8.1
Last updated: September 15th 2022
-
Ubuntu Focal LEMP 7.4
Learn how to set up the Perfect Ubuntu Focal Web Server - Linux NginX PHP 7.4
Last updated: September 15th 2022
-
Ubuntu LEMP 7.2
Learn how to set up the Perfect Ubuntu Web Server - Linux NginX PHP 7.2
Last updated: September 15th 2022
-
Ubuntu LEMP 7.1
Learn how to set up the Perfect Ubuntu Web Server - Linux NginX PHP 7.1
Last updated: September 9th 2022
-
Ubuntu LEMP 5.6
Learn how to set up the Perfect Ubuntu Web Server - Linux NginX PHP 5.6
Last updated: September 9th 2022
-
Ubuntu LAMP 8.1
Learn how to set up the Perfect Ubuntu Web Server - Linux Apache PHP 8.1
Last updated: May 10th 2023
-
Ubuntu Focal LAMP 8.1
Learn how to set up the Perfect Ubuntu Focal Web Server - Linux Apache PHP 8.1
Last updated: September 15th 2022
-
Ubuntu Focal LAMP 7.4
Learn how to set up the Perfect Ubuntu Focal Web Server - Linux Apache PHP 7.4
Last updated: September 15th 2022
-
Ubuntu LAMP 7.3
Learn how to set up the Perfect Ubuntu Web Server - Linux Apache PHP 7.3
Last updated: September 9th 2022
-
Ubuntu LAMP 7.2
Learn how to set up the Perfect Ubuntu Web Server - Linux Apache PHP 7.2
Last updated: September 15th 2022
-
Ubuntu LAMP 7.1
Learn how to set up the Perfect Ubuntu Web Server - Linux Apache PHP 7.1
Last updated: September 9th 2022
-
Ubuntu LAMP 5.6
Learn how to set up the Perfect Ubuntu Web Server - Linux Apache PHP 5.6
Last updated: September 9th 2022
-
Ubuntu LEMP 7.4
Learn how to set up the Perfect Ubuntu Web Server - Linux NginX PHP 7.4
Last updated: September 7th 2023
-
Ubuntu LAMP 7.4
Learn how to set up the Perfect Ubuntu Web Server - Linux Apache PHP 7.4
Last updated: September 7th 2023