Stay Hungry. Stay Foolish.

LEMP 概念

LEMP 指的是 Linux + Nginx (发音 engine x 所以这里是 E 而不是 N) + MySQL + PHP 的简称,国内有些地方叫做 LNMP (因为 LNMP 没法读出来,而 LEMP 可以直接发音,所以今后本站教程一律都会写 LEMP)

以下操作推荐在 root 用户下完成,请使用 sudo -i 切换到 root 用户进行操作

本教程案例的操作环境是 Debian 9.5

更新系统

  • 执行一下系统更新操作:
apt update && apt full-upgrade -y
apt install curl vim wget git sudo unzip apt-transport-https screen lsb-release ca-certificates dialog software-properties-common gnupg2 apparmor dirmngr libelf-dev htop nload -y
  • 更新系统的 apt 源

下面是 Azure Debian 源的内容:

cat > /etc/apt/sources.list << EOF
deb http://debian-archive.trafficmanager.net/debian $(lsb_release -sc) main contrib non-free
deb http://debian-archive.trafficmanager.net/debian-security $(lsb_release -sc)/updates main contrib non-free
deb http://debian-archive.trafficmanager.net/debian $(lsb_release -sc)-updates main contrib non-free
deb http://debian-archive.trafficmanager.net/debian $(lsb_release -sc)-backports main contrib non-free
# deb http://debian-archive.trafficmanager.net/debian $(lsb_release -sc)-proposed-updates main contrib non-free
# deb http://debian-archive.trafficmanager.net/debian $(lsb_release -sc)-backports-sloppy main contrib non-free
EOF

Azure Ubuntu 源内容对应如下:

cat > /etc/apt/sources.list << EOF
deb http://azure.archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main restricted universe multiverse
deb http://azure.archive.ubuntu.com/ubuntu/ $(lsb_release -sc)-security main restricted universe multiverse
deb http://azure.archive.ubuntu.com/ubuntu/ $(lsb_release -sc)-updates main restricted universe multiverse
deb http://azure.archive.ubuntu.com/ubuntu/ $(lsb_release -sc)-backports main restricted universe multiverse
EOF

拿到新系统的话,不妨执行一下 dpkg-reconfigure tzdata 来设置一下正确的时区。
部分系统模板语言设置可能有问题这时候不妨重设语言:

dpkg-reconfigure locales 
export LC_ALL=en_US.UTF-8 && export LANG=en_US.UTF-8 && export LANGUAGE=en_US.UTF-8 && export LC_CTYPE=en_US.UTF-8

更换系统 shell 为 zsh

apt install zsh -y && chsh -s /bin/zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

安装 Nginx

Nginx 实在是有太多玩法啦,这边就只能介绍一点最最最最基础的包安装技巧啦。

更多的内容参考 Nginx 编译教程

使用包管理安装 Nginx

实际上你可以使用官方打包的 Nginx 直接 apt-get install nginx -y 完成安装,但是这样做的后果是你安装的是一个可能非常老旧和充满隐患的 Nginx 我们推荐使用 Ondřej Surý 的 PPA,更新非常快速,而且做的质量也非常好。

  • 首先添加大佬自己打包的 Nginx Mainline 源:

对于 Ubuntu 系列:

add-apt-repository ppa:ondrej/nginx-mainline -y

对于 Debian 系列:

wget -O /etc/apt/trusted.gpg.d/nginx-mainline.gpg https://packages.sury.org/nginx-mainline/apt.gpg

cat >> /etc/apt/sources.list.d/nginx.list << EOF
deb https://packages.sury.org/nginx-mainline/ $(lsb_release -sc) main
EOF
  • 然后我们更新系统、安装必要组件和 Nginx 本身:
apt update && apt install nginx-extras -y
  • 查看 Nginx 版本和参数和安装目录
nginx -V
whereis nginx

增加 Ondřej Surý 大神打包的 PHP 源并安装 PHP 7.x

目前 PHP 官方开发只对 PHP 7.0.x 或 PHP 7.1.x 或 PHP 5.6.x 这三个版本进行维护。

虽然一些老旧的程序、插件不支持 PHP 7.0.x 或 PHP 7.1.x,但是这货速度确实快不少啊,强烈呼吁开发者渐渐的转移到 PHP 7.0.x 或 PHP 7.1.x 的开发中,至于某些国产程序,就只能呵呵哒。

同样,由于 Ubuntu 和 Debian 官方更新实在太慢,导致很多时候没法打上最新的安全补丁,我们同样在这里推荐 Ondřej Surý 的 PPA。

  • Debian 增加大神的 PGP 并加入大神做好的源:
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg 
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
  • Ububtu 可以这样添加源:
add-apt-repository ppa:ondrej/php -y
  • 更新系统并安装需要的 PHP 版本
apt update && apt install php7.2-{bcmath,bz2,cgi,cli,common,curl,dba,dev,fpm,gd,intl,json,mbstring,mysql,opcache,sqlite3,xml,xmlrpc,xsl,zip,memcached,redis,geoip,imagick} -y

如果你需要额外的 PHP 组件,可以通过 apt-cache search php7.2 命令来查找。

如果你需要 7.1.x 7.0.x 或者 5.6.x 那么请修改对应的 PHP 版本号(注意配置文件也要修改的哦)

修改 php.ini 防止跨目录攻击

sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/' /etc/php/7.2/fpm/php.ini  
  • 重启 PHP:
systemctl restart php7.2-fpm  

测试站点建立

cat > /var/www/html/index.php << EOF
<?php phpinfo(); ?>
EOF

cat > /etc/nginx/sites-available/default << EOF
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/html;
    index index.php index.html index.nginx-debian.html;
    server_name _;
    location / {
        try_files \$uri \$uri/ =404;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
    }
    location ~ /\.ht {
        deny all;
    }
}
EOF

执行 service nginx restart 后浏览器输入服务器 ip 地址,如果能正常显示 phpinfo 页面代表配置成功。

安装 MySQL

虽说题目是 MySQL,但是一般实际使用很少真的用 MySQL,用的较多的是他的修改版比如 MariadbPercona Server

更加推荐使用 Percona Server 代替原生的 MySQL

进过长时间的生产环境测试,个人强烈推荐 Percona Server 作为 MySQL 的完美替代。

  • 下载最新版的 deb 安装包文件
wget "https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb"
dpkg -i percona-release*.deb && rm percona-release*.deb

安装 Percona Server 5.7 并进行加固

apt update && apt install percona-server-server-5.7 percona-xtrabackup-24 -y

安装成功后系统会要求输入两次 MySQL 的 root 密码,请切记一定要使用随机的、不可被人猜测的密码。

很多新手(包括我自己)第一次安装用了弱密码,后来服务器就被人日,所以这里强烈推荐安装完 MySQL 后,执行一次安全设置,很简单的一条命令:

mysql_secure_installation

执行后会让您选择密码强度,一般情况下选择 1 或者 2

[email protected]:~# mysql_secure_installation

Securing the MySQL server deployment.

Enter password for user root: 

VALIDATE PASSWORD PLUGIN can be used to test passwords and improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No:y 请输入 y 进行初始安全设置

There are three levels of password validation policy:

LOW Length &gt;= 8  
MEDIUM Length &gt;= 8, numeric, mixed case, and special characters
STRONG Length &gt;= 8, numeric, mixed case, special characters and dictionary file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2 最强大的密码当然要输入 2

Using existing password for root.

Estimated strength of the password: 100  
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n 如果之前设置了强密码,则不需要重新更改 root 密码,反之则按 y 回车后输入两次重置

By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y 移除匿名用户,没啥鸟用就直接移除吧

Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y 关闭 root 远程登录,不需要进行远程登录的话就关了吧  
Success.

By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment.

Remove test database and access to it? (Press y|Y for Yes, any other key for No) :y 移除 test 数据库

Reloading the privilege tables will ensure that all changes made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y 重置数据库权限  

再次提醒,密码一定要随机、不可猜测,使用弱密码而导致服务器被日的例子实在是数不清楚。

简单数据库操作

  • 首先使用 root 登录 MySQL
mysql -u root -p  
  • 会提示输入密码,输入密码登陆后,创建一个名为 example 的数据库
CREATE DATABASE example DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 

由于手机端的流行,我们已经不再使用 utf-8 编码,而改用 utf8mb4 这样我们就可以在 MySQL 数据库里储存 emoji 表情了。你甚至可以尝试使用 emoji 作为用户名或者密码。

  • 接着我们创建一个叫做 example_user 的用户,使用强大的密码并且赋予 example_database 数据库权限
GRANT ALL ON example.* TO 'example_user'@'localhost' IDENTIFIED BY '这里改成你要设置的强大的没人能猜出来的随机的密码'; 

终端会提示类似 Query OK, 0 rows affected, 1 warning 不用去管它

  • 然后刷新权限,没问题就可以退出结束安装了
FLUSH PRIVILEGES;
EXIT;

数据库备份操作

数据库当然是有非常多的玩法的这边介绍最重要的一点,就是备份,删库跑路的故事听的太多了,随时备份是一个好习惯,简单介绍一下增量备份与恢复的过程。

  • 增量备份
mkdir -p /data/backups/
# 首先进行全量备份,不压缩,不加密
xtrabackup --backup --target-dir=/data/backups/base \
--user=root --password='YourPasswd' --databases='example' 
# 按需进行多次增量备份
xtrabackup --backup --target-dir=/data/backups/inc1 --incremental-basedir=/data/backups/base \
--user=root --password='YourPasswd' --databases='example' 
...
  • 备份恢复
xtrabackup --prepare --apply-log-only --target-dir=/data/backups/base --incremental-dir=/data/backups/inc1
xtrabackup --copy-back --target-dir=/data/backups/base
chown -R mysql:mysql /var/lib/mysql

好啦就简单的介绍到这里,一点微小的工作,谢谢大家。