Which boy doesn't want to set up his own LEMP environment?
How to easily and efficiently configure your own LEMP environment?
Introduction#
First, you need to have a Linux server. It doesn't matter which distribution you use, as long as it's not too old.
Due to personal preference, all operations in this article will be based on Debian 10, but other distributions will be quite similar.
Before starting the installation, it is recommended to reset the system in the background. If possible, it is suggested to reinstall the system using this script provided by the Moe Club.
Note: Please run all operations in this article as the
root
user!
Update the system and install dependencies#
The first thing to do is to update your system to the latest version:
apt update && apt upgrade -y
After updating, install the dependencies:
apt install -y build-essential libpcre3 libpcre3-dev zlib1g-dev git libssl-dev libcurl4-openssl-dev pkg-config libfreetype6-dev libjpeg-dev libpng-dev libxml2-dev libwebp-dev libxpm-dev libxslt1-dev cmake libncurses5-dev libc-client-dev lsb-release sqlite3 libsqlite3-dev libonig-dev libzip-dev
Create www user#
Use the following command to create the user and the corresponding user group:
groupadd www
useradd -s /sbin/nologin -g www www
Download required software#
Execute the following commands to download the required software:
mkdir -p /root/tmp/
cd /root/tmp/
wget https://www.openssl.org/source/openssl-1.1.1f.tar.gz
wget https://nginx.org/download/nginx-1.16.1.tar.gz
wget https://www.php.net/distributions/php-7.4.4.tar.gz
wget https://repo.mysql.com/mysql-apt-config_0.8.13-1_all.deb
Generate dhparam file#
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Configure nginx#
Extract source code package#
cd /root/tmp/
tar zxvf nginx-1.16.1.tar.gz
tar zxvf openssl-1.1.1f.tar.gz
Compile and install#
cd /root/tmp/nginx-1.16.1
./configure \
--user=www \
--group=www \
--prefix=/usr/local/nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-stream \
--with-stream_ssl_preread_module \
--with-openssl=../openssl-1.1.1f
make && make install
Link executable files#
ln -sf /usr/local/nginx/sbin/nginx /usr/bin/nginx
Create systemd service file#
Create the /lib/systemd/system/nginx.service
file with the following content:
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/bin/nginx -t
ExecStart=/usr/bin/nginx
ExecReload=/usr/bin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Create configuration folders#
mkdir -p /data/www/default
mkdir -p /data/logs/nginx
mkdir -p /usr/local/nginx/conf/vhosts
Modify configuration file#
Modify the /usr/local/nginx/conf/nginx.conf
file, replacing its content with:
user www www;
worker_processes auto;
worker_cpu_affinity auto;
pid /run/nginx.pid;
worker_rlimit_nofile 51200;
error_log /data/logs/nginx/error.log crit;
events {
use epoll;
worker_connections 51200;
multi_accept off;
accept_mutex off;
}
http {
include mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 64m;
sendfile on;
sendfile_max_chunk 512k;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
server_tokens off;
access_log off;
include vhosts/*.conf;
}
Create the /usr/local/nginx/conf/vhosts/default.conf
file with the following content:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name _;
index index.html index.php;
root /data/www/default;
location /nginx_status {
stub_status on;
access_log off;
}
location ~ /.well-known {
allow all;
}
location ~ /\. {
deny all;
}
access_log /data/logs/nginx/access.log;
}
Create the /usr/local/nginx/conf/enable-ssl.conf
file with the following content:
ssl_protocols TLSv1.3 TLSv1.2;
ssl_stapling on;
ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
Create the /usr/local/nginx/conf/enable-hsts.conf
file with the following content:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
Configure php#
Extract source code package#
cd /root/tmp/
tar zxvf php-7.4.4.tar.gz
Compile and install#
cd /root/tmp/php-7.4.4
./configure \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-config-file-scan-dir=/usr/local/php/conf.d \
--enable-fpm \
--with-fpm-user=www \
--with-fpm-group=www \
--enable-pdo \
--enable-mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-pdo-sqlite \
--with-sqlite3 \
--with-iconv-dir \
--with-jpeg \
--with-webp \
--with-xpm \
--with-freetype \
--with-zlib \
--with-libxml \
--enable-xml \
--disable-rpath \
--enable-bcmath \
--enable-shmop \
--enable-sysvsem \
--enable-inline-optimization \
--with-curl \
--enable-mbregex \
--enable-mbstring \
--enable-intl \
--enable-ftp \
--enable-gd \
--with-mhash \
--enable-pcntl \
--enable-sockets \
--with-xmlrpc \
--with-zip \
--enable-soap \
--with-gettext \
--enable-opcache \
--with-xsl \
--with-openssl
make && make install
If you encounter a freetype
error, create the /usr/bin/freetype-config
file with the following content:
#!/bin/sh
/usr/bin/pkg-config freetype2 $@
Then add execute permissions:
chmod a+x /usr/bin/freetype-config
Link executable files#
ln -sf /usr/local/php/bin/php /usr/bin/php
ln -sf /usr/local/php/bin/phpize /usr/bin/phpize
ln -sf /usr/local/php/sbin/php-fpm /usr/bin/php-fpm
Create systemd service file#
Create the /lib/systemd/system/php-fpm.service
file with the following content:
[Unit]
Description=PHP FastCGI process manager
After=local-fs.target network.target nginx.service
[Service]
PIDFile=/run/php-fpm.pid
ExecStart=/usr/bin/php-fpm --fpm-config /usr/local/php/etc/php-fpm.conf --nodaemonize
ExecReload=/bin/kill -USR2 $MAINPID
Type=simple
[Install]
WantedBy=multi-user.target
Create configuration folders#
mkdir -p /usr/local/php/{etc,conf.d}
mkdir -p /data/logs/php
Modify configuration file#
First, generate the php.ini
file:
cp php.ini-production /usr/local/php/etc/php.ini
sed -i 's/post_max_size =.*/post_max_size = 64M/g' /usr/local/php/etc/php.ini
sed -i 's/upload_max_filesize =.*/upload_max_filesize = 64M/g' /usr/local/php/etc/php.ini
sed -i 's/;date.timezone =.*/date.timezone = Asia\/Shanghai/g' /usr/local/php/etc/php.ini
sed -i 's/;cgi.fix_pathinfo=.*/cgi.fix_pathinfo=0/g' /usr/local/php/etc/php.ini
sed -i 's/max_execution_time =.*/max_execution_time = 300/g' /usr/local/php/etc/php.ini
sed -i 's/expose_php = On/expose_php = Off/g' /usr/local/php/etc/php.ini
Create the /usr/local/php/etc/php-fpm.conf
file with the following content:
[global]
pid = /run/php-fpm.pid
error_log = /data/logs/php/php-fpm.log
log_level = notice
[www]
listen = /run/php-fpm.sock
listen.backlog = -1
listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
listen.mode = 0666
user = www
group = www
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 6
pm.max_requests = 1024
pm.process_idle_timeout = 10s
request_terminate_timeout = 100
request_slowlog_timeout = 0
slowlog = var/log/slow.log
Create the /usr/local/nginx/conf/enable-php.conf
file with the following content:
location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
try_files $fastcgi_script_name =404;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi.conf;
fastcgi_pass unix:/run/php-fpm.sock;
}
Configure mysql#
Since mysql doesn't have many features that need customization, you can directly install it using the official repository:
cd /root/tmp/
dpkg -i mysql-apt-config_0.8.13-1_all.deb
apt update
apt -y install mysql-server
During installation, be sure to select the
Legacy
encryption method.
Then run the mysql security settings:
mysql_secure_installation
For personal use, it is recommended to select
no
for the first two prompts andyes
for the rest.
Configure acme.sh#
curl https://get.acme.sh | sh
source /root/.bashrc
acme.sh --upgrade --auto-upgrade
Start services#
systemctl enable nginx.service
systemctl enable php-fpm.service
systemctl enable mysql.service
systemctl start nginx.service
systemctl start php-fpm.service
systemctl start mysql.service
Usage#
Various directories#
- Website directory:
/data/www/
- Nginx virtual host configuration directory:
/usr/local/nginx/conf/vhosts/
- PHP configuration file directory:
/usr/local/php/etc/
Virtual host file format#
server {
listen 80;
listen [::]:80;
server_name test.com;
return 301 https://$server_name$request_uri;
error_page 497 =301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name test.com;
index index.html index.php;
root /data/www/default;
include enable-ssl.conf;
include enable-hsts.conf;
ssl_certificate /data/ssl/test.com/cert.crt;
ssl_certificate_key /data/ssl/test.com/priv.key;
include enable-php.conf;
access_log /data/logs/nginx/default.log;
}